From 758021bfa9ea25c58e62d2f68512628b19502ce7 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 12 Jan 2009 15:17:09 +0100 Subject: drivers/media: Convert to snd_card_create() Convert from snd_card_new() to the new snd_card_create() function. Signed-off-by: Takashi Iwai --- drivers/media/video/cx88/cx88-alsa.c | 7 ++++--- drivers/media/video/em28xx/em28xx-audio.c | 7 ++++--- drivers/media/video/saa7134/saa7134-alsa.c | 8 ++++---- 3 files changed, 12 insertions(+), 10 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/cx88/cx88-alsa.c b/drivers/media/video/cx88/cx88-alsa.c index 66c755c116dc..ce98d955231a 100644 --- a/drivers/media/video/cx88/cx88-alsa.c +++ b/drivers/media/video/cx88/cx88-alsa.c @@ -803,9 +803,10 @@ static int __devinit cx88_audio_initdev(struct pci_dev *pci, return (-ENOENT); } - card = snd_card_new(index[devno], id[devno], THIS_MODULE, sizeof(snd_cx88_card_t)); - if (!card) - return (-ENOMEM); + err = snd_card_create(index[devno], id[devno], THIS_MODULE, + sizeof(snd_cx88_card_t), &card); + if (err < 0) + return err; card->private_free = snd_cx88_dev_free; diff --git a/drivers/media/video/em28xx/em28xx-audio.c b/drivers/media/video/em28xx/em28xx-audio.c index 94378ccb7505..66579508e175 100644 --- a/drivers/media/video/em28xx/em28xx-audio.c +++ b/drivers/media/video/em28xx/em28xx-audio.c @@ -438,9 +438,10 @@ static int em28xx_audio_init(struct em28xx *dev) printk(KERN_INFO "em28xx-audio.c: Copyright (C) 2006 Markus " "Rechberger\n"); - card = snd_card_new(index[devnr], "Em28xx Audio", THIS_MODULE, 0); - if (card == NULL) - return -ENOMEM; + err = snd_card_create(index[devnr], "Em28xx Audio", THIS_MODULE, 0, + &card); + if (err < 0) + return err; spin_lock_init(&adev->slock); err = snd_pcm_new(card, "Em28xx Audio", 0, 0, 1, &pcm); diff --git a/drivers/media/video/saa7134/saa7134-alsa.c b/drivers/media/video/saa7134/saa7134-alsa.c index 26194a0ce927..482be1436e92 100644 --- a/drivers/media/video/saa7134/saa7134-alsa.c +++ b/drivers/media/video/saa7134/saa7134-alsa.c @@ -990,10 +990,10 @@ static int alsa_card_saa7134_create(struct saa7134_dev *dev, int devnum) if (!enable[devnum]) return -ENODEV; - card = snd_card_new(index[devnum], id[devnum], THIS_MODULE, sizeof(snd_card_saa7134_t)); - - if (card == NULL) - return -ENOMEM; + err = snd_card_create(index[devnum], id[devnum], THIS_MODULE, + sizeof(snd_card_saa7134_t), &card); + if (err < 0) + return err; strcpy(card->driver, "SAA7134"); -- cgit v1.2.3 From 6c5dbb40f4795f3fdbf3e5aab7eda4e2f838d08b Mon Sep 17 00:00:00 2001 From: Russell King Date: Sat, 24 Jan 2009 16:27:06 +0000 Subject: [ARM] omap: omap24xxcam: use short connection IDs for omap2 clocks Signed-off-by: Russell King --- arch/arm/mach-omap2/clock24xx.c | 4 ++-- drivers/media/video/omap24xxcam.c | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers/media/video') diff --git a/arch/arm/mach-omap2/clock24xx.c b/arch/arm/mach-omap2/clock24xx.c index 1e9ac83dca5e..d190b6a74936 100644 --- a/arch/arm/mach-omap2/clock24xx.c +++ b/arch/arm/mach-omap2/clock24xx.c @@ -169,8 +169,8 @@ static struct omap_clk omap24xx_clks[] = { CLK(NULL, "wdt1_ick", &wdt1_ick, CK_243X | CK_242X), CLK(NULL, "omapctrl_ick", &omapctrl_ick, CK_243X | CK_242X), CLK(NULL, "icr_ick", &icr_ick, CK_243X), - CLK(NULL, "cam_fck", &cam_fck, CK_243X | CK_242X), - CLK(NULL, "cam_ick", &cam_ick, CK_243X | CK_242X), + CLK("omap24xxcam", "fck", &cam_fck, CK_243X | CK_242X), + CLK("omap24xxcam", "ick", &cam_ick, CK_243X | CK_242X), CLK(NULL, "mailboxes_ick", &mailboxes_ick, CK_243X | CK_242X), CLK(NULL, "wdt4_ick", &wdt4_ick, CK_243X | CK_242X), CLK(NULL, "wdt4_fck", &wdt4_fck, CK_243X | CK_242X), diff --git a/drivers/media/video/omap24xxcam.c b/drivers/media/video/omap24xxcam.c index 73eb656acfe3..805faaea6449 100644 --- a/drivers/media/video/omap24xxcam.c +++ b/drivers/media/video/omap24xxcam.c @@ -80,17 +80,17 @@ static int omap24xxcam_clock_get(struct omap24xxcam_device *cam) { int rval = 0; - cam->fck = clk_get(cam->dev, "cam_fck"); + cam->fck = clk_get(cam->dev, "fck"); if (IS_ERR(cam->fck)) { - dev_err(cam->dev, "can't get cam_fck"); + dev_err(cam->dev, "can't get camera fck"); rval = PTR_ERR(cam->fck); omap24xxcam_clock_put(cam); return rval; } - cam->ick = clk_get(cam->dev, "cam_ick"); + cam->ick = clk_get(cam->dev, "ick"); if (IS_ERR(cam->ick)) { - dev_err(cam->dev, "can't get cam_ick"); + dev_err(cam->dev, "can't get camera ick"); rval = PTR_ERR(cam->ick); omap24xxcam_clock_put(cam); } -- cgit v1.2.3 From d2c452306ab402d7a3572bc3bf8e575796529bf8 Mon Sep 17 00:00:00 2001 From: Gregory Lardiere Date: Sun, 22 Feb 2009 17:54:11 -0300 Subject: V4L/DVB (10789): m5602-s5k4aa: Split up the initial sensor probe in chunks. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The previous probe rotine tried to read 6 bytes in one chunk which currently isn't allowed. This is the rev. 10346 243399e67c41 readded with a high priority. Signed-off-by: Gregory Lardiere Signed-off-by: Erik Andrén Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/m5602/m5602_s5k4aa.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/gspca/m5602/m5602_s5k4aa.c b/drivers/media/video/gspca/m5602/m5602_s5k4aa.c index e564a61a72d7..48892b5715d5 100644 --- a/drivers/media/video/gspca/m5602/m5602_s5k4aa.c +++ b/drivers/media/video/gspca/m5602/m5602_s5k4aa.c @@ -102,7 +102,11 @@ int s5k4aa_probe(struct sd *sd) } /* Test some registers, but we don't know their exact meaning yet */ - if (m5602_read_sensor(sd, 0x00, prod_id, sizeof(prod_id))) + if (m5602_read_sensor(sd, 0x00, prod_id, 2)) + return -ENODEV; + if (m5602_read_sensor(sd, 0x02, prod_id+2, 2)) + return -ENODEV; + if (m5602_read_sensor(sd, 0x04, prod_id+4, 2)) return -ENODEV; if (memcmp(prod_id, expected_prod_id, sizeof(prod_id))) -- cgit v1.2.3 From 4c6c390eb8ba0c569279266a98c604508c695ef8 Mon Sep 17 00:00:00 2001 From: Vitaly Wool Date: Thu, 5 Mar 2009 13:03:32 -0300 Subject: V4L/DVB (10832): tvaudio: Avoid breakage with tda9874a The 'bytes' array is 64 bytes large but the easy standard programming (TDA9874A_ESP) has a number of 255, outside the shadow array size. This patch increases the size of the shadow array in order to accomodate this register. Signed-off-by: Vitaly Wool Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/tvaudio.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/tvaudio.c b/drivers/media/video/tvaudio.c index 5aeccb301cea..076ed5bf48b1 100644 --- a/drivers/media/video/tvaudio.c +++ b/drivers/media/video/tvaudio.c @@ -54,7 +54,7 @@ MODULE_LICENSE("GPL"); /* ---------------------------------------------------------------------- */ /* our structs */ -#define MAXREGS 64 +#define MAXREGS 256 struct CHIPSTATE; typedef int (*getvalue)(int); -- cgit v1.2.3 From e08e7b5f01de7ec246b996c65e9c26c7cea0c62d Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 5 Mar 2009 16:19:14 -0300 Subject: V4L/DVB (10834): zoran: auto-select bt866 for AverMedia 6 Eyes AFAIK, the bt866 is only seen on AverMedia 6 Eyes. However, no module selects it. Adds a proper select for this driver. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/zoran/Kconfig | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/media/video') diff --git a/drivers/media/video/zoran/Kconfig b/drivers/media/video/zoran/Kconfig index 4ea5fa71de89..8666e19f31a7 100644 --- a/drivers/media/video/zoran/Kconfig +++ b/drivers/media/video/zoran/Kconfig @@ -68,6 +68,7 @@ config VIDEO_ZORAN_AVS6EYES tristate "AverMedia 6 Eyes support (EXPERIMENTAL)" depends on VIDEO_ZORAN_ZR36060 && EXPERIMENTAL && VIDEO_V4L1 select VIDEO_BT856 if VIDEO_HELPER_CHIPS_AUTO + select VIDEO_BT866 if VIDEO_HELPER_CHIPS_AUTO select VIDEO_KS0127 if VIDEO_HELPER_CHIPS_AUTO help Support for the AverMedia 6 Eyes video surveillance card. -- cgit v1.2.3 From 7ebc8d56f407184a457dd5fc739cf39e423a25aa Mon Sep 17 00:00:00 2001 From: Eric Miao Date: Fri, 2 Jan 2009 19:38:42 +0800 Subject: [ARM] pxa: move DMA registers definitions into 1. Driver code where pxa_request_dma() is called will most likely reference DMA registers as well, and it is really unnecessary to include pxa-regs.h just for this. Move the definitions into and make relevant drivers include it instead of . 2. Introduce DMAC_REGS_VIRT as the virtual address base for these DMA registers. This allows later processors to re-use the same IP while registers may start at different I/O address. Signed-off-by: Eric Miao --- arch/arm/mach-pxa/dma.c | 2 -- arch/arm/mach-pxa/include/mach/dma.h | 56 +++++++++++++++++++++++++++++ arch/arm/mach-pxa/include/mach/pxa-regs.h | 59 ------------------------------- drivers/media/video/pxa_camera.c | 1 - drivers/mmc/host/pxamci.c | 3 +- drivers/mtd/nand/pxa3xx_nand.c | 1 - drivers/spi/pxa2xx_spi.c | 2 -- sound/soc/pxa/pxa-ssp.c | 2 +- sound/soc/pxa/pxa2xx-ac97.c | 2 +- sound/soc/pxa/pxa2xx-i2s.c | 2 +- 10 files changed, 60 insertions(+), 70 deletions(-) (limited to 'drivers/media/video') diff --git a/arch/arm/mach-pxa/dma.c b/arch/arm/mach-pxa/dma.c index 4613bf1fe43c..01217e01f7d2 100644 --- a/arch/arm/mach-pxa/dma.c +++ b/arch/arm/mach-pxa/dma.c @@ -23,8 +23,6 @@ #include #include -#include - struct dma_channel { char *name; pxa_dma_prio prio; diff --git a/arch/arm/mach-pxa/include/mach/dma.h b/arch/arm/mach-pxa/include/mach/dma.h index 77607fe4bd65..b0812f59d3f8 100644 --- a/arch/arm/mach-pxa/include/mach/dma.h +++ b/arch/arm/mach-pxa/include/mach/dma.h @@ -12,6 +12,62 @@ #ifndef __ASM_ARCH_DMA_H #define __ASM_ARCH_DMA_H +#include + +/* DMA Controller Registers Definitions */ +#define DMAC_REGS_VIRT io_p2v(0x40000000) +#define DMAC_REG(x) (*((volatile u32 *)(DMAC_REGS_VIRT + (x)))) + +#define DCSR(n) DMAC_REG((n) << 2) +#define DALGN DMAC_REG(0x00a0) /* DMA Alignment Register */ +#define DINT DMAC_REG(0x00f0) /* DMA Interrupt Register */ +#define DDADR(n) DMAC_REG(0x0200 + ((n) << 4)) +#define DSADR(n) DMAC_REG(0x0204 + ((n) << 4)) +#define DTADR(n) DMAC_REG(0x0208 + ((n) << 4)) +#define DCMD(n) DMAC_REG(0x020c + ((n) << 4)) +#define DRCMR(n) DMAC_REG((((n) < 64) ? 0x0100 : 0x1100) + \ + (((n) & 0x3f) << 2)) + +#define DCSR_RUN (1 << 31) /* Run Bit (read / write) */ +#define DCSR_NODESC (1 << 30) /* No-Descriptor Fetch (read / write) */ +#define DCSR_STOPIRQEN (1 << 29) /* Stop Interrupt Enable (read / write) */ +#define DCSR_REQPEND (1 << 8) /* Request Pending (read-only) */ +#define DCSR_STOPSTATE (1 << 3) /* Stop State (read-only) */ +#define DCSR_ENDINTR (1 << 2) /* End Interrupt (read / write) */ +#define DCSR_STARTINTR (1 << 1) /* Start Interrupt (read / write) */ +#define DCSR_BUSERR (1 << 0) /* Bus Error Interrupt (read / write) */ + +#if defined(CONFIG_PXA27x) || defined(CONFIG_PXA3xx) +#define DCSR_EORIRQEN (1 << 28) /* End of Receive Interrupt Enable (R/W) */ +#define DCSR_EORJMPEN (1 << 27) /* Jump to next descriptor on EOR */ +#define DCSR_EORSTOPEN (1 << 26) /* STOP on an EOR */ +#define DCSR_SETCMPST (1 << 25) /* Set Descriptor Compare Status */ +#define DCSR_CLRCMPST (1 << 24) /* Clear Descriptor Compare Status */ +#define DCSR_CMPST (1 << 10) /* The Descriptor Compare Status */ +#define DCSR_EORINTR (1 << 9) /* The end of Receive */ +#endif + +#define DRCMR_MAPVLD (1 << 7) /* Map Valid (read / write) */ +#define DRCMR_CHLNUM 0x1f /* mask for Channel Number (read / write) */ + +#define DDADR_DESCADDR 0xfffffff0 /* Address of next descriptor (mask) */ +#define DDADR_STOP (1 << 0) /* Stop (read / write) */ + +#define DCMD_INCSRCADDR (1 << 31) /* Source Address Increment Setting. */ +#define DCMD_INCTRGADDR (1 << 30) /* Target Address Increment Setting. */ +#define DCMD_FLOWSRC (1 << 29) /* Flow Control by the source. */ +#define DCMD_FLOWTRG (1 << 28) /* Flow Control by the target. */ +#define DCMD_STARTIRQEN (1 << 22) /* Start Interrupt Enable */ +#define DCMD_ENDIRQEN (1 << 21) /* End Interrupt Enable */ +#define DCMD_ENDIAN (1 << 18) /* Device Endian-ness. */ +#define DCMD_BURST8 (1 << 16) /* 8 byte burst */ +#define DCMD_BURST16 (2 << 16) /* 16 byte burst */ +#define DCMD_BURST32 (3 << 16) /* 32 byte burst */ +#define DCMD_WIDTH1 (1 << 14) /* 1 byte width */ +#define DCMD_WIDTH2 (2 << 14) /* 2 byte width (HalfWord) */ +#define DCMD_WIDTH4 (3 << 14) /* 4 byte width (Word) */ +#define DCMD_LENGTH 0x01fff /* length mask (max = 8K - 1) */ + /* * Descriptor structure for PXA's DMA engine * Note: this structure must always be aligned to a 16-byte boundary. diff --git a/arch/arm/mach-pxa/include/mach/pxa-regs.h b/arch/arm/mach-pxa/include/mach/pxa-regs.h index 31d615aa7723..7d8db197615c 100644 --- a/arch/arm/mach-pxa/include/mach/pxa-regs.h +++ b/arch/arm/mach-pxa/include/mach/pxa-regs.h @@ -65,65 +65,6 @@ #define _PCMCIA1Attr _PCMCIAAttr (1) /* PCMCIA 1 Attribute */ #define _PCMCIA1Mem _PCMCIAMem (1) /* PCMCIA 1 Memory */ - - -/* - * DMA Controller - */ -#define DCSR(x) __REG2(0x40000000, (x) << 2) - -#define DCSR_RUN (1 << 31) /* Run Bit (read / write) */ -#define DCSR_NODESC (1 << 30) /* No-Descriptor Fetch (read / write) */ -#define DCSR_STOPIRQEN (1 << 29) /* Stop Interrupt Enable (read / write) */ -#define DCSR_REQPEND (1 << 8) /* Request Pending (read-only) */ -#define DCSR_STOPSTATE (1 << 3) /* Stop State (read-only) */ -#define DCSR_ENDINTR (1 << 2) /* End Interrupt (read / write) */ -#define DCSR_STARTINTR (1 << 1) /* Start Interrupt (read / write) */ -#define DCSR_BUSERR (1 << 0) /* Bus Error Interrupt (read / write) */ - -#if defined(CONFIG_PXA27x) || defined(CONFIG_PXA3xx) -#define DCSR_EORIRQEN (1 << 28) /* End of Receive Interrupt Enable (R/W) */ -#define DCSR_EORJMPEN (1 << 27) /* Jump to next descriptor on EOR */ -#define DCSR_EORSTOPEN (1 << 26) /* STOP on an EOR */ -#define DCSR_SETCMPST (1 << 25) /* Set Descriptor Compare Status */ -#define DCSR_CLRCMPST (1 << 24) /* Clear Descriptor Compare Status */ -#define DCSR_CMPST (1 << 10) /* The Descriptor Compare Status */ -#define DCSR_EORINTR (1 << 9) /* The end of Receive */ -#endif - -#define DALGN __REG(0x400000a0) /* DMA Alignment Register */ -#define DINT __REG(0x400000f0) /* DMA Interrupt Register */ - -#define DRCMR(n) (*(((n) < 64) ? \ - &__REG2(0x40000100, ((n) & 0x3f) << 2) : \ - &__REG2(0x40001100, ((n) & 0x3f) << 2))) - -#define DRCMR_MAPVLD (1 << 7) /* Map Valid (read / write) */ -#define DRCMR_CHLNUM 0x1f /* mask for Channel Number (read / write) */ - -#define DDADR(x) __REG2(0x40000200, (x) << 4) -#define DSADR(x) __REG2(0x40000204, (x) << 4) -#define DTADR(x) __REG2(0x40000208, (x) << 4) -#define DCMD(x) __REG2(0x4000020c, (x) << 4) - -#define DDADR_DESCADDR 0xfffffff0 /* Address of next descriptor (mask) */ -#define DDADR_STOP (1 << 0) /* Stop (read / write) */ - -#define DCMD_INCSRCADDR (1 << 31) /* Source Address Increment Setting. */ -#define DCMD_INCTRGADDR (1 << 30) /* Target Address Increment Setting. */ -#define DCMD_FLOWSRC (1 << 29) /* Flow Control by the source. */ -#define DCMD_FLOWTRG (1 << 28) /* Flow Control by the target. */ -#define DCMD_STARTIRQEN (1 << 22) /* Start Interrupt Enable */ -#define DCMD_ENDIRQEN (1 << 21) /* End Interrupt Enable */ -#define DCMD_ENDIAN (1 << 18) /* Device Endian-ness. */ -#define DCMD_BURST8 (1 << 16) /* 8 byte burst */ -#define DCMD_BURST16 (2 << 16) /* 16 byte burst */ -#define DCMD_BURST32 (3 << 16) /* 32 byte burst */ -#define DCMD_WIDTH1 (1 << 14) /* 1 byte width */ -#define DCMD_WIDTH2 (2 << 14) /* 2 byte width (HalfWord) */ -#define DCMD_WIDTH4 (3 << 14) /* 4 byte width (Word) */ -#define DCMD_LENGTH 0x01fff /* length mask (max = 8K - 1) */ - /* * Real Time Clock */ diff --git a/drivers/media/video/pxa_camera.c b/drivers/media/video/pxa_camera.c index a1d6008efcbb..e3e6b29ea6d2 100644 --- a/drivers/media/video/pxa_camera.c +++ b/drivers/media/video/pxa_camera.c @@ -35,7 +35,6 @@ #include #include -#include #include #define PXA_CAM_VERSION_CODE KERNEL_VERSION(0, 0, 5) diff --git a/drivers/mmc/host/pxamci.c b/drivers/mmc/host/pxamci.c index 9702ad3774cf..430095725f9f 100644 --- a/drivers/mmc/host/pxamci.c +++ b/drivers/mmc/host/pxamci.c @@ -30,9 +30,8 @@ #include -#include #include -#include +#include #include #include "pxamci.h" diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c index cc55cbc2b308..61b69cc40009 100644 --- a/drivers/mtd/nand/pxa3xx_nand.c +++ b/drivers/mtd/nand/pxa3xx_nand.c @@ -22,7 +22,6 @@ #include #include -#include #include #define CHIP_DELAY_TIMEOUT (2 * HZ/10) diff --git a/drivers/spi/pxa2xx_spi.c b/drivers/spi/pxa2xx_spi.c index d0fc4ca2f656..d22fac27219a 100644 --- a/drivers/spi/pxa2xx_spi.c +++ b/drivers/spi/pxa2xx_spi.c @@ -34,8 +34,6 @@ #include #include -#include -#include #include #include #include diff --git a/sound/soc/pxa/pxa-ssp.c b/sound/soc/pxa/pxa-ssp.c index 73cb6b4c2f2d..1dfdf66fb1f3 100644 --- a/sound/soc/pxa/pxa-ssp.c +++ b/sound/soc/pxa/pxa-ssp.c @@ -29,7 +29,7 @@ #include #include -#include +#include #include #include #include diff --git a/sound/soc/pxa/pxa2xx-ac97.c b/sound/soc/pxa/pxa2xx-ac97.c index 812c2b4d3e07..a4a655f7e304 100644 --- a/sound/soc/pxa/pxa2xx-ac97.c +++ b/sound/soc/pxa/pxa2xx-ac97.c @@ -20,8 +20,8 @@ #include #include -#include #include +#include #include "pxa2xx-pcm.h" #include "pxa2xx-ac97.h" diff --git a/sound/soc/pxa/pxa2xx-i2s.c b/sound/soc/pxa/pxa2xx-i2s.c index 517991fb1099..223de890259e 100644 --- a/sound/soc/pxa/pxa2xx-i2s.c +++ b/sound/soc/pxa/pxa2xx-i2s.c @@ -24,7 +24,7 @@ #include #include -#include +#include #include #include -- cgit v1.2.3 From 5f77af93266e107bd46c010c51d772c0fb003232 Mon Sep 17 00:00:00 2001 From: Antti Palosaari Date: Tue, 10 Mar 2009 13:06:40 -0300 Subject: V4L/DVB (10972): zl10353: i2c_gate_ctrl bug fix zl10353 i2c-gate was always closed and due to that devices having tuner behind i2c-gate were broken. Add module configuration which allows disabling i2c-gate only when really needed. Signed-off-by: Antti Palosaari Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/zl10353.c | 2 +- drivers/media/dvb/frontends/zl10353.h | 3 +++ drivers/media/video/saa7134/saa7134-dvb.c | 1 + 3 files changed, 5 insertions(+), 1 deletion(-) (limited to 'drivers/media/video') diff --git a/drivers/media/dvb/frontends/zl10353.c b/drivers/media/dvb/frontends/zl10353.c index 170720b02815..b150ed306696 100644 --- a/drivers/media/dvb/frontends/zl10353.c +++ b/drivers/media/dvb/frontends/zl10353.c @@ -590,7 +590,7 @@ static int zl10353_i2c_gate_ctrl(struct dvb_frontend* fe, int enable) struct zl10353_state *state = fe->demodulator_priv; u8 val = 0x0a; - if (state->config.no_tuner) { + if (state->config.disable_i2c_gate_ctrl) { /* No tuner attached to the internal I2C bus */ /* If set enable I2C bridge, the main I2C bus stopped hardly */ return 0; diff --git a/drivers/media/dvb/frontends/zl10353.h b/drivers/media/dvb/frontends/zl10353.h index fdbb88ff75fe..2287bac46243 100644 --- a/drivers/media/dvb/frontends/zl10353.h +++ b/drivers/media/dvb/frontends/zl10353.h @@ -38,6 +38,9 @@ struct zl10353_config /* set if parallel ts output is required */ int parallel_ts; + + /* set if i2c_gate_ctrl disable is required */ + u8 disable_i2c_gate_ctrl:1; }; #if defined(CONFIG_DVB_ZL10353) || (defined(CONFIG_DVB_ZL10353_MODULE) && defined(MODULE)) diff --git a/drivers/media/video/saa7134/saa7134-dvb.c b/drivers/media/video/saa7134/saa7134-dvb.c index 0776ecf56d27..b5370b3e1a3d 100644 --- a/drivers/media/video/saa7134/saa7134-dvb.c +++ b/drivers/media/video/saa7134/saa7134-dvb.c @@ -860,6 +860,7 @@ static struct zl10353_config behold_h6_config = { .demod_address = 0x1e>>1, .no_tuner = 1, .parallel_ts = 1, + .disable_i2c_gate_ctrl = 1, }; /* ================================================================== -- cgit v1.2.3 From c3ef01ce4f73f41e99b2a5f0796f1f1a1daaaaa2 Mon Sep 17 00:00:00 2001 From: Kay Sievers Date: Tue, 24 Mar 2009 16:38:22 -0700 Subject: v4l: struct device - replace bus_id with dev_name(), dev_set_name() Cc: mchehab@infradead.org Cc: linux-media@vger.kernel.org Acked-by: Greg Kroah-Hartman Signed-off-by: Kay Sievers --- drivers/media/radio/radio-tea5764.c | 3 ++- drivers/media/video/v4l2-device.c | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/radio/radio-tea5764.c b/drivers/media/radio/radio-tea5764.c index 4d35308fc1ff..393623818ade 100644 --- a/drivers/media/radio/radio-tea5764.c +++ b/drivers/media/radio/radio-tea5764.c @@ -298,7 +298,8 @@ static int vidioc_querycap(struct file *file, void *priv, strlcpy(v->driver, dev->dev.driver->name, sizeof(v->driver)); strlcpy(v->card, dev->name, sizeof(v->card)); - snprintf(v->bus_info, sizeof(v->bus_info), "I2C:%s", dev->dev.bus_id); + snprintf(v->bus_info, sizeof(v->bus_info), + "I2C:%s", dev_name(&dev->dev)); v->version = RADIO_VERSION; v->capabilities = V4L2_CAP_TUNER | V4L2_CAP_RADIO; return 0; diff --git a/drivers/media/video/v4l2-device.c b/drivers/media/video/v4l2-device.c index cf9d4c7f571a..8a4b74f3129f 100644 --- a/drivers/media/video/v4l2-device.c +++ b/drivers/media/video/v4l2-device.c @@ -34,7 +34,7 @@ int v4l2_device_register(struct device *dev, struct v4l2_device *v4l2_dev) spin_lock_init(&v4l2_dev->lock); v4l2_dev->dev = dev; snprintf(v4l2_dev->name, sizeof(v4l2_dev->name), "%s %s", - dev->driver->name, dev->bus_id); + dev->driver->name, dev_name(dev)); dev_set_drvdata(dev, v4l2_dev); return 0; } -- cgit v1.2.3 From e164b58a84cc9fdff0653dfe38470c0216df31d2 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sun, 11 Jan 2009 10:29:43 -0300 Subject: V4L/DVB (10211): vivi: Implements 4 inputs on vivi This patch adds the capability of selecting between 4 different inputs on vivi driver. Input 0 is the normal color bar, while inputs 1-3 are modified color bars. This allows testing input selection on userspace applications and serves as an implementation model for other drivers. The current approach allows a maximum of 10 different inputs, since the input name generator assumes that we need just one digit to present the input. It shouldn't be hard to modify it to present a bigger name of inputs, but, in fact, it doesn't make much sense of doing it for this test driver. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/vivi.c | 186 ++++++++++++++++++++++++++++++++++----------- 1 file changed, 142 insertions(+), 44 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/vivi.c b/drivers/media/video/vivi.c index 81d5aa5cf331..13e7bd06a80c 100644 --- a/drivers/media/video/vivi.c +++ b/drivers/media/video/vivi.c @@ -223,6 +223,9 @@ struct vivi_dev { char timestr[13]; int mv_count; /* Controls bars movement */ + + /* Input Number */ + int input; }; struct vivi_fh { @@ -235,6 +238,7 @@ struct vivi_fh { enum v4l2_buf_type type; unsigned char bars[8][3]; + int input; /* Input Number on bars */ }; /* ------------------------------------------------------------------ @@ -254,18 +258,72 @@ enum colors { BLACK, }; -static u8 bars[8][3] = { /* R G B */ - {204, 204, 204}, /* white */ - {208, 208, 0}, /* ambar */ - { 0, 206, 206}, /* cyan */ - { 0, 239, 0}, /* green */ - {239, 0, 239}, /* magenta */ - {205, 0, 0}, /* red */ - { 0, 0, 255}, /* blue */ - { 0, 0, 0}, /* black */ +#define COLOR_WHITE {204, 204, 204} +#define COLOR_AMBAR {208, 208, 0} +#define COLOR_CIAN { 0, 206, 206} +#define COLOR_GREEN { 0, 239, 0} +#define COLOR_MAGENTA {239, 0, 239} +#define COLOR_RED {205, 0, 0} +#define COLOR_BLUE { 0, 0, 255} +#define COLOR_BLACK { 0, 0, 0} + +struct bar_std { + u8 bar[8][3]; +}; + +/* Maximum number of bars are 10 - otherwise, the input print code + should be modified */ +static struct bar_std bars[] = { + { /* Standard ITU-R color bar sequence */ + { + COLOR_WHITE, + COLOR_AMBAR, + COLOR_CIAN, + COLOR_GREEN, + COLOR_MAGENTA, + COLOR_RED, + COLOR_BLUE, + COLOR_BLACK, + } + }, { + { + COLOR_WHITE, + COLOR_AMBAR, + COLOR_BLACK, + COLOR_WHITE, + COLOR_AMBAR, + COLOR_BLACK, + COLOR_WHITE, + COLOR_AMBAR, + } + }, { + { + COLOR_WHITE, + COLOR_CIAN, + COLOR_BLACK, + COLOR_WHITE, + COLOR_CIAN, + COLOR_BLACK, + COLOR_WHITE, + COLOR_CIAN, + } + }, { + { + COLOR_WHITE, + COLOR_GREEN, + COLOR_BLACK, + COLOR_WHITE, + COLOR_GREEN, + COLOR_BLACK, + COLOR_WHITE, + COLOR_GREEN, + } + }, }; +#define NUM_INPUTS ARRAY_SIZE(bars) + #define TO_Y(r, g, b) \ (((16829 * r + 33039 * g + 6416 * b + 32768) >> 16) + 16) /* RGB to V(Cr) Color transform */ @@ -275,9 +333,10 @@ static u8 bars[8][3] = { #define TO_U(r, g, b) \ (((-9714 * r - 19070 * g + 28784 * b + 32768) >> 16) + 128) -#define TSTAMP_MIN_Y 24 -#define TSTAMP_MAX_Y TSTAMP_MIN_Y+15 -#define TSTAMP_MIN_X 64 +#define TSTAMP_MIN_Y 24 +#define TSTAMP_MAX_Y (TSTAMP_MIN_Y + 15) +#define TSTAMP_INPUT_X 10 +#define TSTAMP_MIN_X (54 + TSTAMP_INPUT_X) static void gen_twopix(struct vivi_fh *fh, unsigned char *buf, int colorpos) { @@ -392,9 +451,29 @@ static void gen_line(struct vivi_fh *fh, char *basep, int inipos, int wmax, pos += 4; /* only 16 bpp supported for now */ } - /* Checks if it is possible to show timestamp */ + /* Prints input entry number */ + + /* Checks if it is possible to input number */ if (TSTAMP_MAX_Y >= hmax) goto end; + + if (TSTAMP_INPUT_X + strlen(timestr) >= wmax) + goto end; + + if (line >= TSTAMP_MIN_Y && line <= TSTAMP_MAX_Y) { + chr = rom8x16_bits[fh->input * 16 + line - TSTAMP_MIN_Y]; + pos = TSTAMP_INPUT_X; + for (i = 0; i < 7; i++) { + /* Draw white font on black background */ + if (chr & 1 << (7 - i)) + gen_twopix(fh, basep + pos, WHITE); + else + gen_twopix(fh, basep + pos, BLACK); + pos += 2; + } + } + + /* Checks if it is possible to show timestamp */ if (TSTAMP_MIN_X + strlen(timestr) >= wmax) goto end; @@ -807,38 +886,19 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv, return 0; } -/*FIXME: This seems to be generic enough to be at videodev2 */ -static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, - struct v4l2_format *f) +/* precalculate color bar values to speed up rendering */ +static void precalculate_bars(struct vivi_fh *fh) { - struct vivi_fh *fh = priv; - struct videobuf_queue *q = &fh->vb_vidq; + struct vivi_dev *dev = fh->dev; unsigned char r, g, b; int k, is_yuv; - int ret = vidioc_try_fmt_vid_cap(file, fh, f); - if (ret < 0) - return (ret); - - mutex_lock(&q->vb_lock); - - if (videobuf_queue_is_busy(&fh->vb_vidq)) { - dprintk(fh->dev, 1, "%s queue busy\n", __func__); - ret = -EBUSY; - goto out; - } + fh->input = dev->input; - fh->fmt = get_format(f); - fh->width = f->fmt.pix.width; - fh->height = f->fmt.pix.height; - fh->vb_vidq.field = f->fmt.pix.field; - fh->type = f->type; - - /* precalculate color bar values to speed up rendering */ for (k = 0; k < 8; k++) { - r = bars[k][0]; - g = bars[k][1]; - b = bars[k][2]; + r = bars[fh->input].bar[k][0]; + g = bars[fh->input].bar[k][1]; + b = bars[fh->input].bar[k][2]; is_yuv = 0; switch (fh->fmt->fourcc) { @@ -871,11 +931,40 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, } } +} + +/*FIXME: This seems to be generic enough to be at videodev2 */ +static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, + struct v4l2_format *f) +{ + struct vivi_fh *fh = priv; + struct videobuf_queue *q = &fh->vb_vidq; + + int ret = vidioc_try_fmt_vid_cap(file, fh, f); + if (ret < 0) + return ret; + + mutex_lock(&q->vb_lock); + + if (videobuf_queue_is_busy(&fh->vb_vidq)) { + dprintk(fh->dev, 1, "%s queue busy\n", __func__); + ret = -EBUSY; + goto out; + } + + fh->fmt = get_format(f); + fh->width = f->fmt.pix.width; + fh->height = f->fmt.pix.height; + fh->vb_vidq.field = f->fmt.pix.field; + fh->type = f->type; + + precalculate_bars(fh); + ret = 0; out: mutex_unlock(&q->vb_lock); - return (ret); + return ret; } static int vidioc_reqbufs(struct file *file, void *priv, @@ -950,27 +1039,36 @@ static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *i) static int vidioc_enum_input(struct file *file, void *priv, struct v4l2_input *inp) { - if (inp->index != 0) + if (inp->index >= NUM_INPUTS) return -EINVAL; inp->type = V4L2_INPUT_TYPE_CAMERA; inp->std = V4L2_STD_525_60; - strcpy(inp->name, "Camera"); + sprintf(inp->name, "Camera %u", inp->index); return (0); } static int vidioc_g_input(struct file *file, void *priv, unsigned int *i) { - *i = 0; + struct vivi_fh *fh = priv; + struct vivi_dev *dev = fh->dev; + + *i = dev->input; return (0); } static int vidioc_s_input(struct file *file, void *priv, unsigned int i) { - if (i > 0) + struct vivi_fh *fh = priv; + struct vivi_dev *dev = fh->dev; + + if (i >= NUM_INPUTS) return -EINVAL; + dev->input = i; + precalculate_bars(fh); + return (0); } -- cgit v1.2.3 From 952617f2594a8f0340161b52d630488fbde8c852 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Mon, 12 Jan 2009 18:17:14 -0300 Subject: V4L/DVB (10231): v4l2-subdev: add v4l2_ext_controls support The saa6752hs module needs this. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/v4l2-subdev.c | 6 ++++++ include/media/v4l2-subdev.h | 3 +++ 2 files changed, 9 insertions(+) (limited to 'drivers/media/video') diff --git a/drivers/media/video/v4l2-subdev.c b/drivers/media/video/v4l2-subdev.c index 21208805ea9b..158bc55de166 100644 --- a/drivers/media/video/v4l2-subdev.c +++ b/drivers/media/video/v4l2-subdev.c @@ -33,6 +33,12 @@ int v4l2_subdev_command(struct v4l2_subdev *sd, unsigned cmd, void *arg) return v4l2_subdev_call(sd, core, g_ctrl, arg); case VIDIOC_S_CTRL: return v4l2_subdev_call(sd, core, s_ctrl, arg); + case VIDIOC_G_EXT_CTRLS: + return v4l2_subdev_call(sd, core, g_ext_ctrls, arg); + case VIDIOC_S_EXT_CTRLS: + return v4l2_subdev_call(sd, core, s_ext_ctrls, arg); + case VIDIOC_TRY_EXT_CTRLS: + return v4l2_subdev_call(sd, core, try_ext_ctrls, arg); case VIDIOC_QUERYMENU: return v4l2_subdev_call(sd, core, querymenu, arg); case VIDIOC_LOG_STATUS: diff --git a/include/media/v4l2-subdev.h b/include/media/v4l2-subdev.h index 37b09e56e943..9c1663d91224 100644 --- a/include/media/v4l2-subdev.h +++ b/include/media/v4l2-subdev.h @@ -78,6 +78,9 @@ struct v4l2_subdev_core_ops { int (*queryctrl)(struct v4l2_subdev *sd, struct v4l2_queryctrl *qc); int (*g_ctrl)(struct v4l2_subdev *sd, struct v4l2_control *ctrl); int (*s_ctrl)(struct v4l2_subdev *sd, struct v4l2_control *ctrl); + int (*g_ext_ctrls)(struct v4l2_subdev *sd, struct v4l2_ext_controls *ctrls); + int (*s_ext_ctrls)(struct v4l2_subdev *sd, struct v4l2_ext_controls *ctrls); + int (*try_ext_ctrls)(struct v4l2_subdev *sd, struct v4l2_ext_controls *ctrls); int (*querymenu)(struct v4l2_subdev *sd, struct v4l2_querymenu *qm); long (*ioctl)(struct v4l2_subdev *sd, unsigned int cmd, void *arg); #ifdef CONFIG_VIDEO_ADV_DEBUG -- cgit v1.2.3 From d166b02ea6b03766f6fd867fb1fef378a57683e5 Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Wed, 14 Jan 2009 04:21:29 -0300 Subject: V4L/DVB (10236): pvrusb2: Stop advertising VBI capability - it isn't there Signed-off-by: Mike Isely Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/pvrusb2/pvrusb2-v4l2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/pvrusb2/pvrusb2-v4l2.c b/drivers/media/video/pvrusb2/pvrusb2-v4l2.c index 878fd52a73b3..3163c6df448a 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-v4l2.c +++ b/drivers/media/video/pvrusb2/pvrusb2-v4l2.c @@ -91,7 +91,7 @@ static struct v4l2_capability pvr_capability ={ .card = "Hauppauge WinTV pvr-usb2", .bus_info = "usb", .version = KERNEL_VERSION(0,8,0), - .capabilities = (V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VBI_CAPTURE | + .capabilities = (V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_TUNER | V4L2_CAP_AUDIO | V4L2_CAP_RADIO | V4L2_CAP_READWRITE), .reserved = {0,0,0,0} -- cgit v1.2.3 From 13a887971b6c97751fce62ab803ee93a42a23c5d Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Wed, 14 Jan 2009 04:22:56 -0300 Subject: V4L/DVB (10237): pvrusb2: Generate a device-unique identifier Implement a new internal function to create a string device identifier. This ID stays with the specific device, making it useful to user space to identify specific devices. We use the serial number if available; otherwise we give up and just spit out a unit/instance ID. Signed-off-by: Mike Isely Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h | 12 ++++++++++++ drivers/media/video/pvrusb2/pvrusb2-hdw.c | 19 +++++++++++++++++++ drivers/media/video/pvrusb2/pvrusb2-hdw.h | 3 +++ 3 files changed, 34 insertions(+) (limited to 'drivers/media/video') diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h b/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h index de7ee7264be6..d96f0f51076e 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h +++ b/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h @@ -195,8 +195,20 @@ struct pvr2_hdw { struct mutex big_lock_mutex; int big_lock_held; /* For debugging */ + /* This is a simple string which identifies the instance of this + driver. It is unique within the set of existing devices, but + there is no attempt to keep the name consistent with the same + physical device each time. */ char name[32]; + /* This is a simple string which identifies the physical device + instance itself - if possible. (If not possible, then it is + based on the specific driver instance, similar to name above.) + The idea here is that userspace might hopefully be able to use + this recognize specific tuners. It will encode a serial number, + if available. */ + char identifier[32]; + /* I2C stuff */ struct i2c_adapter i2c_adap; struct i2c_algorithm i2c_algo; diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/drivers/media/video/pvrusb2/pvrusb2-hdw.c index fa304e5f252a..ac5dad0c5fb0 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-hdw.c +++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.c @@ -1283,6 +1283,12 @@ const char *pvr2_hdw_get_bus_info(struct pvr2_hdw *hdw) } +const char *pvr2_hdw_get_device_identifier(struct pvr2_hdw *hdw) +{ + return hdw->identifier; +} + + unsigned long pvr2_hdw_get_cur_freq(struct pvr2_hdw *hdw) { return hdw->freqSelector ? hdw->freqValTelevision : hdw->freqValRadio; @@ -2024,6 +2030,19 @@ static void pvr2_hdw_setup_low(struct pvr2_hdw *hdw) hdw->std_mask_eeprom = V4L2_STD_ALL; } + if (hdw->serial_number) { + idx = scnprintf(hdw->identifier, sizeof(hdw->identifier) - 1, + "sn-%lu", hdw->serial_number); + } else if (hdw->unit_number >= 0) { + idx = scnprintf(hdw->identifier, sizeof(hdw->identifier) - 1, + "unit-%c", + hdw->unit_number + 'a'); + } else { + idx = scnprintf(hdw->identifier, sizeof(hdw->identifier) - 1, + "unit-??"); + } + hdw->identifier[idx] = 0; + pvr2_hdw_setup_std(hdw); if (!get_default_tuner_type(hdw)) { diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.h b/drivers/media/video/pvrusb2/pvrusb2-hdw.h index 1b4fec337c6b..a40f84588cd6 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-hdw.h +++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.h @@ -132,6 +132,9 @@ unsigned long pvr2_hdw_get_sn(struct pvr2_hdw *); /* Retrieve bus location info of device */ const char *pvr2_hdw_get_bus_info(struct pvr2_hdw *); +/* Retrieve per-instance string identifier for this specific device */ +const char *pvr2_hdw_get_device_identifier(struct pvr2_hdw *); + /* Called when hardware has been unplugged */ void pvr2_hdw_disconnect(struct pvr2_hdw *); -- cgit v1.2.3 From 730e92c9acfab4f577c65c112a6d14ad9d3d02ba Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Wed, 14 Jan 2009 04:24:20 -0300 Subject: V4L/DVB (10238): pvrusb2: Change sysfs serial number handling Use the new pvrusb2 internal API to grab the device identifier, rather than generating it directly. This unifies some code and make possible use of that identifier in places other than sysfs. Signed-off-by: Mike Isely Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/pvrusb2/pvrusb2-sysfs.c | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/pvrusb2/pvrusb2-sysfs.c b/drivers/media/video/pvrusb2/pvrusb2-sysfs.c index e641cd971453..e20ba1e6e0ea 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-sysfs.c +++ b/drivers/media/video/pvrusb2/pvrusb2-sysfs.c @@ -627,16 +627,8 @@ static void class_dev_create(struct pvr2_sysfs *sfp, pvr2_sysfs_trace("Creating class_dev id=%p",class_dev); class_dev->class = &class_ptr->class; - if (pvr2_hdw_get_sn(sfp->channel.hdw)) { - dev_set_name(class_dev, "sn-%lu", - pvr2_hdw_get_sn(sfp->channel.hdw)); - } else if (pvr2_hdw_get_unit_number(sfp->channel.hdw) >= 0) { - dev_set_name(class_dev, "unit-%c", - pvr2_hdw_get_unit_number(sfp->channel.hdw) + 'a'); - } else { - kfree(class_dev); - return; - } + dev_set_name(class_dev, "%s", + pvr2_hdw_get_device_identifier(sfp->channel.hdw)); class_dev->parent = &usb_dev->dev; -- cgit v1.2.3 From be4f4aecf8df39444535c9d9be2b74a8f34649b2 Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Wed, 14 Jan 2009 04:40:57 -0300 Subject: V4L/DVB (10239): pvrusb2: Fix misleading comment caused by earlier commit Previous v4l-dvb changeset id 4cc8ed11e2e0 changed the pvrusb2-hdw internal API regarding i2c chip debug register access. However that change failed to also update the corresponding function comment describing the API. As driver maintained I never saw a request for an ack on that change; there probably should have been one especially since the manner in which this API operates was changed - its interface is now entangled with a v4l specific struct and I would have preferred to keep this API clear of moving-target v4l-isms such as this one if at all possible which is why I had done it the way I did before. But whatever. This commit at least fixes the comment issue. Signed-off-by: Mike Isely Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/pvrusb2/pvrusb2-hdw.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.h b/drivers/media/video/pvrusb2/pvrusb2-hdw.h index a40f84588cd6..7b6940554e9a 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-hdw.h +++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.h @@ -239,8 +239,7 @@ void pvr2_hdw_v4l_store_minor_number(struct pvr2_hdw *, enum pvr2_v4l_type index,int); /* Direct read/write access to chip's registers: - match_type - how to interpret match_chip (e.g. driver ID, i2c address) - match_chip - chip match value (e.g. I2C_DRIVERD_xxxx) + match - specify criteria to identify target chip (this is a v4l dbg struct) reg_id - register number to access setFl - true to set the register, false to read it val_ptr - storage location for source / result. */ -- cgit v1.2.3 From e32a7eccd7f016928dd864711ac654e6db62c5f3 Mon Sep 17 00:00:00 2001 From: Nam Phạm Thành Date: Mon, 12 Jan 2009 02:50:17 -0300 Subject: V4L/DVB (10242): pwc: add support for webcam snapshot button This patch adds support for Philips webcam snapshot button as an event input device, for consistency with other webcam drivers. Signed-off-by: Pham Thanh Nam Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/pwc/Kconfig | 10 ++++++ drivers/media/video/pwc/pwc-if.c | 77 +++++++++++++++++++++++++++++++++------- drivers/media/video/pwc/pwc.h | 6 ++++ 3 files changed, 80 insertions(+), 13 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/pwc/Kconfig b/drivers/media/video/pwc/Kconfig index 7298cf2e1650..8b9f0aa844a1 100644 --- a/drivers/media/video/pwc/Kconfig +++ b/drivers/media/video/pwc/Kconfig @@ -35,3 +35,13 @@ config USB_PWC_DEBUG Say Y here in order to have the pwc driver generate verbose debugging messages. A special module options 'trace' is used to control the verbosity. + +config USB_PWC_INPUT_EVDEV + bool "USB Philips Cameras input events device support" + default y + depends on USB_PWC && INPUT + ---help--- + This option makes USB Philips cameras register the snapshot button as + an input device to report button events. + + If you are in doubt, say Y. diff --git a/drivers/media/video/pwc/pwc-if.c b/drivers/media/video/pwc/pwc-if.c index 0d810189dd87..a7c2e7284c20 100644 --- a/drivers/media/video/pwc/pwc-if.c +++ b/drivers/media/video/pwc/pwc-if.c @@ -53,6 +53,7 @@ - Xavier Roche: QuickCam Pro 4000 ID - Jens Knudsen: QuickCam Zoom ID - J. Debert: QuickCam for Notebooks ID + - Pham Thanh Nam: webcam snapshot button as an event input device */ #include @@ -61,6 +62,9 @@ #include #include #include +#ifdef CONFIG_USB_PWC_INPUT_EVDEV +#include +#endif #include #include @@ -586,6 +590,23 @@ static void pwc_frame_dumped(struct pwc_device *pdev) pdev->vframe_count); } +static void pwc_snapshot_button(struct pwc_device *pdev, int down) +{ + if (down) { + PWC_TRACE("Snapshot button pressed.\n"); + pdev->snapshot_button_status = 1; + } else { + PWC_TRACE("Snapshot button released.\n"); + } + +#ifdef CONFIG_USB_PWC_INPUT_EVDEV + if (pdev->button_dev) { + input_report_key(pdev->button_dev, BTN_0, down); + input_sync(pdev->button_dev); + } +#endif +} + static int pwc_rcv_short_packet(struct pwc_device *pdev, const struct pwc_frame_buf *fbuf) { int awake = 0; @@ -603,13 +624,7 @@ static int pwc_rcv_short_packet(struct pwc_device *pdev, const struct pwc_frame_ pdev->vframes_error++; } if ((ptr[0] ^ pdev->vmirror) & 0x01) { - if (ptr[0] & 0x01) { - pdev->snapshot_button_status = 1; - PWC_TRACE("Snapshot button pressed.\n"); - } - else { - PWC_TRACE("Snapshot button released.\n"); - } + pwc_snapshot_button(pdev, ptr[0] & 0x01); } if ((ptr[0] ^ pdev->vmirror) & 0x02) { if (ptr[0] & 0x02) @@ -633,12 +648,7 @@ static int pwc_rcv_short_packet(struct pwc_device *pdev, const struct pwc_frame_ else if (pdev->type == 740 || pdev->type == 720) { unsigned char *ptr = (unsigned char *)fbuf->data; if ((ptr[0] ^ pdev->vmirror) & 0x01) { - if (ptr[0] & 0x01) { - pdev->snapshot_button_status = 1; - PWC_TRACE("Snapshot button pressed.\n"); - } - else - PWC_TRACE("Snapshot button released.\n"); + pwc_snapshot_button(pdev, ptr[0] & 0x01); } pdev->vmirror = ptr[0] & 0x03; } @@ -1216,6 +1226,15 @@ static void pwc_cleanup(struct pwc_device *pdev) { pwc_remove_sysfs_files(pdev->vdev); video_unregister_device(pdev->vdev); + +#ifdef CONFIG_USB_PWC_INPUT_EVDEV + if (pdev->button_dev) { + input_unregister_device(pdev->button_dev); + input_free_device(pdev->button_dev); + kfree(pdev->button_dev->phys); + pdev->button_dev = NULL; + } +#endif } /* Note that all cleanup is done in the reverse order as in _open */ @@ -1483,6 +1502,9 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id int features = 0; int video_nr = -1; /* default: use next available device */ char serial_number[30], *name; +#ifdef CONFIG_USB_PWC_INPUT_EVDEV + char *phys = NULL; +#endif vendor_id = le16_to_cpu(udev->descriptor.idVendor); product_id = le16_to_cpu(udev->descriptor.idProduct); @@ -1807,6 +1829,35 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id pwc_set_leds(pdev, 0, 0); pwc_camera_power(pdev, 0); +#ifdef CONFIG_USB_PWC_INPUT_EVDEV + /* register webcam snapshot button input device */ + pdev->button_dev = input_allocate_device(); + if (!pdev->button_dev) { + PWC_ERROR("Err, insufficient memory for webcam snapshot button device."); + return -ENOMEM; + } + + pdev->button_dev->name = "PWC snapshot button"; + phys = kasprintf(GFP_KERNEL,"usb-%s-%s", pdev->udev->bus->bus_name, pdev->udev->devpath); + if (!phys) { + input_free_device(pdev->button_dev); + return -ENOMEM; + } + pdev->button_dev->phys = phys; + usb_to_input_id(pdev->udev, &pdev->button_dev->id); + pdev->button_dev->dev.parent = &pdev->udev->dev; + pdev->button_dev->evbit[0] = BIT_MASK(EV_KEY); + pdev->button_dev->keybit[BIT_WORD(BTN_0)] = BIT_MASK(BTN_0); + + rc = input_register_device(pdev->button_dev); + if (rc) { + input_free_device(pdev->button_dev); + kfree(pdev->button_dev->phys); + pdev->button_dev = NULL; + return rc; + } +#endif + return 0; err_unreg: diff --git a/drivers/media/video/pwc/pwc.h b/drivers/media/video/pwc/pwc.h index 01411fb2337a..0be6f814f539 100644 --- a/drivers/media/video/pwc/pwc.h +++ b/drivers/media/video/pwc/pwc.h @@ -37,6 +37,9 @@ #include #include #include +#ifdef CONFIG_USB_PWC_INPUT_EVDEV +#include +#endif #include "pwc-uncompress.h" #include @@ -255,6 +258,9 @@ struct pwc_device int pan_angle; /* in degrees * 100 */ int tilt_angle; /* absolute angle; 0,0 is home position */ int snapshot_button_status; /* set to 1 when the user push the button, reset to 0 when this value is read */ +#ifdef CONFIG_USB_PWC_INPUT_EVDEV + struct input_dev *button_dev; /* webcam snapshot button input */ +#endif /*** Misc. data ***/ wait_queue_head_t frameq; /* When waiting for a frame to finish... */ -- cgit v1.2.3 From b634a93f783dbd4be31f3cc9b2292eddfb496d10 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sat, 17 Jan 2009 11:26:59 -0300 Subject: V4L/DVB (10244): v4l2: replace a few snprintfs with strlcpy Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/v4l2-common.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/v4l2-common.c b/drivers/media/video/v4l2-common.c index b8f2be8d5c0e..0f450a73477a 100644 --- a/drivers/media/video/v4l2-common.c +++ b/drivers/media/video/v4l2-common.c @@ -555,7 +555,7 @@ int v4l2_ctrl_query_fill(struct v4l2_queryctrl *qctrl, s32 min, s32 max, s32 ste qctrl->step = step; qctrl->default_value = def; qctrl->reserved[0] = qctrl->reserved[1] = 0; - snprintf(qctrl->name, sizeof(qctrl->name), name); + strlcpy(qctrl->name, name, sizeof(qctrl->name)); return 0; } EXPORT_SYMBOL(v4l2_ctrl_query_fill); @@ -720,7 +720,7 @@ int v4l2_ctrl_query_menu(struct v4l2_querymenu *qmenu, struct v4l2_queryctrl *qc for (i = 0; i < qmenu->index && menu_items[i]; i++) ; if (menu_items[i] == NULL || menu_items[i][0] == '\0') return -EINVAL; - snprintf(qmenu->name, sizeof(qmenu->name), menu_items[qmenu->index]); + strlcpy(qmenu->name, menu_items[qmenu->index], sizeof(qmenu->name)); return 0; } EXPORT_SYMBOL(v4l2_ctrl_query_menu); @@ -737,8 +737,8 @@ int v4l2_ctrl_query_menu_valid_items(struct v4l2_querymenu *qmenu, const u32 *id return -EINVAL; while (*ids != V4L2_CTRL_MENU_IDS_END) { if (*ids++ == qmenu->index) { - snprintf(qmenu->name, sizeof(qmenu->name), - menu_items[qmenu->index]); + strlcpy(qmenu->name, menu_items[qmenu->index], + sizeof(qmenu->name)); return 0; } } -- cgit v1.2.3 From 5b73e98c83fc5087f591c9b12ee546b97e9283d4 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 14 Jan 2009 06:54:38 -0300 Subject: V4L/DVB (10246): saa6752hs: convert to v4l2_subdev. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/saa7134/saa6752hs.c | 566 +++++++++++++++++++------------- 1 file changed, 333 insertions(+), 233 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/saa7134/saa6752hs.c b/drivers/media/video/saa7134/saa6752hs.c index 1fee6e84a512..25e6ab28a0a3 100644 --- a/drivers/media/video/saa7134/saa6752hs.c +++ b/drivers/media/video/saa7134/saa6752hs.c @@ -33,6 +33,7 @@ #include #include #include +#include #include #include #include @@ -95,6 +96,7 @@ static const struct v4l2_format v4l2_format_table[] = }; struct saa6752hs_state { + struct v4l2_subdev sd; int chip; u32 revision; int has_ac3; @@ -115,6 +117,11 @@ enum saa6752hs_command { SAA6752HS_COMMAND_MAX }; +static inline struct saa6752hs_state *to_state(struct v4l2_subdev *sd) +{ + return container_of(sd, struct saa6752hs_state, sd); +} + /* ---------------------------------------------------------------------- */ static u8 PAT[] = { @@ -360,185 +367,191 @@ static int saa6752hs_set_bitrate(struct i2c_client *client, return 0; } -static void saa6752hs_set_subsampling(struct i2c_client *client, - struct v4l2_format *f) -{ - struct saa6752hs_state *h = i2c_get_clientdata(client); - int dist_352, dist_480, dist_720; - - /* - FIXME: translate and round width/height into EMPRESS - subsample type: - type | PAL | NTSC - --------------------------- - SIF | 352x288 | 352x240 - 1/2 D1 | 352x576 | 352x480 - 2/3 D1 | 480x576 | 480x480 - D1 | 720x576 | 720x480 - */ - - dist_352 = abs(f->fmt.pix.width - 352); - dist_480 = abs(f->fmt.pix.width - 480); - dist_720 = abs(f->fmt.pix.width - 720); - if (dist_720 < dist_480) { - f->fmt.pix.width = 720; - f->fmt.pix.height = 576; - h->video_format = SAA6752HS_VF_D1; - } - else if (dist_480 < dist_352) { - f->fmt.pix.width = 480; - f->fmt.pix.height = 576; - h->video_format = SAA6752HS_VF_2_3_D1; - } - else { - f->fmt.pix.width = 352; - if (abs(f->fmt.pix.height - 576) < - abs(f->fmt.pix.height - 288)) { - f->fmt.pix.height = 576; - h->video_format = SAA6752HS_VF_1_2_D1; - } - else { - f->fmt.pix.height = 288; - h->video_format = SAA6752HS_VF_SIF; - } +static int get_ctrl(int has_ac3, struct saa6752hs_mpeg_params *params, + struct v4l2_ext_control *ctrl) +{ + switch (ctrl->id) { + case V4L2_CID_MPEG_STREAM_TYPE: + ctrl->value = V4L2_MPEG_STREAM_TYPE_MPEG2_TS; + break; + case V4L2_CID_MPEG_STREAM_PID_PMT: + ctrl->value = params->ts_pid_pmt; + break; + case V4L2_CID_MPEG_STREAM_PID_AUDIO: + ctrl->value = params->ts_pid_audio; + break; + case V4L2_CID_MPEG_STREAM_PID_VIDEO: + ctrl->value = params->ts_pid_video; + break; + case V4L2_CID_MPEG_STREAM_PID_PCR: + ctrl->value = params->ts_pid_pcr; + break; + case V4L2_CID_MPEG_AUDIO_ENCODING: + ctrl->value = params->au_encoding; + break; + case V4L2_CID_MPEG_AUDIO_L2_BITRATE: + ctrl->value = params->au_l2_bitrate; + break; + case V4L2_CID_MPEG_AUDIO_AC3_BITRATE: + if (!has_ac3) + return -EINVAL; + ctrl->value = params->au_ac3_bitrate; + break; + case V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ: + ctrl->value = V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000; + break; + case V4L2_CID_MPEG_VIDEO_ENCODING: + ctrl->value = V4L2_MPEG_VIDEO_ENCODING_MPEG_2; + break; + case V4L2_CID_MPEG_VIDEO_ASPECT: + ctrl->value = params->vi_aspect; + break; + case V4L2_CID_MPEG_VIDEO_BITRATE: + ctrl->value = params->vi_bitrate * 1000; + break; + case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK: + ctrl->value = params->vi_bitrate_peak * 1000; + break; + case V4L2_CID_MPEG_VIDEO_BITRATE_MODE: + ctrl->value = params->vi_bitrate_mode; + break; + default: + return -EINVAL; } + return 0; } - static int handle_ctrl(int has_ac3, struct saa6752hs_mpeg_params *params, - struct v4l2_ext_control *ctrl, unsigned int cmd) + struct v4l2_ext_control *ctrl, int set) { int old = 0, new; - int set = (cmd == VIDIOC_S_EXT_CTRLS); new = ctrl->value; switch (ctrl->id) { - case V4L2_CID_MPEG_STREAM_TYPE: - old = V4L2_MPEG_STREAM_TYPE_MPEG2_TS; - if (set && new != old) - return -ERANGE; - new = old; - break; - case V4L2_CID_MPEG_STREAM_PID_PMT: - old = params->ts_pid_pmt; - if (set && new > MPEG_PID_MAX) - return -ERANGE; - if (new > MPEG_PID_MAX) - new = MPEG_PID_MAX; - params->ts_pid_pmt = new; - break; - case V4L2_CID_MPEG_STREAM_PID_AUDIO: - old = params->ts_pid_audio; - if (set && new > MPEG_PID_MAX) - return -ERANGE; - if (new > MPEG_PID_MAX) - new = MPEG_PID_MAX; - params->ts_pid_audio = new; - break; - case V4L2_CID_MPEG_STREAM_PID_VIDEO: - old = params->ts_pid_video; - if (set && new > MPEG_PID_MAX) - return -ERANGE; - if (new > MPEG_PID_MAX) - new = MPEG_PID_MAX; - params->ts_pid_video = new; - break; - case V4L2_CID_MPEG_STREAM_PID_PCR: - old = params->ts_pid_pcr; - if (set && new > MPEG_PID_MAX) - return -ERANGE; - if (new > MPEG_PID_MAX) - new = MPEG_PID_MAX; - params->ts_pid_pcr = new; - break; - case V4L2_CID_MPEG_AUDIO_ENCODING: - old = params->au_encoding; - if (set && new != V4L2_MPEG_AUDIO_ENCODING_LAYER_2 && - (!has_ac3 || new != V4L2_MPEG_AUDIO_ENCODING_AC3)) - return -ERANGE; - new = old; - break; - case V4L2_CID_MPEG_AUDIO_L2_BITRATE: - old = params->au_l2_bitrate; - if (set && new != V4L2_MPEG_AUDIO_L2_BITRATE_256K && - new != V4L2_MPEG_AUDIO_L2_BITRATE_384K) - return -ERANGE; - if (new <= V4L2_MPEG_AUDIO_L2_BITRATE_256K) - new = V4L2_MPEG_AUDIO_L2_BITRATE_256K; - else - new = V4L2_MPEG_AUDIO_L2_BITRATE_384K; - params->au_l2_bitrate = new; - break; - case V4L2_CID_MPEG_AUDIO_AC3_BITRATE: - if (!has_ac3) - return -EINVAL; - old = params->au_ac3_bitrate; - if (set && new != V4L2_MPEG_AUDIO_AC3_BITRATE_256K && - new != V4L2_MPEG_AUDIO_AC3_BITRATE_384K) - return -ERANGE; - if (new <= V4L2_MPEG_AUDIO_AC3_BITRATE_256K) - new = V4L2_MPEG_AUDIO_AC3_BITRATE_256K; - else - new = V4L2_MPEG_AUDIO_AC3_BITRATE_384K; - params->au_ac3_bitrate = new; - break; - case V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ: - old = V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000; - if (set && new != old) - return -ERANGE; - new = old; - break; - case V4L2_CID_MPEG_VIDEO_ENCODING: - old = V4L2_MPEG_VIDEO_ENCODING_MPEG_2; - if (set && new != old) - return -ERANGE; - new = old; - break; - case V4L2_CID_MPEG_VIDEO_ASPECT: - old = params->vi_aspect; - if (set && new != V4L2_MPEG_VIDEO_ASPECT_16x9 && - new != V4L2_MPEG_VIDEO_ASPECT_4x3) - return -ERANGE; - if (new != V4L2_MPEG_VIDEO_ASPECT_16x9) - new = V4L2_MPEG_VIDEO_ASPECT_4x3; - params->vi_aspect = new; - break; - case V4L2_CID_MPEG_VIDEO_BITRATE: - old = params->vi_bitrate * 1000; - new = 1000 * (new / 1000); - if (set && new > MPEG_VIDEO_TARGET_BITRATE_MAX * 1000) - return -ERANGE; - if (new > MPEG_VIDEO_TARGET_BITRATE_MAX * 1000) - new = MPEG_VIDEO_TARGET_BITRATE_MAX * 1000; - params->vi_bitrate = new / 1000; - break; - case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK: - old = params->vi_bitrate_peak * 1000; - new = 1000 * (new / 1000); - if (set && new > MPEG_VIDEO_TARGET_BITRATE_MAX * 1000) - return -ERANGE; - if (new > MPEG_VIDEO_TARGET_BITRATE_MAX * 1000) - new = MPEG_VIDEO_TARGET_BITRATE_MAX * 1000; - params->vi_bitrate_peak = new / 1000; - break; - case V4L2_CID_MPEG_VIDEO_BITRATE_MODE: - old = params->vi_bitrate_mode; - params->vi_bitrate_mode = new; - break; - default: + case V4L2_CID_MPEG_STREAM_TYPE: + old = V4L2_MPEG_STREAM_TYPE_MPEG2_TS; + if (set && new != old) + return -ERANGE; + new = old; + break; + case V4L2_CID_MPEG_STREAM_PID_PMT: + old = params->ts_pid_pmt; + if (set && new > MPEG_PID_MAX) + return -ERANGE; + if (new > MPEG_PID_MAX) + new = MPEG_PID_MAX; + params->ts_pid_pmt = new; + break; + case V4L2_CID_MPEG_STREAM_PID_AUDIO: + old = params->ts_pid_audio; + if (set && new > MPEG_PID_MAX) + return -ERANGE; + if (new > MPEG_PID_MAX) + new = MPEG_PID_MAX; + params->ts_pid_audio = new; + break; + case V4L2_CID_MPEG_STREAM_PID_VIDEO: + old = params->ts_pid_video; + if (set && new > MPEG_PID_MAX) + return -ERANGE; + if (new > MPEG_PID_MAX) + new = MPEG_PID_MAX; + params->ts_pid_video = new; + break; + case V4L2_CID_MPEG_STREAM_PID_PCR: + old = params->ts_pid_pcr; + if (set && new > MPEG_PID_MAX) + return -ERANGE; + if (new > MPEG_PID_MAX) + new = MPEG_PID_MAX; + params->ts_pid_pcr = new; + break; + case V4L2_CID_MPEG_AUDIO_ENCODING: + old = params->au_encoding; + if (set && new != V4L2_MPEG_AUDIO_ENCODING_LAYER_2 && + (!has_ac3 || new != V4L2_MPEG_AUDIO_ENCODING_AC3)) + return -ERANGE; + new = old; + break; + case V4L2_CID_MPEG_AUDIO_L2_BITRATE: + old = params->au_l2_bitrate; + if (set && new != V4L2_MPEG_AUDIO_L2_BITRATE_256K && + new != V4L2_MPEG_AUDIO_L2_BITRATE_384K) + return -ERANGE; + if (new <= V4L2_MPEG_AUDIO_L2_BITRATE_256K) + new = V4L2_MPEG_AUDIO_L2_BITRATE_256K; + else + new = V4L2_MPEG_AUDIO_L2_BITRATE_384K; + params->au_l2_bitrate = new; + break; + case V4L2_CID_MPEG_AUDIO_AC3_BITRATE: + if (!has_ac3) return -EINVAL; + old = params->au_ac3_bitrate; + if (set && new != V4L2_MPEG_AUDIO_AC3_BITRATE_256K && + new != V4L2_MPEG_AUDIO_AC3_BITRATE_384K) + return -ERANGE; + if (new <= V4L2_MPEG_AUDIO_AC3_BITRATE_256K) + new = V4L2_MPEG_AUDIO_AC3_BITRATE_256K; + else + new = V4L2_MPEG_AUDIO_AC3_BITRATE_384K; + params->au_ac3_bitrate = new; + break; + case V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ: + old = V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000; + if (set && new != old) + return -ERANGE; + new = old; + break; + case V4L2_CID_MPEG_VIDEO_ENCODING: + old = V4L2_MPEG_VIDEO_ENCODING_MPEG_2; + if (set && new != old) + return -ERANGE; + new = old; + break; + case V4L2_CID_MPEG_VIDEO_ASPECT: + old = params->vi_aspect; + if (set && new != V4L2_MPEG_VIDEO_ASPECT_16x9 && + new != V4L2_MPEG_VIDEO_ASPECT_4x3) + return -ERANGE; + if (new != V4L2_MPEG_VIDEO_ASPECT_16x9) + new = V4L2_MPEG_VIDEO_ASPECT_4x3; + params->vi_aspect = new; + break; + case V4L2_CID_MPEG_VIDEO_BITRATE: + old = params->vi_bitrate * 1000; + new = 1000 * (new / 1000); + if (set && new > MPEG_VIDEO_TARGET_BITRATE_MAX * 1000) + return -ERANGE; + if (new > MPEG_VIDEO_TARGET_BITRATE_MAX * 1000) + new = MPEG_VIDEO_TARGET_BITRATE_MAX * 1000; + params->vi_bitrate = new / 1000; + break; + case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK: + old = params->vi_bitrate_peak * 1000; + new = 1000 * (new / 1000); + if (set && new > MPEG_VIDEO_TARGET_BITRATE_MAX * 1000) + return -ERANGE; + if (new > MPEG_VIDEO_TARGET_BITRATE_MAX * 1000) + new = MPEG_VIDEO_TARGET_BITRATE_MAX * 1000; + params->vi_bitrate_peak = new / 1000; + break; + case V4L2_CID_MPEG_VIDEO_BITRATE_MODE: + old = params->vi_bitrate_mode; + params->vi_bitrate_mode = new; + break; + default: + return -EINVAL; } - if (cmd == VIDIOC_G_EXT_CTRLS) - ctrl->value = old; - else - ctrl->value = new; + ctrl->value = new; return 0; } -static int saa6752hs_qctrl(struct saa6752hs_state *h, - struct v4l2_queryctrl *qctrl) + +static int saa6752hs_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qctrl) { + struct saa6752hs_state *h = to_state(sd); struct saa6752hs_mpeg_params *params = &h->params; int err; @@ -610,8 +623,7 @@ static int saa6752hs_qctrl(struct saa6752hs_state *h, return -EINVAL; } -static int saa6752hs_qmenu(struct saa6752hs_state *h, - struct v4l2_querymenu *qmenu) +static int saa6752hs_querymenu(struct v4l2_subdev *sd, struct v4l2_querymenu *qmenu) { static const u32 mpeg_audio_encoding[] = { V4L2_MPEG_AUDIO_ENCODING_LAYER_2, @@ -632,11 +644,12 @@ static int saa6752hs_qmenu(struct saa6752hs_state *h, V4L2_MPEG_AUDIO_AC3_BITRATE_384K, V4L2_CTRL_MENU_IDS_END }; + struct saa6752hs_state *h = to_state(sd); struct v4l2_queryctrl qctrl; int err; qctrl.id = qmenu->id; - err = saa6752hs_qctrl(h, &qctrl); + err = saa6752hs_queryctrl(sd, &qctrl); if (err) return err; switch (qmenu->id) { @@ -656,17 +669,16 @@ static int saa6752hs_qmenu(struct saa6752hs_state *h, return v4l2_ctrl_query_menu(qmenu, &qctrl, NULL); } -static int saa6752hs_init(struct i2c_client *client, u32 leading_null_bytes) +static int saa6752hs_init(struct v4l2_subdev *sd, u32 leading_null_bytes) { unsigned char buf[9], buf2[4]; - struct saa6752hs_state *h; + struct saa6752hs_state *h = to_state(sd); + struct i2c_client *client = v4l2_get_subdevdata(sd); unsigned size; u32 crc; unsigned char localPAT[256]; unsigned char localPMT[256]; - h = i2c_get_clientdata(client); - /* Set video format - must be done first as it resets other settings */ set_reg8(client, 0x41, h->video_format); @@ -762,7 +774,7 @@ static int saa6752hs_init(struct i2c_client *client, u32 leading_null_bytes) buf[3] = 0x82; buf[4] = 0xB0; buf[5] = buf2[0]; - switch(h->params.vi_aspect) { + switch (h->params.vi_aspect) { case V4L2_MPEG_VIDEO_ASPECT_16x9: buf[6] = buf2[1] | 0x40; break; @@ -770,7 +782,6 @@ static int saa6752hs_init(struct i2c_client *client, u32 leading_null_bytes) default: buf[6] = buf2[1] & 0xBF; break; - break; } buf[7] = buf2[2]; buf[8] = buf2[3]; @@ -779,81 +790,167 @@ static int saa6752hs_init(struct i2c_client *client, u32 leading_null_bytes) return 0; } -static int -saa6752hs_command(struct i2c_client *client, unsigned int cmd, void *arg) +static int saa6752hs_do_ext_ctrls(struct v4l2_subdev *sd, struct v4l2_ext_controls *ctrls, int set) { - struct saa6752hs_state *h = i2c_get_clientdata(client); - struct v4l2_ext_controls *ctrls = arg; + struct saa6752hs_state *h = to_state(sd); struct saa6752hs_mpeg_params params; - int err = 0; int i; - switch (cmd) { - case VIDIOC_INT_INIT: - /* apply settings and start encoder */ - saa6752hs_init(client, *(u32 *)arg); - break; - case VIDIOC_S_EXT_CTRLS: - if (ctrls->ctrl_class != V4L2_CTRL_CLASS_MPEG) - return -EINVAL; - /* fall through */ - case VIDIOC_TRY_EXT_CTRLS: - case VIDIOC_G_EXT_CTRLS: - if (ctrls->ctrl_class != V4L2_CTRL_CLASS_MPEG) - return -EINVAL; - params = h->params; - for (i = 0; i < ctrls->count; i++) { - err = handle_ctrl(h->has_ac3, ¶ms, ctrls->controls + i, cmd); - if (err) { - ctrls->error_idx = i; - return err; - } + if (ctrls->ctrl_class != V4L2_CTRL_CLASS_MPEG) + return -EINVAL; + + params = h->params; + for (i = 0; i < ctrls->count; i++) { + int err = handle_ctrl(h->has_ac3, ¶ms, ctrls->controls + i, set); + + if (err) { + ctrls->error_idx = i; + return err; } - h->params = params; - break; - case VIDIOC_QUERYCTRL: - return saa6752hs_qctrl(h, arg); - case VIDIOC_QUERYMENU: - return saa6752hs_qmenu(h, arg); - case VIDIOC_G_FMT: - { - struct v4l2_format *f = arg; - - if (h->video_format == SAA6752HS_VF_UNKNOWN) - h->video_format = SAA6752HS_VF_D1; - f->fmt.pix.width = - v4l2_format_table[h->video_format].fmt.pix.width; - f->fmt.pix.height = - v4l2_format_table[h->video_format].fmt.pix.height; - break ; } - case VIDIOC_S_FMT: - { - struct v4l2_format *f = arg; + if (set) + h->params = params; + return 0; +} - saa6752hs_set_subsampling(client, f); - break; +static int saa6752hs_s_ext_ctrls(struct v4l2_subdev *sd, struct v4l2_ext_controls *ctrls) +{ + return saa6752hs_do_ext_ctrls(sd, ctrls, 1); +} + +static int saa6752hs_try_ext_ctrls(struct v4l2_subdev *sd, struct v4l2_ext_controls *ctrls) +{ + return saa6752hs_do_ext_ctrls(sd, ctrls, 0); +} + +static int saa6752hs_g_ext_ctrls(struct v4l2_subdev *sd, struct v4l2_ext_controls *ctrls) +{ + struct saa6752hs_state *h = to_state(sd); + int i; + + if (ctrls->ctrl_class != V4L2_CTRL_CLASS_MPEG) + return -EINVAL; + + for (i = 0; i < ctrls->count; i++) { + int err = get_ctrl(h->has_ac3, &h->params, ctrls->controls + i); + + if (err) { + ctrls->error_idx = i; + return err; + } } - case VIDIOC_S_STD: - h->standard = *((v4l2_std_id *) arg); - break; + return 0; +} - case VIDIOC_DBG_G_CHIP_IDENT: - return v4l2_chip_ident_i2c_client(client, - arg, h->chip, h->revision); +static int saa6752hs_g_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) +{ + struct saa6752hs_state *h = to_state(sd); - default: - /* nothing */ - break; + if (h->video_format == SAA6752HS_VF_UNKNOWN) + h->video_format = SAA6752HS_VF_D1; + f->fmt.pix.width = + v4l2_format_table[h->video_format].fmt.pix.width; + f->fmt.pix.height = + v4l2_format_table[h->video_format].fmt.pix.height; + return 0; +} + +static int saa6752hs_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) +{ + struct saa6752hs_state *h = to_state(sd); + int dist_352, dist_480, dist_720; + + /* + FIXME: translate and round width/height into EMPRESS + subsample type: + + type | PAL | NTSC + --------------------------- + SIF | 352x288 | 352x240 + 1/2 D1 | 352x576 | 352x480 + 2/3 D1 | 480x576 | 480x480 + D1 | 720x576 | 720x480 + */ + + dist_352 = abs(f->fmt.pix.width - 352); + dist_480 = abs(f->fmt.pix.width - 480); + dist_720 = abs(f->fmt.pix.width - 720); + if (dist_720 < dist_480) { + f->fmt.pix.width = 720; + f->fmt.pix.height = 576; + h->video_format = SAA6752HS_VF_D1; + } else if (dist_480 < dist_352) { + f->fmt.pix.width = 480; + f->fmt.pix.height = 576; + h->video_format = SAA6752HS_VF_2_3_D1; + } else { + f->fmt.pix.width = 352; + if (abs(f->fmt.pix.height - 576) < + abs(f->fmt.pix.height - 288)) { + f->fmt.pix.height = 576; + h->video_format = SAA6752HS_VF_1_2_D1; + } else { + f->fmt.pix.height = 288; + h->video_format = SAA6752HS_VF_SIF; + } } + return 0; +} + +static int saa6752hs_s_std(struct v4l2_subdev *sd, v4l2_std_id std) +{ + struct saa6752hs_state *h = to_state(sd); + + h->standard = std; + return 0; +} + +static int saa6752hs_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip) +{ + struct i2c_client *client = v4l2_get_subdevdata(sd); + struct saa6752hs_state *h = to_state(sd); + + return v4l2_chip_ident_i2c_client(client, + chip, h->chip, h->revision); +} - return err; +static int saa6752hs_command(struct i2c_client *client, unsigned cmd, void *arg) +{ + return v4l2_subdev_command(i2c_get_clientdata(client), cmd, arg); } +/* ----------------------------------------------------------------------- */ + +static const struct v4l2_subdev_core_ops saa6752hs_core_ops = { + .g_chip_ident = saa6752hs_g_chip_ident, + .init = saa6752hs_init, + .queryctrl = saa6752hs_queryctrl, + .querymenu = saa6752hs_querymenu, + .g_ext_ctrls = saa6752hs_g_ext_ctrls, + .s_ext_ctrls = saa6752hs_s_ext_ctrls, + .try_ext_ctrls = saa6752hs_try_ext_ctrls, +}; + +static const struct v4l2_subdev_tuner_ops saa6752hs_tuner_ops = { + .s_std = saa6752hs_s_std, +}; + +static const struct v4l2_subdev_video_ops saa6752hs_video_ops = { + .s_fmt = saa6752hs_s_fmt, + .g_fmt = saa6752hs_g_fmt, +}; + +static const struct v4l2_subdev_ops saa6752hs_ops = { + .core = &saa6752hs_core_ops, + .tuner = &saa6752hs_tuner_ops, + .video = &saa6752hs_video_ops, +}; + static int saa6752hs_probe(struct i2c_client *client, - const struct i2c_device_id *id) + const struct i2c_device_id *id) { struct saa6752hs_state *h = kzalloc(sizeof(*h), GFP_KERNEL); + struct v4l2_subdev *sd; u8 addr = 0x13; u8 data[12]; @@ -861,6 +958,8 @@ static int saa6752hs_probe(struct i2c_client *client, client->addr << 1, client->adapter->name); if (h == NULL) return -ENOMEM; + sd = &h->sd; + v4l2_i2c_subdev_init(sd, client, &saa6752hs_ops); i2c_master_send(client, &addr, 1); i2c_master_recv(client, data, sizeof(data)); @@ -874,14 +973,15 @@ static int saa6752hs_probe(struct i2c_client *client, } h->params = param_defaults; h->standard = 0; /* Assume 625 input lines */ - - i2c_set_clientdata(client, h); return 0; } static int saa6752hs_remove(struct i2c_client *client) { - kfree(i2c_get_clientdata(client)); + struct v4l2_subdev *sd = i2c_get_clientdata(client); + + v4l2_device_unregister_subdev(sd); + kfree(to_state(sd)); return 0; } -- cgit v1.2.3 From fac6986c4777ae85fa2108ea25fee98de2c1f7b2 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sat, 17 Jan 2009 12:17:14 -0300 Subject: V4L/DVB (10247): saa7134: convert to the new v4l2 framework. Register v4l2_device and switch to v4l2_subdev to access the i2c modules. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/saa7134/saa6752hs.c | 13 +----- drivers/media/video/saa7134/saa7134-cards.c | 13 +++--- drivers/media/video/saa7134/saa7134-core.c | 66 ++++++++++++++++++++++----- drivers/media/video/saa7134/saa7134-dvb.c | 4 +- drivers/media/video/saa7134/saa7134-empress.c | 22 ++++----- drivers/media/video/saa7134/saa7134-i2c.c | 21 +-------- drivers/media/video/saa7134/saa7134-video.c | 17 ++++--- drivers/media/video/saa7134/saa7134.h | 13 ++++-- 8 files changed, 91 insertions(+), 78 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/saa7134/saa6752hs.c b/drivers/media/video/saa7134/saa6752hs.c index 25e6ab28a0a3..2d292ad776e9 100644 --- a/drivers/media/video/saa7134/saa6752hs.c +++ b/drivers/media/video/saa7134/saa6752hs.c @@ -36,7 +36,7 @@ #include #include #include -#include +#include #include #include @@ -45,10 +45,6 @@ #define MPEG_TOTAL_TARGET_BITRATE_MAX 27000 #define MPEG_PID_MAX ((1 << 14) - 1) -/* Addresses to scan */ -static unsigned short normal_i2c[] = {0x20, I2C_CLIENT_END}; - -I2C_CLIENT_INSMOD; MODULE_DESCRIPTION("device driver for saa6752hs MPEG2 encoder"); MODULE_AUTHOR("Andrew de Quincey"); @@ -914,11 +910,6 @@ static int saa6752hs_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_i chip, h->chip, h->revision); } -static int saa6752hs_command(struct i2c_client *client, unsigned cmd, void *arg) -{ - return v4l2_subdev_command(i2c_get_clientdata(client), cmd, arg); -} - /* ----------------------------------------------------------------------- */ static const struct v4l2_subdev_core_ops saa6752hs_core_ops = { @@ -993,8 +984,6 @@ MODULE_DEVICE_TABLE(i2c, saa6752hs_id); static struct v4l2_i2c_driver_data v4l2_i2c_data = { .name = "saa6752hs", - .driverid = I2C_DRIVERID_SAA6752HS, - .command = saa6752hs_command, .probe = saa6752hs_probe, .remove = saa6752hs_remove, .id_table = saa6752hs_id, diff --git a/drivers/media/video/saa7134/saa7134-cards.c b/drivers/media/video/saa7134/saa7134-cards.c index e2febcd6e529..0d50d7448fc5 100644 --- a/drivers/media/video/saa7134/saa7134-cards.c +++ b/drivers/media/video/saa7134/saa7134-cards.c @@ -4611,7 +4611,7 @@ struct saa7134_board saa7134_boards[] = { .tuner_type = TUNER_YMEC_TVF_5533MF, .radio_type = TUNER_TEA5767, .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, + .radio_addr = 0x60, .gpiomask = 0x80000700, .inputs = { { .name = name_tv, @@ -6109,7 +6109,7 @@ static void saa7134_tuner_setup(struct saa7134_dev *dev) tun_setup.mode_mask = T_RADIO; - saa7134_i2c_call_clients(dev, TUNER_SET_TYPE_ADDR, &tun_setup); + saa_call_all(dev, tuner, s_type_addr, &tun_setup); mode_mask &= ~T_RADIO; } @@ -6121,7 +6121,7 @@ static void saa7134_tuner_setup(struct saa7134_dev *dev) tun_setup.mode_mask = mode_mask; - saa7134_i2c_call_clients(dev, TUNER_SET_TYPE_ADDR, &tun_setup); + saa_call_all(dev, tuner, s_type_addr, &tun_setup); } if (dev->tda9887_conf) { @@ -6130,8 +6130,7 @@ static void saa7134_tuner_setup(struct saa7134_dev *dev) tda9887_cfg.tuner = TUNER_TDA9887; tda9887_cfg.priv = &dev->tda9887_conf; - saa7134_i2c_call_clients(dev, TUNER_SET_CONFIG, - &tda9887_cfg); + saa_call_all(dev, tuner, s_config, &tda9887_cfg); } if (dev->tuner_type == TUNER_XC2028) { @@ -6158,7 +6157,7 @@ static void saa7134_tuner_setup(struct saa7134_dev *dev) xc2028_cfg.tuner = TUNER_XC2028; xc2028_cfg.priv = &ctl; - saa7134_i2c_call_clients(dev, TUNER_SET_CONFIG, &xc2028_cfg); + saa_call_all(dev, tuner, s_config, &xc2028_cfg); } } @@ -6401,7 +6400,7 @@ int saa7134_board_init2(struct saa7134_dev *dev) ctl.xtal_freq = TEA5767_HIGH_LO_13MHz; tea5767_cfg.tuner = TUNER_TEA5767; tea5767_cfg.priv = &ctl; - saa7134_i2c_call_clients(dev, TUNER_SET_CONFIG, &tea5767_cfg); + saa_call_all(dev, tuner, s_config, &tea5767_cfg); break; } } /* switch() */ diff --git a/drivers/media/video/saa7134/saa7134-core.c b/drivers/media/video/saa7134/saa7134-core.c index 99221d726edb..ac23ff53543d 100644 --- a/drivers/media/video/saa7134/saa7134-core.c +++ b/drivers/media/video/saa7134/saa7134-core.c @@ -851,6 +851,10 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev, if (NULL == dev) return -ENOMEM; + err = v4l2_device_register(&pci_dev->dev, &dev->v4l2_dev); + if (err) + goto fail0; + /* pci init */ dev->pci = pci_dev; if (pci_enable_device(pci_dev)) { @@ -927,6 +931,8 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev, dev->autodetected = card[dev->nr] != dev->board; dev->tuner_type = saa7134_boards[dev->board].tuner_type; dev->tuner_addr = saa7134_boards[dev->board].tuner_addr; + dev->radio_type = saa7134_boards[dev->board].radio_type; + dev->radio_addr = saa7134_boards[dev->board].radio_addr; dev->tda9887_conf = saa7134_boards[dev->board].tda9887_conf; if (UNSET != tuner[dev->nr]) dev->tuner_type = tuner[dev->nr]; @@ -973,15 +979,50 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev, saa7134_i2c_register(dev); /* initialize hardware #2 */ - if (TUNER_ABSENT != dev->tuner_type) - request_module("tuner"); + if (TUNER_ABSENT != dev->tuner_type) { + if (dev->radio_type != UNSET) { + v4l2_i2c_new_subdev(&dev->i2c_adap, "tuner", "tuner", + dev->radio_addr); + } + if (dev->tda9887_conf & TDA9887_PRESENT) { + unsigned short addrs[] = { 0x42, 0x43, 0x4a, 0x4b, + I2C_CLIENT_END }; + + v4l2_i2c_new_probed_subdev(&dev->i2c_adap, + "tuner", "tuner", addrs); + } + if (dev->tuner_addr != ADDR_UNSET) { + v4l2_i2c_new_subdev(&dev->i2c_adap, + "tuner", "tuner", dev->tuner_addr); + } else { + unsigned short addrs[] = { + 0x42, 0x43, 0x4a, 0x4b, /* tda8290 */ + 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, + 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, + I2C_CLIENT_END + }; + + if (dev->tda9887_conf & TDA9887_PRESENT) { + v4l2_i2c_new_probed_subdev(&dev->i2c_adap, + "tuner", "tuner", addrs + 4); + } else { + v4l2_i2c_new_probed_subdev(&dev->i2c_adap, + "tuner", "tuner", addrs); + } + } + } saa7134_board_init2(dev); saa7134_hwinit2(dev); /* load i2c helpers */ if (card_is_empress(dev)) { - request_module("saa6752hs"); + struct v4l2_subdev *sd = + v4l2_i2c_new_subdev(&dev->i2c_adap, "saa6752hs", + "saa6752hs", 0x20); + + if (sd) + sd->grp_id = GRP_EMPRESS; } request_submodules(dev); @@ -1023,7 +1064,6 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev, } /* everything worked */ - pci_set_drvdata(pci_dev,dev); saa7134_devcount++; mutex_lock(&devlist_lock); @@ -1040,7 +1080,7 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev, } if (TUNER_ABSENT != dev->tuner_type) - saa7134_i2c_call_clients(dev, TUNER_SET_STANDBY, NULL); + saa_call_all(dev, core, s_standby, 0); return 0; @@ -1055,13 +1095,16 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev, release_mem_region(pci_resource_start(pci_dev,0), pci_resource_len(pci_dev,0)); fail1: + v4l2_device_unregister(&dev->v4l2_dev); + fail0: kfree(dev); return err; } static void __devexit saa7134_finidev(struct pci_dev *pci_dev) { - struct saa7134_dev *dev = pci_get_drvdata(pci_dev); + struct v4l2_device *v4l2_dev = pci_get_drvdata(pci_dev); + struct saa7134_dev *dev = container_of(v4l2_dev, struct saa7134_dev, v4l2_dev); struct saa7134_mpeg_ops *mops; /* Release DMA sound modules if present */ @@ -1113,7 +1156,8 @@ static void __devexit saa7134_finidev(struct pci_dev *pci_dev) release_mem_region(pci_resource_start(pci_dev,0), pci_resource_len(pci_dev,0)); - pci_set_drvdata(pci_dev, NULL); + + v4l2_device_unregister(&dev->v4l2_dev); /* free memory */ kfree(dev); @@ -1148,8 +1192,8 @@ static int saa7134_buffer_requeue(struct saa7134_dev *dev, static int saa7134_suspend(struct pci_dev *pci_dev , pm_message_t state) { - - struct saa7134_dev *dev = pci_get_drvdata(pci_dev); + struct v4l2_device *v4l2_dev = pci_get_drvdata(pci_dev); + struct saa7134_dev *dev = container_of(v4l2_dev, struct saa7134_dev, v4l2_dev); /* disable overlay - apps should enable it explicitly on resume*/ dev->ovenable = 0; @@ -1185,7 +1229,8 @@ static int saa7134_suspend(struct pci_dev *pci_dev , pm_message_t state) static int saa7134_resume(struct pci_dev *pci_dev) { - struct saa7134_dev *dev = pci_get_drvdata(pci_dev); + struct v4l2_device *v4l2_dev = pci_get_drvdata(pci_dev); + struct saa7134_dev *dev = container_of(v4l2_dev, struct saa7134_dev, v4l2_dev); unsigned long flags; pci_set_power_state(pci_dev, PCI_D0); @@ -1307,7 +1352,6 @@ module_exit(saa7134_fini); /* ----------------------------------------------------------- */ EXPORT_SYMBOL(saa7134_set_gpio); -EXPORT_SYMBOL(saa7134_i2c_call_clients); EXPORT_SYMBOL(saa7134_devlist); EXPORT_SYMBOL(saa7134_boards); diff --git a/drivers/media/video/saa7134/saa7134-dvb.c b/drivers/media/video/saa7134/saa7134-dvb.c index b5370b3e1a3d..af9a22d1b94d 100644 --- a/drivers/media/video/saa7134/saa7134-dvb.c +++ b/drivers/media/video/saa7134/saa7134-dvb.c @@ -189,7 +189,7 @@ static int mt352_pinnacle_tuner_set_params(struct dvb_frontend* fe, if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 1); i2c_transfer(&dev->i2c_adap, &msg, 1); - saa7134_i2c_call_clients(dev,VIDIOC_S_FREQUENCY,&f); + saa_call_all(dev, tuner, s_frequency, &f); msg.buf = on; if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 1); @@ -1449,7 +1449,7 @@ static int dvb_fini(struct saa7134_dev *dev) tda9887_cfg.priv = &on; /* otherwise we don't detect the tuner on next insmod */ - saa7134_i2c_call_clients(dev, TUNER_SET_CONFIG, &tda9887_cfg); + saa_call_all(dev, tuner, s_config, &tda9887_cfg); } else if (dev->board == SAA7134_BOARD_MEDION_MD8800_QUADRO) { if ((dev->eedata[2] == 0x07) && use_frontend) { /* turn off the 2nd lnb supply */ diff --git a/drivers/media/video/saa7134/saa7134-empress.c b/drivers/media/video/saa7134/saa7134-empress.c index c9d8beb87a60..d9d9607044a7 100644 --- a/drivers/media/video/saa7134/saa7134-empress.c +++ b/drivers/media/video/saa7134/saa7134-empress.c @@ -76,7 +76,7 @@ static int ts_init_encoder(struct saa7134_dev* dev) break; } ts_reset_encoder(dev); - saa7134_i2c_call_clients(dev, VIDIOC_INT_INIT, &leading_null_bytes); + saa_call_all(dev, core, init, leading_null_bytes); dev->empress_started = 1; return 0; } @@ -234,7 +234,7 @@ static int empress_g_fmt_vid_cap(struct file *file, void *priv, { struct saa7134_dev *dev = file->private_data; - saa7134_i2c_call_clients(dev, VIDIOC_G_FMT, f); + saa_call_all(dev, video, g_fmt, f); f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG; f->fmt.pix.sizeimage = TS_PACKET_SIZE * dev->ts.nr_packets; @@ -247,7 +247,7 @@ static int empress_s_fmt_vid_cap(struct file *file, void *priv, { struct saa7134_dev *dev = file->private_data; - saa7134_i2c_call_clients(dev, VIDIOC_S_FMT, f); + saa_call_all(dev, video, s_fmt, f); f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG; f->fmt.pix.sizeimage = TS_PACKET_SIZE * dev->ts.nr_packets; @@ -317,7 +317,7 @@ static int empress_s_ext_ctrls(struct file *file, void *priv, if (ctrls->ctrl_class != V4L2_CTRL_CLASS_MPEG) return -EINVAL; - err = saa7134_i2c_call_saa6752(dev, VIDIOC_S_EXT_CTRLS, ctrls); + err = saa_call_empress(dev, core, s_ext_ctrls, ctrls); ts_init_encoder(dev); return err; @@ -330,7 +330,7 @@ static int empress_g_ext_ctrls(struct file *file, void *priv, if (ctrls->ctrl_class != V4L2_CTRL_CLASS_MPEG) return -EINVAL; - return saa7134_i2c_call_saa6752(dev, VIDIOC_G_EXT_CTRLS, ctrls); + return saa_call_empress(dev, core, g_ext_ctrls, ctrls); } static int empress_g_ctrl(struct file *file, void *priv, @@ -391,7 +391,7 @@ static int empress_queryctrl(struct file *file, void *priv, return v4l2_ctrl_query_fill_std(c); if (V4L2_CTRL_ID2CLASS(c->id) != V4L2_CTRL_CLASS_MPEG) return saa7134_queryctrl(file, priv, c); - return saa7134_i2c_call_saa6752(dev, VIDIOC_QUERYCTRL, c); + return saa_call_empress(dev, core, queryctrl, c); } static int empress_querymenu(struct file *file, void *priv, @@ -401,7 +401,7 @@ static int empress_querymenu(struct file *file, void *priv, if (V4L2_CTRL_ID2CLASS(c->id) != V4L2_CTRL_CLASS_MPEG) return -EINVAL; - return saa7134_i2c_call_saa6752(dev, VIDIOC_QUERYMENU, c); + return saa_call_empress(dev, core, querymenu, c); } static int empress_g_chip_ident(struct file *file, void *fh, @@ -411,14 +411,12 @@ static int empress_g_chip_ident(struct file *file, void *fh, chip->ident = V4L2_IDENT_NONE; chip->revision = 0; - if (dev->mpeg_i2c_client == NULL) - return -EINVAL; if (chip->match.type == V4L2_CHIP_MATCH_I2C_DRIVER && !strcmp(chip->match.name, "saa6752hs")) - return saa7134_i2c_call_saa6752(dev, VIDIOC_DBG_G_CHIP_IDENT, chip); + return saa_call_empress(dev, core, g_chip_ident, chip); if (chip->match.type == V4L2_CHIP_MATCH_I2C_ADDR && - chip->match.addr == dev->mpeg_i2c_client->addr) - return saa7134_i2c_call_saa6752(dev, VIDIOC_DBG_G_CHIP_IDENT, chip); + chip->match.addr == 0x20) + return saa_call_empress(dev, core, g_chip_ident, chip); return -EINVAL; } diff --git a/drivers/media/video/saa7134/saa7134-i2c.c b/drivers/media/video/saa7134/saa7134-i2c.c index 20c1b33caf7b..2e15f43d26ec 100644 --- a/drivers/media/video/saa7134/saa7134-i2c.c +++ b/drivers/media/video/saa7134/saa7134-i2c.c @@ -327,8 +327,6 @@ static int attach_inform(struct i2c_client *client) d1printk( "%s i2c attach [addr=0x%x,client=%s]\n", client->driver->driver.name, client->addr, client->name); - if (client->addr == 0x20 && client->driver && client->driver->command) - dev->mpeg_i2c_client = client; /* Am I an i2c remote control? */ @@ -357,7 +355,6 @@ static struct i2c_algorithm saa7134_algo = { static struct i2c_adapter saa7134_adap_template = { .owner = THIS_MODULE, - .class = I2C_CLASS_TV_ANALOG, .name = "saa7134", .id = I2C_HW_SAA7134, .algo = &saa7134_algo, @@ -421,29 +418,13 @@ static void do_i2c_scan(char *name, struct i2c_client *c) } } -void saa7134_i2c_call_clients(struct saa7134_dev *dev, - unsigned int cmd, void *arg) -{ - BUG_ON(NULL == dev->i2c_adap.algo_data); - i2c_clients_command(&dev->i2c_adap, cmd, arg); -} - -int saa7134_i2c_call_saa6752(struct saa7134_dev *dev, - unsigned int cmd, void *arg) -{ - if (dev->mpeg_i2c_client == NULL) - return -EINVAL; - return dev->mpeg_i2c_client->driver->command(dev->mpeg_i2c_client, - cmd, arg); -} -EXPORT_SYMBOL_GPL(saa7134_i2c_call_saa6752); - int saa7134_i2c_register(struct saa7134_dev *dev) { dev->i2c_adap = saa7134_adap_template; dev->i2c_adap.dev.parent = &dev->pci->dev; strcpy(dev->i2c_adap.name,dev->name); dev->i2c_adap.algo_data = dev; + i2c_set_adapdata(&dev->i2c_adap, &dev->v4l2_dev); i2c_add_adapter(&dev->i2c_adap); dev->i2c_client = saa7134_client_template; diff --git a/drivers/media/video/saa7134/saa7134-video.c b/drivers/media/video/saa7134/saa7134-video.c index a1f7e351f572..193b07d83d1e 100644 --- a/drivers/media/video/saa7134/saa7134-video.c +++ b/drivers/media/video/saa7134/saa7134-video.c @@ -627,10 +627,10 @@ void saa7134_set_tvnorm_hw(struct saa7134_dev *dev) saa7134_set_decoder(dev); if (card_in(dev, dev->ctl_input).tv) - saa7134_i2c_call_clients(dev, VIDIOC_S_STD, &dev->tvnorm->id); + saa_call_all(dev, tuner, s_std, dev->tvnorm->id); /* Set the correct norm for the saa6752hs. This function does nothing if there is no saa6752hs. */ - saa7134_i2c_call_saa6752(dev, VIDIOC_S_STD, &dev->tvnorm->id); + saa_call_empress(dev, tuner, s_std, dev->tvnorm->id); } static void set_h_prescale(struct saa7134_dev *dev, int task, int prescale) @@ -1266,8 +1266,7 @@ int saa7134_s_ctrl_internal(struct saa7134_dev *dev, struct saa7134_fh *fh, str else dev->tda9887_conf &= ~TDA9887_AUTOMUTE; - saa7134_i2c_call_clients(dev, TUNER_SET_CONFIG, - &tda9887_cfg); + saa_call_all(dev, tuner, s_config, &tda9887_cfg); } break; } @@ -1387,7 +1386,7 @@ static int video_open(struct file *file) if (fh->radio) { /* switch to radio mode */ saa7134_tvaudio_setinput(dev,&card(dev).radio); - saa7134_i2c_call_clients(dev,AUDC_SET_RADIO, NULL); + saa_call_all(dev, tuner, s_radio); } else { /* switch to video/vbi mode */ video_mux(dev,dev->ctl_input); @@ -1498,7 +1497,7 @@ static int video_release(struct file *file) saa_andorb(SAA7134_OFMT_DATA_A, 0x1f, 0); saa_andorb(SAA7134_OFMT_DATA_B, 0x1f, 0); - saa7134_i2c_call_clients(dev, TUNER_SET_STANDBY, NULL); + saa_call_all(dev, core, s_standby, 0); /* free stuff */ videobuf_mmap_free(&fh->cap); @@ -2041,7 +2040,7 @@ static int saa7134_s_frequency(struct file *file, void *priv, mutex_lock(&dev->lock); dev->ctl_freq = f->frequency; - saa7134_i2c_call_clients(dev, VIDIOC_S_FREQUENCY, f); + saa_call_all(dev, tuner, s_frequency, f); saa7134_tvaudio_do_scan(dev); mutex_unlock(&dev->lock); @@ -2299,7 +2298,7 @@ static int radio_g_tuner(struct file *file, void *priv, strcpy(t->name, "Radio"); t->type = V4L2_TUNER_RADIO; - saa7134_i2c_call_clients(dev, VIDIOC_G_TUNER, t); + saa_call_all(dev, tuner, g_tuner, t); if (dev->input->amux == TV) { t->signal = 0xf800 - ((saa_readb(0x581) & 0x1f) << 11); t->rxsubchans = (saa_readb(0x529) & 0x08) ? @@ -2316,7 +2315,7 @@ static int radio_s_tuner(struct file *file, void *priv, if (0 != t->index) return -EINVAL; - saa7134_i2c_call_clients(dev, VIDIOC_S_TUNER, t); + saa_call_all(dev, tuner, s_tuner, t); return 0; } diff --git a/drivers/media/video/saa7134/saa7134.h b/drivers/media/video/saa7134/saa7134.h index 14ee265f3374..bb6952118d01 100644 --- a/drivers/media/video/saa7134/saa7134.h +++ b/drivers/media/video/saa7134/saa7134.h @@ -35,6 +35,7 @@ #include #include +#include #include #include #include @@ -482,6 +483,7 @@ struct saa7134_dev { struct mutex lock; spinlock_t slock; struct v4l2_prio_state prio; + struct v4l2_device v4l2_dev; /* workstruct for loading modules */ struct work_struct request_module_wk; @@ -572,7 +574,6 @@ struct saa7134_dev { enum saa7134_ts_status ts_state; unsigned int buff_cnt; struct saa7134_mpeg_ops *mops; - struct i2c_client *mpeg_i2c_client; /* SAA7134_MPEG_EMPRESS only */ struct video_device *empress_dev; @@ -616,6 +617,12 @@ struct saa7134_dev { V4L2_STD_NTSC | V4L2_STD_PAL_M | \ V4L2_STD_PAL_60) +#define GRP_EMPRESS (1) +#define saa_call_all(dev, o, f, args...) \ + v4l2_device_call_all(&(dev)->v4l2_dev, 0, o, f , ##args) +#define saa_call_empress(dev, o, f, args...) \ + v4l2_device_call_until_err(&(dev)->v4l2_dev, GRP_EMPRESS, o, f , ##args) + /* ----------------------------------------------------------- */ /* saa7134-core.c */ @@ -668,10 +675,6 @@ int saa7134_tuner_callback(void *priv, int component, int command, int arg); int saa7134_i2c_register(struct saa7134_dev *dev); int saa7134_i2c_unregister(struct saa7134_dev *dev); -void saa7134_i2c_call_clients(struct saa7134_dev *dev, - unsigned int cmd, void *arg); -int saa7134_i2c_call_saa6752(struct saa7134_dev *dev, - unsigned int cmd, void *arg); /* ----------------------------------------------------------- */ -- cgit v1.2.3 From c7d29e2f530654aa0c323aafb94d42a6a718482c Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sun, 18 Jan 2009 19:37:59 -0300 Subject: V4L/DVB (10249): v4l2-common: added v4l2_i2c_tuner_addrs() Add v4l2_i2c_tuner_addrs() to obtain the various I2C tuner addresses. This will be used in several drivers, so make this a common function as we do not want to have these I2C addresses all over the place. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/saa7134/saa7134-core.c | 42 ++++++++++++------------------ drivers/media/video/v4l2-common.c | 36 +++++++++++++++++++++++++ include/media/v4l2-common.h | 13 +++++++++ 3 files changed, 65 insertions(+), 26 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/saa7134/saa7134-core.c b/drivers/media/video/saa7134/saa7134-core.c index ac23ff53543d..829006ebdf34 100644 --- a/drivers/media/video/saa7134/saa7134-core.c +++ b/drivers/media/video/saa7134/saa7134-core.c @@ -980,35 +980,25 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev, /* initialize hardware #2 */ if (TUNER_ABSENT != dev->tuner_type) { - if (dev->radio_type != UNSET) { - v4l2_i2c_new_subdev(&dev->i2c_adap, "tuner", "tuner", - dev->radio_addr); - } - if (dev->tda9887_conf & TDA9887_PRESENT) { - unsigned short addrs[] = { 0x42, 0x43, 0x4a, 0x4b, - I2C_CLIENT_END }; + int has_demod = (dev->tda9887_conf & TDA9887_PRESENT); - v4l2_i2c_new_probed_subdev(&dev->i2c_adap, - "tuner", "tuner", addrs); - } - if (dev->tuner_addr != ADDR_UNSET) { + /* Note: radio tuner address is always filled in, + so we do not need to probe for a radio tuner device. */ + if (dev->radio_type != UNSET) v4l2_i2c_new_subdev(&dev->i2c_adap, - "tuner", "tuner", dev->tuner_addr); + "tuner", "tuner", dev->radio_addr); + if (has_demod) + v4l2_i2c_new_probed_subdev(&dev->i2c_adap, "tuner", + "tuner", v4l2_i2c_tuner_addrs(ADDRS_DEMOD)); + if (dev->tuner_addr == ADDR_UNSET) { + enum v4l2_i2c_tuner_type type = + has_demod ? ADDRS_TV_WITH_DEMOD : ADDRS_TV; + + v4l2_i2c_new_probed_subdev(&dev->i2c_adap, "tuner", + "tuner", v4l2_i2c_tuner_addrs(type)); } else { - unsigned short addrs[] = { - 0x42, 0x43, 0x4a, 0x4b, /* tda8290 */ - 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, - 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, - I2C_CLIENT_END - }; - - if (dev->tda9887_conf & TDA9887_PRESENT) { - v4l2_i2c_new_probed_subdev(&dev->i2c_adap, - "tuner", "tuner", addrs + 4); - } else { - v4l2_i2c_new_probed_subdev(&dev->i2c_adap, - "tuner", "tuner", addrs); - } + v4l2_i2c_new_subdev(&dev->i2c_adap, + "tuner", "tuner", dev->tuner_addr); } } saa7134_board_init2(dev); diff --git a/drivers/media/video/v4l2-common.c b/drivers/media/video/v4l2-common.c index 0f450a73477a..26e162f13f7f 100644 --- a/drivers/media/video/v4l2-common.c +++ b/drivers/media/video/v4l2-common.c @@ -991,4 +991,40 @@ struct v4l2_subdev *v4l2_i2c_new_probed_subdev(struct i2c_adapter *adapter, } EXPORT_SYMBOL_GPL(v4l2_i2c_new_probed_subdev); +/* Return a list of I2C tuner addresses to probe. Use only if the tuner + addresses are unknown. */ +const unsigned short *v4l2_i2c_tuner_addrs(enum v4l2_i2c_tuner_type type) +{ + static const unsigned short radio_addrs[] = { +#if defined(CONFIG_MEDIA_TUNER_TEA5761) || defined(CONFIG_MEDIA_TUNER_TEA5761_MODULE) + 0x10, +#endif + 0x60, + I2C_CLIENT_END + }; + static const unsigned short demod_addrs[] = { + 0x42, 0x43, 0x4a, 0x4b, + I2C_CLIENT_END + }; + static const unsigned short tv_addrs[] = { + 0x42, 0x43, 0x4a, 0x4b, /* tda8290 */ + 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, + 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, + I2C_CLIENT_END + }; + + switch (type) { + case ADDRS_RADIO: + return radio_addrs; + case ADDRS_DEMOD: + return demod_addrs; + case ADDRS_TV: + return tv_addrs; + case ADDRS_TV_WITH_DEMOD: + return tv_addrs + 4; + } + return NULL; +} +EXPORT_SYMBOL_GPL(v4l2_i2c_tuner_addrs); + #endif diff --git a/include/media/v4l2-common.h b/include/media/v4l2-common.h index 95e74f1874e1..0f864f8daaf2 100644 --- a/include/media/v4l2-common.h +++ b/include/media/v4l2-common.h @@ -150,6 +150,19 @@ struct v4l2_subdev *v4l2_i2c_new_probed_subdev(struct i2c_adapter *adapter, void v4l2_i2c_subdev_init(struct v4l2_subdev *sd, struct i2c_client *client, const struct v4l2_subdev_ops *ops); +enum v4l2_i2c_tuner_type { + ADDRS_RADIO, /* Radio tuner addresses */ + ADDRS_DEMOD, /* Demod tuner addresses */ + ADDRS_TV, /* TV tuner addresses */ + /* TV tuner addresses if demod is present, this excludes + addresses used by the demodulator from the list of + candidates. */ + ADDRS_TV_WITH_DEMOD, +}; +/* Return a list of I2C tuner addresses to probe. Use only if the tuner + addresses are unknown. */ +const unsigned short *v4l2_i2c_tuner_addrs(enum v4l2_i2c_tuner_type type); + /* ------------------------------------------------------------------------- */ /* Internal ioctls */ -- cgit v1.2.3 From 6ca187abb2fc1a52b2a8e0422f3ffce2e3bb7ad0 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Thu, 15 Jan 2009 05:53:18 -0300 Subject: V4L/DVB (10251): cx25840: add comments explaining what the init() does. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx25840/cx25840-core.c | 10 ++++++++++ include/media/cx25840.h | 12 ++++++++++++ 2 files changed, 22 insertions(+) (limited to 'drivers/media/video') diff --git a/drivers/media/video/cx25840/cx25840-core.c b/drivers/media/video/cx25840/cx25840-core.c index 25eb3bec9e5d..be467b4b9545 100644 --- a/drivers/media/video/cx25840/cx25840-core.c +++ b/drivers/media/video/cx25840/cx25840-core.c @@ -1101,6 +1101,16 @@ static void log_audio_status(struct i2c_client *client) /* ----------------------------------------------------------------------- */ +/* This init operation must be called to load the driver's firmware. + Without this the audio standard detection will fail and you will + only get mono. + + Since loading the firmware is often problematic when the driver is + compiled into the kernel I recommend postponing calling this function + until the first open of the video device. Another reason for + postponing it is that loading this firmware takes a long time (seconds) + due to the slow i2c bus speed. So it will speed up the boot process if + you can avoid loading the fw as long as the video device isn't used. */ static int cx25840_init(struct v4l2_subdev *sd, u32 val) { struct cx25840_state *state = to_state(sd); diff --git a/include/media/cx25840.h b/include/media/cx25840.h index db431d513f2f..2c3fbaa33f74 100644 --- a/include/media/cx25840.h +++ b/include/media/cx25840.h @@ -21,6 +21,18 @@ #ifndef _CX25840_H_ #define _CX25840_H_ +/* Note that the cx25840 driver requires that the bridge driver calls the + v4l2_subdev's init operation in order to load the driver's firmware. + Without this the audio standard detection will fail and you will + only get mono. + + Since loading the firmware is often problematic when the driver is + compiled into the kernel I recommend postponing calling this function + until the first open of the video device. Another reason for + postponing it is that loading this firmware takes a long time (seconds) + due to the slow i2c bus speed. So it will speed up the boot process if + you can avoid loading the fw as long as the video device isn't used. */ + enum cx25840_video_input { /* Composite video inputs In1-In8 */ CX25840_COMPOSITE1 = 1, -- cgit v1.2.3 From 8ed06fd4729d25959f6af8b7ce4e3888866bfe56 Mon Sep 17 00:00:00 2001 From: Robert Krakora Date: Sun, 18 Jan 2009 21:44:46 -0300 Subject: V4L/DVB (10255): em28xx: Clock (XCLK) Cleanup Clock (XCLK) Cleanup Signed-off-by: Robert Krakora Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/em28xx/em28xx-core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/em28xx/em28xx-core.c b/drivers/media/video/em28xx/em28xx-core.c index 94fb1b639a2e..3ac8ce0adec3 100644 --- a/drivers/media/video/em28xx/em28xx-core.c +++ b/drivers/media/video/em28xx/em28xx-core.c @@ -424,7 +424,7 @@ int em28xx_audio_analog_set(struct em28xx *dev) xclk = dev->board.xclk & 0x7f; if (!dev->mute) - xclk |= 0x80; + xclk |= EM28XX_XCLK_AUDIO_UNMUTE; ret = em28xx_write_reg(dev, EM28XX_R0F_XCLK, xclk); if (ret < 0) -- cgit v1.2.3 From 2cc3b6bff46129374ee31236f804637278c5f323 Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Fri, 16 Jan 2009 03:06:02 -0300 Subject: V4L/DVB (10258): pvrusb2: Issue VIDIOC_INT_INIT to v4l2 modules when they first attach It appears that various v4l-dvb drivers are changing to require explicit initialization before use. This change to the pvrusb2 driver implements an automatic issuance of VIDIOC_INT_INIT when a module is bound to the driver, thus conforming to the new behavior. Signed-off-by: Mike Isely Signed-off-by: Mauro Carvalho Chehab --- .../media/video/pvrusb2/pvrusb2-i2c-chips-v4l2.c | 23 ++++++++++++---------- drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.c | 14 +++++++++++++ drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.h | 1 + drivers/media/video/pvrusb2/pvrusb2-i2c-core.c | 2 +- 4 files changed, 29 insertions(+), 11 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/pvrusb2/pvrusb2-i2c-chips-v4l2.c b/drivers/media/video/pvrusb2/pvrusb2-i2c-chips-v4l2.c index 94a47718e88e..4cf980c49d01 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-i2c-chips-v4l2.c +++ b/drivers/media/video/pvrusb2/pvrusb2-i2c-chips-v4l2.c @@ -31,17 +31,19 @@ #define trace_i2c(...) pvr2_trace(PVR2_TRACE_I2C,__VA_ARGS__) -#define OP_STANDARD 0 -#define OP_AUDIOMODE 1 -#define OP_BCSH 2 -#define OP_VOLUME 3 -#define OP_FREQ 4 -#define OP_AUDIORATE 5 -#define OP_CROP 6 -#define OP_SIZE 7 -#define OP_LOG 8 +#define OP_INIT 0 /* MUST come first so it is run first */ +#define OP_STANDARD 1 +#define OP_AUDIOMODE 2 +#define OP_BCSH 3 +#define OP_VOLUME 4 +#define OP_FREQ 5 +#define OP_AUDIORATE 6 +#define OP_CROP 7 +#define OP_SIZE 8 +#define OP_LOG 9 static const struct pvr2_i2c_op * const ops[] = { + [OP_INIT] = &pvr2_i2c_op_v4l2_init, [OP_STANDARD] = &pvr2_i2c_op_v4l2_standard, [OP_AUDIOMODE] = &pvr2_i2c_op_v4l2_audiomode, [OP_BCSH] = &pvr2_i2c_op_v4l2_bcsh, @@ -56,7 +58,8 @@ void pvr2_i2c_probe(struct pvr2_hdw *hdw,struct pvr2_i2c_client *cp) { int id; id = cp->client->driver->id; - cp->ctl_mask = ((1 << OP_STANDARD) | + cp->ctl_mask = ((1 << OP_INIT) | + (1 << OP_STANDARD) | (1 << OP_AUDIOMODE) | (1 << OP_BCSH) | (1 << OP_VOLUME) | diff --git a/drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.c b/drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.c index 16bb11902a52..0f2885440f2f 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.c +++ b/drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.c @@ -25,6 +25,20 @@ #include #include +static void execute_init(struct pvr2_hdw *hdw) +{ + u32 dummy = 0; + pvr2_trace(PVR2_TRACE_CHIPS, "i2c v4l2 init"); + pvr2_i2c_core_cmd(hdw, VIDIOC_INT_INIT, &dummy); +} + + +const struct pvr2_i2c_op pvr2_i2c_op_v4l2_init = { + .update = execute_init, + .name = "v4l2_init", +}; + + static void set_standard(struct pvr2_hdw *hdw) { pvr2_trace(PVR2_TRACE_CHIPS,"i2c v4l2 set_standard"); diff --git a/drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.h b/drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.h index eb744a20610d..69a63f2a8a7b 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.h +++ b/drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.h @@ -24,6 +24,7 @@ #include "pvrusb2-i2c-core.h" +extern const struct pvr2_i2c_op pvr2_i2c_op_v4l2_init; extern const struct pvr2_i2c_op pvr2_i2c_op_v4l2_standard; extern const struct pvr2_i2c_op pvr2_i2c_op_v4l2_radio; extern const struct pvr2_i2c_op pvr2_i2c_op_v4l2_bcsh; diff --git a/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c b/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c index d6a35401fefb..57a024737722 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c +++ b/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c @@ -763,7 +763,7 @@ int pvr2_i2c_core_check_stale(struct pvr2_hdw *hdw) if (!(msk & pm)) continue; pm &= ~msk; opf = pvr2_i2c_get_op(idx); - if (!opf) continue; + if (!(opf && opf->check)) continue; if (opf->check(hdw)) { sm |= msk; } -- cgit v1.2.3 From 94b5ff9cf3edf06e0666fea87398a7fff98a15a4 Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Fri, 16 Jan 2009 03:09:34 -0300 Subject: V4L/DVB (10259): pvrusb2: Code module name directly in printk The name of the pvrusb2 module is not likely to ever change, and there are plenty of other places where the name is directly coded, so there is little utility in using a macro to infer the module name here. In addition, using that macro complicates other uses of the driver involving older kernels where this macro works differently. Yes I know for many places we don't have to worry about that. But my alternative is that I have to build special logic in the pvrusb2 standalone driver to special-case what is otherwise costmetic and that is just plain nuts for something as trivial as this, especially since this change does not at all have any compile time or run time impact on the driver. I'm just removing a nicety that didn't have a lot of value here to begin with. Signed-off-by: Mike Isely Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/pvrusb2/pvrusb2-main.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/pvrusb2/pvrusb2-main.c b/drivers/media/video/pvrusb2/pvrusb2-main.c index 9b3c874d96d6..8689ddb54420 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-main.c +++ b/drivers/media/video/pvrusb2/pvrusb2-main.c @@ -137,10 +137,10 @@ static int __init pvr_init(void) ret = usb_register(&pvr_driver); if (ret == 0) - printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" + printk(KERN_INFO "pvrusb2: " DRIVER_VERSION ":" DRIVER_DESC "\n"); if (pvrusb2_debug) - printk(KERN_INFO KBUILD_MODNAME ": Debug mask is %d (0x%x)\n", + printk(KERN_INFO "pvrusb2: Debug mask is %d (0x%x)\n", pvrusb2_debug,pvrusb2_debug); pvr2_trace(PVR2_TRACE_INIT,"pvr_init complete"); -- cgit v1.2.3 From c76b638ca20d6cbf91ee017c6f2afd7d3fcd57ff Mon Sep 17 00:00:00 2001 From: Antoine Jacquet Date: Sat, 17 Jan 2009 22:49:08 -0300 Subject: V4L/DVB (10263): zr364xx: add support for Aiptek DV T300 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Tested-by: Hámorszky Balázs Signed-off-by: Antoine Jacquet Signed-off-by: Mauro Carvalho Chehab --- Documentation/video4linux/zr364xx.txt | 1 + drivers/media/video/zr364xx.c | 1 + 2 files changed, 2 insertions(+) (limited to 'drivers/media/video') diff --git a/Documentation/video4linux/zr364xx.txt b/Documentation/video4linux/zr364xx.txt index 5c81e3ae6458..7f3d1955d214 100644 --- a/Documentation/video4linux/zr364xx.txt +++ b/Documentation/video4linux/zr364xx.txt @@ -65,3 +65,4 @@ Vendor Product Distributor Model 0x06d6 0x003b Trust Powerc@m 970Z 0x0a17 0x004e Pentax Optio 50 0x041e 0x405d Creative DiVi CAM 516 +0x08ca 0x2102 Aiptek DV T300 diff --git a/drivers/media/video/zr364xx.c b/drivers/media/video/zr364xx.c index 93023560f324..f2f8cdd71c46 100644 --- a/drivers/media/video/zr364xx.c +++ b/drivers/media/video/zr364xx.c @@ -96,6 +96,7 @@ static struct usb_device_id device_table[] = { {USB_DEVICE(0x06d6, 0x003b), .driver_info = METHOD0 }, {USB_DEVICE(0x0a17, 0x004e), .driver_info = METHOD2 }, {USB_DEVICE(0x041e, 0x405d), .driver_info = METHOD2 }, + {USB_DEVICE(0x08ca, 0x2102), .driver_info = METHOD2 }, {} /* Terminating entry */ }; -- cgit v1.2.3 From 96318d0cca02a91b22a2e1a1097ffeea0b3becae Mon Sep 17 00:00:00 2001 From: "Igor M. Liplianin" Date: Sat, 17 Jan 2009 12:11:20 -0300 Subject: V4L/DVB (10266): Add support for TurboSight TBS6920 DVB-S2 PCI-e card. TurboSight TBS6920 DVB-S2 PCI-e card contains cx23885 PCI-e bridge and cx24116 demodulator. http://www.linuxtv.org/wiki/index.php/TBS_6920 The card tested by me (Igor). Signed-off-by: Igor M. Liplianin Signed-off-by: Mauro Carvalho Chehab --- Documentation/video4linux/CARDLIST.cx23885 | 1 + drivers/media/video/cx23885/cx23885-cards.c | 18 ++++++++++++++++++ drivers/media/video/cx23885/cx23885-dvb.c | 29 +++++++++++++++++++++++++++++ drivers/media/video/cx23885/cx23885.h | 1 + 4 files changed, 49 insertions(+) (limited to 'drivers/media/video') diff --git a/Documentation/video4linux/CARDLIST.cx23885 b/Documentation/video4linux/CARDLIST.cx23885 index 35ea130e9898..3af13a06ee6e 100644 --- a/Documentation/video4linux/CARDLIST.cx23885 +++ b/Documentation/video4linux/CARDLIST.cx23885 @@ -12,3 +12,4 @@ 11 -> DViCO FusionHDTV DVB-T Dual Express [18ac:db78] 12 -> Leadtek Winfast PxDVR3200 H [107d:6681] 13 -> Compro VideoMate E650F [185b:e800] + 14 -> TurboSight TBS 6920 [6920:8888] diff --git a/drivers/media/video/cx23885/cx23885-cards.c b/drivers/media/video/cx23885/cx23885-cards.c index caa098beeecf..0b050bc88ef5 100644 --- a/drivers/media/video/cx23885/cx23885-cards.c +++ b/drivers/media/video/cx23885/cx23885-cards.c @@ -162,6 +162,10 @@ struct cx23885_board cx23885_boards[] = { .name = "Compro VideoMate E650F", .portc = CX23885_MPEG_DVB, }, + [CX23885_BOARD_TBS_6920] = { + .name = "TurboSight TBS 6920", + .portb = CX23885_MPEG_DVB, + }, }; const unsigned int cx23885_bcount = ARRAY_SIZE(cx23885_boards); @@ -245,6 +249,10 @@ struct cx23885_subid cx23885_subids[] = { .subvendor = 0x185b, .subdevice = 0xe800, .card = CX23885_BOARD_COMPRO_VIDEOMATE_E650F, + }, { + .subvendor = 0x6920, + .subdevice = 0x8888, + .card = CX23885_BOARD_TBS_6920, }, }; const unsigned int cx23885_idcount = ARRAY_SIZE(cx23885_subids); @@ -552,6 +560,11 @@ void cx23885_gpio_setup(struct cx23885_dev *dev) mdelay(20); cx_set(GP0_IO, 0x00040004); break; + case CX23885_BOARD_TBS_6920: + cx_write(MC417_CTL, 0x00000036); + cx_write(MC417_OEN, 0x00001000); + cx_write(MC417_RWD, 0x00001800); + break; } } @@ -632,6 +645,11 @@ void cx23885_card_setup(struct cx23885_dev *dev) ts2->ts_clk_en_val = 0x1; /* Enable TS_CLK */ ts2->src_sel_val = CX23885_SRC_SEL_PARALLEL_MPEG_VIDEO; break; + case CX23885_BOARD_TBS_6920: + ts1->gen_ctrl_val = 0x5; /* Parallel */ + ts1->ts_clk_en_val = 0x1; /* Enable TS_CLK */ + ts1->src_sel_val = CX23885_SRC_SEL_PARALLEL_MPEG_VIDEO; + break; case CX23885_BOARD_HAUPPAUGE_HVR1250: case CX23885_BOARD_HAUPPAUGE_HVR1500: case CX23885_BOARD_HAUPPAUGE_HVR1500Q: diff --git a/drivers/media/video/cx23885/cx23885-dvb.c b/drivers/media/video/cx23885/cx23885-dvb.c index 1c454128a9df..3e0b04074e55 100644 --- a/drivers/media/video/cx23885/cx23885-dvb.c +++ b/drivers/media/video/cx23885/cx23885-dvb.c @@ -43,6 +43,7 @@ #include "dib7000p.h" #include "dibx000_common.h" #include "zl10353.h" +#include "cx24116.h" static unsigned int debug; @@ -308,6 +309,24 @@ static struct zl10353_config dvico_fusionhdtv_xc3028 = { .no_tuner = 1, }; +static int tbs_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage) +{ + struct cx23885_tsport *port = fe->dvb->priv; + struct cx23885_dev *dev = port->dev; + + if (voltage == SEC_VOLTAGE_18) + cx_write(MC417_RWD, 0x00001e00);/* GPIO-13 high */ + else if (voltage == SEC_VOLTAGE_13) + cx_write(MC417_RWD, 0x00001a00);/* GPIO-13 low */ + else + cx_write(MC417_RWD, 0x00001800);/* GPIO-12 low */ + return 0; +} + +static struct cx24116_config tbs_cx24116_config = { + .demod_address = 0x05, +}; + static int dvb_register(struct cx23885_tsport *port) { struct cx23885_dev *dev = port->dev; @@ -525,6 +544,16 @@ static int dvb_register(struct cx23885_tsport *port) if (fe != NULL && fe->ops.tuner_ops.set_config != NULL) fe->ops.tuner_ops.set_config(fe, &ctl); } + break; + case CX23885_BOARD_TBS_6920: + i2c_bus = &dev->i2c_bus[0]; + + fe0->dvb.frontend = dvb_attach(cx24116_attach, + &tbs_cx24116_config, + &i2c_bus->i2c_adap); + if (fe0->dvb.frontend != NULL) + fe0->dvb.frontend->ops.set_voltage = tbs_set_voltage; + break; default: printk(KERN_INFO "%s: The frontend of your DVB/ATSC card " diff --git a/drivers/media/video/cx23885/cx23885.h b/drivers/media/video/cx23885/cx23885.h index 67828029fc69..b4f23238598f 100644 --- a/drivers/media/video/cx23885/cx23885.h +++ b/drivers/media/video/cx23885/cx23885.h @@ -67,6 +67,7 @@ #define CX23885_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL_EXP 11 #define CX23885_BOARD_LEADTEK_WINFAST_PXDVR3200_H 12 #define CX23885_BOARD_COMPRO_VIDEOMATE_E650F 13 +#define CX23885_BOARD_TBS_6920 14 /* Currently unsupported by the driver: PAL/H, NTSC/Kr, SECAM B/G/H/LC */ #define CX23885_NORMS (\ -- cgit v1.2.3 From 579943f5487baa7f9fd8e3189a4f357d6b06c76d Mon Sep 17 00:00:00 2001 From: "Igor M. Liplianin" Date: Sat, 17 Jan 2009 12:18:26 -0300 Subject: V4L/DVB (10267): Add support for TeVii S470 DVB-S2 PCI-e card. TeVii S470 DVB-S2 PCI-e card contains cx23885 PCI-e bridge and cx24116 demodulator. http://www.linuxtv.org/wiki/index.php/TeVii_S470 The card tested by me (Igor). Signed-off-by: Igor M. Liplianin Signed-off-by: Mauro Carvalho Chehab --- Documentation/video4linux/CARDLIST.cx23885 | 1 + drivers/media/video/cx23885/cx23885-cards.c | 10 ++++++++++ drivers/media/video/cx23885/cx23885-dvb.c | 14 ++++++++++++++ drivers/media/video/cx23885/cx23885.h | 1 + 4 files changed, 26 insertions(+) (limited to 'drivers/media/video') diff --git a/Documentation/video4linux/CARDLIST.cx23885 b/Documentation/video4linux/CARDLIST.cx23885 index 3af13a06ee6e..43d290ea75bf 100644 --- a/Documentation/video4linux/CARDLIST.cx23885 +++ b/Documentation/video4linux/CARDLIST.cx23885 @@ -13,3 +13,4 @@ 12 -> Leadtek Winfast PxDVR3200 H [107d:6681] 13 -> Compro VideoMate E650F [185b:e800] 14 -> TurboSight TBS 6920 [6920:8888] + 15 -> TeVii S470 [d470:9022] diff --git a/drivers/media/video/cx23885/cx23885-cards.c b/drivers/media/video/cx23885/cx23885-cards.c index 0b050bc88ef5..dbc59d26f6f6 100644 --- a/drivers/media/video/cx23885/cx23885-cards.c +++ b/drivers/media/video/cx23885/cx23885-cards.c @@ -166,6 +166,10 @@ struct cx23885_board cx23885_boards[] = { .name = "TurboSight TBS 6920", .portb = CX23885_MPEG_DVB, }, + [CX23885_BOARD_TEVII_S470] = { + .name = "TeVii S470", + .portb = CX23885_MPEG_DVB, + }, }; const unsigned int cx23885_bcount = ARRAY_SIZE(cx23885_boards); @@ -253,6 +257,10 @@ struct cx23885_subid cx23885_subids[] = { .subvendor = 0x6920, .subdevice = 0x8888, .card = CX23885_BOARD_TBS_6920, + }, { + .subvendor = 0xd470, + .subdevice = 0x9022, + .card = CX23885_BOARD_TEVII_S470, }, }; const unsigned int cx23885_idcount = ARRAY_SIZE(cx23885_subids); @@ -561,6 +569,7 @@ void cx23885_gpio_setup(struct cx23885_dev *dev) cx_set(GP0_IO, 0x00040004); break; case CX23885_BOARD_TBS_6920: + case CX23885_BOARD_TEVII_S470: cx_write(MC417_CTL, 0x00000036); cx_write(MC417_OEN, 0x00001000); cx_write(MC417_RWD, 0x00001800); @@ -645,6 +654,7 @@ void cx23885_card_setup(struct cx23885_dev *dev) ts2->ts_clk_en_val = 0x1; /* Enable TS_CLK */ ts2->src_sel_val = CX23885_SRC_SEL_PARALLEL_MPEG_VIDEO; break; + case CX23885_BOARD_TEVII_S470: case CX23885_BOARD_TBS_6920: ts1->gen_ctrl_val = 0x5; /* Parallel */ ts1->ts_clk_en_val = 0x1; /* Enable TS_CLK */ diff --git a/drivers/media/video/cx23885/cx23885-dvb.c b/drivers/media/video/cx23885/cx23885-dvb.c index 3e0b04074e55..a6b62a7bf618 100644 --- a/drivers/media/video/cx23885/cx23885-dvb.c +++ b/drivers/media/video/cx23885/cx23885-dvb.c @@ -327,6 +327,10 @@ static struct cx24116_config tbs_cx24116_config = { .demod_address = 0x05, }; +static struct cx24116_config tevii_cx24116_config = { + .demod_address = 0x55, +}; + static int dvb_register(struct cx23885_tsport *port) { struct cx23885_dev *dev = port->dev; @@ -554,6 +558,16 @@ static int dvb_register(struct cx23885_tsport *port) if (fe0->dvb.frontend != NULL) fe0->dvb.frontend->ops.set_voltage = tbs_set_voltage; + break; + case CX23885_BOARD_TEVII_S470: + i2c_bus = &dev->i2c_bus[1]; + + fe0->dvb.frontend = dvb_attach(cx24116_attach, + &tevii_cx24116_config, + &i2c_bus->i2c_adap); + if (fe0->dvb.frontend != NULL) + fe0->dvb.frontend->ops.set_voltage = tbs_set_voltage; + break; default: printk(KERN_INFO "%s: The frontend of your DVB/ATSC card " diff --git a/drivers/media/video/cx23885/cx23885.h b/drivers/media/video/cx23885/cx23885.h index b4f23238598f..01856fb48a40 100644 --- a/drivers/media/video/cx23885/cx23885.h +++ b/drivers/media/video/cx23885/cx23885.h @@ -68,6 +68,7 @@ #define CX23885_BOARD_LEADTEK_WINFAST_PXDVR3200_H 12 #define CX23885_BOARD_COMPRO_VIDEOMATE_E650F 13 #define CX23885_BOARD_TBS_6920 14 +#define CX23885_BOARD_TEVII_S470 15 /* Currently unsupported by the driver: PAL/H, NTSC/Kr, SECAM B/G/H/LC */ #define CX23885_NORMS (\ -- cgit v1.2.3 From c9b8b04b267f9a7e472daa06cdf6d4963d503d1f Mon Sep 17 00:00:00 2001 From: "Igor M. Liplianin" Date: Sat, 17 Jan 2009 12:23:31 -0300 Subject: V4L/DVB (10269): Add support for DVBWorld DVBS2 PCI-e 2005. DVBWorld DVBS2 PCI-e 2005 card contains cx23885 PCI-e bridge and cx24116 demodulator. http://www.linuxtv.org/wiki/index.php/DVBWorld_DVB-S2_2005_PCI-Express_Card The card tested by me (Igor). Signed-off-by: Igor M. Liplianin Signed-off-by: Mauro Carvalho Chehab --- Documentation/video4linux/CARDLIST.cx23885 | 1 + drivers/media/video/cx23885/cx23885-cards.c | 9 +++++++++ drivers/media/video/cx23885/cx23885-dvb.c | 11 +++++++++++ drivers/media/video/cx23885/cx23885.h | 1 + 4 files changed, 22 insertions(+) (limited to 'drivers/media/video') diff --git a/Documentation/video4linux/CARDLIST.cx23885 b/Documentation/video4linux/CARDLIST.cx23885 index 43d290ea75bf..5937ff958f04 100644 --- a/Documentation/video4linux/CARDLIST.cx23885 +++ b/Documentation/video4linux/CARDLIST.cx23885 @@ -14,3 +14,4 @@ 13 -> Compro VideoMate E650F [185b:e800] 14 -> TurboSight TBS 6920 [6920:8888] 15 -> TeVii S470 [d470:9022] + 16 -> DVBWorld DVB-S2 2005 [0001:2005] diff --git a/drivers/media/video/cx23885/cx23885-cards.c b/drivers/media/video/cx23885/cx23885-cards.c index dbc59d26f6f6..7ff339a2e3f2 100644 --- a/drivers/media/video/cx23885/cx23885-cards.c +++ b/drivers/media/video/cx23885/cx23885-cards.c @@ -170,6 +170,10 @@ struct cx23885_board cx23885_boards[] = { .name = "TeVii S470", .portb = CX23885_MPEG_DVB, }, + [CX23885_BOARD_DVBWORLD_2005] = { + .name = "DVBWorld DVB-S2 2005", + .portb = CX23885_MPEG_DVB, + }, }; const unsigned int cx23885_bcount = ARRAY_SIZE(cx23885_boards); @@ -261,6 +265,10 @@ struct cx23885_subid cx23885_subids[] = { .subvendor = 0xd470, .subdevice = 0x9022, .card = CX23885_BOARD_TEVII_S470, + }, { + .subvendor = 0x0001, + .subdevice = 0x2005, + .card = CX23885_BOARD_DVBWORLD_2005, }, }; const unsigned int cx23885_idcount = ARRAY_SIZE(cx23885_subids); @@ -656,6 +664,7 @@ void cx23885_card_setup(struct cx23885_dev *dev) break; case CX23885_BOARD_TEVII_S470: case CX23885_BOARD_TBS_6920: + case CX23885_BOARD_DVBWORLD_2005: ts1->gen_ctrl_val = 0x5; /* Parallel */ ts1->ts_clk_en_val = 0x1; /* Enable TS_CLK */ ts1->src_sel_val = CX23885_SRC_SEL_PARALLEL_MPEG_VIDEO; diff --git a/drivers/media/video/cx23885/cx23885-dvb.c b/drivers/media/video/cx23885/cx23885-dvb.c index a6b62a7bf618..14a6540b826c 100644 --- a/drivers/media/video/cx23885/cx23885-dvb.c +++ b/drivers/media/video/cx23885/cx23885-dvb.c @@ -331,6 +331,10 @@ static struct cx24116_config tevii_cx24116_config = { .demod_address = 0x55, }; +static struct cx24116_config dvbworld_cx24116_config = { + .demod_address = 0x05, +}; + static int dvb_register(struct cx23885_tsport *port) { struct cx23885_dev *dev = port->dev; @@ -569,6 +573,13 @@ static int dvb_register(struct cx23885_tsport *port) fe0->dvb.frontend->ops.set_voltage = tbs_set_voltage; break; + case CX23885_BOARD_DVBWORLD_2005: + i2c_bus = &dev->i2c_bus[1]; + + fe0->dvb.frontend = dvb_attach(cx24116_attach, + &dvbworld_cx24116_config, + &i2c_bus->i2c_adap); + break; default: printk(KERN_INFO "%s: The frontend of your DVB/ATSC card " " isn't supported yet\n", diff --git a/drivers/media/video/cx23885/cx23885.h b/drivers/media/video/cx23885/cx23885.h index 01856fb48a40..37a88b1683c3 100644 --- a/drivers/media/video/cx23885/cx23885.h +++ b/drivers/media/video/cx23885/cx23885.h @@ -69,6 +69,7 @@ #define CX23885_BOARD_COMPRO_VIDEOMATE_E650F 13 #define CX23885_BOARD_TBS_6920 14 #define CX23885_BOARD_TEVII_S470 15 +#define CX23885_BOARD_DVBWORLD_2005 16 /* Currently unsupported by the driver: PAL/H, NTSC/Kr, SECAM B/G/H/LC */ #define CX23885_NORMS (\ -- cgit v1.2.3 From b960074fec573fb1b226d9e2686ce51be807cdf1 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sun, 18 Jan 2009 19:59:11 -0300 Subject: V4L/DVB (10271): saa7146: convert to video_ioctl2. The conversion to video_ioctl2 is the first phase to converting this driver to the latest v4l2 framework. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/common/saa7146_fops.c | 36 +- drivers/media/common/saa7146_video.c | 1258 ++++++++++++++++------------------ drivers/media/dvb/ttpci/av7110_v4l.c | 479 +++++++------ drivers/media/dvb/ttpci/budget-av.c | 88 +-- drivers/media/video/hexium_gemini.c | 292 ++++---- drivers/media/video/hexium_orion.c | 103 ++- drivers/media/video/mxb.c | 641 ++++++++--------- include/media/saa7146_vv.h | 17 +- 8 files changed, 1404 insertions(+), 1510 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/common/saa7146_fops.c b/drivers/media/common/saa7146_fops.c index cf06f4d10ad4..4a27d4eda628 100644 --- a/drivers/media/common/saa7146_fops.c +++ b/drivers/media/common/saa7146_fops.c @@ -308,14 +308,6 @@ static int fops_release(struct file *file) return 0; } -static long fops_ioctl(struct file *file, unsigned int cmd, unsigned long arg) -{ -/* - DEB_EE(("file:%p, cmd:%d, arg:%li\n", file, cmd, arg)); -*/ - return video_usercopy(file, cmd, arg, saa7146_video_do_ioctl); -} - static int fops_mmap(struct file *file, struct vm_area_struct * vma) { struct saa7146_fh *fh = file->private_data; @@ -425,7 +417,7 @@ static const struct v4l2_file_operations video_fops = .write = fops_write, .poll = fops_poll, .mmap = fops_mmap, - .ioctl = fops_ioctl, + .ioctl = video_ioctl2, }; static void vv_callback(struct saa7146_dev *dev, unsigned long status) @@ -452,19 +444,16 @@ static void vv_callback(struct saa7146_dev *dev, unsigned long status) } } -static struct video_device device_template = -{ - .fops = &video_fops, - .minor = -1, -}; - int saa7146_vv_init(struct saa7146_dev* dev, struct saa7146_ext_vv *ext_vv) { - struct saa7146_vv *vv = kzalloc (sizeof(struct saa7146_vv),GFP_KERNEL); - if( NULL == vv ) { + struct saa7146_vv *vv = kzalloc(sizeof(struct saa7146_vv), GFP_KERNEL); + + if (vv == NULL) { ERR(("out of memory. aborting.\n")); return -1; } + ext_vv->ops = saa7146_video_ioctl_ops; + ext_vv->core_ops = &saa7146_video_ioctl_ops; DEB_EE(("dev:%p\n",dev)); @@ -521,6 +510,7 @@ int saa7146_register_device(struct video_device **vid, struct saa7146_dev* dev, { struct saa7146_vv *vv = dev->vv_data; struct video_device *vfd; + int err; DEB_EE(("dev:%p, name:'%s', type:%d\n",dev,name,type)); @@ -529,16 +519,18 @@ int saa7146_register_device(struct video_device **vid, struct saa7146_dev* dev, if (vfd == NULL) return -ENOMEM; - memcpy(vfd, &device_template, sizeof(struct video_device)); - strlcpy(vfd->name, name, sizeof(vfd->name)); + vfd->fops = &video_fops; + vfd->ioctl_ops = dev->ext_vv_data ? &dev->ext_vv_data->ops : + &saa7146_video_ioctl_ops; vfd->release = video_device_release; + strlcpy(vfd->name, name, sizeof(vfd->name)); video_set_drvdata(vfd, dev); - // fixme: -1 should be an insmod parameter *for the extension* (like "video_nr"); - if (video_register_device(vfd, type, -1) < 0) { + err = video_register_device(vfd, type, -1); + if (err < 0) { ERR(("cannot register v4l2 device. skipping.\n")); video_device_release(vfd); - return -1; + return err; } if( VFL_TYPE_GRABBER == type ) { diff --git a/drivers/media/common/saa7146_video.c b/drivers/media/common/saa7146_video.c index 47fee05eaefb..91b7a4def46c 100644 --- a/drivers/media/common/saa7146_video.c +++ b/drivers/media/common/saa7146_video.c @@ -97,172 +97,13 @@ struct saa7146_format* format_by_fourcc(struct saa7146_dev *dev, int fourcc) return NULL; } -static int g_fmt(struct saa7146_fh *fh, struct v4l2_format *f) -{ - struct saa7146_dev *dev = fh->dev; - DEB_EE(("dev:%p, fh:%p\n",dev,fh)); - - switch (f->type) { - case V4L2_BUF_TYPE_VIDEO_CAPTURE: - f->fmt.pix = fh->video_fmt; - return 0; - case V4L2_BUF_TYPE_VIDEO_OVERLAY: - f->fmt.win = fh->ov.win; - return 0; - case V4L2_BUF_TYPE_VBI_CAPTURE: - { - f->fmt.vbi = fh->vbi_fmt; - return 0; - } - default: - DEB_D(("invalid format type '%d'.\n",f->type)); - return -EINVAL; - } -} - -static int try_win(struct saa7146_dev *dev, struct v4l2_window *win) -{ - struct saa7146_vv *vv = dev->vv_data; - enum v4l2_field field; - int maxw, maxh; - - DEB_EE(("dev:%p\n",dev)); - - if (NULL == vv->ov_fb.base) { - DEB_D(("no fb base set.\n")); - return -EINVAL; - } - if (NULL == vv->ov_fmt) { - DEB_D(("no fb fmt set.\n")); - return -EINVAL; - } - if (win->w.width < 48 || win->w.height < 32) { - DEB_D(("min width/height. (%d,%d)\n",win->w.width,win->w.height)); - return -EINVAL; - } - if (win->clipcount > 16) { - DEB_D(("clipcount too big.\n")); - return -EINVAL; - } - - field = win->field; - maxw = vv->standard->h_max_out; - maxh = vv->standard->v_max_out; - - if (V4L2_FIELD_ANY == field) { - field = (win->w.height > maxh/2) - ? V4L2_FIELD_INTERLACED - : V4L2_FIELD_TOP; - } - switch (field) { - case V4L2_FIELD_TOP: - case V4L2_FIELD_BOTTOM: - case V4L2_FIELD_ALTERNATE: - maxh = maxh / 2; - break; - case V4L2_FIELD_INTERLACED: - break; - default: { - DEB_D(("no known field mode '%d'.\n",field)); - return -EINVAL; - } - } - - win->field = field; - if (win->w.width > maxw) - win->w.width = maxw; - if (win->w.height > maxh) - win->w.height = maxh; - - return 0; -} - -static int try_fmt(struct saa7146_fh *fh, struct v4l2_format *f) -{ - struct saa7146_dev *dev = fh->dev; - struct saa7146_vv *vv = dev->vv_data; - int err; - - switch (f->type) { - case V4L2_BUF_TYPE_VIDEO_CAPTURE: - { - struct saa7146_format *fmt; - enum v4l2_field field; - int maxw, maxh; - int calc_bpl; - - DEB_EE(("V4L2_BUF_TYPE_VIDEO_CAPTURE: dev:%p, fh:%p\n",dev,fh)); - - fmt = format_by_fourcc(dev,f->fmt.pix.pixelformat); - if (NULL == fmt) { - return -EINVAL; - } - - field = f->fmt.pix.field; - maxw = vv->standard->h_max_out; - maxh = vv->standard->v_max_out; - - if (V4L2_FIELD_ANY == field) { - field = (f->fmt.pix.height > maxh/2) - ? V4L2_FIELD_INTERLACED - : V4L2_FIELD_BOTTOM; - } - switch (field) { - case V4L2_FIELD_ALTERNATE: { - vv->last_field = V4L2_FIELD_TOP; - maxh = maxh / 2; - break; - } - case V4L2_FIELD_TOP: - case V4L2_FIELD_BOTTOM: - vv->last_field = V4L2_FIELD_INTERLACED; - maxh = maxh / 2; - break; - case V4L2_FIELD_INTERLACED: - vv->last_field = V4L2_FIELD_INTERLACED; - break; - default: { - DEB_D(("no known field mode '%d'.\n",field)); - return -EINVAL; - } - } - - f->fmt.pix.field = field; - if (f->fmt.pix.width > maxw) - f->fmt.pix.width = maxw; - if (f->fmt.pix.height > maxh) - f->fmt.pix.height = maxh; - - calc_bpl = (f->fmt.pix.width * fmt->depth)/8; - - if (f->fmt.pix.bytesperline < calc_bpl) - f->fmt.pix.bytesperline = calc_bpl; - - if (f->fmt.pix.bytesperline > (2*PAGE_SIZE * fmt->depth)/8) /* arbitrary constraint */ - f->fmt.pix.bytesperline = calc_bpl; - - f->fmt.pix.sizeimage = f->fmt.pix.bytesperline * f->fmt.pix.height; - DEB_D(("w:%d, h:%d, bytesperline:%d, sizeimage:%d\n",f->fmt.pix.width,f->fmt.pix.height,f->fmt.pix.bytesperline,f->fmt.pix.sizeimage)); - - return 0; - } - case V4L2_BUF_TYPE_VIDEO_OVERLAY: - DEB_EE(("V4L2_BUF_TYPE_VIDEO_OVERLAY: dev:%p, fh:%p\n",dev,fh)); - err = try_win(dev,&f->fmt.win); - if (0 != err) { - return err; - } - return 0; - default: - DEB_EE(("unknown format type '%d'\n",f->type)); - return -EINVAL; - } -} +static int vidioc_try_fmt_vid_overlay(struct file *file, void *fh, struct v4l2_format *f); int saa7146_start_preview(struct saa7146_fh *fh) { struct saa7146_dev *dev = fh->dev; struct saa7146_vv *vv = dev->vv_data; + struct v4l2_format fmt; int ret = 0, err = 0; DEB_EE(("dev:%p, fh:%p\n",dev,fh)); @@ -294,12 +135,13 @@ int saa7146_start_preview(struct saa7146_fh *fh) return -EBUSY; } - err = try_win(dev,&fh->ov.win); + fmt.fmt.win = fh->ov.win; + err = vidioc_try_fmt_vid_overlay(NULL, fh, &fmt); if (0 != err) { saa7146_res_free(vv->video_fh, RESOURCE_DMA1_HPS|RESOURCE_DMA2_CLP); return -EBUSY; } - + fh->ov.win = fmt.fmt.win; vv->ov_data = &fh->ov; DEB_D(("%dx%d+%d+%d %s field=%s\n", @@ -355,58 +197,6 @@ int saa7146_stop_preview(struct saa7146_fh *fh) } EXPORT_SYMBOL_GPL(saa7146_stop_preview); -static int s_fmt(struct saa7146_fh *fh, struct v4l2_format *f) -{ - struct saa7146_dev *dev = fh->dev; - struct saa7146_vv *vv = dev->vv_data; - - int err; - - switch (f->type) { - case V4L2_BUF_TYPE_VIDEO_CAPTURE: - DEB_EE(("V4L2_BUF_TYPE_VIDEO_CAPTURE: dev:%p, fh:%p\n",dev,fh)); - if (IS_CAPTURE_ACTIVE(fh) != 0) { - DEB_EE(("streaming capture is active\n")); - return -EBUSY; - } - err = try_fmt(fh,f); - if (0 != err) - return err; - fh->video_fmt = f->fmt.pix; - DEB_EE(("set to pixelformat '%4.4s'\n",(char *)&fh->video_fmt.pixelformat)); - return 0; - case V4L2_BUF_TYPE_VIDEO_OVERLAY: - DEB_EE(("V4L2_BUF_TYPE_VIDEO_OVERLAY: dev:%p, fh:%p\n",dev,fh)); - err = try_win(dev,&f->fmt.win); - if (0 != err) - return err; - mutex_lock(&dev->lock); - fh->ov.win = f->fmt.win; - fh->ov.nclips = f->fmt.win.clipcount; - if (fh->ov.nclips > 16) - fh->ov.nclips = 16; - if (copy_from_user(fh->ov.clips,f->fmt.win.clips,sizeof(struct v4l2_clip)*fh->ov.nclips)) { - mutex_unlock(&dev->lock); - return -EFAULT; - } - - /* fh->ov.fh is used to indicate that we have valid overlay informations, too */ - fh->ov.fh = fh; - - mutex_unlock(&dev->lock); - - /* check if our current overlay is active */ - if (IS_OVERLAY_ACTIVE(fh) != 0) { - saa7146_stop_preview(fh); - saa7146_start_preview(fh); - } - return 0; - default: - DEB_D(("unknown format type '%d'\n",f->type)); - return -EINVAL; - } -} - /********************************************************************************/ /* device controls */ @@ -463,132 +253,6 @@ static struct v4l2_queryctrl* ctrl_by_id(int id) return NULL; } -static int get_control(struct saa7146_fh *fh, struct v4l2_control *c) -{ - struct saa7146_dev *dev = fh->dev; - struct saa7146_vv *vv = dev->vv_data; - - const struct v4l2_queryctrl* ctrl; - u32 value = 0; - - ctrl = ctrl_by_id(c->id); - if (NULL == ctrl) - return -EINVAL; - switch (c->id) { - case V4L2_CID_BRIGHTNESS: - value = saa7146_read(dev, BCS_CTRL); - c->value = 0xff & (value >> 24); - DEB_D(("V4L2_CID_BRIGHTNESS: %d\n",c->value)); - break; - case V4L2_CID_CONTRAST: - value = saa7146_read(dev, BCS_CTRL); - c->value = 0x7f & (value >> 16); - DEB_D(("V4L2_CID_CONTRAST: %d\n",c->value)); - break; - case V4L2_CID_SATURATION: - value = saa7146_read(dev, BCS_CTRL); - c->value = 0x7f & (value >> 0); - DEB_D(("V4L2_CID_SATURATION: %d\n",c->value)); - break; - case V4L2_CID_VFLIP: - c->value = vv->vflip; - DEB_D(("V4L2_CID_VFLIP: %d\n",c->value)); - break; - case V4L2_CID_HFLIP: - c->value = vv->hflip; - DEB_D(("V4L2_CID_HFLIP: %d\n",c->value)); - break; - default: - return -EINVAL; - } - - return 0; -} - -static int set_control(struct saa7146_fh *fh, struct v4l2_control *c) -{ - struct saa7146_dev *dev = fh->dev; - struct saa7146_vv *vv = dev->vv_data; - - const struct v4l2_queryctrl* ctrl; - - ctrl = ctrl_by_id(c->id); - if (NULL == ctrl) { - DEB_D(("unknown control %d\n",c->id)); - return -EINVAL; - } - - mutex_lock(&dev->lock); - - switch (ctrl->type) { - case V4L2_CTRL_TYPE_BOOLEAN: - case V4L2_CTRL_TYPE_MENU: - case V4L2_CTRL_TYPE_INTEGER: - if (c->value < ctrl->minimum) - c->value = ctrl->minimum; - if (c->value > ctrl->maximum) - c->value = ctrl->maximum; - break; - default: - /* nothing */; - }; - - switch (c->id) { - case V4L2_CID_BRIGHTNESS: { - u32 value = saa7146_read(dev, BCS_CTRL); - value &= 0x00ffffff; - value |= (c->value << 24); - saa7146_write(dev, BCS_CTRL, value); - saa7146_write(dev, MC2, MASK_22 | MASK_06 ); - break; - } - case V4L2_CID_CONTRAST: { - u32 value = saa7146_read(dev, BCS_CTRL); - value &= 0xff00ffff; - value |= (c->value << 16); - saa7146_write(dev, BCS_CTRL, value); - saa7146_write(dev, MC2, MASK_22 | MASK_06 ); - break; - } - case V4L2_CID_SATURATION: { - u32 value = saa7146_read(dev, BCS_CTRL); - value &= 0xffffff00; - value |= (c->value << 0); - saa7146_write(dev, BCS_CTRL, value); - saa7146_write(dev, MC2, MASK_22 | MASK_06 ); - break; - } - case V4L2_CID_HFLIP: - /* fixme: we can support changing VFLIP and HFLIP here... */ - if (IS_CAPTURE_ACTIVE(fh) != 0) { - DEB_D(("V4L2_CID_HFLIP while active capture.\n")); - mutex_unlock(&dev->lock); - return -EINVAL; - } - vv->hflip = c->value; - break; - case V4L2_CID_VFLIP: - if (IS_CAPTURE_ACTIVE(fh) != 0) { - DEB_D(("V4L2_CID_VFLIP while active capture.\n")); - mutex_unlock(&dev->lock); - return -EINVAL; - } - vv->vflip = c->value; - break; - default: { - mutex_unlock(&dev->lock); - return -EINVAL; - } - } - mutex_unlock(&dev->lock); - - if (IS_OVERLAY_ACTIVE(fh) != 0) { - saa7146_stop_preview(fh); - saa7146_start_preview(fh); - } - return 0; -} - /********************************************************************************/ /* common pagetable functions */ @@ -829,231 +493,451 @@ static int video_end(struct saa7146_fh *fh, struct file *file) return 0; } -/* - * This function is _not_ called directly, but from - * video_generic_ioctl (and maybe others). userspace - * copying is done already, arg is a kernel pointer. - */ +static int vidioc_querycap(struct file *file, void *fh, struct v4l2_capability *cap) +{ + struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev; + + strcpy((char *)cap->driver, "saa7146 v4l2"); + strlcpy((char *)cap->card, dev->ext->name, sizeof(cap->card)); + sprintf((char *)cap->bus_info, "PCI:%s", pci_name(dev->pci)); + cap->version = SAA7146_VERSION_CODE; + cap->capabilities = + V4L2_CAP_VIDEO_CAPTURE | + V4L2_CAP_VIDEO_OVERLAY | + V4L2_CAP_READWRITE | + V4L2_CAP_STREAMING; + cap->capabilities |= dev->ext_vv_data->capabilities; + return 0; +} -long saa7146_video_do_ioctl(struct file *file, unsigned int cmd, void *arg) +static int vidioc_g_fbuf(struct file *file, void *fh, struct v4l2_framebuffer *fb) { - struct saa7146_fh *fh = file->private_data; - struct saa7146_dev *dev = fh->dev; + struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev; struct saa7146_vv *vv = dev->vv_data; - long err = 0; - int result = 0, ee = 0; + *fb = vv->ov_fb; + fb->capability = V4L2_FBUF_CAP_LIST_CLIPPING; + return 0; +} - struct saa7146_use_ops *ops; - struct videobuf_queue *q; +static int vidioc_s_fbuf(struct file *file, void *fh, struct v4l2_framebuffer *fb) +{ + struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev; + struct saa7146_vv *vv = dev->vv_data; + struct saa7146_format *fmt; - /* check if extension handles the command */ - for(ee = 0; dev->ext_vv_data->ioctls[ee].flags != 0; ee++) { - if( cmd == dev->ext_vv_data->ioctls[ee].cmd ) - break; - } + DEB_EE(("VIDIOC_S_FBUF\n")); - if( 0 != (dev->ext_vv_data->ioctls[ee].flags & SAA7146_EXCLUSIVE) ) { - DEB_D(("extension handles ioctl exclusive.\n")); - result = dev->ext_vv_data->ioctl(fh, cmd, arg); - return result; - } - if( 0 != (dev->ext_vv_data->ioctls[ee].flags & SAA7146_BEFORE) ) { - DEB_D(("extension handles ioctl before.\n")); - result = dev->ext_vv_data->ioctl(fh, cmd, arg); - if( -EAGAIN != result ) { - return result; - } - } + if (!capable(CAP_SYS_ADMIN) && !capable(CAP_SYS_RAWIO)) + return -EPERM; - /* fixme: add handle "after" case (is it still needed?) */ + /* check args */ + fmt = format_by_fourcc(dev, fb->fmt.pixelformat); + if (NULL == fmt) + return -EINVAL; - switch (fh->type) { - case V4L2_BUF_TYPE_VIDEO_CAPTURE: { - ops = &saa7146_video_uops; - q = &fh->video_q; - break; - } - case V4L2_BUF_TYPE_VBI_CAPTURE: { - ops = &saa7146_vbi_uops; - q = &fh->vbi_q; - break; - } - default: - BUG(); - return 0; + /* planar formats are not allowed for overlay video, clipping and video dma would clash */ + if (fmt->flags & FORMAT_IS_PLANAR) + DEB_S(("planar pixelformat '%4.4s' not allowed for overlay\n", + (char *)&fmt->pixelformat)); + + /* check if overlay is running */ + if (IS_OVERLAY_ACTIVE(fh) != 0) { + if (vv->video_fh != fh) { + DEB_D(("refusing to change framebuffer informations while overlay is active in another open.\n")); + return -EBUSY; + } } - switch (cmd) { - case VIDIOC_QUERYCAP: - { - struct v4l2_capability *cap = arg; - memset(cap,0,sizeof(*cap)); - - DEB_EE(("VIDIOC_QUERYCAP\n")); - - strcpy((char *)cap->driver, "saa7146 v4l2"); - strlcpy((char *)cap->card, dev->ext->name, sizeof(cap->card)); - sprintf((char *)cap->bus_info,"PCI:%s", pci_name(dev->pci)); - cap->version = SAA7146_VERSION_CODE; - cap->capabilities = - V4L2_CAP_VIDEO_CAPTURE | - V4L2_CAP_VIDEO_OVERLAY | - V4L2_CAP_READWRITE | - V4L2_CAP_STREAMING; - cap->capabilities |= dev->ext_vv_data->capabilities; - return 0; + mutex_lock(&dev->lock); + + /* ok, accept it */ + vv->ov_fb = *fb; + vv->ov_fmt = fmt; + if (0 == vv->ov_fb.fmt.bytesperline) + vv->ov_fb.fmt.bytesperline = + vv->ov_fb.fmt.width * fmt->depth / 8; + + mutex_unlock(&dev->lock); + return 0; +} + +static int vidioc_enum_fmt_vid_cap(struct file *file, void *fh, struct v4l2_fmtdesc *f) +{ + if (f->index >= NUM_FORMATS) + return -EINVAL; + strlcpy((char *)f->description, formats[f->index].name, + sizeof(f->description)); + f->pixelformat = formats[f->index].pixelformat; + return 0; +} + +static int vidioc_enum_fmt_vid_overlay(struct file *file, void *fh, struct v4l2_fmtdesc *f) +{ + return vidioc_enum_fmt_vid_cap(file, fh, f); +} + +static int vidioc_queryctrl(struct file *file, void *fh, struct v4l2_queryctrl *c) +{ + const struct v4l2_queryctrl *ctrl; + + if ((c->id < V4L2_CID_BASE || + c->id >= V4L2_CID_LASTP1) && + (c->id < V4L2_CID_PRIVATE_BASE || + c->id >= V4L2_CID_PRIVATE_LASTP1)) + return -EINVAL; + + ctrl = ctrl_by_id(c->id); + if (ctrl == NULL) + return -EINVAL; + + DEB_EE(("VIDIOC_QUERYCTRL: id:%d\n", c->id)); + *c = *ctrl; + return 0; +} + +static int vidioc_g_ctrl(struct file *file, void *fh, struct v4l2_control *c) +{ + struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev; + struct saa7146_vv *vv = dev->vv_data; + const struct v4l2_queryctrl *ctrl; + u32 value = 0; + + ctrl = ctrl_by_id(c->id); + if (NULL == ctrl) + return -EINVAL; + switch (c->id) { + case V4L2_CID_BRIGHTNESS: + value = saa7146_read(dev, BCS_CTRL); + c->value = 0xff & (value >> 24); + DEB_D(("V4L2_CID_BRIGHTNESS: %d\n", c->value)); + break; + case V4L2_CID_CONTRAST: + value = saa7146_read(dev, BCS_CTRL); + c->value = 0x7f & (value >> 16); + DEB_D(("V4L2_CID_CONTRAST: %d\n", c->value)); + break; + case V4L2_CID_SATURATION: + value = saa7146_read(dev, BCS_CTRL); + c->value = 0x7f & (value >> 0); + DEB_D(("V4L2_CID_SATURATION: %d\n", c->value)); + break; + case V4L2_CID_VFLIP: + c->value = vv->vflip; + DEB_D(("V4L2_CID_VFLIP: %d\n", c->value)); + break; + case V4L2_CID_HFLIP: + c->value = vv->hflip; + DEB_D(("V4L2_CID_HFLIP: %d\n", c->value)); + break; + default: + return -EINVAL; } - case VIDIOC_G_FBUF: - { - struct v4l2_framebuffer *fb = arg; + return 0; +} - DEB_EE(("VIDIOC_G_FBUF\n")); +static int vidioc_s_ctrl(struct file *file, void *fh, struct v4l2_control *c) +{ + struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev; + struct saa7146_vv *vv = dev->vv_data; + const struct v4l2_queryctrl *ctrl; - *fb = vv->ov_fb; - fb->capability = V4L2_FBUF_CAP_LIST_CLIPPING; - return 0; + ctrl = ctrl_by_id(c->id); + if (NULL == ctrl) { + DEB_D(("unknown control %d\n", c->id)); + return -EINVAL; } - case VIDIOC_S_FBUF: - { - struct v4l2_framebuffer *fb = arg; - struct saa7146_format *fmt; - DEB_EE(("VIDIOC_S_FBUF\n")); + mutex_lock(&dev->lock); - if(!capable(CAP_SYS_ADMIN) && - !capable(CAP_SYS_RAWIO)) - return -EPERM; + switch (ctrl->type) { + case V4L2_CTRL_TYPE_BOOLEAN: + case V4L2_CTRL_TYPE_MENU: + case V4L2_CTRL_TYPE_INTEGER: + if (c->value < ctrl->minimum) + c->value = ctrl->minimum; + if (c->value > ctrl->maximum) + c->value = ctrl->maximum; + break; + default: + /* nothing */; + } - /* check args */ - fmt = format_by_fourcc(dev,fb->fmt.pixelformat); - if (NULL == fmt) { + switch (c->id) { + case V4L2_CID_BRIGHTNESS: { + u32 value = saa7146_read(dev, BCS_CTRL); + value &= 0x00ffffff; + value |= (c->value << 24); + saa7146_write(dev, BCS_CTRL, value); + saa7146_write(dev, MC2, MASK_22 | MASK_06); + break; + } + case V4L2_CID_CONTRAST: { + u32 value = saa7146_read(dev, BCS_CTRL); + value &= 0xff00ffff; + value |= (c->value << 16); + saa7146_write(dev, BCS_CTRL, value); + saa7146_write(dev, MC2, MASK_22 | MASK_06); + break; + } + case V4L2_CID_SATURATION: { + u32 value = saa7146_read(dev, BCS_CTRL); + value &= 0xffffff00; + value |= (c->value << 0); + saa7146_write(dev, BCS_CTRL, value); + saa7146_write(dev, MC2, MASK_22 | MASK_06); + break; + } + case V4L2_CID_HFLIP: + /* fixme: we can support changing VFLIP and HFLIP here... */ + if (IS_CAPTURE_ACTIVE(fh) != 0) { + DEB_D(("V4L2_CID_HFLIP while active capture.\n")); + mutex_unlock(&dev->lock); return -EINVAL; } - - /* planar formats are not allowed for overlay video, clipping and video dma would clash */ - if (0 != (fmt->flags & FORMAT_IS_PLANAR)) { - DEB_S(("planar pixelformat '%4.4s' not allowed for overlay\n",(char *)&fmt->pixelformat)); + vv->hflip = c->value; + break; + case V4L2_CID_VFLIP: + if (IS_CAPTURE_ACTIVE(fh) != 0) { + DEB_D(("V4L2_CID_VFLIP while active capture.\n")); + mutex_unlock(&dev->lock); + return -EINVAL; } + vv->vflip = c->value; + break; + default: + mutex_unlock(&dev->lock); + return -EINVAL; + } + mutex_unlock(&dev->lock); - /* check if overlay is running */ - if (IS_OVERLAY_ACTIVE(fh) != 0) { - if (vv->video_fh != fh) { - DEB_D(("refusing to change framebuffer informations while overlay is active in another open.\n")); - return -EBUSY; - } - } + if (IS_OVERLAY_ACTIVE(fh) != 0) { + saa7146_stop_preview(fh); + saa7146_start_preview(fh); + } + return 0; +} - mutex_lock(&dev->lock); +static int vidioc_g_parm(struct file *file, void *fh, + struct v4l2_streamparm *parm) +{ + if (parm->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + return -EINVAL; + parm->parm.capture.readbuffers = 1; + /* fixme: only for PAL! */ + parm->parm.capture.timeperframe.numerator = 1; + parm->parm.capture.timeperframe.denominator = 25; + return 0; +} - /* ok, accept it */ - vv->ov_fb = *fb; - vv->ov_fmt = fmt; - if (0 == vv->ov_fb.fmt.bytesperline) - vv->ov_fb.fmt.bytesperline = - vv->ov_fb.fmt.width*fmt->depth/8; +static int vidioc_g_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *f) +{ + f->fmt.pix = ((struct saa7146_fh *)fh)->video_fmt; + return 0; +} - mutex_unlock(&dev->lock); +static int vidioc_g_fmt_vid_overlay(struct file *file, void *fh, struct v4l2_format *f) +{ + f->fmt.win = ((struct saa7146_fh *)fh)->ov.win; + return 0; +} - return 0; - } - case VIDIOC_ENUM_FMT: - { - struct v4l2_fmtdesc *f = arg; - - switch (f->type) { - case V4L2_BUF_TYPE_VIDEO_CAPTURE: - case V4L2_BUF_TYPE_VIDEO_OVERLAY: - if (f->index >= NUM_FORMATS) - return -EINVAL; - strlcpy((char *)f->description, formats[f->index].name, - sizeof(f->description)); - f->pixelformat = formats[f->index].pixelformat; - f->flags = 0; - memset(f->reserved, 0, sizeof(f->reserved)); - break; - default: - return -EINVAL; - } +static int vidioc_g_fmt_vbi_cap(struct file *file, void *fh, struct v4l2_format *f) +{ + f->fmt.vbi = ((struct saa7146_fh *)fh)->vbi_fmt; + return 0; +} - DEB_EE(("VIDIOC_ENUM_FMT: type:%d, index:%d\n",f->type,f->index)); - return 0; +static int vidioc_try_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *f) +{ + struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev; + struct saa7146_vv *vv = dev->vv_data; + struct saa7146_format *fmt; + enum v4l2_field field; + int maxw, maxh; + int calc_bpl; + + DEB_EE(("V4L2_BUF_TYPE_VIDEO_CAPTURE: dev:%p, fh:%p\n", dev, fh)); + + fmt = format_by_fourcc(dev, f->fmt.pix.pixelformat); + if (NULL == fmt) + return -EINVAL; + + field = f->fmt.pix.field; + maxw = vv->standard->h_max_out; + maxh = vv->standard->v_max_out; + + if (V4L2_FIELD_ANY == field) { + field = (f->fmt.pix.height > maxh / 2) + ? V4L2_FIELD_INTERLACED + : V4L2_FIELD_BOTTOM; + } + switch (field) { + case V4L2_FIELD_ALTERNATE: + vv->last_field = V4L2_FIELD_TOP; + maxh = maxh / 2; + break; + case V4L2_FIELD_TOP: + case V4L2_FIELD_BOTTOM: + vv->last_field = V4L2_FIELD_INTERLACED; + maxh = maxh / 2; + break; + case V4L2_FIELD_INTERLACED: + vv->last_field = V4L2_FIELD_INTERLACED; + break; + default: + DEB_D(("no known field mode '%d'.\n", field)); + return -EINVAL; } - case VIDIOC_QUERYCTRL: - { - const struct v4l2_queryctrl *ctrl; - struct v4l2_queryctrl *c = arg; - if ((c->id < V4L2_CID_BASE || - c->id >= V4L2_CID_LASTP1) && - (c->id < V4L2_CID_PRIVATE_BASE || - c->id >= V4L2_CID_PRIVATE_LASTP1)) - return -EINVAL; + f->fmt.pix.field = field; + if (f->fmt.pix.width > maxw) + f->fmt.pix.width = maxw; + if (f->fmt.pix.height > maxh) + f->fmt.pix.height = maxh; - ctrl = ctrl_by_id(c->id); - if( NULL == ctrl ) { - return -EINVAL; -/* - c->flags = V4L2_CTRL_FLAG_DISABLED; - return 0; -*/ - } + calc_bpl = (f->fmt.pix.width * fmt->depth) / 8; - DEB_EE(("VIDIOC_QUERYCTRL: id:%d\n",c->id)); - *c = *ctrl; - return 0; + if (f->fmt.pix.bytesperline < calc_bpl) + f->fmt.pix.bytesperline = calc_bpl; + + if (f->fmt.pix.bytesperline > (2 * PAGE_SIZE * fmt->depth) / 8) /* arbitrary constraint */ + f->fmt.pix.bytesperline = calc_bpl; + + f->fmt.pix.sizeimage = f->fmt.pix.bytesperline * f->fmt.pix.height; + DEB_D(("w:%d, h:%d, bytesperline:%d, sizeimage:%d\n", f->fmt.pix.width, + f->fmt.pix.height, f->fmt.pix.bytesperline, f->fmt.pix.sizeimage)); + + return 0; +} + + +static int vidioc_try_fmt_vid_overlay(struct file *file, void *fh, struct v4l2_format *f) +{ + struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev; + struct saa7146_vv *vv = dev->vv_data; + struct v4l2_window *win = &f->fmt.win; + enum v4l2_field field; + int maxw, maxh; + + DEB_EE(("dev:%p\n", dev)); + + if (NULL == vv->ov_fb.base) { + DEB_D(("no fb base set.\n")); + return -EINVAL; } - case VIDIOC_G_CTRL: { - DEB_EE(("VIDIOC_G_CTRL\n")); - return get_control(fh,arg); + if (NULL == vv->ov_fmt) { + DEB_D(("no fb fmt set.\n")); + return -EINVAL; } - case VIDIOC_S_CTRL: - { - DEB_EE(("VIDIOC_S_CTRL\n")); - err = set_control(fh,arg); - return err; + if (win->w.width < 48 || win->w.height < 32) { + DEB_D(("min width/height. (%d,%d)\n", win->w.width, win->w.height)); + return -EINVAL; } - case VIDIOC_G_PARM: - { - struct v4l2_streamparm *parm = arg; - if( parm->type != V4L2_BUF_TYPE_VIDEO_CAPTURE ) { - return -EINVAL; - } - memset(&parm->parm.capture,0,sizeof(struct v4l2_captureparm)); - parm->parm.capture.readbuffers = 1; - // fixme: only for PAL! - parm->parm.capture.timeperframe.numerator = 1; - parm->parm.capture.timeperframe.denominator = 25; - return 0; + if (win->clipcount > 16) { + DEB_D(("clipcount too big.\n")); + return -EINVAL; } - case VIDIOC_G_FMT: - { - struct v4l2_format *f = arg; - DEB_EE(("VIDIOC_G_FMT\n")); - return g_fmt(fh,f); + + field = win->field; + maxw = vv->standard->h_max_out; + maxh = vv->standard->v_max_out; + + if (V4L2_FIELD_ANY == field) { + field = (win->w.height > maxh / 2) + ? V4L2_FIELD_INTERLACED + : V4L2_FIELD_TOP; + } + switch (field) { + case V4L2_FIELD_TOP: + case V4L2_FIELD_BOTTOM: + case V4L2_FIELD_ALTERNATE: + maxh = maxh / 2; + break; + case V4L2_FIELD_INTERLACED: + break; + default: + DEB_D(("no known field mode '%d'.\n", field)); + return -EINVAL; } - case VIDIOC_S_FMT: - { - struct v4l2_format *f = arg; - DEB_EE(("VIDIOC_S_FMT\n")); - return s_fmt(fh,f); + + win->field = field; + if (win->w.width > maxw) + win->w.width = maxw; + if (win->w.height > maxh) + win->w.height = maxh; + + return 0; +} + +static int vidioc_s_fmt_vid_cap(struct file *file, void *__fh, struct v4l2_format *f) +{ + struct saa7146_fh *fh = __fh; + struct saa7146_dev *dev = fh->dev; + struct saa7146_vv *vv = dev->vv_data; + int err; + + DEB_EE(("V4L2_BUF_TYPE_VIDEO_CAPTURE: dev:%p, fh:%p\n", dev, fh)); + if (IS_CAPTURE_ACTIVE(fh) != 0) { + DEB_EE(("streaming capture is active\n")); + return -EBUSY; } - case VIDIOC_TRY_FMT: - { - struct v4l2_format *f = arg; - DEB_EE(("VIDIOC_TRY_FMT\n")); - return try_fmt(fh,f); + err = vidioc_try_fmt_vid_cap(file, fh, f); + if (0 != err) + return err; + fh->video_fmt = f->fmt.pix; + DEB_EE(("set to pixelformat '%4.4s'\n", (char *)&fh->video_fmt.pixelformat)); + return 0; +} + +static int vidioc_s_fmt_vid_overlay(struct file *file, void *__fh, struct v4l2_format *f) +{ + struct saa7146_fh *fh = __fh; + struct saa7146_dev *dev = fh->dev; + struct saa7146_vv *vv = dev->vv_data; + int err; + + DEB_EE(("V4L2_BUF_TYPE_VIDEO_OVERLAY: dev:%p, fh:%p\n", dev, fh)); + err = vidioc_try_fmt_vid_overlay(file, fh, f); + if (0 != err) + return err; + mutex_lock(&dev->lock); + fh->ov.win = f->fmt.win; + fh->ov.nclips = f->fmt.win.clipcount; + if (fh->ov.nclips > 16) + fh->ov.nclips = 16; + if (copy_from_user(fh->ov.clips, f->fmt.win.clips, + sizeof(struct v4l2_clip) * fh->ov.nclips)) { + mutex_unlock(&dev->lock); + return -EFAULT; } - case VIDIOC_G_STD: - { - v4l2_std_id *id = arg; - DEB_EE(("VIDIOC_G_STD\n")); - *id = vv->standard->id; - return 0; + + /* fh->ov.fh is used to indicate that we have valid overlay informations, too */ + fh->ov.fh = fh; + + mutex_unlock(&dev->lock); + + /* check if our current overlay is active */ + if (IS_OVERLAY_ACTIVE(fh) != 0) { + saa7146_stop_preview(fh); + saa7146_start_preview(fh); } + return 0; +} + +static int vidioc_g_std(struct file *file, void *fh, v4l2_std_id *norm) +{ + struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev; + struct saa7146_vv *vv = dev->vv_data; + + *norm = vv->standard->id; + return 0; +} + /* the saa7146 supfhrts (used in conjunction with the saa7111a for example) PAL / NTSC / SECAM. if your hardware does not (or does more) -- override this function in your extension */ +/* case VIDIOC_ENUMSTD: { struct v4l2_standard *e = arg; @@ -1066,162 +950,228 @@ long saa7146_video_do_ioctl(struct file *file, unsigned int cmd, void *arg) } return -EINVAL; } - case VIDIOC_S_STD: - { - v4l2_std_id *id = arg; - int found = 0; - int i; + */ - DEB_EE(("VIDIOC_S_STD\n")); +static int vidioc_s_std(struct file *file, void *fh, v4l2_std_id *id) +{ + struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev; + struct saa7146_vv *vv = dev->vv_data; + int found = 0; + int err, i; - if ((vv->video_status & STATUS_CAPTURE) == STATUS_CAPTURE) { - DEB_D(("cannot change video standard while streaming capture is active\n")); - return -EBUSY; - } + DEB_EE(("VIDIOC_S_STD\n")); - if ((vv->video_status & STATUS_OVERLAY) != 0) { - vv->ov_suspend = vv->video_fh; - err = saa7146_stop_preview(vv->video_fh); /* side effect: video_status is now 0, video_fh is NULL */ - if (0 != err) { - DEB_D(("suspending video failed. aborting\n")); - return err; - } - } - - mutex_lock(&dev->lock); + if ((vv->video_status & STATUS_CAPTURE) == STATUS_CAPTURE) { + DEB_D(("cannot change video standard while streaming capture is active\n")); + return -EBUSY; + } - for(i = 0; i < dev->ext_vv_data->num_stds; i++) - if (*id & dev->ext_vv_data->stds[i].id) - break; - if (i != dev->ext_vv_data->num_stds) { - vv->standard = &dev->ext_vv_data->stds[i]; - if( NULL != dev->ext_vv_data->std_callback ) - dev->ext_vv_data->std_callback(dev, vv->standard); - found = 1; + if ((vv->video_status & STATUS_OVERLAY) != 0) { + vv->ov_suspend = vv->video_fh; + err = saa7146_stop_preview(vv->video_fh); /* side effect: video_status is now 0, video_fh is NULL */ + if (0 != err) { + DEB_D(("suspending video failed. aborting\n")); + return err; } + } - mutex_unlock(&dev->lock); + mutex_lock(&dev->lock); - if (vv->ov_suspend != NULL) { - saa7146_start_preview(vv->ov_suspend); - vv->ov_suspend = NULL; - } + for (i = 0; i < dev->ext_vv_data->num_stds; i++) + if (*id & dev->ext_vv_data->stds[i].id) + break; + if (i != dev->ext_vv_data->num_stds) { + vv->standard = &dev->ext_vv_data->stds[i]; + if (NULL != dev->ext_vv_data->std_callback) + dev->ext_vv_data->std_callback(dev, vv->standard); + found = 1; + } - if( 0 == found ) { - DEB_EE(("VIDIOC_S_STD: standard not found.\n")); - return -EINVAL; - } + mutex_unlock(&dev->lock); - DEB_EE(("VIDIOC_S_STD: set to standard to '%s'\n",vv->standard->name)); - return 0; + if (vv->ov_suspend != NULL) { + saa7146_start_preview(vv->ov_suspend); + vv->ov_suspend = NULL; } - case VIDIOC_OVERLAY: - { - int on = *(int *)arg; - DEB_D(("VIDIOC_OVERLAY on:%d\n",on)); - if (on != 0) { - err = saa7146_start_preview(fh); - } else { - err = saa7146_stop_preview(fh); - } - return err; - } - case VIDIOC_REQBUFS: { - struct v4l2_requestbuffers *req = arg; - DEB_D(("VIDIOC_REQBUFS, type:%d\n",req->type)); - return videobuf_reqbufs(q,req); - } - case VIDIOC_QUERYBUF: { - struct v4l2_buffer *buf = arg; - DEB_D(("VIDIOC_QUERYBUF, type:%d, offset:%d\n",buf->type,buf->m.offset)); - return videobuf_querybuf(q,buf); - } - case VIDIOC_QBUF: { - struct v4l2_buffer *buf = arg; - int ret = 0; - ret = videobuf_qbuf(q,buf); - DEB_D(("VIDIOC_QBUF: ret:%d, index:%d\n",ret,buf->index)); - return ret; - } - case VIDIOC_DQBUF: { - struct v4l2_buffer *buf = arg; - int ret = 0; - ret = videobuf_dqbuf(q,buf,file->f_flags & O_NONBLOCK); - DEB_D(("VIDIOC_DQBUF: ret:%d, index:%d\n",ret,buf->index)); - return ret; + if (!found) { + DEB_EE(("VIDIOC_S_STD: standard not found.\n")); + return -EINVAL; } - case VIDIOC_STREAMON: { - int *type = arg; - DEB_D(("VIDIOC_STREAMON, type:%d\n",*type)); - err = video_begin(fh); - if( 0 != err) { - return err; - } - err = videobuf_streamon(q); - return err; - } - case VIDIOC_STREAMOFF: { - int *type = arg; + DEB_EE(("VIDIOC_S_STD: set to standard to '%s'\n", vv->standard->name)); + return 0; +} - DEB_D(("VIDIOC_STREAMOFF, type:%d\n",*type)); +static int vidioc_overlay(struct file *file, void *fh, unsigned int on) +{ + int err; - /* ugly: we need to copy some checks from video_end(), - because videobuf_streamoff() relies on the capture running. - check and fix this */ - if ((vv->video_status & STATUS_CAPTURE) != STATUS_CAPTURE) { - DEB_S(("not capturing.\n")); - return 0; - } + DEB_D(("VIDIOC_OVERLAY on:%d\n", on)); + if (on) + err = saa7146_start_preview(fh); + else + err = saa7146_stop_preview(fh); + return err; +} - if (vv->video_fh != fh) { - DEB_S(("capturing, but in another open.\n")); - return -EBUSY; - } +static int vidioc_reqbufs(struct file *file, void *__fh, struct v4l2_requestbuffers *b) +{ + struct saa7146_fh *fh = __fh; - err = videobuf_streamoff(q); - if (0 != err) { - DEB_D(("warning: videobuf_streamoff() failed.\n")); - video_end(fh, file); - } else { - err = video_end(fh, file); - } - return err; - } -#ifdef CONFIG_VIDEO_V4L1_COMPAT - case VIDIOCGMBUF: - { - struct video_mbuf *mbuf = arg; - int i; + if (b->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) + return videobuf_reqbufs(&fh->video_q, b); + if (b->type == V4L2_BUF_TYPE_VBI_CAPTURE) + return videobuf_reqbufs(&fh->vbi_q, b); + return -EINVAL; +} - /* fixme: number of capture buffers and sizes for v4l apps */ - int gbuffers = 2; - int gbufsize = 768*576*4; +static int vidioc_querybuf(struct file *file, void *__fh, struct v4l2_buffer *buf) +{ + struct saa7146_fh *fh = __fh; - DEB_D(("VIDIOCGMBUF \n")); + if (buf->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) + return videobuf_querybuf(&fh->video_q, buf); + if (buf->type == V4L2_BUF_TYPE_VBI_CAPTURE) + return videobuf_querybuf(&fh->vbi_q, buf); + return -EINVAL; +} - q = &fh->video_q; - err = videobuf_mmap_setup(q,gbuffers,gbufsize, - V4L2_MEMORY_MMAP); - if (err < 0) - return err; +static int vidioc_qbuf(struct file *file, void *__fh, struct v4l2_buffer *buf) +{ + struct saa7146_fh *fh = __fh; + + if (buf->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) + return videobuf_qbuf(&fh->video_q, buf); + if (buf->type == V4L2_BUF_TYPE_VBI_CAPTURE) + return videobuf_qbuf(&fh->vbi_q, buf); + return -EINVAL; +} + +static int vidioc_dqbuf(struct file *file, void *__fh, struct v4l2_buffer *buf) +{ + struct saa7146_fh *fh = __fh; + + if (buf->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) + return videobuf_dqbuf(&fh->video_q, buf, file->f_flags & O_NONBLOCK); + if (buf->type == V4L2_BUF_TYPE_VBI_CAPTURE) + return videobuf_dqbuf(&fh->vbi_q, buf, file->f_flags & O_NONBLOCK); + return -EINVAL; +} + +static int vidioc_streamon(struct file *file, void *__fh, enum v4l2_buf_type type) +{ + struct saa7146_fh *fh = __fh; + int err; + + DEB_D(("VIDIOC_STREAMON, type:%d\n", type)); + + err = video_begin(fh); + if (err) + return err; + if (type == V4L2_BUF_TYPE_VIDEO_CAPTURE) + return videobuf_streamon(&fh->video_q); + if (type == V4L2_BUF_TYPE_VBI_CAPTURE) + return videobuf_streamon(&fh->vbi_q); + return -EINVAL; +} + +static int vidioc_streamoff(struct file *file, void *__fh, enum v4l2_buf_type type) +{ + struct saa7146_fh *fh = __fh; + struct saa7146_dev *dev = fh->dev; + struct saa7146_vv *vv = dev->vv_data; + int err; - gbuffers = err; - memset(mbuf,0,sizeof(*mbuf)); - mbuf->frames = gbuffers; - mbuf->size = gbuffers * gbufsize; - for (i = 0; i < gbuffers; i++) - mbuf->offsets[i] = i * gbufsize; + DEB_D(("VIDIOC_STREAMOFF, type:%d\n", type)); + + /* ugly: we need to copy some checks from video_end(), + because videobuf_streamoff() relies on the capture running. + check and fix this */ + if ((vv->video_status & STATUS_CAPTURE) != STATUS_CAPTURE) { + DEB_S(("not capturing.\n")); return 0; } -#endif - default: - return v4l_compat_translate_ioctl(file, cmd, arg, - saa7146_video_do_ioctl); + + if (vv->video_fh != fh) { + DEB_S(("capturing, but in another open.\n")); + return -EBUSY; } + + err = -EINVAL; + if (type == V4L2_BUF_TYPE_VIDEO_CAPTURE) + err = videobuf_streamoff(&fh->video_q); + else if (type == V4L2_BUF_TYPE_VBI_CAPTURE) + err = videobuf_streamoff(&fh->vbi_q); + if (0 != err) { + DEB_D(("warning: videobuf_streamoff() failed.\n")); + video_end(fh, file); + } else { + err = video_end(fh, file); + } + return err; +} + +#ifdef CONFIG_VIDEO_V4L1_COMPAT +static int vidiocgmbuf(struct file *file, void *__fh, struct video_mbuf *mbuf) +{ + struct saa7146_fh *fh = __fh; + struct videobuf_queue *q = &fh->video_q; + int err, i; + + /* fixme: number of capture buffers and sizes for v4l apps */ + int gbuffers = 2; + int gbufsize = 768 * 576 * 4; + + DEB_D(("VIDIOCGMBUF \n")); + + q = &fh->video_q; + err = videobuf_mmap_setup(q, gbuffers, gbufsize, + V4L2_MEMORY_MMAP); + if (err < 0) + return err; + + gbuffers = err; + memset(mbuf, 0, sizeof(*mbuf)); + mbuf->frames = gbuffers; + mbuf->size = gbuffers * gbufsize; + for (i = 0; i < gbuffers; i++) + mbuf->offsets[i] = i * gbufsize; return 0; } +#endif + +const struct v4l2_ioctl_ops saa7146_video_ioctl_ops = { + .vidioc_querycap = vidioc_querycap, + .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap, + .vidioc_enum_fmt_vid_overlay = vidioc_enum_fmt_vid_overlay, + .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap, + .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap, + .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap, + .vidioc_g_fmt_vid_overlay = vidioc_g_fmt_vid_overlay, + .vidioc_try_fmt_vid_overlay = vidioc_try_fmt_vid_overlay, + .vidioc_s_fmt_vid_overlay = vidioc_s_fmt_vid_overlay, + .vidioc_g_fmt_vbi_cap = vidioc_g_fmt_vbi_cap, + + .vidioc_overlay = vidioc_overlay, + .vidioc_g_fbuf = vidioc_g_fbuf, + .vidioc_s_fbuf = vidioc_s_fbuf, + .vidioc_reqbufs = vidioc_reqbufs, + .vidioc_querybuf = vidioc_querybuf, + .vidioc_qbuf = vidioc_qbuf, + .vidioc_dqbuf = vidioc_dqbuf, + .vidioc_g_std = vidioc_g_std, + .vidioc_s_std = vidioc_s_std, + .vidioc_queryctrl = vidioc_queryctrl, + .vidioc_g_ctrl = vidioc_g_ctrl, + .vidioc_s_ctrl = vidioc_s_ctrl, + .vidioc_streamon = vidioc_streamon, + .vidioc_streamoff = vidioc_streamoff, + .vidioc_g_parm = vidioc_g_parm, +#ifdef CONFIG_VIDEO_V4L1_COMPAT + .vidiocgmbuf = vidiocgmbuf, +#endif +}; /*********************************************************************************/ /* buffer handling functions */ diff --git a/drivers/media/dvb/ttpci/av7110_v4l.c b/drivers/media/dvb/ttpci/av7110_v4l.c index c5b9c70563dc..04334058f8f8 100644 --- a/drivers/media/dvb/ttpci/av7110_v4l.c +++ b/drivers/media/dvb/ttpci/av7110_v4l.c @@ -316,253 +316,260 @@ static int av7110_dvb_c_switch(struct saa7146_fh *fh) return 0; } -static long av7110_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg) +static int vidioc_g_tuner(struct file *file, void *fh, struct v4l2_tuner *t) { - struct saa7146_dev *dev = fh->dev; - struct av7110 *av7110 = (struct av7110*) dev->ext_priv; - dprintk(4, "saa7146_dev: %p\n", dev); + struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev; + struct av7110 *av7110 = (struct av7110 *)dev->ext_priv; + u16 stereo_det; + s8 stereo; - switch (cmd) { - case VIDIOC_G_TUNER: - { - struct v4l2_tuner *t = arg; - u16 stereo_det; - s8 stereo; + dprintk(2, "VIDIOC_G_TUNER: %d\n", t->index); - dprintk(2, "VIDIOC_G_TUNER: %d\n", t->index); + if (!av7110->analog_tuner_flags || t->index != 0) + return -EINVAL; - if (!av7110->analog_tuner_flags || t->index != 0) - return -EINVAL; + memset(t, 0, sizeof(*t)); + strcpy((char *)t->name, "Television"); + + t->type = V4L2_TUNER_ANALOG_TV; + t->capability = V4L2_TUNER_CAP_NORM | V4L2_TUNER_CAP_STEREO | + V4L2_TUNER_CAP_LANG1 | V4L2_TUNER_CAP_LANG2 | V4L2_TUNER_CAP_SAP; + t->rangelow = 772; /* 48.25 MHZ / 62.5 kHz = 772, see fi1216mk2-specs, page 2 */ + t->rangehigh = 13684; /* 855.25 MHz / 62.5 kHz = 13684 */ + /* FIXME: add the real signal strength here */ + t->signal = 0xffff; + t->afc = 0; + + /* FIXME: standard / stereo detection is still broken */ + msp_readreg(av7110, MSP_RD_DEM, 0x007e, &stereo_det); + dprintk(1, "VIDIOC_G_TUNER: msp3400 TV standard detection: 0x%04x\n", stereo_det); + msp_readreg(av7110, MSP_RD_DSP, 0x0018, &stereo_det); + dprintk(1, "VIDIOC_G_TUNER: msp3400 stereo detection: 0x%04x\n", stereo_det); + stereo = (s8)(stereo_det >> 8); + if (stereo > 0x10) { + /* stereo */ + t->rxsubchans = V4L2_TUNER_SUB_STEREO | V4L2_TUNER_SUB_MONO; + t->audmode = V4L2_TUNER_MODE_STEREO; + } else if (stereo < -0x10) { + /* bilingual */ + t->rxsubchans = V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_LANG2; + t->audmode = V4L2_TUNER_MODE_LANG1; + } else /* mono */ + t->rxsubchans = V4L2_TUNER_SUB_MONO; - memset(t, 0, sizeof(*t)); - strcpy((char *)t->name, "Television"); - - t->type = V4L2_TUNER_ANALOG_TV; - t->capability = V4L2_TUNER_CAP_NORM | V4L2_TUNER_CAP_STEREO | - V4L2_TUNER_CAP_LANG1 | V4L2_TUNER_CAP_LANG2 | V4L2_TUNER_CAP_SAP; - t->rangelow = 772; /* 48.25 MHZ / 62.5 kHz = 772, see fi1216mk2-specs, page 2 */ - t->rangehigh = 13684; /* 855.25 MHz / 62.5 kHz = 13684 */ - /* FIXME: add the real signal strength here */ - t->signal = 0xffff; - t->afc = 0; - - // FIXME: standard / stereo detection is still broken - msp_readreg(av7110, MSP_RD_DEM, 0x007e, &stereo_det); - dprintk(1, "VIDIOC_G_TUNER: msp3400 TV standard detection: 0x%04x\n", stereo_det); - msp_readreg(av7110, MSP_RD_DSP, 0x0018, &stereo_det); - dprintk(1, "VIDIOC_G_TUNER: msp3400 stereo detection: 0x%04x\n", stereo_det); - stereo = (s8)(stereo_det >> 8); - if (stereo > 0x10) { - /* stereo */ - t->rxsubchans = V4L2_TUNER_SUB_STEREO | V4L2_TUNER_SUB_MONO; - t->audmode = V4L2_TUNER_MODE_STEREO; - } - else if (stereo < -0x10) { - /* bilingual */ - t->rxsubchans = V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_LANG2; - t->audmode = V4L2_TUNER_MODE_LANG1; - } - else /* mono */ - t->rxsubchans = V4L2_TUNER_SUB_MONO; + return 0; +} - return 0; - } - case VIDIOC_S_TUNER: - { - struct v4l2_tuner *t = arg; - u16 fm_matrix, src; - dprintk(2, "VIDIOC_S_TUNER: %d\n", t->index); +static int vidioc_s_tuner(struct file *file, void *fh, struct v4l2_tuner *t) +{ + struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev; + struct av7110 *av7110 = (struct av7110 *)dev->ext_priv; + u16 fm_matrix, src; + dprintk(2, "VIDIOC_S_TUNER: %d\n", t->index); - if (!av7110->analog_tuner_flags || av7110->current_input != 1) - return -EINVAL; + if (!av7110->analog_tuner_flags || av7110->current_input != 1) + return -EINVAL; - switch (t->audmode) { - case V4L2_TUNER_MODE_STEREO: - dprintk(2, "VIDIOC_S_TUNER: V4L2_TUNER_MODE_STEREO\n"); - fm_matrix = 0x3001; // stereo - src = 0x0020; - break; - case V4L2_TUNER_MODE_LANG1_LANG2: - dprintk(2, "VIDIOC_S_TUNER: V4L2_TUNER_MODE_LANG1_LANG2\n"); - fm_matrix = 0x3000; // bilingual - src = 0x0020; - break; - case V4L2_TUNER_MODE_LANG1: - dprintk(2, "VIDIOC_S_TUNER: V4L2_TUNER_MODE_LANG1\n"); - fm_matrix = 0x3000; // mono - src = 0x0000; - break; - case V4L2_TUNER_MODE_LANG2: - dprintk(2, "VIDIOC_S_TUNER: V4L2_TUNER_MODE_LANG2\n"); - fm_matrix = 0x3000; // mono - src = 0x0010; - break; - default: /* case V4L2_TUNER_MODE_MONO: */ - dprintk(2, "VIDIOC_S_TUNER: TDA9840_SET_MONO\n"); - fm_matrix = 0x3000; // mono - src = 0x0030; - break; - } - msp_writereg(av7110, MSP_WR_DSP, 0x000e, fm_matrix); - msp_writereg(av7110, MSP_WR_DSP, 0x0008, src); - msp_writereg(av7110, MSP_WR_DSP, 0x0009, src); - msp_writereg(av7110, MSP_WR_DSP, 0x000a, src); - return 0; + switch (t->audmode) { + case V4L2_TUNER_MODE_STEREO: + dprintk(2, "VIDIOC_S_TUNER: V4L2_TUNER_MODE_STEREO\n"); + fm_matrix = 0x3001; /* stereo */ + src = 0x0020; + break; + case V4L2_TUNER_MODE_LANG1_LANG2: + dprintk(2, "VIDIOC_S_TUNER: V4L2_TUNER_MODE_LANG1_LANG2\n"); + fm_matrix = 0x3000; /* bilingual */ + src = 0x0020; + break; + case V4L2_TUNER_MODE_LANG1: + dprintk(2, "VIDIOC_S_TUNER: V4L2_TUNER_MODE_LANG1\n"); + fm_matrix = 0x3000; /* mono */ + src = 0x0000; + break; + case V4L2_TUNER_MODE_LANG2: + dprintk(2, "VIDIOC_S_TUNER: V4L2_TUNER_MODE_LANG2\n"); + fm_matrix = 0x3000; /* mono */ + src = 0x0010; + break; + default: /* case V4L2_TUNER_MODE_MONO: */ + dprintk(2, "VIDIOC_S_TUNER: TDA9840_SET_MONO\n"); + fm_matrix = 0x3000; /* mono */ + src = 0x0030; + break; } - case VIDIOC_G_FREQUENCY: - { - struct v4l2_frequency *f = arg; + msp_writereg(av7110, MSP_WR_DSP, 0x000e, fm_matrix); + msp_writereg(av7110, MSP_WR_DSP, 0x0008, src); + msp_writereg(av7110, MSP_WR_DSP, 0x0009, src); + msp_writereg(av7110, MSP_WR_DSP, 0x000a, src); + return 0; +} + +static int vidioc_g_frequency(struct file *file, void *fh, struct v4l2_frequency *f) +{ + struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev; + struct av7110 *av7110 = (struct av7110 *)dev->ext_priv; - dprintk(2, "VIDIOC_G_FREQ: freq:0x%08x.\n", f->frequency); + dprintk(2, "VIDIOC_G_FREQ: freq:0x%08x.\n", f->frequency); - if (!av7110->analog_tuner_flags || av7110->current_input != 1) - return -EINVAL; + if (!av7110->analog_tuner_flags || av7110->current_input != 1) + return -EINVAL; - memset(f, 0, sizeof(*f)); - f->type = V4L2_TUNER_ANALOG_TV; - f->frequency = av7110->current_freq; - return 0; - } - case VIDIOC_S_FREQUENCY: - { - struct v4l2_frequency *f = arg; + memset(f, 0, sizeof(*f)); + f->type = V4L2_TUNER_ANALOG_TV; + f->frequency = av7110->current_freq; + return 0; +} - dprintk(2, "VIDIOC_S_FREQUENCY: freq:0x%08x.\n", f->frequency); +static int vidioc_s_frequency(struct file *file, void *fh, struct v4l2_frequency *f) +{ + struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev; + struct av7110 *av7110 = (struct av7110 *)dev->ext_priv; - if (!av7110->analog_tuner_flags || av7110->current_input != 1) - return -EINVAL; + dprintk(2, "VIDIOC_S_FREQUENCY: freq:0x%08x.\n", f->frequency); - if (V4L2_TUNER_ANALOG_TV != f->type) - return -EINVAL; + if (!av7110->analog_tuner_flags || av7110->current_input != 1) + return -EINVAL; - msp_writereg(av7110, MSP_WR_DSP, 0x0000, 0xffe0); // fast mute - msp_writereg(av7110, MSP_WR_DSP, 0x0007, 0xffe0); + if (V4L2_TUNER_ANALOG_TV != f->type) + return -EINVAL; - /* tune in desired frequency */ - if (av7110->analog_tuner_flags & ANALOG_TUNER_VES1820) { - ves1820_set_tv_freq(dev, f->frequency); - } else if (av7110->analog_tuner_flags & ANALOG_TUNER_STV0297) { - stv0297_set_tv_freq(dev, f->frequency); - } - av7110->current_freq = f->frequency; + msp_writereg(av7110, MSP_WR_DSP, 0x0000, 0xffe0); /* fast mute */ + msp_writereg(av7110, MSP_WR_DSP, 0x0007, 0xffe0); - msp_writereg(av7110, MSP_WR_DSP, 0x0015, 0x003f); // start stereo detection - msp_writereg(av7110, MSP_WR_DSP, 0x0015, 0x0000); - msp_writereg(av7110, MSP_WR_DSP, 0x0000, 0x4f00); // loudspeaker + headphone - msp_writereg(av7110, MSP_WR_DSP, 0x0007, 0x4f00); // SCART 1 volume - return 0; - } - case VIDIOC_ENUMINPUT: - { - struct v4l2_input *i = arg; + /* tune in desired frequency */ + if (av7110->analog_tuner_flags & ANALOG_TUNER_VES1820) + ves1820_set_tv_freq(dev, f->frequency); + else if (av7110->analog_tuner_flags & ANALOG_TUNER_STV0297) + stv0297_set_tv_freq(dev, f->frequency); + av7110->current_freq = f->frequency; - dprintk(2, "VIDIOC_ENUMINPUT: %d\n", i->index); + msp_writereg(av7110, MSP_WR_DSP, 0x0015, 0x003f); /* start stereo detection */ + msp_writereg(av7110, MSP_WR_DSP, 0x0015, 0x0000); + msp_writereg(av7110, MSP_WR_DSP, 0x0000, 0x4f00); /* loudspeaker + headphone */ + msp_writereg(av7110, MSP_WR_DSP, 0x0007, 0x4f00); /* SCART 1 volume */ + return 0; +} - if (av7110->analog_tuner_flags) { - if (i->index < 0 || i->index >= 4) - return -EINVAL; - } else { - if (i->index != 0) - return -EINVAL; - } +static int vidioc_enum_input(struct file *file, void *fh, struct v4l2_input *i) +{ + struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev; + struct av7110 *av7110 = (struct av7110 *)dev->ext_priv; - memcpy(i, &inputs[i->index], sizeof(struct v4l2_input)); + dprintk(2, "VIDIOC_ENUMINPUT: %d\n", i->index); - return 0; + if (av7110->analog_tuner_flags) { + if (i->index < 0 || i->index >= 4) + return -EINVAL; + } else { + if (i->index != 0) + return -EINVAL; } - case VIDIOC_G_INPUT: - { - int *input = (int *)arg; - *input = av7110->current_input; - dprintk(2, "VIDIOC_G_INPUT: %d\n", *input); + + memcpy(i, &inputs[i->index], sizeof(struct v4l2_input)); + + return 0; +} + +static int vidioc_g_input(struct file *file, void *fh, unsigned int *input) +{ + struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev; + struct av7110 *av7110 = (struct av7110 *)dev->ext_priv; + + *input = av7110->current_input; + dprintk(2, "VIDIOC_G_INPUT: %d\n", *input); + return 0; +} + +static int vidioc_s_input(struct file *file, void *fh, unsigned int input) +{ + struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev; + struct av7110 *av7110 = (struct av7110 *)dev->ext_priv; + + dprintk(2, "VIDIOC_S_INPUT: %d\n", input); + + if (!av7110->analog_tuner_flags) return 0; - } - case VIDIOC_S_INPUT: - { - int input = *(int *)arg; - dprintk(2, "VIDIOC_S_INPUT: %d\n", input); + if (input < 0 || input >= 4) + return -EINVAL; - if (!av7110->analog_tuner_flags) - return 0; + av7110->current_input = input; + return av7110_dvb_c_switch(fh); +} - if (input < 0 || input >= 4) - return -EINVAL; +static int vidioc_g_audio(struct file *file, void *fh, struct v4l2_audio *a) +{ + dprintk(2, "VIDIOC_G_AUDIO: %d\n", a->index); + if (a->index != 0) + return -EINVAL; + memcpy(a, &msp3400_v4l2_audio, sizeof(struct v4l2_audio)); + return 0; +} - av7110->current_input = input; - return av7110_dvb_c_switch(fh); - } - case VIDIOC_G_AUDIO: - { - struct v4l2_audio *a = arg; +static int vidioc_s_audio(struct file *file, void *fh, struct v4l2_audio *a) +{ + dprintk(2, "VIDIOC_S_AUDIO: %d\n", a->index); + return 0; +} - dprintk(2, "VIDIOC_G_AUDIO: %d\n", a->index); - if (a->index != 0) - return -EINVAL; - memcpy(a, &msp3400_v4l2_audio, sizeof(struct v4l2_audio)); - break; - } - case VIDIOC_S_AUDIO: - { - struct v4l2_audio *a = arg; - dprintk(2, "VIDIOC_S_AUDIO: %d\n", a->index); - break; - } - case VIDIOC_G_SLICED_VBI_CAP: - { - struct v4l2_sliced_vbi_cap *cap = arg; - dprintk(2, "VIDIOC_G_SLICED_VBI_CAP\n"); - memset(cap, 0, sizeof *cap); - if (FW_VERSION(av7110->arm_app) >= 0x2623) { - cap->service_set = V4L2_SLICED_WSS_625; - cap->service_lines[0][23] = V4L2_SLICED_WSS_625; - } - break; - } - case VIDIOC_G_FMT: - { - struct v4l2_format *f = arg; - dprintk(2, "VIDIOC_G_FMT:\n"); - if (f->type != V4L2_BUF_TYPE_SLICED_VBI_OUTPUT || - FW_VERSION(av7110->arm_app) < 0x2623) - return -EAGAIN; /* handled by core driver */ - memset(&f->fmt.sliced, 0, sizeof f->fmt.sliced); - if (av7110->wssMode) { - f->fmt.sliced.service_set = V4L2_SLICED_WSS_625; - f->fmt.sliced.service_lines[0][23] = V4L2_SLICED_WSS_625; - f->fmt.sliced.io_size = sizeof (struct v4l2_sliced_vbi_data); - } - break; +static int vidioc_g_sliced_vbi_cap(struct file *file, void *fh, + struct v4l2_sliced_vbi_cap *cap) +{ + struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev; + struct av7110 *av7110 = (struct av7110 *)dev->ext_priv; + + dprintk(2, "VIDIOC_G_SLICED_VBI_CAP\n"); + memset(cap, 0, sizeof(*cap)); + if (FW_VERSION(av7110->arm_app) >= 0x2623) { + cap->service_set = V4L2_SLICED_WSS_625; + cap->service_lines[0][23] = V4L2_SLICED_WSS_625; } - case VIDIOC_S_FMT: - { - struct v4l2_format *f = arg; - dprintk(2, "VIDIOC_S_FMT\n"); - if (f->type != V4L2_BUF_TYPE_SLICED_VBI_OUTPUT || - FW_VERSION(av7110->arm_app) < 0x2623) - return -EAGAIN; /* handled by core driver */ - if (f->fmt.sliced.service_set != V4L2_SLICED_WSS_625 && - f->fmt.sliced.service_lines[0][23] != V4L2_SLICED_WSS_625) { - memset(&f->fmt.sliced, 0, sizeof f->fmt.sliced); - /* WSS controlled by firmware */ - av7110->wssMode = 0; - av7110->wssData = 0; - return av7110_fw_cmd(av7110, COMTYPE_ENCODER, - SetWSSConfig, 1, 0); - } else { - memset(&f->fmt.sliced, 0, sizeof f->fmt.sliced); - f->fmt.sliced.service_set = V4L2_SLICED_WSS_625; - f->fmt.sliced.service_lines[0][23] = V4L2_SLICED_WSS_625; - f->fmt.sliced.io_size = sizeof (struct v4l2_sliced_vbi_data); - /* WSS controlled by userspace */ - av7110->wssMode = 1; - av7110->wssData = 0; - } - break; + return 0; +} + +static int vidioc_g_fmt_sliced_vbi_out(struct file *file, void *fh, + struct v4l2_format *f) +{ + struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev; + struct av7110 *av7110 = (struct av7110 *)dev->ext_priv; + + dprintk(2, "VIDIOC_G_FMT:\n"); + if (FW_VERSION(av7110->arm_app) < 0x2623) + return -EINVAL; + memset(&f->fmt.sliced, 0, sizeof f->fmt.sliced); + if (av7110->wssMode) { + f->fmt.sliced.service_set = V4L2_SLICED_WSS_625; + f->fmt.sliced.service_lines[0][23] = V4L2_SLICED_WSS_625; + f->fmt.sliced.io_size = sizeof(struct v4l2_sliced_vbi_data); } - default: - printk("no such ioctl\n"); - return -ENOIOCTLCMD; + return 0; +} + +static int vidioc_s_fmt_sliced_vbi_out(struct file *file, void *fh, + struct v4l2_format *f) +{ + struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev; + struct av7110 *av7110 = (struct av7110 *)dev->ext_priv; + + dprintk(2, "VIDIOC_S_FMT\n"); + if (FW_VERSION(av7110->arm_app) < 0x2623) + return -EINVAL; + if (f->fmt.sliced.service_set != V4L2_SLICED_WSS_625 && + f->fmt.sliced.service_lines[0][23] != V4L2_SLICED_WSS_625) { + memset(&f->fmt.sliced, 0, sizeof(f->fmt.sliced)); + /* WSS controlled by firmware */ + av7110->wssMode = 0; + av7110->wssData = 0; + return av7110_fw_cmd(av7110, COMTYPE_ENCODER, + SetWSSConfig, 1, 0); + } else { + memset(&f->fmt.sliced, 0, sizeof(f->fmt.sliced)); + f->fmt.sliced.service_set = V4L2_SLICED_WSS_625; + f->fmt.sliced.service_lines[0][23] = V4L2_SLICED_WSS_625; + f->fmt.sliced.io_size = sizeof(struct v4l2_sliced_vbi_data); + /* WSS controlled by userspace */ + av7110->wssMode = 1; + av7110->wssData = 0; } return 0; } @@ -609,22 +616,6 @@ static ssize_t av7110_vbi_write(struct file *file, const char __user *data, size * INITIALIZATION ****************************************************************************/ -static struct saa7146_extension_ioctls ioctls[] = { - { VIDIOC_ENUMINPUT, SAA7146_EXCLUSIVE }, - { VIDIOC_G_INPUT, SAA7146_EXCLUSIVE }, - { VIDIOC_S_INPUT, SAA7146_EXCLUSIVE }, - { VIDIOC_G_FREQUENCY, SAA7146_EXCLUSIVE }, - { VIDIOC_S_FREQUENCY, SAA7146_EXCLUSIVE }, - { VIDIOC_G_TUNER, SAA7146_EXCLUSIVE }, - { VIDIOC_S_TUNER, SAA7146_EXCLUSIVE }, - { VIDIOC_G_AUDIO, SAA7146_EXCLUSIVE }, - { VIDIOC_S_AUDIO, SAA7146_EXCLUSIVE }, - { VIDIOC_G_SLICED_VBI_CAP, SAA7146_EXCLUSIVE }, - { VIDIOC_G_FMT, SAA7146_BEFORE }, - { VIDIOC_S_FMT, SAA7146_BEFORE }, - { 0, 0 } -}; - static u8 saa7113_init_regs[] = { 0x02, 0xd0, 0x03, 0x23, @@ -788,20 +779,34 @@ int av7110_init_analog_module(struct av7110 *av7110) int av7110_init_v4l(struct av7110 *av7110) { struct saa7146_dev* dev = av7110->dev; + struct saa7146_ext_vv *vv_data; int ret; /* special case DVB-C: these cards have an analog tuner plus need some special handling, so we have separate saa7146_ext_vv data for these... */ if (av7110->analog_tuner_flags) - ret = saa7146_vv_init(dev, &av7110_vv_data_c); + vv_data = &av7110_vv_data_c; else - ret = saa7146_vv_init(dev, &av7110_vv_data_st); + vv_data = &av7110_vv_data_st; + ret = saa7146_vv_init(dev, vv_data); if (ret) { ERR(("cannot init capture device. skipping.\n")); return -ENODEV; } + vv_data->ops.vidioc_enum_input = vidioc_enum_input; + vv_data->ops.vidioc_g_input = vidioc_g_input; + vv_data->ops.vidioc_s_input = vidioc_s_input; + vv_data->ops.vidioc_g_tuner = vidioc_g_tuner; + vv_data->ops.vidioc_s_tuner = vidioc_s_tuner; + vv_data->ops.vidioc_g_frequency = vidioc_g_frequency; + vv_data->ops.vidioc_s_frequency = vidioc_s_frequency; + vv_data->ops.vidioc_g_audio = vidioc_g_audio; + vv_data->ops.vidioc_s_audio = vidioc_s_audio; + vv_data->ops.vidioc_g_sliced_vbi_cap = vidioc_g_sliced_vbi_cap; + vv_data->ops.vidioc_g_fmt_sliced_vbi_out = vidioc_g_fmt_sliced_vbi_out; + vv_data->ops.vidioc_s_fmt_sliced_vbi_out = vidioc_s_fmt_sliced_vbi_out; if (saa7146_register_device(&av7110->v4l_dev, dev, "av7110", VFL_TYPE_GRABBER)) { ERR(("cannot register capture device. skipping.\n")); @@ -900,9 +905,6 @@ static struct saa7146_ext_vv av7110_vv_data_st = { .num_stds = ARRAY_SIZE(standard), .std_callback = &std_callback, - .ioctls = &ioctls[0], - .ioctl = av7110_ioctl, - .vbi_fops.open = av7110_vbi_reset, .vbi_fops.release = av7110_vbi_reset, .vbi_fops.write = av7110_vbi_write, @@ -918,9 +920,6 @@ static struct saa7146_ext_vv av7110_vv_data_c = { .num_stds = ARRAY_SIZE(standard), .std_callback = &std_callback, - .ioctls = &ioctls[0], - .ioctl = av7110_ioctl, - .vbi_fops.open = av7110_vbi_reset, .vbi_fops.release = av7110_vbi_reset, .vbi_fops.write = av7110_vbi_write, diff --git a/drivers/media/dvb/ttpci/budget-av.c b/drivers/media/dvb/ttpci/budget-av.c index 4182121d7e5d..855fe74b640b 100644 --- a/drivers/media/dvb/ttpci/budget-av.c +++ b/drivers/media/dvb/ttpci/budget-av.c @@ -1404,6 +1404,41 @@ static int budget_av_detach(struct saa7146_dev *dev) return err; } +#define KNC1_INPUTS 2 +static struct v4l2_input knc1_inputs[KNC1_INPUTS] = { + {0, "Composite", V4L2_INPUT_TYPE_TUNER, 1, 0, V4L2_STD_PAL_BG | V4L2_STD_NTSC_M, 0}, + {1, "S-Video", V4L2_INPUT_TYPE_CAMERA, 2, 0, V4L2_STD_PAL_BG | V4L2_STD_NTSC_M, 0}, +}; + +static int vidioc_enum_input(struct file *file, void *fh, struct v4l2_input *i) +{ + dprintk(1, "VIDIOC_ENUMINPUT %d.\n", i->index); + if (i->index < 0 || i->index >= KNC1_INPUTS) + return -EINVAL; + memcpy(i, &knc1_inputs[i->index], sizeof(struct v4l2_input)); + return 0; +} + +static int vidioc_g_input(struct file *file, void *fh, unsigned int *i) +{ + struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev; + struct budget_av *budget_av = (struct budget_av *)dev->ext_priv; + + *i = budget_av->cur_input; + + dprintk(1, "VIDIOC_G_INPUT %d.\n", *i); + return 0; +} + +static int vidioc_s_input(struct file *file, void *fh, unsigned int input) +{ + struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev; + struct budget_av *budget_av = (struct budget_av *)dev->ext_priv; + + dprintk(1, "VIDIOC_S_INPUT %d.\n", input); + return saa7113_setinput(budget_av, input); +} + static struct saa7146_ext_vv vv_data; static int budget_av_attach(struct saa7146_dev *dev, struct saa7146_pci_extension_data *info) @@ -1442,6 +1477,9 @@ static int budget_av_attach(struct saa7146_dev *dev, struct saa7146_pci_extensio ERR(("cannot init vv subsystem.\n")); return err; } + vv_data.ops.vidioc_enum_input = vidioc_enum_input; + vv_data.ops.vidioc_g_input = vidioc_g_input; + vv_data.ops.vidioc_s_input = vidioc_s_input; if ((err = saa7146_register_device(&budget_av->vd, dev, "knc1", VFL_TYPE_GRABBER))) { /* fixme: proper cleanup here */ @@ -1480,54 +1518,6 @@ static int budget_av_attach(struct saa7146_dev *dev, struct saa7146_pci_extensio return 0; } -#define KNC1_INPUTS 2 -static struct v4l2_input knc1_inputs[KNC1_INPUTS] = { - {0, "Composite", V4L2_INPUT_TYPE_TUNER, 1, 0, V4L2_STD_PAL_BG | V4L2_STD_NTSC_M, 0}, - {1, "S-Video", V4L2_INPUT_TYPE_CAMERA, 2, 0, V4L2_STD_PAL_BG | V4L2_STD_NTSC_M, 0}, -}; - -static struct saa7146_extension_ioctls ioctls[] = { - {VIDIOC_ENUMINPUT, SAA7146_EXCLUSIVE}, - {VIDIOC_G_INPUT, SAA7146_EXCLUSIVE}, - {VIDIOC_S_INPUT, SAA7146_EXCLUSIVE}, - {0, 0} -}; - -static long av_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg) -{ - struct saa7146_dev *dev = fh->dev; - struct budget_av *budget_av = (struct budget_av *) dev->ext_priv; - - switch (cmd) { - case VIDIOC_ENUMINPUT:{ - struct v4l2_input *i = arg; - - dprintk(1, "VIDIOC_ENUMINPUT %d.\n", i->index); - if (i->index < 0 || i->index >= KNC1_INPUTS) { - return -EINVAL; - } - memcpy(i, &knc1_inputs[i->index], sizeof(struct v4l2_input)); - return 0; - } - case VIDIOC_G_INPUT:{ - int *input = (int *) arg; - - *input = budget_av->cur_input; - - dprintk(1, "VIDIOC_G_INPUT %d.\n", *input); - return 0; - } - case VIDIOC_S_INPUT:{ - int input = *(int *) arg; - dprintk(1, "VIDIOC_S_INPUT %d.\n", input); - return saa7113_setinput(budget_av, input); - } - default: - return -ENOIOCTLCMD; - } - return 0; -} - static struct saa7146_standard standard[] = { {.name = "PAL",.id = V4L2_STD_PAL, .v_offset = 0x17,.v_field = 288, @@ -1546,8 +1536,6 @@ static struct saa7146_ext_vv vv_data = { .flags = 0, .stds = &standard[0], .num_stds = ARRAY_SIZE(standard), - .ioctls = &ioctls[0], - .ioctl = av_ioctl, }; static struct saa7146_extension budget_extension; diff --git a/drivers/media/video/hexium_gemini.c b/drivers/media/video/hexium_gemini.c index 79393d1772e4..8e1463ee1b64 100644 --- a/drivers/media/video/hexium_gemini.c +++ b/drivers/media/video/hexium_gemini.c @@ -56,17 +56,6 @@ struct hexium_data u8 byte; }; -static struct saa7146_extension_ioctls ioctls[] = { - { VIDIOC_G_INPUT, SAA7146_EXCLUSIVE }, - { VIDIOC_S_INPUT, SAA7146_EXCLUSIVE }, - { VIDIOC_QUERYCTRL, SAA7146_BEFORE }, - { VIDIOC_ENUMINPUT, SAA7146_EXCLUSIVE }, - { VIDIOC_S_STD, SAA7146_AFTER }, - { VIDIOC_G_CTRL, SAA7146_BEFORE }, - { VIDIOC_S_CTRL, SAA7146_BEFORE }, - { 0, 0 } -}; - #define HEXIUM_CONTROLS 1 static struct v4l2_queryctrl hexium_controls[] = { { V4L2_CID_PRIVATE_BASE, V4L2_CTRL_TYPE_BOOLEAN, "B/W", 0, 1, 1, 0, 0 }, @@ -231,6 +220,132 @@ static int hexium_set_standard(struct hexium *hexium, struct hexium_data *vdec) return 0; } +static int vidioc_enum_input(struct file *file, void *fh, struct v4l2_input *i) +{ + DEB_EE(("VIDIOC_ENUMINPUT %d.\n", i->index)); + + if (i->index < 0 || i->index >= HEXIUM_INPUTS) + return -EINVAL; + + memcpy(i, &hexium_inputs[i->index], sizeof(struct v4l2_input)); + + DEB_D(("v4l2_ioctl: VIDIOC_ENUMINPUT %d.\n", i->index)); + return 0; +} + +static int vidioc_g_input(struct file *file, void *fh, unsigned int *input) +{ + struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev; + struct hexium *hexium = (struct hexium *) dev->ext_priv; + + *input = hexium->cur_input; + + DEB_D(("VIDIOC_G_INPUT: %d\n", *input)); + return 0; +} + +static int vidioc_s_input(struct file *file, void *fh, unsigned int input) +{ + struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev; + struct hexium *hexium = (struct hexium *) dev->ext_priv; + + DEB_EE(("VIDIOC_S_INPUT %d.\n", input)); + + if (input < 0 || input >= HEXIUM_INPUTS) + return -EINVAL; + + hexium->cur_input = input; + hexium_set_input(hexium, input); + return 0; +} + +/* the saa7146 provides some controls (brightness, contrast, saturation) + which gets registered *after* this function. because of this we have + to return with a value != 0 even if the function succeded.. */ +static int vidioc_queryctrl(struct file *file, void *fh, struct v4l2_queryctrl *qc) +{ + struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev; + int i; + + for (i = HEXIUM_CONTROLS - 1; i >= 0; i--) { + if (hexium_controls[i].id == qc->id) { + *qc = hexium_controls[i]; + DEB_D(("VIDIOC_QUERYCTRL %d.\n", qc->id)); + return 0; + } + } + return dev->ext_vv_data->core_ops->vidioc_queryctrl(file, fh, qc); +} + +static int vidioc_g_ctrl(struct file *file, void *fh, struct v4l2_control *vc) +{ + struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev; + struct hexium *hexium = (struct hexium *) dev->ext_priv; + int i; + + for (i = HEXIUM_CONTROLS - 1; i >= 0; i--) { + if (hexium_controls[i].id == vc->id) + break; + } + + if (i < 0) + return dev->ext_vv_data->core_ops->vidioc_g_ctrl(file, fh, vc); + + if (vc->id == V4L2_CID_PRIVATE_BASE) { + vc->value = hexium->cur_bw; + DEB_D(("VIDIOC_G_CTRL BW:%d.\n", vc->value)); + return 0; + } + return -EINVAL; +} + +static int vidioc_s_ctrl(struct file *file, void *fh, struct v4l2_control *vc) +{ + struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev; + struct hexium *hexium = (struct hexium *) dev->ext_priv; + int i = 0; + + for (i = HEXIUM_CONTROLS - 1; i >= 0; i--) { + if (hexium_controls[i].id == vc->id) + break; + } + + if (i < 0) + return dev->ext_vv_data->core_ops->vidioc_s_ctrl(file, fh, vc); + + if (vc->id == V4L2_CID_PRIVATE_BASE) + hexium->cur_bw = vc->value; + + DEB_D(("VIDIOC_S_CTRL BW:%d.\n", hexium->cur_bw)); + + if (0 == hexium->cur_bw && V4L2_STD_PAL == hexium->cur_std) { + hexium_set_standard(hexium, hexium_pal); + return 0; + } + if (0 == hexium->cur_bw && V4L2_STD_NTSC == hexium->cur_std) { + hexium_set_standard(hexium, hexium_ntsc); + return 0; + } + if (0 == hexium->cur_bw && V4L2_STD_SECAM == hexium->cur_std) { + hexium_set_standard(hexium, hexium_secam); + return 0; + } + if (1 == hexium->cur_bw && V4L2_STD_PAL == hexium->cur_std) { + hexium_set_standard(hexium, hexium_pal_bw); + return 0; + } + if (1 == hexium->cur_bw && V4L2_STD_NTSC == hexium->cur_std) { + hexium_set_standard(hexium, hexium_ntsc_bw); + return 0; + } + if (1 == hexium->cur_bw && V4L2_STD_SECAM == hexium->cur_std) + /* fixme: is there no bw secam mode? */ + return -EINVAL; + + return -EINVAL; +} + + static struct saa7146_ext_vv vv_data; /* this function only gets called when the probing was successful */ @@ -279,6 +394,12 @@ static int hexium_attach(struct saa7146_dev *dev, struct saa7146_pci_extension_d hexium->cur_input = 0; saa7146_vv_init(dev, &vv_data); + vv_data.ops.vidioc_queryctrl = vidioc_queryctrl; + vv_data.ops.vidioc_g_ctrl = vidioc_g_ctrl; + vv_data.ops.vidioc_s_ctrl = vidioc_s_ctrl; + vv_data.ops.vidioc_enum_input = vidioc_enum_input; + vv_data.ops.vidioc_g_input = vidioc_g_input; + vv_data.ops.vidioc_s_input = vidioc_s_input; if (0 != saa7146_register_device(&hexium->video_dev, dev, "hexium gemini", VFL_TYPE_GRABBER)) { printk("hexium_gemini: cannot register capture v4l2 device. skipping.\n"); return -1; @@ -306,153 +427,6 @@ static int hexium_detach(struct saa7146_dev *dev) return 0; } -static long hexium_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg) -{ - struct saa7146_dev *dev = fh->dev; - struct hexium *hexium = (struct hexium *) dev->ext_priv; -/* - struct saa7146_vv *vv = dev->vv_data; -*/ - switch (cmd) { - case VIDIOC_ENUMINPUT: - { - struct v4l2_input *i = arg; - DEB_EE(("VIDIOC_ENUMINPUT %d.\n", i->index)); - - if (i->index < 0 || i->index >= HEXIUM_INPUTS) { - return -EINVAL; - } - - memcpy(i, &hexium_inputs[i->index], sizeof(struct v4l2_input)); - - DEB_D(("v4l2_ioctl: VIDIOC_ENUMINPUT %d.\n", i->index)); - return 0; - } - case VIDIOC_G_INPUT: - { - int *input = (int *) arg; - *input = hexium->cur_input; - - DEB_D(("VIDIOC_G_INPUT: %d\n", *input)); - return 0; - } - case VIDIOC_S_INPUT: - { - int input = *(int *) arg; - - DEB_EE(("VIDIOC_S_INPUT %d.\n", input)); - - if (input < 0 || input >= HEXIUM_INPUTS) { - return -EINVAL; - } - - hexium->cur_input = input; - hexium_set_input(hexium, input); - - return 0; - } - /* the saa7146 provides some controls (brightness, contrast, saturation) - which gets registered *after* this function. because of this we have - to return with a value != 0 even if the function succeded.. */ - case VIDIOC_QUERYCTRL: - { - struct v4l2_queryctrl *qc = arg; - int i; - - for (i = HEXIUM_CONTROLS - 1; i >= 0; i--) { - if (hexium_controls[i].id == qc->id) { - *qc = hexium_controls[i]; - DEB_D(("VIDIOC_QUERYCTRL %d.\n", qc->id)); - return 0; - } - } - return -EAGAIN; - } - case VIDIOC_G_CTRL: - { - struct v4l2_control *vc = arg; - int i; - - for (i = HEXIUM_CONTROLS - 1; i >= 0; i--) { - if (hexium_controls[i].id == vc->id) { - break; - } - } - - if (i < 0) { - return -EAGAIN; - } - - switch (vc->id) { - case V4L2_CID_PRIVATE_BASE:{ - vc->value = hexium->cur_bw; - DEB_D(("VIDIOC_G_CTRL BW:%d.\n", vc->value)); - return 0; - } - } - return -EINVAL; - } - - case VIDIOC_S_CTRL: - { - struct v4l2_control *vc = arg; - int i = 0; - - for (i = HEXIUM_CONTROLS - 1; i >= 0; i--) { - if (hexium_controls[i].id == vc->id) { - break; - } - } - - if (i < 0) { - return -EAGAIN; - } - - switch (vc->id) { - case V4L2_CID_PRIVATE_BASE:{ - hexium->cur_bw = vc->value; - break; - } - } - - DEB_D(("VIDIOC_S_CTRL BW:%d.\n", hexium->cur_bw)); - - if (0 == hexium->cur_bw && V4L2_STD_PAL == hexium->cur_std) { - hexium_set_standard(hexium, hexium_pal); - return 0; - } - if (0 == hexium->cur_bw && V4L2_STD_NTSC == hexium->cur_std) { - hexium_set_standard(hexium, hexium_ntsc); - return 0; - } - if (0 == hexium->cur_bw && V4L2_STD_SECAM == hexium->cur_std) { - hexium_set_standard(hexium, hexium_secam); - return 0; - } - if (1 == hexium->cur_bw && V4L2_STD_PAL == hexium->cur_std) { - hexium_set_standard(hexium, hexium_pal_bw); - return 0; - } - if (1 == hexium->cur_bw && V4L2_STD_NTSC == hexium->cur_std) { - hexium_set_standard(hexium, hexium_ntsc_bw); - return 0; - } - if (1 == hexium->cur_bw && V4L2_STD_SECAM == hexium->cur_std) { - /* fixme: is there no bw secam mode? */ - return -EINVAL; - } - - return -EINVAL; - } - default: -/* - DEB_D(("hexium_ioctl() does not handle this ioctl.\n")); -*/ - return -ENOIOCTLCMD; - } - return 0; -} - static int std_callback(struct saa7146_dev *dev, struct saa7146_standard *std) { struct hexium *hexium = (struct hexium *) dev->ext_priv; @@ -514,8 +488,6 @@ static struct saa7146_ext_vv vv_data = { .stds = &hexium_standards[0], .num_stds = sizeof(hexium_standards) / sizeof(struct saa7146_standard), .std_callback = &std_callback, - .ioctls = &ioctls[0], - .ioctl = hexium_ioctl, }; static struct saa7146_extension hexium_extension = { diff --git a/drivers/media/video/hexium_orion.c b/drivers/media/video/hexium_orion.c index 074bec711fe0..2bc39f628455 100644 --- a/drivers/media/video/hexium_orion.c +++ b/drivers/media/video/hexium_orion.c @@ -57,14 +57,6 @@ struct hexium_data u8 byte; }; -static struct saa7146_extension_ioctls ioctls[] = { - { VIDIOC_G_INPUT, SAA7146_EXCLUSIVE }, - { VIDIOC_S_INPUT, SAA7146_EXCLUSIVE }, - { VIDIOC_ENUMINPUT, SAA7146_EXCLUSIVE }, - { VIDIOC_S_STD, SAA7146_AFTER }, - { 0, 0 } -}; - struct hexium { int type; @@ -329,6 +321,44 @@ static int hexium_set_input(struct hexium *hexium, int input) return 0; } +static int vidioc_enum_input(struct file *file, void *fh, struct v4l2_input *i) +{ + DEB_EE(("VIDIOC_ENUMINPUT %d.\n", i->index)); + + if (i->index < 0 || i->index >= HEXIUM_INPUTS) + return -EINVAL; + + memcpy(i, &hexium_inputs[i->index], sizeof(struct v4l2_input)); + + DEB_D(("v4l2_ioctl: VIDIOC_ENUMINPUT %d.\n", i->index)); + return 0; +} + +static int vidioc_g_input(struct file *file, void *fh, unsigned int *input) +{ + struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev; + struct hexium *hexium = (struct hexium *) dev->ext_priv; + + *input = hexium->cur_input; + + DEB_D(("VIDIOC_G_INPUT: %d\n", *input)); + return 0; +} + +static int vidioc_s_input(struct file *file, void *fh, unsigned int input) +{ + struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev; + struct hexium *hexium = (struct hexium *) dev->ext_priv; + + if (input < 0 || input >= HEXIUM_INPUTS) + return -EINVAL; + + hexium->cur_input = input; + hexium_set_input(hexium, input); + + return 0; +} + static struct saa7146_ext_vv vv_data; /* this function only gets called when the probing was successful */ @@ -339,6 +369,9 @@ static int hexium_attach(struct saa7146_dev *dev, struct saa7146_pci_extension_d DEB_EE((".\n")); saa7146_vv_init(dev, &vv_data); + vv_data.ops.vidioc_enum_input = vidioc_enum_input; + vv_data.ops.vidioc_g_input = vidioc_g_input; + vv_data.ops.vidioc_s_input = vidioc_s_input; if (0 != saa7146_register_device(&hexium->video_dev, dev, "hexium orion", VFL_TYPE_GRABBER)) { printk("hexium_orion: cannot register capture v4l2 device. skipping.\n"); return -1; @@ -370,58 +403,6 @@ static int hexium_detach(struct saa7146_dev *dev) return 0; } -static long hexium_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg) -{ - struct saa7146_dev *dev = fh->dev; - struct hexium *hexium = (struct hexium *) dev->ext_priv; -/* - struct saa7146_vv *vv = dev->vv_data; -*/ - switch (cmd) { - case VIDIOC_ENUMINPUT: - { - struct v4l2_input *i = arg; - DEB_EE(("VIDIOC_ENUMINPUT %d.\n", i->index)); - - if (i->index < 0 || i->index >= HEXIUM_INPUTS) { - return -EINVAL; - } - - memcpy(i, &hexium_inputs[i->index], sizeof(struct v4l2_input)); - - DEB_D(("v4l2_ioctl: VIDIOC_ENUMINPUT %d.\n", i->index)); - return 0; - } - case VIDIOC_G_INPUT: - { - int *input = (int *) arg; - *input = hexium->cur_input; - - DEB_D(("VIDIOC_G_INPUT: %d\n", *input)); - return 0; - } - case VIDIOC_S_INPUT: - { - int input = *(int *) arg; - - if (input < 0 || input >= HEXIUM_INPUTS) { - return -EINVAL; - } - - hexium->cur_input = input; - hexium_set_input(hexium, input); - - return 0; - } - default: -/* - DEB_D(("hexium_ioctl() does not handle this ioctl.\n")); -*/ - return -ENOIOCTLCMD; - } - return 0; -} - static int std_callback(struct saa7146_dev *dev, struct saa7146_standard *std) { return 0; @@ -479,8 +460,6 @@ static struct saa7146_ext_vv vv_data = { .stds = &hexium_standards[0], .num_stds = sizeof(hexium_standards) / sizeof(struct saa7146_standard), .std_callback = &std_callback, - .ioctls = &ioctls[0], - .ioctl = hexium_ioctl, }; static struct saa7146_extension extension = { diff --git a/drivers/media/video/mxb.c b/drivers/media/video/mxb.c index e3cbe14c349a..8ecda8dfbd04 100644 --- a/drivers/media/video/mxb.c +++ b/drivers/media/video/mxb.c @@ -110,26 +110,6 @@ static struct v4l2_queryctrl mxb_controls[] = { { V4L2_CID_AUDIO_MUTE, V4L2_CTRL_TYPE_BOOLEAN, "Mute", 0, 1, 1, 0, 0 }, }; -static struct saa7146_extension_ioctls ioctls[] = { - { VIDIOC_ENUMINPUT, SAA7146_EXCLUSIVE }, - { VIDIOC_G_INPUT, SAA7146_EXCLUSIVE }, - { VIDIOC_S_INPUT, SAA7146_EXCLUSIVE }, - { VIDIOC_QUERYCTRL, SAA7146_BEFORE }, - { VIDIOC_G_CTRL, SAA7146_BEFORE }, - { VIDIOC_S_CTRL, SAA7146_BEFORE }, - { VIDIOC_G_TUNER, SAA7146_EXCLUSIVE }, - { VIDIOC_S_TUNER, SAA7146_EXCLUSIVE }, - { VIDIOC_G_FREQUENCY, SAA7146_EXCLUSIVE }, - { VIDIOC_S_FREQUENCY, SAA7146_EXCLUSIVE }, - { VIDIOC_G_AUDIO, SAA7146_EXCLUSIVE }, - { VIDIOC_S_AUDIO, SAA7146_EXCLUSIVE }, - { VIDIOC_DBG_G_REGISTER, SAA7146_EXCLUSIVE }, - { VIDIOC_DBG_S_REGISTER, SAA7146_EXCLUSIVE }, - { MXB_S_AUDIO_CD, SAA7146_EXCLUSIVE }, /* custom control */ - { MXB_S_AUDIO_LINE, SAA7146_EXCLUSIVE }, /* custom control */ - { 0, 0 } -}; - struct mxb { struct video_device *video_dev; @@ -424,387 +404,430 @@ void mxb_irq_bh(struct saa7146_dev* dev, u32* irq_mask) } */ -static struct saa7146_ext_vv vv_data; - -/* this function only gets called when the probing was successful */ -static int mxb_attach(struct saa7146_dev *dev, struct saa7146_pci_extension_data *info) +static int vidioc_queryctrl(struct file *file, void *fh, struct v4l2_queryctrl *qc) { - struct mxb *mxb = (struct mxb *)dev->ext_priv; + struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev; + int i; - DEB_EE(("dev:%p\n", dev)); + for (i = MAXCONTROLS - 1; i >= 0; i--) { + if (mxb_controls[i].id == qc->id) { + *qc = mxb_controls[i]; + DEB_D(("VIDIOC_QUERYCTRL %d.\n", qc->id)); + return 0; + } + } + return dev->ext_vv_data->core_ops->vidioc_queryctrl(file, fh, qc); +} - /* checking for i2c-devices can be omitted here, because we - already did this in "mxb_vl42_probe" */ +static int vidioc_g_ctrl(struct file *file, void *fh, struct v4l2_control *vc) +{ + struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev; + struct mxb *mxb = (struct mxb *)dev->ext_priv; + int i; - saa7146_vv_init(dev, &vv_data); - if (saa7146_register_device(&mxb->video_dev, dev, "mxb", VFL_TYPE_GRABBER)) { - ERR(("cannot register capture v4l2 device. skipping.\n")); - return -1; + for (i = MAXCONTROLS - 1; i >= 0; i--) { + if (mxb_controls[i].id == vc->id) + break; } - /* initialization stuff (vbi) (only for revision > 0 and for extensions which want it)*/ - if (MXB_BOARD_CAN_DO_VBI(dev)) { - if (saa7146_register_device(&mxb->vbi_dev, dev, "mxb", VFL_TYPE_VBI)) { - ERR(("cannot register vbi v4l2 device. skipping.\n")); - } - } + if (i < 0) + return dev->ext_vv_data->core_ops->vidioc_g_ctrl(file, fh, vc); - i2c_use_client(mxb->tea6420_1); - i2c_use_client(mxb->tea6420_2); - i2c_use_client(mxb->tea6415c); - i2c_use_client(mxb->tda9840); - i2c_use_client(mxb->saa7111a); - i2c_use_client(mxb->tuner); - - printk("mxb: found Multimedia eXtension Board #%d.\n", mxb_num); + if (vc->id == V4L2_CID_AUDIO_MUTE) { + vc->value = mxb->cur_mute; + DEB_D(("VIDIOC_G_CTRL V4L2_CID_AUDIO_MUTE:%d.\n", vc->value)); + return 0; + } - mxb_num++; - mxb_init_done(dev); + DEB_EE(("VIDIOC_G_CTRL V4L2_CID_AUDIO_MUTE:%d.\n", vc->value)); return 0; } -static int mxb_detach(struct saa7146_dev *dev) +static int vidioc_s_ctrl(struct file *file, void *fh, struct v4l2_control *vc) { + struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev; struct mxb *mxb = (struct mxb *)dev->ext_priv; + int i = 0; - DEB_EE(("dev:%p\n", dev)); - - i2c_release_client(mxb->tea6420_1); - i2c_release_client(mxb->tea6420_2); - i2c_release_client(mxb->tea6415c); - i2c_release_client(mxb->tda9840); - i2c_release_client(mxb->saa7111a); - i2c_release_client(mxb->tuner); - - saa7146_unregister_device(&mxb->video_dev,dev); - if (MXB_BOARD_CAN_DO_VBI(dev)) - saa7146_unregister_device(&mxb->vbi_dev, dev); - saa7146_vv_release(dev); + for (i = MAXCONTROLS - 1; i >= 0; i--) { + if (mxb_controls[i].id == vc->id) + break; + } - mxb_num--; + if (i < 0) + return dev->ext_vv_data->core_ops->vidioc_s_ctrl(file, fh, vc); - i2c_del_adapter(&mxb->i2c_adapter); - kfree(mxb); + if (vc->id == V4L2_CID_AUDIO_MUTE) { + mxb->cur_mute = vc->value; + if (!vc->value) { + /* switch the audio-source */ + mxb->tea6420_1->driver->command(mxb->tea6420_1, TEA6420_SWITCH, + &TEA6420_line[video_audio_connect[mxb->cur_input]][0]); + mxb->tea6420_2->driver->command(mxb->tea6420_2, TEA6420_SWITCH, + &TEA6420_line[video_audio_connect[mxb->cur_input]][1]); + } else { + mxb->tea6420_1->driver->command(mxb->tea6420_1, TEA6420_SWITCH, + &TEA6420_line[6][0]); + mxb->tea6420_2->driver->command(mxb->tea6420_2, TEA6420_SWITCH, + &TEA6420_line[6][1]); + } + DEB_EE(("VIDIOC_S_CTRL, V4L2_CID_AUDIO_MUTE: %d.\n", vc->value)); + } + return 0; +} +static int vidioc_enum_input(struct file *file, void *fh, struct v4l2_input *i) +{ + DEB_EE(("VIDIOC_ENUMINPUT %d.\n", i->index)); + if (i->index < 0 || i->index >= MXB_INPUTS) + return -EINVAL; + memcpy(i, &mxb_inputs[i->index], sizeof(struct v4l2_input)); return 0; } -static long mxb_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg) +static int vidioc_g_input(struct file *file, void *fh, unsigned int *i) { - struct saa7146_dev *dev = fh->dev; + struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev; struct mxb *mxb = (struct mxb *)dev->ext_priv; - struct saa7146_vv *vv = dev->vv_data; + *i = mxb->cur_input; - switch(cmd) { - case VIDIOC_ENUMINPUT: - { - struct v4l2_input *i = arg; + DEB_EE(("VIDIOC_G_INPUT %d.\n", *i)); + return 0; +} - DEB_EE(("VIDIOC_ENUMINPUT %d.\n",i->index)); - if (i->index < 0 || i->index >= MXB_INPUTS) - return -EINVAL; - memcpy(i, &mxb_inputs[i->index], sizeof(struct v4l2_input)); - return 0; - } - /* the saa7146 provides some controls (brightness, contrast, saturation) - which gets registered *after* this function. because of this we have - to return with a value != 0 even if the function succeded.. */ - case VIDIOC_QUERYCTRL: - { - struct v4l2_queryctrl *qc = arg; - int i; - - for (i = MAXCONTROLS - 1; i >= 0; i--) { - if (mxb_controls[i].id == qc->id) { - *qc = mxb_controls[i]; - DEB_D(("VIDIOC_QUERYCTRL %d.\n", qc->id)); - return 0; - } - } - return -EAGAIN; - } - case VIDIOC_G_CTRL: - { - struct v4l2_control *vc = arg; - int i; +static int vidioc_s_input(struct file *file, void *fh, unsigned int input) +{ + struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev; + struct mxb *mxb = (struct mxb *)dev->ext_priv; + struct tea6415c_multiplex vm; + struct v4l2_routing route; + int i = 0; - for (i = MAXCONTROLS - 1; i >= 0; i--) { - if (mxb_controls[i].id == vc->id) - break; - } + DEB_EE(("VIDIOC_S_INPUT %d.\n", input)); - if (i < 0) - return -EAGAIN; + if (input < 0 || input >= MXB_INPUTS) + return -EINVAL; - if (vc->id == V4L2_CID_AUDIO_MUTE) { - vc->value = mxb->cur_mute; - DEB_D(("VIDIOC_G_CTRL V4L2_CID_AUDIO_MUTE:%d.\n", vc->value)); - return 0; - } + mxb->cur_input = input; - DEB_EE(("VIDIOC_G_CTRL V4L2_CID_AUDIO_MUTE:%d.\n", vc->value)); - return 0; - } + saa7146_set_hps_source_and_sync(dev, input_port_selection[input].hps_source, + input_port_selection[input].hps_sync); - case VIDIOC_S_CTRL: - { - struct v4l2_control *vc = arg; - int i = 0; + /* prepare switching of tea6415c and saa7111a; + have a look at the 'background'-file for further informations */ + switch (input) { + case TUNER: + i = SAA7115_COMPOSITE0; + vm.in = 3; + vm.out = 17; - for (i = MAXCONTROLS - 1; i >= 0; i--) { - if (mxb_controls[i].id == vc->id) - break; + if (mxb->tea6415c->driver->command(mxb->tea6415c, TEA6415C_SWITCH, &vm)) { + printk(KERN_ERR "VIDIOC_S_INPUT: could not address tea6415c #1\n"); + return -EFAULT; } + /* connect tuner-output always to multicable */ + vm.in = 3; + vm.out = 13; + break; + case AUX3_YC: + /* nothing to be done here. aux3_yc is + directly connected to the saa711a */ + i = SAA7115_SVIDEO1; + break; + case AUX3: + /* nothing to be done here. aux3 is + directly connected to the saa711a */ + i = SAA7115_COMPOSITE1; + break; + case AUX1: + i = SAA7115_COMPOSITE0; + vm.in = 1; + vm.out = 17; + break; + } - if (i < 0) - return -EAGAIN; - - if (vc->id == V4L2_CID_AUDIO_MUTE) { - mxb->cur_mute = vc->value; - if (!vc->value) { - /* switch the audio-source */ - mxb->tea6420_1->driver->command(mxb->tea6420_1, TEA6420_SWITCH, - &TEA6420_line[video_audio_connect[mxb->cur_input]][0]); - mxb->tea6420_2->driver->command(mxb->tea6420_2, TEA6420_SWITCH, - &TEA6420_line[video_audio_connect[mxb->cur_input]][1]); - } else { - mxb->tea6420_1->driver->command(mxb->tea6420_1, TEA6420_SWITCH, - &TEA6420_line[6][0]); - mxb->tea6420_2->driver->command(mxb->tea6420_2, TEA6420_SWITCH, - &TEA6420_line[6][1]); - } - DEB_EE(("VIDIOC_S_CTRL, V4L2_CID_AUDIO_MUTE: %d.\n", vc->value)); + /* switch video in tea6415c only if necessary */ + switch (input) { + case TUNER: + case AUX1: + if (mxb->tea6415c->driver->command(mxb->tea6415c, TEA6415C_SWITCH, &vm)) { + printk(KERN_ERR "VIDIOC_S_INPUT: could not address tea6415c #3\n"); + return -EFAULT; } - return 0; + break; + default: + break; } - case VIDIOC_G_INPUT: - { - int *input = (int *)arg; - *input = mxb->cur_input; - DEB_EE(("VIDIOC_G_INPUT %d.\n", *input)); - return 0; + /* switch video in saa7111a */ + route.input = i; + route.output = 0; + if (mxb->saa7111a->driver->command(mxb->saa7111a, VIDIOC_INT_S_VIDEO_ROUTING, &route)) + printk(KERN_ERR "VIDIOC_S_INPUT: could not address saa7111a #1.\n"); + + /* switch the audio-source only if necessary */ + if (0 == mxb->cur_mute) { + mxb->tea6420_1->driver->command(mxb->tea6420_1, TEA6420_SWITCH, + &TEA6420_line[video_audio_connect[input]][0]); + mxb->tea6420_2->driver->command(mxb->tea6420_2, TEA6420_SWITCH, + &TEA6420_line[video_audio_connect[input]][1]); } - case VIDIOC_S_INPUT: - { - int input = *(int *)arg; - struct tea6415c_multiplex vm; - struct v4l2_routing route; - int i = 0; - DEB_EE(("VIDIOC_S_INPUT %d.\n", input)); + return 0; +} - if (input < 0 || input >= MXB_INPUTS) - return -EINVAL; +static int vidioc_g_tuner(struct file *file, void *fh, struct v4l2_tuner *t) +{ + struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev; + struct mxb *mxb = (struct mxb *)dev->ext_priv; - mxb->cur_input = input; + if (t->index) { + DEB_D(("VIDIOC_G_TUNER: channel %d does not have a tuner attached.\n", t->index)); + return -EINVAL; + } - saa7146_set_hps_source_and_sync(dev, input_port_selection[input].hps_source, - input_port_selection[input].hps_sync); + DEB_EE(("VIDIOC_G_TUNER: %d\n", t->index)); - /* prepare switching of tea6415c and saa7111a; - have a look at the 'background'-file for further informations */ - switch (input) { - case TUNER: - i = SAA7115_COMPOSITE0; - vm.in = 3; - vm.out = 17; + memset(t, 0, sizeof(*t)); + i2c_clients_command(&mxb->i2c_adapter, VIDIOC_G_TUNER, t); - if (mxb->tea6415c->driver->command(mxb->tea6415c, TEA6415C_SWITCH, &vm)) { - printk(KERN_ERR "VIDIOC_S_INPUT: could not address tea6415c #1\n"); - return -EFAULT; - } - /* connect tuner-output always to multicable */ - vm.in = 3; - vm.out = 13; - break; - case AUX3_YC: - /* nothing to be done here. aux3_yc is - directly connected to the saa711a */ - i = SAA7115_SVIDEO1; - break; - case AUX3: - /* nothing to be done here. aux3 is - directly connected to the saa711a */ - i = SAA7115_COMPOSITE1; - break; - case AUX1: - i = SAA7115_COMPOSITE0; - vm.in = 1; - vm.out = 17; - break; - } + strlcpy(t->name, "TV Tuner", sizeof(t->name)); + t->type = V4L2_TUNER_ANALOG_TV; + t->capability = V4L2_TUNER_CAP_NORM | V4L2_TUNER_CAP_STEREO | + V4L2_TUNER_CAP_LANG1 | V4L2_TUNER_CAP_LANG2 | V4L2_TUNER_CAP_SAP; + t->audmode = mxb->cur_mode; + return 0; +} - /* switch video in tea6415c only if necessary */ - switch (input) { - case TUNER: - case AUX1: - if (mxb->tea6415c->driver->command(mxb->tea6415c, TEA6415C_SWITCH, &vm)) { - printk(KERN_ERR "VIDIOC_S_INPUT: could not address tea6415c #3\n"); - return -EFAULT; - } - break; - default: - break; - } +static int vidioc_s_tuner(struct file *file, void *fh, struct v4l2_tuner *t) +{ + struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev; + struct mxb *mxb = (struct mxb *)dev->ext_priv; - /* switch video in saa7111a */ - route.input = i; - route.output = 0; - if (mxb->saa7111a->driver->command(mxb->saa7111a, VIDIOC_INT_S_VIDEO_ROUTING, &route)) - printk("VIDIOC_S_INPUT: could not address saa7111a #1.\n"); + if (t->index) { + DEB_D(("VIDIOC_S_TUNER: channel %d does not have a tuner attached.\n", t->index)); + return -EINVAL; + } - /* switch the audio-source only if necessary */ - if( 0 == mxb->cur_mute ) { - mxb->tea6420_1->driver->command(mxb->tea6420_1, TEA6420_SWITCH, - &TEA6420_line[video_audio_connect[input]][0]); - mxb->tea6420_2->driver->command(mxb->tea6420_2, TEA6420_SWITCH, - &TEA6420_line[video_audio_connect[input]][1]); - } + mxb->cur_mode = t->audmode; + i2c_clients_command(&mxb->i2c_adapter, VIDIOC_S_TUNER, t); + return 0; +} - return 0; +static int vidioc_g_frequency(struct file *file, void *fh, struct v4l2_frequency *f) +{ + struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev; + struct mxb *mxb = (struct mxb *)dev->ext_priv; + + if (mxb->cur_input) { + DEB_D(("VIDIOC_G_FREQ: channel %d does not have a tuner!\n", + mxb->cur_input)); + return -EINVAL; } - case VIDIOC_G_TUNER: - { - struct v4l2_tuner *t = arg; - if (t->index) { - DEB_D(("VIDIOC_G_TUNER: channel %d does not have a tuner attached.\n", t->index)); - return -EINVAL; - } + *f = mxb->cur_freq; - DEB_EE(("VIDIOC_G_TUNER: %d\n", t->index)); + DEB_EE(("VIDIOC_G_FREQ: freq:0x%08x.\n", mxb->cur_freq.frequency)); + return 0; +} - memset(t, 0, sizeof(*t)); - i2c_clients_command(&mxb->i2c_adapter, cmd, arg); +static int vidioc_s_frequency(struct file *file, void *fh, struct v4l2_frequency *f) +{ + struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev; + struct mxb *mxb = (struct mxb *)dev->ext_priv; + struct saa7146_vv *vv = dev->vv_data; - strlcpy(t->name, "TV Tuner", sizeof(t->name)); - t->type = V4L2_TUNER_ANALOG_TV; - t->capability = V4L2_TUNER_CAP_NORM | V4L2_TUNER_CAP_STEREO | \ - V4L2_TUNER_CAP_LANG1 | V4L2_TUNER_CAP_LANG2 | V4L2_TUNER_CAP_SAP; - t->audmode = mxb->cur_mode; - return 0; - } - case VIDIOC_S_TUNER: - { - struct v4l2_tuner *t = arg; + if (f->tuner) + return -EINVAL; - if (t->index) { - DEB_D(("VIDIOC_S_TUNER: channel %d does not have a tuner attached.\n",t->index)); - return -EINVAL; - } + if (V4L2_TUNER_ANALOG_TV != f->type) + return -EINVAL; - mxb->cur_mode = t->audmode; - i2c_clients_command(&mxb->i2c_adapter, cmd, arg); - return 0; + if (mxb->cur_input) { + DEB_D(("VIDIOC_S_FREQ: channel %d does not have a tuner!\n", mxb->cur_input)); + return -EINVAL; } - case VIDIOC_G_FREQUENCY: - { - struct v4l2_frequency *f = arg; - if (mxb->cur_input) { - DEB_D(("VIDIOC_G_FREQ: channel %d does not have a tuner!\n", - mxb->cur_input)); - return -EINVAL; - } + mxb->cur_freq = *f; + DEB_EE(("VIDIOC_S_FREQUENCY: freq:0x%08x.\n", mxb->cur_freq.frequency)); - *f = mxb->cur_freq; + /* tune in desired frequency */ + mxb->tuner->driver->command(mxb->tuner, VIDIOC_S_FREQUENCY, &mxb->cur_freq); - DEB_EE(("VIDIOC_G_FREQ: freq:0x%08x.\n", mxb->cur_freq.frequency)); - return 0; + /* hack: changing the frequency should invalidate the vbi-counter (=> alevt) */ + spin_lock(&dev->slock); + vv->vbi_fieldcount = 0; + spin_unlock(&dev->slock); + + return 0; +} + +static int vidioc_g_audio(struct file *file, void *fh, struct v4l2_audio *a) +{ + struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev; + struct mxb *mxb = (struct mxb *)dev->ext_priv; + + if (a->index < 0 || a->index > MXB_INPUTS) { + DEB_D(("VIDIOC_G_AUDIO %d out of range.\n", a->index)); + return -EINVAL; } - case VIDIOC_S_FREQUENCY: - { - struct v4l2_frequency *f = arg; - if (f->tuner) - return -EINVAL; + DEB_EE(("VIDIOC_G_AUDIO %d.\n", a->index)); + memcpy(a, &mxb_audios[video_audio_connect[mxb->cur_input]], sizeof(struct v4l2_audio)); + return 0; +} - if (V4L2_TUNER_ANALOG_TV != f->type) - return -EINVAL; +static int vidioc_s_audio(struct file *file, void *fh, struct v4l2_audio *a) +{ + DEB_D(("VIDIOC_S_AUDIO %d.\n", a->index)); + return 0; +} - if (mxb->cur_input) { - DEB_D(("VIDIOC_S_FREQ: channel %d does not have a tuner!\n", mxb->cur_input)); - return -EINVAL; - } +#ifdef CONFIG_VIDEO_ADV_DEBUG +static int vidioc_g_register(struct file *file, void *fh, struct v4l2_dbg_register *reg) +{ + struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev; + struct mxb *mxb = (struct mxb *)dev->ext_priv; - mxb->cur_freq = *f; - DEB_EE(("VIDIOC_S_FREQUENCY: freq:0x%08x.\n", mxb->cur_freq.frequency)); + i2c_clients_command(&mxb->i2c_adapter, VIDIOC_DBG_G_REGISTER, reg); + return 0; +} - /* tune in desired frequency */ - mxb->tuner->driver->command(mxb->tuner, VIDIOC_S_FREQUENCY, &mxb->cur_freq); +static int vidioc_s_register(struct file *file, void *fh, struct v4l2_dbg_register *reg) +{ + struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev; + struct mxb *mxb = (struct mxb *)dev->ext_priv; - /* hack: changing the frequency should invalidate the vbi-counter (=> alevt) */ - spin_lock(&dev->slock); - vv->vbi_fieldcount = 0; - spin_unlock(&dev->slock); + i2c_clients_command(&mxb->i2c_adapter, VIDIOC_DBG_S_REGISTER, reg); + return 0; +} +#endif - return 0; - } +static long vidioc_default(struct file *file, void *fh, int cmd, void *arg) +{ + struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev; + struct mxb *mxb = (struct mxb *)dev->ext_priv; + + switch (cmd) { case MXB_S_AUDIO_CD: { - int i = *(int*)arg; + int i = *(int *)arg; if (i < 0 || i >= MXB_AUDIOS) { - DEB_D(("illegal argument to MXB_S_AUDIO_CD: i:%d.\n",i)); + DEB_D(("illegal argument to MXB_S_AUDIO_CD: i:%d.\n", i)); return -EINVAL; } - DEB_EE(("MXB_S_AUDIO_CD: i:%d.\n",i)); + DEB_EE(("MXB_S_AUDIO_CD: i:%d.\n", i)); - mxb->tea6420_1->driver->command(mxb->tea6420_1,TEA6420_SWITCH, &TEA6420_cd[i][0]); - mxb->tea6420_2->driver->command(mxb->tea6420_2,TEA6420_SWITCH, &TEA6420_cd[i][1]); + mxb->tea6420_1->driver->command(mxb->tea6420_1, TEA6420_SWITCH, &TEA6420_cd[i][0]); + mxb->tea6420_2->driver->command(mxb->tea6420_2, TEA6420_SWITCH, &TEA6420_cd[i][1]); return 0; } case MXB_S_AUDIO_LINE: { - int i = *(int*)arg; + int i = *(int *)arg; if (i < 0 || i >= MXB_AUDIOS) { - DEB_D(("illegal argument to MXB_S_AUDIO_LINE: i:%d.\n",i)); + DEB_D(("illegal argument to MXB_S_AUDIO_LINE: i:%d.\n", i)); return -EINVAL; } - DEB_EE(("MXB_S_AUDIO_LINE: i:%d.\n",i)); - mxb->tea6420_1->driver->command(mxb->tea6420_1,TEA6420_SWITCH, &TEA6420_line[i][0]); - mxb->tea6420_2->driver->command(mxb->tea6420_2,TEA6420_SWITCH, &TEA6420_line[i][1]); + DEB_EE(("MXB_S_AUDIO_LINE: i:%d.\n", i)); + mxb->tea6420_1->driver->command(mxb->tea6420_1, TEA6420_SWITCH, &TEA6420_line[i][0]); + mxb->tea6420_2->driver->command(mxb->tea6420_2, TEA6420_SWITCH, &TEA6420_line[i][1]); return 0; } - case VIDIOC_G_AUDIO: - { - struct v4l2_audio *a = arg; + default: +/* + DEB2(printk("does not handle this ioctl.\n")); +*/ + return -ENOIOCTLCMD; + } + return 0; +} - if (a->index < 0 || a->index > MXB_INPUTS) { - DEB_D(("VIDIOC_G_AUDIO %d out of range.\n", a->index)); - return -EINVAL; - } +static struct saa7146_ext_vv vv_data; + +/* this function only gets called when the probing was successful */ +static int mxb_attach(struct saa7146_dev *dev, struct saa7146_pci_extension_data *info) +{ + struct mxb *mxb = (struct mxb *)dev->ext_priv; - DEB_EE(("VIDIOC_G_AUDIO %d.\n", a->index)); - memcpy(a, &mxb_audios[video_audio_connect[mxb->cur_input]], sizeof(struct v4l2_audio)); + DEB_EE(("dev:%p\n", dev)); - return 0; - } - case VIDIOC_S_AUDIO: - { - struct v4l2_audio *a = arg; + /* checking for i2c-devices can be omitted here, because we + already did this in "mxb_vl42_probe" */ - DEB_D(("VIDIOC_S_AUDIO %d.\n", a->index)); - return 0; - } + saa7146_vv_init(dev, &vv_data); + vv_data.ops.vidioc_queryctrl = vidioc_queryctrl; + vv_data.ops.vidioc_g_ctrl = vidioc_g_ctrl; + vv_data.ops.vidioc_s_ctrl = vidioc_s_ctrl; + vv_data.ops.vidioc_enum_input = vidioc_enum_input; + vv_data.ops.vidioc_g_input = vidioc_g_input; + vv_data.ops.vidioc_s_input = vidioc_s_input; + vv_data.ops.vidioc_g_tuner = vidioc_g_tuner; + vv_data.ops.vidioc_s_tuner = vidioc_s_tuner; + vv_data.ops.vidioc_g_frequency = vidioc_g_frequency; + vv_data.ops.vidioc_s_frequency = vidioc_s_frequency; + vv_data.ops.vidioc_g_audio = vidioc_g_audio; + vv_data.ops.vidioc_s_audio = vidioc_s_audio; #ifdef CONFIG_VIDEO_ADV_DEBUG - case VIDIOC_DBG_S_REGISTER: - case VIDIOC_DBG_G_REGISTER: - i2c_clients_command(&mxb->i2c_adapter, cmd, arg); - return 0; + vv_data.ops.vidioc_g_register = vidioc_g_register; + vv_data.ops.vidioc_s_register = vidioc_s_register; #endif - default: -/* - DEB2(printk("does not handle this ioctl.\n")); -*/ - return -ENOIOCTLCMD; + vv_data.ops.vidioc_default = vidioc_default; + if (saa7146_register_device(&mxb->video_dev, dev, "mxb", VFL_TYPE_GRABBER)) { + ERR(("cannot register capture v4l2 device. skipping.\n")); + return -1; + } + + /* initialization stuff (vbi) (only for revision > 0 and for extensions which want it)*/ + if (MXB_BOARD_CAN_DO_VBI(dev)) { + if (saa7146_register_device(&mxb->vbi_dev, dev, "mxb", VFL_TYPE_VBI)) { + ERR(("cannot register vbi v4l2 device. skipping.\n")); + } } + + i2c_use_client(mxb->tea6420_1); + i2c_use_client(mxb->tea6420_2); + i2c_use_client(mxb->tea6415c); + i2c_use_client(mxb->tda9840); + i2c_use_client(mxb->saa7111a); + i2c_use_client(mxb->tuner); + + printk("mxb: found Multimedia eXtension Board #%d.\n", mxb_num); + + mxb_num++; + mxb_init_done(dev); + return 0; +} + +static int mxb_detach(struct saa7146_dev *dev) +{ + struct mxb *mxb = (struct mxb *)dev->ext_priv; + + DEB_EE(("dev:%p\n", dev)); + + i2c_release_client(mxb->tea6420_1); + i2c_release_client(mxb->tea6420_2); + i2c_release_client(mxb->tea6415c); + i2c_release_client(mxb->tda9840); + i2c_release_client(mxb->saa7111a); + i2c_release_client(mxb->tuner); + + saa7146_unregister_device(&mxb->video_dev,dev); + if (MXB_BOARD_CAN_DO_VBI(dev)) + saa7146_unregister_device(&mxb->vbi_dev, dev); + saa7146_vv_release(dev); + + mxb_num--; + + i2c_del_adapter(&mxb->i2c_adapter); + kfree(mxb); + return 0; } @@ -885,8 +908,6 @@ static struct saa7146_ext_vv vv_data = { .stds = &standard[0], .num_stds = sizeof(standard)/sizeof(struct saa7146_standard), .std_callback = &std_callback, - .ioctls = &ioctls[0], - .ioctl = mxb_ioctl, }; static struct saa7146_extension extension = { diff --git a/include/media/saa7146_vv.h b/include/media/saa7146_vv.h index c8d0b23fde29..eed5fccc83f3 100644 --- a/include/media/saa7146_vv.h +++ b/include/media/saa7146_vv.h @@ -150,16 +150,6 @@ struct saa7146_vv unsigned int resources; /* resource management for device */ }; -#define SAA7146_EXCLUSIVE 0x1 -#define SAA7146_BEFORE 0x2 -#define SAA7146_AFTER 0x4 - -struct saa7146_extension_ioctls -{ - unsigned int cmd; - int flags; -}; - /* flags */ #define SAA7146_USE_PORT_B_FOR_VBI 0x2 /* use input port b for vbi hardware bug workaround */ @@ -176,8 +166,10 @@ struct saa7146_ext_vv int num_stds; int (*std_callback)(struct saa7146_dev*, struct saa7146_standard *); - struct saa7146_extension_ioctls *ioctls; - long (*ioctl)(struct saa7146_fh *, unsigned int cmd, void *arg); + /* the extension can override this */ + struct v4l2_ioctl_ops ops; + /* pointer to the saa7146 core ops */ + const struct v4l2_ioctl_ops *core_ops; struct v4l2_file_operations vbi_fops; }; @@ -213,6 +205,7 @@ void saa7146_set_hps_source_and_sync(struct saa7146_dev *saa, int source, int sy void saa7146_set_gpio(struct saa7146_dev *saa, u8 pin, u8 data); /* from saa7146_video.c */ +extern const struct v4l2_ioctl_ops saa7146_video_ioctl_ops; extern struct saa7146_use_ops saa7146_video_uops; int saa7146_start_preview(struct saa7146_fh *fh); int saa7146_stop_preview(struct saa7146_fh *fh); -- cgit v1.2.3 From 903bfeac50ecc7725db606c19edbbc93966772c2 Mon Sep 17 00:00:00 2001 From: Andy Walls Date: Thu, 1 Jan 2009 11:09:24 -0300 Subject: V4L/DVB (10274): cx18: Fix a PLL divisor update for the I2S master clock A redundant PLL divisior update for the I2S master clock after AV core firmware load was missed in earlier PLL parameter changes. This one really doesn't matter because it's redundant and gets overwritten, but the driver should be self consistent in the values used. Signed-off-by: Andy Walls Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx18/cx18-av-firmware.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/cx18/cx18-av-firmware.c b/drivers/media/video/cx18/cx18-av-firmware.c index c64fd0a05a97..d1fa0289b067 100644 --- a/drivers/media/video/cx18/cx18-av-firmware.c +++ b/drivers/media/video/cx18/cx18-av-firmware.c @@ -115,9 +115,9 @@ int cx18_av_loadfw(struct cx18 *cx) are generated) */ cx18_av_write4(cx, CXADEC_I2S_OUT_CTL, 0x000001A0); - /* set alt I2s master clock to /16 and enable alt divider i2s + /* set alt I2s master clock to /0x16 and enable alt divider i2s passthrough */ - cx18_av_write4(cx, CXADEC_PIN_CFG3, 0x5000B687); + cx18_av_write4(cx, CXADEC_PIN_CFG3, 0x5600B687); cx18_av_write4_expect(cx, CXADEC_STD_DET_CTL, 0x000000F6, 0x000000F6, 0x3F00FFFF); -- cgit v1.2.3 From 50299994181b835e5a6ee2882df2ee07e7fb4491 Mon Sep 17 00:00:00 2001 From: Andy Walls Date: Thu, 1 Jan 2009 12:35:06 -0300 Subject: V4L/DVB (10275): cx18: Additional debug to display outgoing mailbox parameters Added debug display of outgoing mailbox arguments. Fixed a minor problem with display of stale incoming mailbox contents, when user was not looking for debug warnings. Signed-off-by: Andy Walls Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx18/cx18-mailbox.c | 42 +++++++++++++++++++++++---------- 1 file changed, 30 insertions(+), 12 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/cx18/cx18-mailbox.c b/drivers/media/video/cx18/cx18-mailbox.c index de5e723fdf44..89c033112e1f 100644 --- a/drivers/media/video/cx18/cx18-mailbox.c +++ b/drivers/media/video/cx18/cx18-mailbox.c @@ -98,21 +98,30 @@ static const struct cx18_api_info *find_api_info(u32 cmd) return NULL; } -static void dump_mb(struct cx18 *cx, struct cx18_mailbox *mb, char *name) +/* Call with buf of n*11+1 bytes */ +static char *u32arr2hex(u32 data[], int n, char *buf) { - char argstr[MAX_MB_ARGUMENTS*11+1]; char *p; int i; + for (i = 0, p = buf; i < n; i++, p += 11) { + /* kernel snprintf() appends '\0' always */ + snprintf(p, 12, " %#010x", data[i]); + } + *p = '\0'; + return buf; +} + +static void dump_mb(struct cx18 *cx, struct cx18_mailbox *mb, char *name) +{ + char argstr[MAX_MB_ARGUMENTS*11+1]; + if (!(cx18_debug & CX18_DBGFLG_API)) return; - for (i = 0, p = argstr; i < MAX_MB_ARGUMENTS; i++, p += 11) { - /* kernel snprintf() appends '\0' always */ - snprintf(p, 12, " %#010x", mb->args[i]); - } CX18_DEBUG_API("%s: req %#010x ack %#010x cmd %#010x err %#010x args%s" - "\n", name, mb->request, mb->ack, mb->cmd, mb->error, argstr); + "\n", name, mb->request, mb->ack, mb->cmd, mb->error, + u32arr2hex(mb->args, MAX_MB_ARGUMENTS, argstr)); } @@ -439,7 +448,8 @@ void cx18_api_epu_cmd_irq(struct cx18 *cx, int rpu) "incoming %s to EPU mailbox (sequence no. %u)" "\n", rpu_str[rpu], rpu_str[rpu], order_mb->request); - dump_mb(cx, order_mb, "incoming"); + if (cx18_debug & CX18_DBGFLG_WARN) + dump_mb(cx, order_mb, "incoming"); order->flags = CX18_F_EWO_MB_STALE_UPON_RECEIPT; } @@ -468,16 +478,24 @@ static int cx18_api_call(struct cx18 *cx, u32 cmd, int args, u32 data[]) struct mutex *mb_lock; long int timeout, ret; int i; + char argstr[MAX_MB_ARGUMENTS*11+1]; if (info == NULL) { CX18_WARN("unknown cmd %x\n", cmd); return -EINVAL; } - if (cmd == CX18_CPU_DE_SET_MDL) - CX18_DEBUG_HI_API("%s\n", info->name); - else - CX18_DEBUG_API("%s\n", info->name); + if (cx18_debug & CX18_DBGFLG_API) { /* only call u32arr2hex if needed */ + if (cmd == CX18_CPU_DE_SET_MDL) { + if (cx18_debug & CX18_DBGFLG_HIGHVOL) + CX18_DEBUG_HI_API("%s\tcmd %#010x args%s\n", + info->name, cmd, + u32arr2hex(data, args, argstr)); + } else + CX18_DEBUG_API("%s\tcmd %#010x args%s\n", + info->name, cmd, + u32arr2hex(data, args, argstr)); + } switch (info->rpu) { case APU: -- cgit v1.2.3 From 0d82fe801d7c6d8cb8987e66b570f6decde9e235 Mon Sep 17 00:00:00 2001 From: Andy Walls Date: Thu, 1 Jan 2009 19:02:31 -0300 Subject: V4L/DVB (10276): cx18, cx2341x, ivtv: Add AC-3 audio encoding control to cx18 Initial addition of controls to set AC-3 audio encoding for the CX23418 - it does not work yet due to firmware or cx18 driver issues. This change affects the common cx2341x and ivtv modules due to shared structures and common functions. Signed-off-by: Andy Walls Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx18/cx18-driver.c | 3 +- drivers/media/video/cx18/cx18-driver.h | 2 +- drivers/media/video/cx18/cx18-fileops.c | 8 ++-- drivers/media/video/cx2341x.c | 73 ++++++++++++++++++++++++++++++--- drivers/media/video/ivtv/ivtv-driver.h | 2 +- drivers/media/video/ivtv/ivtv-fileops.c | 8 ++-- include/media/cx2341x.h | 7 +++- 7 files changed, 84 insertions(+), 19 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/cx18/cx18-driver.c b/drivers/media/video/cx18/cx18-driver.c index f50cf2167adc..f9df3cc5aa3d 100644 --- a/drivers/media/video/cx18/cx18-driver.c +++ b/drivers/media/video/cx18/cx18-driver.c @@ -587,7 +587,8 @@ static int __devinit cx18_init_struct1(struct cx18 *cx) (cx->params.video_temporal_filter_mode << 1) | (cx->params.video_median_filter_type << 2); cx->params.port = CX2341X_PORT_MEMORY; - cx->params.capabilities = CX2341X_CAP_HAS_TS; + cx->params.capabilities = CX2341X_CAP_HAS_TS | CX2341X_CAP_HAS_AC3 | + CX2341X_CAP_HAS_LPCM; init_waitqueue_head(&cx->cap_w); init_waitqueue_head(&cx->mb_apu_waitq); init_waitqueue_head(&cx->mb_cpu_waitq); diff --git a/drivers/media/video/cx18/cx18-driver.h b/drivers/media/video/cx18/cx18-driver.h index 0d2edebc39b4..36809dd3d848 100644 --- a/drivers/media/video/cx18/cx18-driver.h +++ b/drivers/media/video/cx18/cx18-driver.h @@ -413,7 +413,7 @@ struct cx18 { /* dualwatch */ unsigned long dualwatch_jiffies; - u16 dualwatch_stereo_mode; + u32 dualwatch_stereo_mode; /* Digitizer type */ int digitizer; /* 0x00EF = saa7114 0x00FO = saa7115 0x0106 = mic */ diff --git a/drivers/media/video/cx18/cx18-fileops.c b/drivers/media/video/cx18/cx18-fileops.c index 055f6e004b2d..863d29db85eb 100644 --- a/drivers/media/video/cx18/cx18-fileops.c +++ b/drivers/media/video/cx18/cx18-fileops.c @@ -128,10 +128,10 @@ static void cx18_release_stream(struct cx18_stream *s) static void cx18_dualwatch(struct cx18 *cx) { struct v4l2_tuner vt; - u16 new_bitmap; - u16 new_stereo_mode; - const u16 stereo_mask = 0x0300; - const u16 dual = 0x0200; + u32 new_bitmap; + u32 new_stereo_mode; + const u32 stereo_mask = 0x0300; + const u32 dual = 0x0200; u32 h; new_stereo_mode = cx->params.audio_properties & stereo_mask; diff --git a/drivers/media/video/cx2341x.c b/drivers/media/video/cx2341x.c index cbbe47fb87b7..0acfacfa9436 100644 --- a/drivers/media/video/cx2341x.c +++ b/drivers/media/video/cx2341x.c @@ -1,5 +1,5 @@ /* - * cx2341x - generic code for cx23415/6 based devices + * cx2341x - generic code for cx23415/6/8 based devices * * Copyright (C) 2006 Hans Verkuil * @@ -30,7 +30,7 @@ #include #include -MODULE_DESCRIPTION("cx23415/6 driver"); +MODULE_DESCRIPTION("cx23415/6/8 driver"); MODULE_AUTHOR("Hans Verkuil"); MODULE_LICENSE("GPL"); @@ -45,6 +45,7 @@ const u32 cx2341x_mpeg_ctrls[] = { V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ, V4L2_CID_MPEG_AUDIO_ENCODING, V4L2_CID_MPEG_AUDIO_L2_BITRATE, + V4L2_CID_MPEG_AUDIO_AC3_BITRATE, V4L2_CID_MPEG_AUDIO_MODE, V4L2_CID_MPEG_AUDIO_MODE_EXTENSION, V4L2_CID_MPEG_AUDIO_EMPHASIS, @@ -94,6 +95,7 @@ static const struct cx2341x_mpeg_params default_params = { .audio_sampling_freq = V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000, .audio_encoding = V4L2_MPEG_AUDIO_ENCODING_LAYER_2, .audio_l2_bitrate = V4L2_MPEG_AUDIO_L2_BITRATE_224K, + .audio_ac3_bitrate = V4L2_MPEG_AUDIO_AC3_BITRATE_224K, .audio_mode = V4L2_MPEG_AUDIO_MODE_STEREO, .audio_mode_extension = V4L2_MPEG_AUDIO_MODE_EXTENSION_BOUND_4, .audio_emphasis = V4L2_MPEG_AUDIO_EMPHASIS_NONE, @@ -148,6 +150,9 @@ static int cx2341x_get_ctrl(const struct cx2341x_mpeg_params *params, case V4L2_CID_MPEG_AUDIO_L2_BITRATE: ctrl->value = params->audio_l2_bitrate; break; + case V4L2_CID_MPEG_AUDIO_AC3_BITRATE: + ctrl->value = params->audio_ac3_bitrate; + break; case V4L2_CID_MPEG_AUDIO_MODE: ctrl->value = params->audio_mode; break; @@ -256,6 +261,12 @@ static int cx2341x_set_ctrl(struct cx2341x_mpeg_params *params, int busy, params->audio_sampling_freq = ctrl->value; break; case V4L2_CID_MPEG_AUDIO_ENCODING: + if (busy) + return -EBUSY; + if (params->capabilities & CX2341X_CAP_HAS_AC3 && + ctrl->value != V4L2_MPEG_AUDIO_ENCODING_LAYER_2 && + ctrl->value != V4L2_MPEG_AUDIO_ENCODING_AC3) + return -EINVAL; params->audio_encoding = ctrl->value; break; case V4L2_CID_MPEG_AUDIO_L2_BITRATE: @@ -263,6 +274,11 @@ static int cx2341x_set_ctrl(struct cx2341x_mpeg_params *params, int busy, return -EBUSY; params->audio_l2_bitrate = ctrl->value; break; + case V4L2_CID_MPEG_AUDIO_AC3_BITRATE: + if (busy) + return -EBUSY; + params->audio_ac3_bitrate = ctrl->value; + break; case V4L2_CID_MPEG_AUDIO_MODE: params->audio_mode = ctrl->value; break; @@ -482,6 +498,12 @@ int cx2341x_ctrl_query(const struct cx2341x_mpeg_params *params, switch (qctrl->id) { case V4L2_CID_MPEG_AUDIO_ENCODING: + if (params->capabilities & CX2341X_CAP_HAS_AC3) + return v4l2_ctrl_query_fill(qctrl, + V4L2_MPEG_AUDIO_ENCODING_LAYER_2, + V4L2_MPEG_AUDIO_ENCODING_AC3, 1, + default_params.audio_encoding); + return v4l2_ctrl_query_fill(qctrl, V4L2_MPEG_AUDIO_ENCODING_LAYER_2, V4L2_MPEG_AUDIO_ENCODING_LAYER_2, 1, @@ -497,6 +519,12 @@ int cx2341x_ctrl_query(const struct cx2341x_mpeg_params *params, case V4L2_CID_MPEG_AUDIO_L3_BITRATE: return -EINVAL; + case V4L2_CID_MPEG_AUDIO_AC3_BITRATE: + return v4l2_ctrl_query_fill(qctrl, + V4L2_MPEG_AUDIO_AC3_BITRATE_48K, + V4L2_MPEG_AUDIO_AC3_BITRATE_448K, 1, + default_params.audio_ac3_bitrate); + case V4L2_CID_MPEG_AUDIO_MODE_EXTENSION: err = v4l2_ctrl_query_fill_std(qctrl); if (err == 0 && @@ -671,6 +699,15 @@ const char **cx2341x_ctrl_get_menu(const struct cx2341x_mpeg_params *p, u32 id) NULL }; + static const char *mpeg_audio_encoding_l2_ac3[] = { + "", + "MPEG-1/2 Layer II", + "", + "", + "AC-3", + NULL + }; + static const char *cx2341x_video_spatial_filter_mode_menu[] = { "Manual", "Auto", @@ -711,6 +748,9 @@ const char **cx2341x_ctrl_get_menu(const struct cx2341x_mpeg_params *p, u32 id) case V4L2_CID_MPEG_STREAM_TYPE: return (p->capabilities & CX2341X_CAP_HAS_TS) ? mpeg_stream_type_with_ts : mpeg_stream_type_without_ts; + case V4L2_CID_MPEG_AUDIO_ENCODING: + return (p->capabilities & CX2341X_CAP_HAS_AC3) ? + mpeg_audio_encoding_l2_ac3 : v4l2_ctrl_get_menu(id); case V4L2_CID_MPEG_AUDIO_L1_BITRATE: case V4L2_CID_MPEG_AUDIO_L3_BITRATE: return NULL; @@ -730,16 +770,34 @@ const char **cx2341x_ctrl_get_menu(const struct cx2341x_mpeg_params *p, u32 id) } EXPORT_SYMBOL(cx2341x_ctrl_get_menu); +/* definitions for audio properties bits 29-28 */ +#define CX2341X_AUDIO_ENCDING_METHOD_MPEG 0 +#define CX2341X_AUDIO_ENCDING_METHOD_AC3 1 +#define CX2341X_AUDIO_ENCDING_METHOD_LPCM 2 + static void cx2341x_calc_audio_properties(struct cx2341x_mpeg_params *params) { - params->audio_properties = (params->audio_sampling_freq << 0) | - ((3 - params->audio_encoding) << 2) | - ((1 + params->audio_l2_bitrate) << 4) | + params->audio_properties = + (params->audio_sampling_freq << 0) | (params->audio_mode << 8) | (params->audio_mode_extension << 10) | (((params->audio_emphasis == V4L2_MPEG_AUDIO_EMPHASIS_CCITT_J17) ? 3 : params->audio_emphasis) << 12) | (params->audio_crc << 14); + + if ((params->capabilities & CX2341X_CAP_HAS_AC3) && + params->audio_encoding == V4L2_MPEG_AUDIO_ENCODING_AC3) { + params->audio_properties |= + /* Not sure if this MPEG Layer II setting is required */ + ((3 - V4L2_MPEG_AUDIO_ENCODING_LAYER_2) << 2) | + (params->audio_ac3_bitrate << 4) | + (CX2341X_AUDIO_ENCDING_METHOD_AC3 << 28); + } else { + /* Assuming MPEG Layer II */ + params->audio_properties |= + ((3 - params->audio_encoding) << 2) | + ((1 + params->audio_l2_bitrate) << 4); + } } int cx2341x_ext_ctrls(struct cx2341x_mpeg_params *params, int busy, @@ -1022,7 +1080,10 @@ void cx2341x_log_status(const struct cx2341x_mpeg_params *p, const char *prefix) prefix, cx2341x_menu_item(p, V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ), cx2341x_menu_item(p, V4L2_CID_MPEG_AUDIO_ENCODING), - cx2341x_menu_item(p, V4L2_CID_MPEG_AUDIO_L2_BITRATE), + cx2341x_menu_item(p, + p->audio_encoding == V4L2_MPEG_AUDIO_ENCODING_AC3 + ? V4L2_CID_MPEG_AUDIO_AC3_BITRATE + : V4L2_CID_MPEG_AUDIO_L2_BITRATE), cx2341x_menu_item(p, V4L2_CID_MPEG_AUDIO_MODE), p->audio_mute ? " (muted)" : ""); if (p->audio_mode == V4L2_MPEG_AUDIO_MODE_JOINT_STEREO) diff --git a/drivers/media/video/ivtv/ivtv-driver.h b/drivers/media/video/ivtv/ivtv-driver.h index ce8d9b74357e..94f7f44d5989 100644 --- a/drivers/media/video/ivtv/ivtv-driver.h +++ b/drivers/media/video/ivtv/ivtv-driver.h @@ -696,7 +696,7 @@ struct ivtv { u64 vbi_data_inserted; /* number of VBI bytes inserted into the MPEG stream */ u32 last_dec_timing[3]; /* cache last retrieved pts/scr/frame values */ unsigned long dualwatch_jiffies;/* jiffies value of the previous dualwatch check */ - u16 dualwatch_stereo_mode; /* current detected dualwatch stereo mode */ + u32 dualwatch_stereo_mode; /* current detected dualwatch stereo mode */ /* VBI state info */ diff --git a/drivers/media/video/ivtv/ivtv-fileops.c b/drivers/media/video/ivtv/ivtv-fileops.c index d594bc29f07f..617667d1ceba 100644 --- a/drivers/media/video/ivtv/ivtv-fileops.c +++ b/drivers/media/video/ivtv/ivtv-fileops.c @@ -148,10 +148,10 @@ void ivtv_release_stream(struct ivtv_stream *s) static void ivtv_dualwatch(struct ivtv *itv) { struct v4l2_tuner vt; - u16 new_bitmap; - u16 new_stereo_mode; - const u16 stereo_mask = 0x0300; - const u16 dual = 0x0200; + u32 new_bitmap; + u32 new_stereo_mode; + const u32 stereo_mask = 0x0300; + const u32 dual = 0x0200; new_stereo_mode = itv->params.audio_properties & stereo_mask; memset(&vt, 0, sizeof(vt)); diff --git a/include/media/cx2341x.h b/include/media/cx2341x.h index 9ec4d5889ef5..2601bc71c51d 100644 --- a/include/media/cx2341x.h +++ b/include/media/cx2341x.h @@ -1,5 +1,5 @@ /* - cx23415/6 header containing common defines. + cx23415/6/8 header containing common defines. 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 @@ -28,6 +28,8 @@ enum cx2341x_port { enum cx2341x_cap { CX2341X_CAP_HAS_SLICED_VBI = 1 << 0, CX2341X_CAP_HAS_TS = 1 << 1, + CX2341X_CAP_HAS_AC3 = 1 << 2, + CX2341X_CAP_HAS_LPCM = 1 << 3, }; struct cx2341x_mpeg_params { @@ -47,11 +49,12 @@ struct cx2341x_mpeg_params { enum v4l2_mpeg_audio_sampling_freq audio_sampling_freq; enum v4l2_mpeg_audio_encoding audio_encoding; enum v4l2_mpeg_audio_l2_bitrate audio_l2_bitrate; + enum v4l2_mpeg_audio_ac3_bitrate audio_ac3_bitrate; enum v4l2_mpeg_audio_mode audio_mode; enum v4l2_mpeg_audio_mode_extension audio_mode_extension; enum v4l2_mpeg_audio_emphasis audio_emphasis; enum v4l2_mpeg_audio_crc audio_crc; - u16 audio_properties; + u32 audio_properties; u16 audio_mute; /* video */ -- cgit v1.2.3 From 31230c5f6f3a3e549f16857b7af45f5e08ca6f30 Mon Sep 17 00:00:00 2001 From: Andy Walls Date: Sat, 3 Jan 2009 14:21:30 -0300 Subject: V4L/DVB (10277): cx18, cx2341x: Fix bugs in cx18 AC3 control and comply with V4L2 spec Fix bugs in the cx18 AC3 control implementation that would have affected ivtv and other drivers via the cx2341x module. Bring AC3 controls behavior into comliance with V4L2 specification. Thanks to Hans Verkuil for reviewing the previous patch and pointing out the problems. Reported-by: Hans Verkuil Signed-off-by: Andy Walls Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx18/cx18-driver.c | 3 +-- drivers/media/video/cx2341x.c | 46 ++++++++++++++++++++++++++-------- include/media/cx2341x.h | 1 - 3 files changed, 36 insertions(+), 14 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/cx18/cx18-driver.c b/drivers/media/video/cx18/cx18-driver.c index f9df3cc5aa3d..7e455fdcf774 100644 --- a/drivers/media/video/cx18/cx18-driver.c +++ b/drivers/media/video/cx18/cx18-driver.c @@ -587,8 +587,7 @@ static int __devinit cx18_init_struct1(struct cx18 *cx) (cx->params.video_temporal_filter_mode << 1) | (cx->params.video_median_filter_type << 2); cx->params.port = CX2341X_PORT_MEMORY; - cx->params.capabilities = CX2341X_CAP_HAS_TS | CX2341X_CAP_HAS_AC3 | - CX2341X_CAP_HAS_LPCM; + cx->params.capabilities = CX2341X_CAP_HAS_TS | CX2341X_CAP_HAS_AC3; init_waitqueue_head(&cx->cap_w); init_waitqueue_head(&cx->mb_apu_waitq); init_waitqueue_head(&cx->mb_cpu_waitq); diff --git a/drivers/media/video/cx2341x.c b/drivers/media/video/cx2341x.c index 0acfacfa9436..6f4821616f75 100644 --- a/drivers/media/video/cx2341x.c +++ b/drivers/media/video/cx2341x.c @@ -263,10 +263,10 @@ static int cx2341x_set_ctrl(struct cx2341x_mpeg_params *params, int busy, case V4L2_CID_MPEG_AUDIO_ENCODING: if (busy) return -EBUSY; - if (params->capabilities & CX2341X_CAP_HAS_AC3 && - ctrl->value != V4L2_MPEG_AUDIO_ENCODING_LAYER_2 && - ctrl->value != V4L2_MPEG_AUDIO_ENCODING_AC3) - return -EINVAL; + if (params->capabilities & CX2341X_CAP_HAS_AC3) + if (ctrl->value != V4L2_MPEG_AUDIO_ENCODING_LAYER_2 && + ctrl->value != V4L2_MPEG_AUDIO_ENCODING_AC3) + return -ERANGE; params->audio_encoding = ctrl->value; break; case V4L2_CID_MPEG_AUDIO_L2_BITRATE: @@ -277,6 +277,8 @@ static int cx2341x_set_ctrl(struct cx2341x_mpeg_params *params, int busy, case V4L2_CID_MPEG_AUDIO_AC3_BITRATE: if (busy) return -EBUSY; + if (!(params->capabilities & CX2341X_CAP_HAS_AC3)) + return -EINVAL; params->audio_ac3_bitrate = ctrl->value; break; case V4L2_CID_MPEG_AUDIO_MODE: @@ -498,11 +500,18 @@ int cx2341x_ctrl_query(const struct cx2341x_mpeg_params *params, switch (qctrl->id) { case V4L2_CID_MPEG_AUDIO_ENCODING: - if (params->capabilities & CX2341X_CAP_HAS_AC3) + if (params->capabilities & CX2341X_CAP_HAS_AC3) { + /* + * The state of L2 & AC3 bitrate controls can change + * when this control changes, but v4l2_ctrl_query_fill() + * already sets V4L2_CTRL_FLAG_UPDATE for + * V4L2_CID_MPEG_AUDIO_ENCODING, so we don't here. + */ return v4l2_ctrl_query_fill(qctrl, V4L2_MPEG_AUDIO_ENCODING_LAYER_2, V4L2_MPEG_AUDIO_ENCODING_AC3, 1, default_params.audio_encoding); + } return v4l2_ctrl_query_fill(qctrl, V4L2_MPEG_AUDIO_ENCODING_LAYER_2, @@ -510,20 +519,35 @@ int cx2341x_ctrl_query(const struct cx2341x_mpeg_params *params, default_params.audio_encoding); case V4L2_CID_MPEG_AUDIO_L2_BITRATE: - return v4l2_ctrl_query_fill(qctrl, + err = v4l2_ctrl_query_fill(qctrl, V4L2_MPEG_AUDIO_L2_BITRATE_192K, V4L2_MPEG_AUDIO_L2_BITRATE_384K, 1, default_params.audio_l2_bitrate); + if (err) + return err; + if (params->capabilities & CX2341X_CAP_HAS_AC3 && + params->audio_encoding != V4L2_MPEG_AUDIO_ENCODING_LAYER_2) + qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE; + return 0; case V4L2_CID_MPEG_AUDIO_L1_BITRATE: case V4L2_CID_MPEG_AUDIO_L3_BITRATE: return -EINVAL; case V4L2_CID_MPEG_AUDIO_AC3_BITRATE: - return v4l2_ctrl_query_fill(qctrl, + err = v4l2_ctrl_query_fill(qctrl, V4L2_MPEG_AUDIO_AC3_BITRATE_48K, V4L2_MPEG_AUDIO_AC3_BITRATE_448K, 1, default_params.audio_ac3_bitrate); + if (err) + return err; + if (params->capabilities & CX2341X_CAP_HAS_AC3) { + if (params->audio_encoding != + V4L2_MPEG_AUDIO_ENCODING_AC3) + qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE; + } else + qctrl->flags |= V4L2_CTRL_FLAG_DISABLED; + return 0; case V4L2_CID_MPEG_AUDIO_MODE_EXTENSION: err = v4l2_ctrl_query_fill_std(qctrl); @@ -771,9 +795,9 @@ const char **cx2341x_ctrl_get_menu(const struct cx2341x_mpeg_params *p, u32 id) EXPORT_SYMBOL(cx2341x_ctrl_get_menu); /* definitions for audio properties bits 29-28 */ -#define CX2341X_AUDIO_ENCDING_METHOD_MPEG 0 -#define CX2341X_AUDIO_ENCDING_METHOD_AC3 1 -#define CX2341X_AUDIO_ENCDING_METHOD_LPCM 2 +#define CX2341X_AUDIO_ENCODING_METHOD_MPEG 0 +#define CX2341X_AUDIO_ENCODING_METHOD_AC3 1 +#define CX2341X_AUDIO_ENCODING_METHOD_LPCM 2 static void cx2341x_calc_audio_properties(struct cx2341x_mpeg_params *params) { @@ -791,7 +815,7 @@ static void cx2341x_calc_audio_properties(struct cx2341x_mpeg_params *params) /* Not sure if this MPEG Layer II setting is required */ ((3 - V4L2_MPEG_AUDIO_ENCODING_LAYER_2) << 2) | (params->audio_ac3_bitrate << 4) | - (CX2341X_AUDIO_ENCDING_METHOD_AC3 << 28); + (CX2341X_AUDIO_ENCODING_METHOD_AC3 << 28); } else { /* Assuming MPEG Layer II */ params->audio_properties |= diff --git a/include/media/cx2341x.h b/include/media/cx2341x.h index 2601bc71c51d..9ebe8558b9b6 100644 --- a/include/media/cx2341x.h +++ b/include/media/cx2341x.h @@ -29,7 +29,6 @@ enum cx2341x_cap { CX2341X_CAP_HAS_SLICED_VBI = 1 << 0, CX2341X_CAP_HAS_TS = 1 << 1, CX2341X_CAP_HAS_AC3 = 1 << 2, - CX2341X_CAP_HAS_LPCM = 1 << 3, }; struct cx2341x_mpeg_params { -- cgit v1.2.3 From 350145a4f7d0edffdccdace1221efc6d1d362a36 Mon Sep 17 00:00:00 2001 From: Andy Walls Date: Sun, 4 Jan 2009 21:51:17 -0300 Subject: V4L/DVB (10278): cx18: Fix bad audio in first analog capture. Normalize the APU state before the second firmware load so that audio for the first analog capture is correct. Many thanks to Conexant for supporting me in finding a solution for this problem. Signed-off-by: Andy Walls Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx18/cx18-driver.c | 17 +++++++++++++++-- drivers/media/video/cx18/cx18-mailbox.c | 2 ++ drivers/media/video/cx18/cx23418.h | 16 ++++++++++++++++ 3 files changed, 33 insertions(+), 2 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/cx18/cx18-driver.c b/drivers/media/video/cx18/cx18-driver.c index 7e455fdcf774..e161d29beb70 100644 --- a/drivers/media/video/cx18/cx18-driver.c +++ b/drivers/media/video/cx18/cx18-driver.c @@ -1043,8 +1043,21 @@ int cx18_init_on_first_open(struct cx18 *cx) } set_bit(CX18_F_I_LOADED_FW, &cx->i_flags); - /* Init the firmware twice to work around a silicon bug - * transport related. */ + /* + * Init the firmware twice to work around a silicon bug + * with the digital TS. + * + * The second firmware load requires us to normalize the APU state, + * or the audio for the first analog capture will be badly incorrect. + * + * I can't seem to call APU_RESETAI and have it succeed without the + * APU capturing audio, so we start and stop it here to do the reset + */ + + /* MPEG Encoding, 224 kbps, MPEG Layer II, 48 ksps */ + cx18_vapi(cx, CX18_APU_START, 2, CX18_APU_ENCODING_METHOD_MPEG|0xb9, 0); + cx18_vapi(cx, CX18_APU_RESETAI, 0); + cx18_vapi(cx, CX18_APU_STOP, 1, CX18_APU_ENCODING_METHOD_MPEG); fw_retry_count = 3; while (--fw_retry_count > 0) { diff --git a/drivers/media/video/cx18/cx18-mailbox.c b/drivers/media/video/cx18/cx18-mailbox.c index 89c033112e1f..2226e5791e99 100644 --- a/drivers/media/video/cx18/cx18-mailbox.c +++ b/drivers/media/video/cx18/cx18-mailbox.c @@ -83,6 +83,8 @@ static const struct cx18_api_info api_info[] = { API_ENTRY(CPU, CX18_CPU_DE_SET_MDL_ACK, 0), API_ENTRY(CPU, CX18_CPU_DE_SET_MDL, API_FAST), API_ENTRY(CPU, CX18_CPU_DE_RELEASE_MDL, API_SLOW), + API_ENTRY(APU, CX18_APU_START, 0), + API_ENTRY(APU, CX18_APU_STOP, 0), API_ENTRY(APU, CX18_APU_RESETAI, 0), API_ENTRY(CPU, CX18_CPU_DEBUG_PEEK32, 0), API_ENTRY(0, 0, 0), diff --git a/drivers/media/video/cx18/cx23418.h b/drivers/media/video/cx18/cx23418.h index 601f3a2ab742..9956abf576c5 100644 --- a/drivers/media/video/cx18/cx23418.h +++ b/drivers/media/video/cx18/cx23418.h @@ -56,6 +56,22 @@ #define APU_CMD_MASK 0x10000000 #define APU_CMD_MASK_ACK (APU_CMD_MASK | 0x80000000) +#define CX18_APU_ENCODING_METHOD_MPEG (0 << 28) +#define CX18_APU_ENCODING_METHOD_AC3 (1 << 28) + +/* Description: Command APU to start audio + IN[0] - audio parameters (same as CX18_CPU_SET_AUDIO_PARAMETERS?) + IN[1] - caller buffer address, or 0 + ReturnCode - ??? */ +#define CX18_APU_START (APU_CMD_MASK | 0x01) + +/* Description: Command APU to stop audio + IN[0] - encoding method to stop + ReturnCode - ??? */ +#define CX18_APU_STOP (APU_CMD_MASK | 0x02) + +/* Description: Command APU to reset the AI + ReturnCode - ??? */ #define CX18_APU_RESETAI (APU_CMD_MASK | 0x05) /* Description: This command indicates that a Memory Descriptor List has been -- cgit v1.2.3 From e0f28b6a69b73ebf610f4f9759999bcdabdcda8e Mon Sep 17 00:00:00 2001 From: Andy Walls Date: Sat, 10 Jan 2009 14:13:46 -0300 Subject: V4L/DVB (10279): cx18: Print driver version number when logging status Make sure v4l2-ctl --log-status outputs the driver version. Reported-by: David Dombroski Signed-off-by: Andy Walls Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx18/cx18-ioctl.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/cx18/cx18-ioctl.c b/drivers/media/video/cx18/cx18-ioctl.c index 7086aaba77d6..f38ca207cad2 100644 --- a/drivers/media/video/cx18/cx18-ioctl.c +++ b/drivers/media/video/cx18/cx18-ioctl.c @@ -708,7 +708,9 @@ static int cx18_log_status(struct file *file, void *fh) struct v4l2_audio audin; int i; - CX18_INFO("================= START STATUS CARD #%d =================\n", cx->num); + CX18_INFO("================= START STATUS CARD #%d " + "=================\n", cx->num); + CX18_INFO("Version: %s Card: %s\n", CX18_VERSION, cx->card_name); if (cx->hw_flags & CX18_HW_TVEEPROM) { struct tveeprom tv; -- cgit v1.2.3 From 3d05913d894a460b7dc8e5d93415fde21b986411 Mon Sep 17 00:00:00 2001 From: Andy Walls Date: Sat, 10 Jan 2009 21:54:39 -0300 Subject: V4L/DVB (10280): cx18: Rename structure members: dev to pci_dev and v4l2dev to video_dev Renamed structure member name to be more specific to type in anticipation of updating to the v4l2_device/v4l2_subdev framework. Too many objects named "dev" and /v4l2_\{0,1\}dev/ would be to confusing. Signed-off-by: Andy Walls Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx18/cx18-av-firmware.c | 2 +- drivers/media/video/cx18/cx18-driver.c | 55 ++++++++++++++------------- drivers/media/video/cx18/cx18-driver.h | 4 +- drivers/media/video/cx18/cx18-dvb.c | 2 +- drivers/media/video/cx18/cx18-fileops.c | 2 +- drivers/media/video/cx18/cx18-firmware.c | 4 +- drivers/media/video/cx18/cx18-i2c.c | 2 +- drivers/media/video/cx18/cx18-ioctl.c | 5 ++- drivers/media/video/cx18/cx18-queue.c | 4 +- drivers/media/video/cx18/cx18-queue.h | 4 +- drivers/media/video/cx18/cx18-streams.c | 59 +++++++++++++++-------------- 11 files changed, 73 insertions(+), 70 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/cx18/cx18-av-firmware.c b/drivers/media/video/cx18/cx18-av-firmware.c index d1fa0289b067..b374c74d3e7b 100644 --- a/drivers/media/video/cx18/cx18-av-firmware.c +++ b/drivers/media/video/cx18/cx18-av-firmware.c @@ -36,7 +36,7 @@ int cx18_av_loadfw(struct cx18 *cx) int i; int retries1 = 0; - if (request_firmware(&fw, FWFILE, &cx->dev->dev) != 0) { + if (request_firmware(&fw, FWFILE, &cx->pci_dev->dev) != 0) { CX18_ERR("unable to open firmware %s\n", FWFILE); return -EINVAL; } diff --git a/drivers/media/video/cx18/cx18-driver.c b/drivers/media/video/cx18/cx18-driver.c index e161d29beb70..52d04f640b73 100644 --- a/drivers/media/video/cx18/cx18-driver.c +++ b/drivers/media/video/cx18/cx18-driver.c @@ -502,7 +502,7 @@ static void cx18_process_options(struct cx18 *cx) else if (cx->options.cardtype != 0) CX18_ERR("Unknown user specified type, trying to autodetect card\n"); if (cx->card == NULL) { - if (cx->dev->subsystem_vendor == CX18_PCI_ID_HAUPPAUGE) { + if (cx->pci_dev->subsystem_vendor == CX18_PCI_ID_HAUPPAUGE) { cx->card = cx18_get_card(CX18_CARD_HVR_1600_ESMT); CX18_INFO("Autodetected Hauppauge card\n"); } @@ -512,13 +512,13 @@ static void cx18_process_options(struct cx18 *cx) if (cx->card->pci_list == NULL) continue; for (j = 0; cx->card->pci_list[j].device; j++) { - if (cx->dev->device != + if (cx->pci_dev->device != cx->card->pci_list[j].device) continue; - if (cx->dev->subsystem_vendor != + if (cx->pci_dev->subsystem_vendor != cx->card->pci_list[j].subsystem_vendor) continue; - if (cx->dev->subsystem_device != + if (cx->pci_dev->subsystem_device != cx->card->pci_list[j].subsystem_device) continue; CX18_INFO("Autodetected %s card\n", cx->card->name); @@ -531,9 +531,10 @@ done: if (cx->card == NULL) { cx->card = cx18_get_card(CX18_CARD_HVR_1600_ESMT); CX18_ERR("Unknown card: vendor/device: [%04x:%04x]\n", - cx->dev->vendor, cx->dev->device); + cx->pci_dev->vendor, cx->pci_dev->device); CX18_ERR(" subsystem vendor/device: [%04x:%04x]\n", - cx->dev->subsystem_vendor, cx->dev->subsystem_device); + cx->pci_dev->subsystem_vendor, + cx->pci_dev->subsystem_device); CX18_ERR("Defaulting to %s card\n", cx->card->name); CX18_ERR("Please mail the vendor/device and subsystem vendor/device IDs and what kind of\n"); CX18_ERR("card you have to the ivtv-devel mailinglist (www.ivtvdriver.org)\n"); @@ -553,7 +554,7 @@ static int __devinit cx18_init_struct1(struct cx18 *cx) { int i; - cx->base_addr = pci_resource_start(cx->dev, 0); + cx->base_addr = pci_resource_start(cx->pci_dev, 0); mutex_init(&cx->serialize_lock); mutex_init(&cx->i2c_bus_lock[0]); @@ -676,7 +677,7 @@ static void __devinit cx18_init_struct2(struct cx18 *cx) cx->av_state.vbi_line_offset = 8; } -static int cx18_setup_pci(struct cx18 *cx, struct pci_dev *dev, +static int cx18_setup_pci(struct cx18 *cx, struct pci_dev *pci_dev, const struct pci_device_id *pci_id) { u16 cmd; @@ -684,11 +685,11 @@ static int cx18_setup_pci(struct cx18 *cx, struct pci_dev *dev, CX18_DEBUG_INFO("Enabling pci device\n"); - if (pci_enable_device(dev)) { + if (pci_enable_device(pci_dev)) { CX18_ERR("Can't enable device %d!\n", cx->num); return -EIO; } - if (pci_set_dma_mask(dev, 0xffffffff)) { + if (pci_set_dma_mask(pci_dev, 0xffffffff)) { CX18_ERR("No suitable DMA available on card %d.\n", cx->num); return -EIO; } @@ -698,25 +699,25 @@ static int cx18_setup_pci(struct cx18 *cx, struct pci_dev *dev, } /* Enable bus mastering and memory mapped IO for the CX23418 */ - pci_read_config_word(dev, PCI_COMMAND, &cmd); + pci_read_config_word(pci_dev, PCI_COMMAND, &cmd); cmd |= PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER; - pci_write_config_word(dev, PCI_COMMAND, cmd); + pci_write_config_word(pci_dev, PCI_COMMAND, cmd); - pci_read_config_byte(dev, PCI_CLASS_REVISION, &cx->card_rev); - pci_read_config_byte(dev, PCI_LATENCY_TIMER, &pci_latency); + pci_read_config_byte(pci_dev, PCI_CLASS_REVISION, &cx->card_rev); + pci_read_config_byte(pci_dev, PCI_LATENCY_TIMER, &pci_latency); if (pci_latency < 64 && cx18_pci_latency) { CX18_INFO("Unreasonably low latency timer, " "setting to 64 (was %d)\n", pci_latency); - pci_write_config_byte(dev, PCI_LATENCY_TIMER, 64); - pci_read_config_byte(dev, PCI_LATENCY_TIMER, &pci_latency); + pci_write_config_byte(pci_dev, PCI_LATENCY_TIMER, 64); + pci_read_config_byte(pci_dev, PCI_LATENCY_TIMER, &pci_latency); } CX18_DEBUG_INFO("cx%d (rev %d) at %02x:%02x.%x, " "irq: %d, latency: %d, memory: 0x%lx\n", - cx->dev->device, cx->card_rev, dev->bus->number, - PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn), - cx->dev->irq, pci_latency, (unsigned long)cx->base_addr); + cx->pci_dev->device, cx->card_rev, pci_dev->bus->number, + PCI_SLOT(pci_dev->devfn), PCI_FUNC(pci_dev->devfn), + cx->pci_dev->irq, pci_latency, (unsigned long)cx->base_addr); return 0; } @@ -771,7 +772,7 @@ static void cx18_load_and_init_modules(struct cx18 *cx) hw = cx->hw_flags; } -static int __devinit cx18_probe(struct pci_dev *dev, +static int __devinit cx18_probe(struct pci_dev *pci_dev, const struct pci_device_id *pci_id) { int retval = 0; @@ -796,7 +797,7 @@ static int __devinit cx18_probe(struct pci_dev *dev, return -ENOMEM; } cx18_cards[cx18_cards_active] = cx; - cx->dev = dev; + cx->pci_dev = pci_dev; cx->num = cx18_cards_active++; snprintf(cx->name, sizeof(cx->name), "cx18-%d", cx->num); CX18_INFO("Initializing card #%d\n", cx->num); @@ -816,12 +817,12 @@ static int __devinit cx18_probe(struct pci_dev *dev, CX18_DEBUG_INFO("base addr: 0x%08x\n", cx->base_addr); /* PCI Device Setup */ - retval = cx18_setup_pci(cx, dev, pci_id); + retval = cx18_setup_pci(cx, pci_dev, pci_id); if (retval != 0) goto free_workqueue; /* save cx in the pci struct for later use */ - pci_set_drvdata(dev, cx); + pci_set_drvdata(pci_dev, cx); /* map io memory */ CX18_DEBUG_INFO("attempting ioremap at 0x%08x len 0x%08x\n", @@ -881,7 +882,7 @@ static int __devinit cx18_probe(struct pci_dev *dev, cx18_init_scb(cx); /* Register IRQ */ - retval = request_irq(cx->dev->irq, cx18_irq_handler, + retval = request_irq(cx->pci_dev->irq, cx18_irq_handler, IRQF_SHARED | IRQF_DISABLED, cx->name, (void *)cx); if (retval) { CX18_ERR("Failed to register irq %d\n", retval); @@ -992,7 +993,7 @@ static int __devinit cx18_probe(struct pci_dev *dev, free_streams: cx18_streams_cleanup(cx, 1); free_irq: - free_irq(cx->dev->irq, (void *)cx); + free_irq(cx->pci_dev->irq, (void *)cx); free_i2c: exit_cx18_i2c(cx); free_map: @@ -1128,13 +1129,13 @@ static void cx18_remove(struct pci_dev *pci_dev) exit_cx18_i2c(cx); - free_irq(cx->dev->irq, (void *)cx); + free_irq(cx->pci_dev->irq, (void *)cx); cx18_iounmap(cx); release_mem_region(cx->base_addr, CX18_MEM_SIZE); - pci_disable_device(cx->dev); + pci_disable_device(cx->pci_dev); CX18_INFO("Removed %s, card #%d\n", cx->card_name, cx->num); } diff --git a/drivers/media/video/cx18/cx18-driver.h b/drivers/media/video/cx18/cx18-driver.h index 36809dd3d848..316ff333d4a5 100644 --- a/drivers/media/video/cx18/cx18-driver.h +++ b/drivers/media/video/cx18/cx18-driver.h @@ -279,7 +279,7 @@ struct cx18_epu_work_order { struct cx18_stream { /* These first four fields are always set, even if the stream is not actually created. */ - struct video_device *v4l2dev; /* NULL when stream not created */ + struct video_device *video_dev; /* NULL when stream not created */ struct cx18 *cx; /* for ease of use */ const char *name; /* name of the stream */ int type; /* stream type */ @@ -385,7 +385,7 @@ struct cx18_i2c_algo_callback_data { struct cx18 { int num; /* board number, -1 during init! */ char name[8]; /* board name for printk and interrupts (e.g. 'cx180') */ - struct pci_dev *dev; /* PCI device */ + struct pci_dev *pci_dev; const struct cx18_card *card; /* card information */ const char *card_name; /* full name of the card */ const struct cx18_card_tuner_i2c *card_i2c; /* i2c addresses to probe for tuner */ diff --git a/drivers/media/video/cx18/cx18-dvb.c b/drivers/media/video/cx18/cx18-dvb.c index bd5e6f3fd4d0..3b86f57cd15a 100644 --- a/drivers/media/video/cx18/cx18-dvb.c +++ b/drivers/media/video/cx18/cx18-dvb.c @@ -167,7 +167,7 @@ int cx18_dvb_register(struct cx18_stream *stream) ret = dvb_register_adapter(&dvb->dvb_adapter, CX18_DRIVER_NAME, - THIS_MODULE, &cx->dev->dev, adapter_nr); + THIS_MODULE, &cx->pci_dev->dev, adapter_nr); if (ret < 0) goto err_out; diff --git a/drivers/media/video/cx18/cx18-fileops.c b/drivers/media/video/cx18/cx18-fileops.c index 863d29db85eb..23006f7d9159 100644 --- a/drivers/media/video/cx18/cx18-fileops.c +++ b/drivers/media/video/cx18/cx18-fileops.c @@ -665,7 +665,7 @@ int cx18_v4l2_open(struct file *filp) if (cx18_cards[x] == NULL) continue; s = &cx18_cards[x]->streams[y]; - if (s->v4l2dev && s->v4l2dev->minor == minor) { + if (s->video_dev && s->video_dev->minor == minor) { cx = cx18_cards[x]; break; } diff --git a/drivers/media/video/cx18/cx18-firmware.c b/drivers/media/video/cx18/cx18-firmware.c index 1fa95da1575e..aa89bee65af0 100644 --- a/drivers/media/video/cx18/cx18-firmware.c +++ b/drivers/media/video/cx18/cx18-firmware.c @@ -107,7 +107,7 @@ static int load_cpu_fw_direct(const char *fn, u8 __iomem *mem, struct cx18 *cx) u32 __iomem *dst = (u32 __iomem *)mem; const u32 *src; - if (request_firmware(&fw, fn, &cx->dev->dev)) { + if (request_firmware(&fw, fn, &cx->pci_dev->dev)) { CX18_ERR("Unable to open firmware %s\n", fn); CX18_ERR("Did you put the firmware in the hotplug firmware directory?\n"); return -ENOMEM; @@ -151,7 +151,7 @@ static int load_apu_fw_direct(const char *fn, u8 __iomem *dst, struct cx18 *cx, u32 apu_version = 0; int sz; - if (request_firmware(&fw, fn, &cx->dev->dev)) { + if (request_firmware(&fw, fn, &cx->pci_dev->dev)) { CX18_ERR("unable to open firmware %s\n", fn); CX18_ERR("did you put the firmware in the hotplug firmware directory?\n"); cx18_setup_page(cx, 0); diff --git a/drivers/media/video/cx18/cx18-i2c.c b/drivers/media/video/cx18/cx18-i2c.c index 83e1c6333126..200d9257a926 100644 --- a/drivers/media/video/cx18/cx18-i2c.c +++ b/drivers/media/video/cx18/cx18-i2c.c @@ -366,7 +366,7 @@ int init_cx18_i2c(struct cx18 *cx) sprintf(cx->i2c_client[i].name + strlen(cx->i2c_client[i].name), "%d", i); cx->i2c_client[i].adapter = &cx->i2c_adap[i]; - cx->i2c_adap[i].dev.parent = &cx->dev->dev; + cx->i2c_adap[i].dev.parent = &cx->pci_dev->dev; } if (cx18_read_reg(cx, CX18_REG_I2C_2_WR) != 0x0003c02f) { diff --git a/drivers/media/video/cx18/cx18-ioctl.c b/drivers/media/video/cx18/cx18-ioctl.c index f38ca207cad2..20467fce5251 100644 --- a/drivers/media/video/cx18/cx18-ioctl.c +++ b/drivers/media/video/cx18/cx18-ioctl.c @@ -335,7 +335,8 @@ static int cx18_querycap(struct file *file, void *fh, strlcpy(vcap->driver, CX18_DRIVER_NAME, sizeof(vcap->driver)); strlcpy(vcap->card, cx->card_name, sizeof(vcap->card)); - snprintf(vcap->bus_info, sizeof(vcap->bus_info), "PCI:%s", pci_name(cx->dev)); + snprintf(vcap->bus_info, sizeof(vcap->bus_info), + "PCI:%s", pci_name(cx->pci_dev)); vcap->version = CX18_DRIVER_VERSION; /* version */ vcap->capabilities = cx->v4l2_cap; /* capabilities */ return 0; @@ -732,7 +733,7 @@ static int cx18_log_status(struct file *file, void *fh) for (i = 0; i < CX18_MAX_STREAMS; i++) { struct cx18_stream *s = &cx->streams[i]; - if (s->v4l2dev == NULL || s->buffers == 0) + if (s->video_dev == NULL || s->buffers == 0) continue; CX18_INFO("Stream %s: status 0x%04lx, %d%% of %d KiB (%d buffers) in use\n", s->name, s->s_flags, diff --git a/drivers/media/video/cx18/cx18-queue.c b/drivers/media/video/cx18/cx18-queue.c index 8d9441e88c4e..3046b8e74345 100644 --- a/drivers/media/video/cx18/cx18-queue.c +++ b/drivers/media/video/cx18/cx18-queue.c @@ -204,7 +204,7 @@ int cx18_stream_alloc(struct cx18_stream *s) } buf->id = cx->buffer_id++; INIT_LIST_HEAD(&buf->list); - buf->dma_handle = pci_map_single(s->cx->dev, + buf->dma_handle = pci_map_single(s->cx->pci_dev, buf->buf, s->buf_size, s->dma); cx18_buf_sync_for_cpu(s, buf); cx18_enqueue(s, buf, &s->q_free); @@ -227,7 +227,7 @@ void cx18_stream_free(struct cx18_stream *s) /* empty q_free */ while ((buf = cx18_dequeue(s, &s->q_free))) { - pci_unmap_single(s->cx->dev, buf->dma_handle, + pci_unmap_single(s->cx->pci_dev, buf->dma_handle, s->buf_size, s->dma); kfree(buf->buf); kfree(buf); diff --git a/drivers/media/video/cx18/cx18-queue.h b/drivers/media/video/cx18/cx18-queue.h index 456cec3bc28f..4de06269d88f 100644 --- a/drivers/media/video/cx18/cx18-queue.h +++ b/drivers/media/video/cx18/cx18-queue.h @@ -29,14 +29,14 @@ static inline void cx18_buf_sync_for_cpu(struct cx18_stream *s, struct cx18_buffer *buf) { - pci_dma_sync_single_for_cpu(s->cx->dev, buf->dma_handle, + pci_dma_sync_single_for_cpu(s->cx->pci_dev, buf->dma_handle, s->buf_size, s->dma); } static inline void cx18_buf_sync_for_device(struct cx18_stream *s, struct cx18_buffer *buf) { - pci_dma_sync_single_for_device(s->cx->dev, buf->dma_handle, + pci_dma_sync_single_for_device(s->cx->pci_dev, buf->dma_handle, s->buf_size, s->dma); } diff --git a/drivers/media/video/cx18/cx18-streams.c b/drivers/media/video/cx18/cx18-streams.c index 89c1ec94f335..abc3fe605f00 100644 --- a/drivers/media/video/cx18/cx18-streams.c +++ b/drivers/media/video/cx18/cx18-streams.c @@ -101,11 +101,11 @@ static struct { static void cx18_stream_init(struct cx18 *cx, int type) { struct cx18_stream *s = &cx->streams[type]; - struct video_device *dev = s->v4l2dev; + struct video_device *video_dev = s->video_dev; - /* we need to keep v4l2dev, so restore it afterwards */ + /* we need to keep video_dev, so restore it afterwards */ memset(s, 0, sizeof(*s)); - s->v4l2dev = dev; + s->video_dev = video_dev; /* initialize cx18_stream fields */ s->cx = cx; @@ -132,10 +132,10 @@ static int cx18_prep_dev(struct cx18 *cx, int type) int num_offset = cx18_stream_info[type].num_offset; int num = cx->num + cx18_first_minor + num_offset; - /* These four fields are always initialized. If v4l2dev == NULL, then + /* These four fields are always initialized. If video_dev == NULL, then this stream is not in use. In that case no other fields but these four can be used. */ - s->v4l2dev = NULL; + s->video_dev = NULL; s->cx = cx; s->type = type; s->name = cx18_stream_info[type].name; @@ -163,22 +163,22 @@ static int cx18_prep_dev(struct cx18 *cx, int type) return 0; /* allocate and initialize the v4l2 video device structure */ - s->v4l2dev = video_device_alloc(); - if (s->v4l2dev == NULL) { + s->video_dev = video_device_alloc(); + if (s->video_dev == NULL) { CX18_ERR("Couldn't allocate v4l2 video_device for %s\n", s->name); return -ENOMEM; } - snprintf(s->v4l2dev->name, sizeof(s->v4l2dev->name), "cx18-%d", + snprintf(s->video_dev->name, sizeof(s->video_dev->name), "cx18-%d", cx->num); - s->v4l2dev->num = num; - s->v4l2dev->parent = &cx->dev->dev; - s->v4l2dev->fops = &cx18_v4l2_enc_fops; - s->v4l2dev->release = video_device_release; - s->v4l2dev->tvnorms = V4L2_STD_ALL; - cx18_set_funcs(s->v4l2dev); + s->video_dev->num = num; + s->video_dev->parent = &cx->pci_dev->dev; + s->video_dev->fops = &cx18_v4l2_enc_fops; + s->video_dev->release = video_device_release; + s->video_dev->tvnorms = V4L2_STD_ALL; + cx18_set_funcs(s->video_dev); return 0; } @@ -227,28 +227,29 @@ static int cx18_reg_dev(struct cx18 *cx, int type) } } - if (s->v4l2dev == NULL) + if (s->video_dev == NULL) return 0; - num = s->v4l2dev->num; + num = s->video_dev->num; /* card number + user defined offset + device offset */ if (type != CX18_ENC_STREAM_TYPE_MPG) { struct cx18_stream *s_mpg = &cx->streams[CX18_ENC_STREAM_TYPE_MPG]; - if (s_mpg->v4l2dev) - num = s_mpg->v4l2dev->num + cx18_stream_info[type].num_offset; + if (s_mpg->video_dev) + num = s_mpg->video_dev->num + + cx18_stream_info[type].num_offset; } /* Register device. First try the desired minor, then any free one. */ - ret = video_register_device(s->v4l2dev, vfl_type, num); + ret = video_register_device(s->video_dev, vfl_type, num); if (ret < 0) { CX18_ERR("Couldn't register v4l2 device for %s kernel number %d\n", s->name, num); - video_device_release(s->v4l2dev); - s->v4l2dev = NULL; + video_device_release(s->video_dev); + s->video_dev = NULL; return ret; } - num = s->v4l2dev->num; + num = s->video_dev->num; switch (vfl_type) { case VFL_TYPE_GRABBER: @@ -312,9 +313,9 @@ void cx18_streams_cleanup(struct cx18 *cx, int unregister) cx->streams[type].dvb.enabled = false; } - vdev = cx->streams[type].v4l2dev; + vdev = cx->streams[type].video_dev; - cx->streams[type].v4l2dev = NULL; + cx->streams[type].video_dev = NULL; if (vdev == NULL) continue; @@ -437,7 +438,7 @@ int cx18_start_v4l2_encode_stream(struct cx18_stream *s) int ts = 0; int captype = 0; - if (s->v4l2dev == NULL && s->dvb.enabled == 0) + if (s->video_dev == NULL && s->dvb.enabled == 0) return -EINVAL; CX18_DEBUG_INFO("Start encoder stream %s\n", s->name); @@ -565,7 +566,7 @@ void cx18_stop_all_captures(struct cx18 *cx) for (i = CX18_MAX_STREAMS - 1; i >= 0; i--) { struct cx18_stream *s = &cx->streams[i]; - if (s->v4l2dev == NULL && s->dvb.enabled == 0) + if (s->video_dev == NULL && s->dvb.enabled == 0) continue; if (test_bit(CX18_F_S_STREAMING, &s->s_flags)) cx18_stop_v4l2_encode_stream(s, 0); @@ -577,7 +578,7 @@ int cx18_stop_v4l2_encode_stream(struct cx18_stream *s, int gop_end) struct cx18 *cx = s->cx; unsigned long then; - if (s->v4l2dev == NULL && s->dvb.enabled == 0) + if (s->video_dev == NULL && s->dvb.enabled == 0) return -EINVAL; /* This function assumes that you are allowed to stop the capture @@ -629,7 +630,7 @@ u32 cx18_find_handle(struct cx18 *cx) for (i = 0; i < CX18_MAX_STREAMS; i++) { struct cx18_stream *s = &cx->streams[i]; - if (s->v4l2dev && (s->handle != CX18_INVALID_TASK_HANDLE)) + if (s->video_dev && (s->handle != CX18_INVALID_TASK_HANDLE)) return s->handle; } return CX18_INVALID_TASK_HANDLE; @@ -647,7 +648,7 @@ struct cx18_stream *cx18_handle_to_stream(struct cx18 *cx, u32 handle) s = &cx->streams[i]; if (s->handle != handle) continue; - if (s->v4l2dev || s->dvb.enabled) + if (s->video_dev || s->dvb.enabled) return s; } return NULL; -- cgit v1.2.3 From 888cdb07741ab0098ccb8d9feff3f98cad048c26 Mon Sep 17 00:00:00 2001 From: Andy Walls Date: Sun, 11 Jan 2009 15:08:53 -0300 Subject: V4L/DVB (10281): cx18: Conversion to new V4L2 framework: use v4l2_device object First step in conversion to the new V4L2 framework. Added per cx18 device instance of the v4l2_device and its registration. Signed-off-by: Andy Walls Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx18/cx18-driver.c | 23 ++++++++++++++++------- drivers/media/video/cx18/cx18-driver.h | 3 +++ 2 files changed, 19 insertions(+), 7 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/cx18/cx18-driver.c b/drivers/media/video/cx18/cx18-driver.c index 52d04f640b73..450c48dd995a 100644 --- a/drivers/media/video/cx18/cx18-driver.c +++ b/drivers/media/video/cx18/cx18-driver.c @@ -797,21 +797,28 @@ static int __devinit cx18_probe(struct pci_dev *pci_dev, return -ENOMEM; } cx18_cards[cx18_cards_active] = cx; - cx->pci_dev = pci_dev; cx->num = cx18_cards_active++; snprintf(cx->name, sizeof(cx->name), "cx18-%d", cx->num); CX18_INFO("Initializing card #%d\n", cx->num); spin_unlock(&cx18_cards_lock); + cx->pci_dev = pci_dev; + retval = v4l2_device_register(&pci_dev->dev, &cx->v4l2_dev); + if (retval) { + CX18_ERR("Call to v4l2_device_register() failed\n"); + goto err; + } + CX18_DEBUG_INFO("registered v4l2_device name: %s\n", cx->v4l2_dev.name); + cx18_process_options(cx); if (cx->options.cardtype == -1) { retval = -ENODEV; - goto err; + goto unregister_v4l2; } if (cx18_init_struct1(cx)) { retval = -ENOMEM; - goto err; + goto unregister_v4l2; } CX18_DEBUG_INFO("base addr: 0x%08x\n", cx->base_addr); @@ -821,9 +828,6 @@ static int __devinit cx18_probe(struct pci_dev *pci_dev, if (retval != 0) goto free_workqueue; - /* save cx in the pci struct for later use */ - pci_set_drvdata(pci_dev, cx); - /* map io memory */ CX18_DEBUG_INFO("attempting ioremap at 0x%08x len 0x%08x\n", cx->base_addr + CX18_MEM_OFFSET, CX18_MEM_SIZE); @@ -1002,6 +1006,8 @@ free_mem: release_mem_region(cx->base_addr, CX18_MEM_SIZE); free_workqueue: destroy_workqueue(cx->work_queue); +unregister_v4l2: + v4l2_device_unregister(&cx->v4l2_dev); err: if (retval == 0) retval = -ENODEV; @@ -1106,7 +1112,8 @@ static void cx18_cancel_epu_work_orders(struct cx18 *cx) static void cx18_remove(struct pci_dev *pci_dev) { - struct cx18 *cx = pci_get_drvdata(pci_dev); + struct v4l2_device *v4l2_dev = pci_get_drvdata(pci_dev); + struct cx18 *cx = container_of(v4l2_dev, struct cx18, v4l2_dev); CX18_DEBUG_INFO("Removing Card #%d\n", cx->num); @@ -1137,6 +1144,8 @@ static void cx18_remove(struct pci_dev *pci_dev) pci_disable_device(cx->pci_dev); + v4l2_device_unregister(v4l2_dev); + CX18_INFO("Removed %s, card #%d\n", cx->card_name, cx->num); } diff --git a/drivers/media/video/cx18/cx18-driver.h b/drivers/media/video/cx18/cx18-driver.h index 316ff333d4a5..2d5bcbf1b236 100644 --- a/drivers/media/video/cx18/cx18-driver.h +++ b/drivers/media/video/cx18/cx18-driver.h @@ -48,6 +48,7 @@ #include #include #include +#include #include #include "cx18-mailbox.h" #include "cx18-av-core.h" @@ -386,6 +387,8 @@ struct cx18 { int num; /* board number, -1 during init! */ char name[8]; /* board name for printk and interrupts (e.g. 'cx180') */ struct pci_dev *pci_dev; + struct v4l2_device v4l2_dev; + const struct cx18_card *card; /* card information */ const char *card_name; /* full name of the card */ const struct cx18_card_tuner_i2c *card_i2c; /* i2c addresses to probe for tuner */ -- cgit v1.2.3 From be411df610a970a0ab90e3b02d025ab2a3554b61 Mon Sep 17 00:00:00 2001 From: Andy Walls Date: Sat, 17 Jan 2009 13:37:36 -0300 Subject: V4L/DVB (10283): cx18: Call request_module() with proper argument types. request_module() needs to be called with a string literal for a format string or with 1 or more variable arguments to avoid compiler warnings and possible exploits, if someone could cause us to get a format string with a '%' code in the format string when we make the call. Reported-by: Brandon Jenkins Signed-off-by: Andy Walls Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx18/cx18-driver.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/cx18/cx18-driver.c b/drivers/media/video/cx18/cx18-driver.c index 450c48dd995a..1d3a865b9c6d 100644 --- a/drivers/media/video/cx18/cx18-driver.c +++ b/drivers/media/video/cx18/cx18-driver.c @@ -728,7 +728,7 @@ static u32 cx18_request_module(struct cx18 *cx, u32 hw, { if ((hw & id) == 0) return hw; - if (request_module(name) != 0) { + if (request_module("%s", name) != 0) { CX18_ERR("Failed to load module %s\n", name); return hw & ~id; } -- cgit v1.2.3 From 6ce9ee539c42291475c1fd7b374a10c1fe00ea33 Mon Sep 17 00:00:00 2001 From: Andy Walls Date: Mon, 19 Jan 2009 18:31:22 -0300 Subject: V4L/DVB (10284): cx18: Add initial entry for a Leadtek DVR3100 H hybrid card Card report provided by Patryk on the ivtv-devel list: http://ivtvdriver.org/pipermail/ivtv-devel/2009-January/005922.html Reported-by: Pat Signed-off-by: Andy Walls Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx18/cx18-cards.c | 5 +++-- drivers/media/video/cx18/cx18-driver.c | 2 +- drivers/media/video/cx18/cx18-driver.h | 2 +- 3 files changed, 5 insertions(+), 4 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/cx18/cx18-cards.c b/drivers/media/video/cx18/cx18-cards.c index e274043657dd..a0d4d2e49d1b 100644 --- a/drivers/media/video/cx18/cx18-cards.c +++ b/drivers/media/video/cx18/cx18-cards.c @@ -339,13 +339,14 @@ static const struct cx18_card cx18_card_toshiba_qosmio_dvbt = { /* Leadtek WinFast PVR2100 */ static const struct cx18_card_pci_info cx18_pci_leadtek_pvr2100[] = { - { PCI_DEVICE_ID_CX23418, CX18_PCI_ID_LEADTEK, 0x6f27 }, + { PCI_DEVICE_ID_CX23418, CX18_PCI_ID_LEADTEK, 0x6f27 }, /* PVR2100 */ + { PCI_DEVICE_ID_CX23418, CX18_PCI_ID_LEADTEK, 0x6690 }, /* DVR3100 H */ { 0, 0, 0 } }; static const struct cx18_card cx18_card_leadtek_pvr2100 = { .type = CX18_CARD_LEADTEK_PVR2100, - .name = "Leadtek WinFast PVR2100", + .name = "Leadtek WinFast PVR2100/DVR3100 H", .comment = "Experimenters and photos needed for device to work well.\n" "\tTo help, mail the ivtv-devel list (www.ivtvdriver.org).\n", .v4l2_capabilities = CX18_CAP_ENCODER, diff --git a/drivers/media/video/cx18/cx18-driver.c b/drivers/media/video/cx18/cx18-driver.c index 1d3a865b9c6d..0f13fdd890a4 100644 --- a/drivers/media/video/cx18/cx18-driver.c +++ b/drivers/media/video/cx18/cx18-driver.c @@ -159,7 +159,7 @@ MODULE_PARM_DESC(cardtype, "\t\t\t 4 = Yuan MPC718\n" "\t\t\t 5 = Conexant Raptor PAL/SECAM\n" "\t\t\t 6 = Toshiba Qosmio DVB-T/Analog\n" - "\t\t\t 7 = Leadtek WinFast PVR2100\n" + "\t\t\t 7 = Leadtek WinFast PVR2100/DVR3100 H\n" "\t\t\t 0 = Autodetect (default)\n" "\t\t\t-1 = Ignore this card\n\t\t"); MODULE_PARM_DESC(pal, "Set PAL standard: B, G, H, D, K, I, M, N, Nc, 60"); diff --git a/drivers/media/video/cx18/cx18-driver.h b/drivers/media/video/cx18/cx18-driver.h index 2d5bcbf1b236..3a21013cd82b 100644 --- a/drivers/media/video/cx18/cx18-driver.h +++ b/drivers/media/video/cx18/cx18-driver.h @@ -80,7 +80,7 @@ #define CX18_CARD_YUAN_MPC718 3 /* Yuan MPC718 */ #define CX18_CARD_CNXT_RAPTOR_PAL 4 /* Conexant Raptor PAL */ #define CX18_CARD_TOSHIBA_QOSMIO_DVBT 5 /* Toshiba Qosmio Interal DVB-T/Analog*/ -#define CX18_CARD_LEADTEK_PVR2100 6 /* Leadtek WinFast PVR2100 */ +#define CX18_CARD_LEADTEK_PVR2100 6 /* Leadtek WinFast PVR2100/DVR3100 H */ #define CX18_CARD_LAST 6 #define CX18_ENC_STREAM_TYPE_MPG 0 -- cgit v1.2.3 From 07f7db4ce7b29d431553b426e0dcb720c5297a4b Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 21 Jan 2009 17:06:42 -0300 Subject: V4L/DVB (10291): em28xx: fix VIDIOC_G_CTRL when there is no msp34xx device. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/em28xx/em28xx-video.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/em28xx/em28xx-video.c b/drivers/media/video/em28xx/em28xx-video.c index 8e61b2ca9167..d8b45b5ee041 100644 --- a/drivers/media/video/em28xx/em28xx-video.c +++ b/drivers/media/video/em28xx/em28xx-video.c @@ -1008,8 +1008,13 @@ static int vidioc_g_ctrl(struct file *file, void *priv, if (dev->board.has_msp34xx) em28xx_i2c_call_clients(dev, VIDIOC_G_CTRL, ctrl); - else + else { rc = em28xx_get_ctrl(dev, ctrl); + if (rc < 0) { + em28xx_i2c_call_clients(dev, VIDIOC_G_CTRL, ctrl); + rc = 0; + } + } mutex_unlock(&dev->lock); return rc; -- cgit v1.2.3 From d0ebf3073f8812464c9f6014d6cee09ab37c3fb5 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Thu, 8 Jan 2009 14:05:11 -0300 Subject: V4L/DVB (10293): uvcvideo: replace strn{cpy,cat} with strl{cpy,cat}. strncpy is unsafe as it doesn't append a terminating NUL character when the source string doesn't fit in the destination buffer. Replace it with strlcpy. strncat is misused as its size argument refers to the source string, not the destination buffer. Replace it with strlcat. Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/uvc/uvc_ctrl.c | 2 +- drivers/media/video/uvc/uvc_driver.c | 16 ++++++++-------- drivers/media/video/uvc/uvc_v4l2.c | 12 ++++++------ 3 files changed, 15 insertions(+), 15 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/uvc/uvc_ctrl.c b/drivers/media/video/uvc/uvc_ctrl.c index d2576f6391c0..0d7e38d6ff6a 100644 --- a/drivers/media/video/uvc/uvc_ctrl.c +++ b/drivers/media/video/uvc/uvc_ctrl.c @@ -786,7 +786,7 @@ int uvc_query_v4l2_ctrl(struct uvc_video_device *video, memset(v4l2_ctrl, 0, sizeof *v4l2_ctrl); v4l2_ctrl->id = mapping->id; v4l2_ctrl->type = mapping->v4l2_type; - strncpy(v4l2_ctrl->name, mapping->name, sizeof v4l2_ctrl->name); + strlcpy(v4l2_ctrl->name, mapping->name, sizeof v4l2_ctrl->name); v4l2_ctrl->flags = 0; if (!(ctrl->info->flags & UVC_CONTROL_SET_CUR)) diff --git a/drivers/media/video/uvc/uvc_driver.c b/drivers/media/video/uvc/uvc_driver.c index b12873265cc5..6dba5ead8836 100644 --- a/drivers/media/video/uvc/uvc_driver.c +++ b/drivers/media/video/uvc/uvc_driver.c @@ -314,7 +314,7 @@ static int uvc_parse_format(struct uvc_device *dev, fmtdesc = uvc_format_by_guid(&buffer[5]); if (fmtdesc != NULL) { - strncpy(format->name, fmtdesc->name, + strlcpy(format->name, fmtdesc->name, sizeof format->name); format->fcc = fmtdesc->fcc; } else { @@ -345,7 +345,7 @@ static int uvc_parse_format(struct uvc_device *dev, return -EINVAL; } - strncpy(format->name, "MJPEG", sizeof format->name); + strlcpy(format->name, "MJPEG", sizeof format->name); format->fcc = V4L2_PIX_FMT_MJPEG; format->flags = UVC_FMT_FLAG_COMPRESSED; format->bpp = 0; @@ -363,13 +363,13 @@ static int uvc_parse_format(struct uvc_device *dev, switch (buffer[8] & 0x7f) { case 0: - strncpy(format->name, "SD-DV", sizeof format->name); + strlcpy(format->name, "SD-DV", sizeof format->name); break; case 1: - strncpy(format->name, "SDL-DV", sizeof format->name); + strlcpy(format->name, "SDL-DV", sizeof format->name); break; case 2: - strncpy(format->name, "HD-DV", sizeof format->name); + strlcpy(format->name, "HD-DV", sizeof format->name); break; default: uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming" @@ -379,7 +379,7 @@ static int uvc_parse_format(struct uvc_device *dev, return -EINVAL; } - strncat(format->name, buffer[8] & (1 << 7) ? " 60Hz" : " 50Hz", + strlcat(format->name, buffer[8] & (1 << 7) ? " 60Hz" : " 50Hz", sizeof format->name); format->fcc = V4L2_PIX_FMT_DV; @@ -1526,7 +1526,7 @@ static int uvc_register_video(struct uvc_device *dev) vdev->minor = -1; vdev->fops = &uvc_fops; vdev->release = video_device_release; - strncpy(vdev->name, dev->name, sizeof vdev->name); + strlcpy(vdev->name, dev->name, sizeof vdev->name); /* Set the driver data before calling video_register_device, otherwise * uvc_v4l2_open might race us. @@ -1621,7 +1621,7 @@ static int uvc_probe(struct usb_interface *intf, dev->quirks = id->driver_info | uvc_quirks_param; if (udev->product != NULL) - strncpy(dev->name, udev->product, sizeof dev->name); + strlcpy(dev->name, udev->product, sizeof dev->name); else snprintf(dev->name, sizeof dev->name, "UVC Camera (%04x:%04x)", diff --git a/drivers/media/video/uvc/uvc_v4l2.c b/drivers/media/video/uvc/uvc_v4l2.c index d681519d0c8a..011ebd4da44a 100644 --- a/drivers/media/video/uvc/uvc_v4l2.c +++ b/drivers/media/video/uvc/uvc_v4l2.c @@ -55,7 +55,7 @@ static int uvc_v4l2_query_menu(struct uvc_video_device *video, return -EINVAL; menu_info = &mapping->menu_info[query_menu->index]; - strncpy(query_menu->name, menu_info->name, 32); + strlcpy(query_menu->name, menu_info->name, sizeof query_menu->name); return 0; } @@ -486,9 +486,9 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg) struct v4l2_capability *cap = arg; memset(cap, 0, sizeof *cap); - strncpy(cap->driver, "uvcvideo", sizeof cap->driver); - strncpy(cap->card, vdev->name, 32); - strncpy(cap->bus_info, video->dev->udev->bus->bus_name, + strlcpy(cap->driver, "uvcvideo", sizeof cap->driver); + strlcpy(cap->card, vdev->name, sizeof cap->card); + strlcpy(cap->bus_info, video->dev->udev->bus->bus_name, sizeof cap->bus_info); cap->version = DRIVER_VERSION_NUMBER; if (video->streaming->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) @@ -620,7 +620,7 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg) memset(input, 0, sizeof *input); input->index = index; - strncpy(input->name, iterm->name, sizeof input->name); + strlcpy(input->name, iterm->name, sizeof input->name); if (UVC_ENTITY_TYPE(iterm) == ITT_CAMERA) input->type = V4L2_INPUT_TYPE_CAMERA; break; @@ -682,7 +682,7 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg) fmt->flags = 0; if (format->flags & UVC_FMT_FLAG_COMPRESSED) fmt->flags |= V4L2_FMT_FLAG_COMPRESSED; - strncpy(fmt->description, format->name, + strlcpy(fmt->description, format->name, sizeof fmt->description); fmt->description[sizeof fmt->description - 1] = 0; fmt->pixelformat = format->fcc; -- cgit v1.2.3 From f61d1d8a563b1f3c5f1f55d856278aae3fd3987e Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Wed, 14 Jan 2009 12:49:11 -0300 Subject: V4L/DVB (10294): uvcvideo: Add support for the Alcor Micro AU3820 chipset. The Alcor Micro AU3820 chipset (found in the Future Boy PC USB webcam) requires the MINMAX quirk. Add a corresponding entry in the device IDs list. Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/uvc/uvc_driver.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/uvc/uvc_driver.c b/drivers/media/video/uvc/uvc_driver.c index 6dba5ead8836..ebcd5bf0edb7 100644 --- a/drivers/media/video/uvc/uvc_driver.c +++ b/drivers/media/video/uvc/uvc_driver.c @@ -1833,6 +1833,15 @@ static struct usb_device_id uvc_ids[] = { .bInterfaceClass = USB_CLASS_VENDOR_SPEC, .bInterfaceSubClass = 1, .bInterfaceProtocol = 0 }, + /* Alcor Micro AU3820 (Future Boy PC USB Webcam) */ + { .match_flags = USB_DEVICE_ID_MATCH_DEVICE + | USB_DEVICE_ID_MATCH_INT_INFO, + .idVendor = 0x058f, + .idProduct = 0x3820, + .bInterfaceClass = USB_CLASS_VIDEO, + .bInterfaceSubClass = 1, + .bInterfaceProtocol = 0, + .driver_info = UVC_QUIRK_PROBE_MINMAX }, /* Apple Built-In iSight */ { .match_flags = USB_DEVICE_ID_MATCH_DEVICE | USB_DEVICE_ID_MATCH_INT_INFO, @@ -1879,7 +1888,7 @@ static struct usb_device_id uvc_ids[] = { .bInterfaceSubClass = 1, .bInterfaceProtocol = 0, .driver_info = UVC_QUIRK_STREAM_NO_FID }, - /* Asus F9SG */ + /* Syntek (Asus F9SG) */ { .match_flags = USB_DEVICE_ID_MATCH_DEVICE | USB_DEVICE_ID_MATCH_INT_INFO, .idVendor = 0x174f, -- cgit v1.2.3 From efdc8a9585ce02e70e538e46f235aefd63a3f8da Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Sun, 18 Jan 2009 17:46:30 -0300 Subject: V4L/DVB (10295): uvcvideo: Retry URB buffers allocation when the system is low on memory. URB buffers for video transfers are sized to UVC_MAX_PACKETS bulk/isochronous packets by default. If the system is too low on memory try successively smaller numbers of packets until allocation succeeds. Tested-by: Johannes Berg Signed-off-by: Laurent Pinchart Reviewed-by: Johannes Berg Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/uvc/uvc_video.c | 79 ++++++++++++++++++++----------------- drivers/media/video/uvc/uvcvideo.h | 6 +-- 2 files changed, 44 insertions(+), 41 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/uvc/uvc_video.c b/drivers/media/video/uvc/uvc_video.c index 9bc4705be78d..7ebb89539c36 100644 --- a/drivers/media/video/uvc/uvc_video.c +++ b/drivers/media/video/uvc/uvc_video.c @@ -699,27 +699,47 @@ static void uvc_free_urb_buffers(struct uvc_video_device *video) * already allocated when resuming from suspend, in which case it will * return without touching the buffers. * - * Return 0 on success or -ENOMEM when out of memory. + * Limit the buffer size to UVC_MAX_PACKETS bulk/isochronous packets. If the + * system is too low on memory try successively smaller numbers of packets + * until allocation succeeds. + * + * Return the number of allocated packets on success or 0 when out of memory. */ static int uvc_alloc_urb_buffers(struct uvc_video_device *video, - unsigned int size) + unsigned int size, unsigned int psize, gfp_t gfp_flags) { + unsigned int npackets; unsigned int i; /* Buffers are already allocated, bail out. */ if (video->urb_size) return 0; - for (i = 0; i < UVC_URBS; ++i) { - video->urb_buffer[i] = usb_buffer_alloc(video->dev->udev, - size, GFP_KERNEL, &video->urb_dma[i]); - if (video->urb_buffer[i] == NULL) { - uvc_free_urb_buffers(video); - return -ENOMEM; + /* Compute the number of packets. Bulk endpoints might transfer UVC + * payloads accross multiple URBs. + */ + npackets = DIV_ROUND_UP(size, psize); + if (npackets > UVC_MAX_PACKETS) + npackets = UVC_MAX_PACKETS; + + /* Retry allocations until one succeed. */ + for (; npackets > 1; npackets /= 2) { + for (i = 0; i < UVC_URBS; ++i) { + video->urb_buffer[i] = usb_buffer_alloc( + video->dev->udev, psize * npackets, + gfp_flags | __GFP_NOWARN, &video->urb_dma[i]); + if (!video->urb_buffer[i]) { + uvc_free_urb_buffers(video); + break; + } + } + + if (i == UVC_URBS) { + video->urb_size = psize * npackets; + return npackets; } } - video->urb_size = size; return 0; } @@ -753,29 +773,19 @@ static int uvc_init_video_isoc(struct uvc_video_device *video, { struct urb *urb; unsigned int npackets, i, j; - __u16 psize; - __u32 size; + u16 psize; + u32 size; - /* Compute the number of isochronous packets to allocate by dividing - * the maximum video frame size by the packet size. Limit the result - * to UVC_MAX_ISO_PACKETS. - */ psize = le16_to_cpu(ep->desc.wMaxPacketSize); psize = (psize & 0x07ff) * (1 + ((psize >> 11) & 3)); - size = video->streaming->ctrl.dwMaxVideoFrameSize; - if (size > UVC_MAX_FRAME_SIZE) - return -EINVAL; - npackets = DIV_ROUND_UP(size, psize); - if (npackets > UVC_MAX_ISO_PACKETS) - npackets = UVC_MAX_ISO_PACKETS; + npackets = uvc_alloc_urb_buffers(video, size, psize, gfp_flags); + if (npackets == 0) + return -ENOMEM; size = npackets * psize; - if (uvc_alloc_urb_buffers(video, size) < 0) - return -ENOMEM; - for (i = 0; i < UVC_URBS; ++i) { urb = usb_alloc_urb(npackets, gfp_flags); if (urb == NULL) { @@ -814,25 +824,20 @@ static int uvc_init_video_bulk(struct uvc_video_device *video, struct usb_host_endpoint *ep, gfp_t gfp_flags) { struct urb *urb; - unsigned int pipe, i; - __u16 psize; - __u32 size; - - /* Compute the bulk URB size. Some devices set the maximum payload - * size to a value too high for memory-constrained devices. We must - * then transfer the payload accross multiple URBs. To be consistant - * with isochronous mode, allocate maximum UVC_MAX_ISO_PACKETS per bulk - * URB. - */ + unsigned int npackets, pipe, i; + u16 psize; + u32 size; + psize = le16_to_cpu(ep->desc.wMaxPacketSize) & 0x07ff; size = video->streaming->ctrl.dwMaxPayloadTransferSize; video->bulk.max_payload_size = size; - if (size > psize * UVC_MAX_ISO_PACKETS) - size = psize * UVC_MAX_ISO_PACKETS; - if (uvc_alloc_urb_buffers(video, size) < 0) + npackets = uvc_alloc_urb_buffers(video, size, psize, gfp_flags); + if (npackets == 0) return -ENOMEM; + size = npackets * psize; + if (usb_endpoint_dir_in(&ep->desc)) pipe = usb_rcvbulkpipe(video->dev->udev, ep->desc.bEndpointAddress); diff --git a/drivers/media/video/uvc/uvcvideo.h b/drivers/media/video/uvc/uvcvideo.h index 027947ea9b6e..b2639878f9b2 100644 --- a/drivers/media/video/uvc/uvcvideo.h +++ b/drivers/media/video/uvc/uvcvideo.h @@ -296,10 +296,8 @@ struct uvc_xu_control { /* Number of isochronous URBs. */ #define UVC_URBS 5 -/* Maximum number of packets per isochronous URB. */ -#define UVC_MAX_ISO_PACKETS 40 -/* Maximum frame size in bytes, for sanity checking. */ -#define UVC_MAX_FRAME_SIZE (16*1024*1024) +/* Maximum number of packets per URB. */ +#define UVC_MAX_PACKETS 32 /* Maximum number of video buffers. */ #define UVC_MAX_VIDEO_BUFFERS 32 /* Maximum status buffer size in bytes of interrupt URB. */ -- cgit v1.2.3 From f180152376c984a6faa9decb8f2811c373da9141 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Thu, 22 Jan 2009 12:45:10 -0300 Subject: V4L/DVB (10296): uvcvideo: Fix memory leak in input device handling The dynamically allocated input_dev->phys buffer isn't freed when unregistering the device. As the input layer doesn't provide any release callback, use a fixed-size buffer inside the uvc_device structure. Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/uvc/uvc_status.c | 16 ++++------------ drivers/media/video/uvc/uvcvideo.h | 1 + 2 files changed, 5 insertions(+), 12 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/uvc/uvc_status.c b/drivers/media/video/uvc/uvc_status.c index c705f248da88..21d87124986b 100644 --- a/drivers/media/video/uvc/uvc_status.c +++ b/drivers/media/video/uvc/uvc_status.c @@ -24,26 +24,19 @@ #ifdef CONFIG_USB_VIDEO_CLASS_INPUT_EVDEV static int uvc_input_init(struct uvc_device *dev) { - struct usb_device *udev = dev->udev; struct input_dev *input; - char *phys = NULL; int ret; input = input_allocate_device(); if (input == NULL) return -ENOMEM; - phys = kmalloc(6 + strlen(udev->bus->bus_name) + strlen(udev->devpath), - GFP_KERNEL); - if (phys == NULL) { - ret = -ENOMEM; - goto error; - } - sprintf(phys, "usb-%s-%s", udev->bus->bus_name, udev->devpath); + usb_make_path(dev->udev, dev->input_phys, sizeof(dev->input_phys)); + strlcat(dev->input_phys, "/button", sizeof(dev->input_phys)); input->name = dev->name; - input->phys = phys; - usb_to_input_id(udev, &input->id); + input->phys = dev->input_phys; + usb_to_input_id(dev->udev, &input->id); input->dev.parent = &dev->intf->dev; __set_bit(EV_KEY, input->evbit); @@ -57,7 +50,6 @@ static int uvc_input_init(struct uvc_device *dev) error: input_free_device(input); - kfree(phys); return ret; } diff --git a/drivers/media/video/uvc/uvcvideo.h b/drivers/media/video/uvc/uvcvideo.h index b2639878f9b2..6f55c4d49cf4 100644 --- a/drivers/media/video/uvc/uvcvideo.h +++ b/drivers/media/video/uvc/uvcvideo.h @@ -647,6 +647,7 @@ struct uvc_device { struct urb *int_urb; __u8 *status; struct input_dev *input; + char input_phys[64]; /* Video Streaming interfaces */ struct list_head streaming; -- cgit v1.2.3 From be9ed5117d95cdc4e601f9da220ebeaaab131679 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 8 Jan 2009 09:13:42 -0300 Subject: V4L/DVB (10298): remove err macro from few usb devices Patch removes err() macros from few usb devices. It places pr_err in pvrusb2-v4l2.c, dev_err in dabusb and in usbvision drivers. Beside placing dev_err, patch defines new s2255_dev_err macro with S2255_DRIVER_NAME in s2255 module. Signed-off-by: Alexey Klimov Acked-by: Thierry Merle Acked-by: Mike Isely Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/dabusb.c | 70 +++++++++++++++---------- drivers/media/video/pvrusb2/pvrusb2-v4l2.c | 12 +++-- drivers/media/video/s2255drv.c | 38 ++++++++------ drivers/media/video/usbvision/usbvision-core.c | 44 ++++++++++------ drivers/media/video/usbvision/usbvision-i2c.c | 6 ++- drivers/media/video/usbvision/usbvision-video.c | 36 ++++++++----- 6 files changed, 126 insertions(+), 80 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/dabusb.c b/drivers/media/video/dabusb.c index 298810d5262b..f40c676489a4 100644 --- a/drivers/media/video/dabusb.c +++ b/drivers/media/video/dabusb.c @@ -189,17 +189,20 @@ static void dabusb_iso_complete (struct urb *purb) dst += len; } else - err("dabusb_iso_complete: invalid len %d", len); + dev_err(&purb->dev->dev, + "dabusb_iso_complete: invalid len %d\n", len); } else dev_warn(&purb->dev->dev, "dabusb_iso_complete: corrupted packet status: %d\n", purb->iso_frame_desc[i].status); if (dst != purb->actual_length) - err("dst!=purb->actual_length:%d!=%d", dst, purb->actual_length); + dev_err(&purb->dev->dev, + "dst!=purb->actual_length:%d!=%d\n", + dst, purb->actual_length); } if (atomic_dec_and_test (&s->pending_io) && !s->remove_pending && s->state != _stopped) { s->overruns++; - err("overrun (%d)", s->overruns); + dev_err(&purb->dev->dev, "overrun (%d)\n", s->overruns); } wake_up (&s->wait); } @@ -220,13 +223,14 @@ static int dabusb_alloc_buffers (pdabusb_t s) while (transfer_len < (s->total_buffer_size << 10)) { b = kzalloc(sizeof (buff_t), GFP_KERNEL); if (!b) { - err("kzalloc(sizeof(buff_t))==NULL"); + dev_err(&s->usbdev->dev, + "kzalloc(sizeof(buff_t))==NULL\n"); goto err; } b->s = s; b->purb = usb_alloc_urb(packets, GFP_KERNEL); if (!b->purb) { - err("usb_alloc_urb == NULL"); + dev_err(&s->usbdev->dev, "usb_alloc_urb == NULL\n"); kfree (b); goto err; } @@ -235,7 +239,8 @@ static int dabusb_alloc_buffers (pdabusb_t s) if (!b->purb->transfer_buffer) { kfree (b->purb); kfree (b); - err("kmalloc(%d)==NULL", transfer_buffer_length); + dev_err(&s->usbdev->dev, + "kmalloc(%d)==NULL\n", transfer_buffer_length); goto err; } @@ -279,10 +284,11 @@ static int dabusb_bulk (pdabusb_t s, pbulk_transfer_t pb) ret=usb_bulk_msg(s->usbdev, pipe, pb->data, pb->size, &actual_length, 100); if(ret<0) { - err("dabusb: usb_bulk_msg failed(%d)",ret); + dev_err(&s->usbdev->dev, + "usb_bulk_msg failed(%d)\n", ret); if (usb_set_interface (s->usbdev, _DABUSB_IF, 1) < 0) { - err("set_interface failed"); + dev_err(&s->usbdev->dev, "set_interface failed\n"); return -EINVAL; } @@ -291,7 +297,7 @@ static int dabusb_bulk (pdabusb_t s, pbulk_transfer_t pb) if( ret == -EPIPE ) { dev_warn(&s->usbdev->dev, "CLEAR_FEATURE request to remove STALL condition.\n"); if(usb_clear_halt(s->usbdev, usb_pipeendpoint(pipe))) - err("request failed"); + dev_err(&s->usbdev->dev, "request failed\n"); } pb->size = actual_length; @@ -305,7 +311,8 @@ static int dabusb_writemem (pdabusb_t s, int pos, const unsigned char *data, unsigned char *transfer_buffer = kmalloc (len, GFP_KERNEL); if (!transfer_buffer) { - err("dabusb_writemem: kmalloc(%d) failed.", len); + dev_err(&s->usbdev->dev, + "dabusb_writemem: kmalloc(%d) failed.\n", len); return -ENOMEM; } @@ -333,7 +340,8 @@ static int dabusb_loadmem (pdabusb_t s, const char *fname) ret = request_ihex_firmware(&fw, "dabusb/firmware.fw", &s->usbdev->dev); if (ret) { - err("Failed to load \"dabusb/firmware.fw\": %d\n", ret); + dev_err(&s->usbdev->dev, + "Failed to load \"dabusb/firmware.fw\": %d\n", ret); goto out; } ret = dabusb_8051_reset (s, 1); @@ -346,9 +354,10 @@ static int dabusb_loadmem (pdabusb_t s, const char *fname) ret = dabusb_writemem(s, be32_to_cpu(rec->addr), rec->data, be16_to_cpu(rec->len)); if (ret < 0) { - err("dabusb_writemem failed (%d %04X %p %d)", ret, - be32_to_cpu(rec->addr), rec->data, - be16_to_cpu(rec->len)); + dev_err(&s->usbdev->dev, + "dabusb_writemem failed (%d %04X %p %d)\n", + ret, be32_to_cpu(rec->addr), + rec->data, be16_to_cpu(rec->len)); break; } } @@ -396,13 +405,15 @@ static int dabusb_fpga_download (pdabusb_t s, const char *fname) dbg("Enter dabusb_fpga_download (internal)"); if (!b) { - err("kmalloc(sizeof(bulk_transfer_t))==NULL"); + dev_err(&s->usbdev->dev, + "kmalloc(sizeof(bulk_transfer_t))==NULL\n"); return -ENOMEM; } ret = request_firmware(&fw, "dabusb/bitstream.bin", &s->usbdev->dev); if (ret) { - err("Failed to load \"dabusb/bitstream.bin\": %d\n", ret); + dev_err(&s->usbdev->dev, + "Failed to load \"dabusb/bitstream.bin\": %d\n", ret); kfree(b); return ret; } @@ -425,7 +436,7 @@ static int dabusb_fpga_download (pdabusb_t s, const char *fname) memcpy (b->data + 4, fw->data + 74 + n, 60); ret = dabusb_bulk (s, b); if (ret < 0) { - err("dabusb_bulk failed."); + dev_err(&s->usbdev->dev, "dabusb_bulk failed.\n"); break; } mdelay (1); @@ -478,9 +489,11 @@ static int dabusb_startrek (pdabusb_t s) ret = usb_submit_urb (end->purb, GFP_KERNEL); if (ret) { - err("usb_submit_urb returned:%d", ret); + dev_err(&s->usbdev->dev, + "usb_submit_urb returned:%d\n", ret); if (dabusb_add_buf_tail (s, &s->free_buff_list, &s->rec_buff_list)) - err("startrek: dabusb_add_buf_tail failed"); + dev_err(&s->usbdev->dev, + "startrek: dabusb_add_buf_tail failed\n"); break; } else @@ -523,7 +536,8 @@ static ssize_t dabusb_read (struct file *file, char __user *buf, size_t count, l spin_unlock_irqrestore(&s->lock, flags); - err("error: rec_buf_list is empty"); + dev_err(&s->usbdev->dev, + "error: rec_buf_list is empty\n"); goto err; } @@ -552,7 +566,8 @@ static ssize_t dabusb_read (struct file *file, char __user *buf, size_t count, l if (list_empty (&s->rec_buff_list)) { spin_unlock_irqrestore(&s->lock, flags); - err("error: still no buffer available."); + dev_err(&s->usbdev->dev, + "error: still no buffer available.\n"); goto err; } spin_unlock_irqrestore(&s->lock, flags); @@ -573,7 +588,7 @@ static ssize_t dabusb_read (struct file *file, char __user *buf, size_t count, l dbg("copy_to_user:%p %p %d",buf, purb->transfer_buffer + s->readptr, cnt); if (copy_to_user (buf, purb->transfer_buffer + s->readptr, cnt)) { - err("read: copy_to_user failed"); + dev_err(&s->usbdev->dev, "read: copy_to_user failed\n"); if (!ret) ret = -EFAULT; goto err; @@ -587,7 +602,8 @@ static ssize_t dabusb_read (struct file *file, char __user *buf, size_t count, l if (s->readptr == purb->actual_length) { // finished, take next buffer if (dabusb_add_buf_tail (s, &s->free_buff_list, &s->rec_buff_list)) - err("read: dabusb_add_buf_tail failed"); + dev_err(&s->usbdev->dev, + "read: dabusb_add_buf_tail failed\n"); s->readptr = 0; } } @@ -623,7 +639,7 @@ static int dabusb_open (struct inode *inode, struct file *file) } if (usb_set_interface (s->usbdev, _DABUSB_IF, 1) < 0) { mutex_unlock(&s->mutex); - err("set_interface failed"); + dev_err(&s->usbdev->dev, "set_interface failed\n"); return -EINVAL; } s->opened = 1; @@ -648,7 +664,7 @@ static int dabusb_release (struct inode *inode, struct file *file) if (!s->remove_pending) { if (usb_set_interface (s->usbdev, _DABUSB_IF, 0) < 0) - err("set_interface failed"); + dev_err(&s->usbdev->dev, "set_interface failed\n"); } else wake_up (&s->remove_ok); @@ -764,7 +780,7 @@ static int dabusb_probe (struct usb_interface *intf, s->devnum = intf->minor; if (usb_reset_configuration (usbdev) < 0) { - err("reset_configuration failed"); + dev_err(&intf->dev, "reset_configuration failed\n"); goto reject; } if (le16_to_cpu(usbdev->descriptor.idProduct) == 0x2131) { @@ -775,7 +791,7 @@ static int dabusb_probe (struct usb_interface *intf, dabusb_fpga_download (s, NULL); if (usb_set_interface (s->usbdev, _DABUSB_IF, 0) < 0) { - err("set_interface failed"); + dev_err(&intf->dev, "set_interface failed\n"); goto reject; } } diff --git a/drivers/media/video/pvrusb2/pvrusb2-v4l2.c b/drivers/media/video/pvrusb2/pvrusb2-v4l2.c index 3163c6df448a..b7caf135ed55 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-v4l2.c +++ b/drivers/media/video/pvrusb2/pvrusb2-v4l2.c @@ -1268,8 +1268,9 @@ static void pvr2_v4l2_dev_init(struct pvr2_v4l2_dev *dip, dip->minor_type = pvr2_v4l_type_video; nr_ptr = video_nr; if (!dip->stream) { - err("Failed to set up pvrusb2 v4l video dev" - " due to missing stream instance"); + pr_err(KBUILD_MODNAME + ": Failed to set up pvrusb2 v4l video dev" + " due to missing stream instance\n"); return; } break; @@ -1286,8 +1287,8 @@ static void pvr2_v4l2_dev_init(struct pvr2_v4l2_dev *dip, break; default: /* Bail out (this should be impossible) */ - err("Failed to set up pvrusb2 v4l dev" - " due to unrecognized config"); + pr_err(KBUILD_MODNAME ": Failed to set up pvrusb2 v4l dev" + " due to unrecognized config\n"); return; } @@ -1303,7 +1304,8 @@ static void pvr2_v4l2_dev_init(struct pvr2_v4l2_dev *dip, dip->v4l_type, mindevnum) < 0) && (video_register_device(&dip->devbase, dip->v4l_type, -1) < 0)) { - err("Failed to register pvrusb2 v4l device"); + pr_err(KBUILD_MODNAME + ": Failed to register pvrusb2 v4l device\n"); } printk(KERN_INFO "pvrusb2: registered device %s%u [%s]\n", diff --git a/drivers/media/video/s2255drv.c b/drivers/media/video/s2255drv.c index 13f85ad363cd..31bc94075268 100644 --- a/drivers/media/video/s2255drv.c +++ b/drivers/media/video/s2255drv.c @@ -336,14 +336,19 @@ static long s2255_vendor_req(struct s2255_dev *dev, unsigned char req, u16 index, u16 value, void *buf, s32 buf_len, int bOut); +/* dev_err macro with driver name */ +#define S2255_DRIVER_NAME "s2255" +#define s2255_dev_err(dev, fmt, arg...) \ + dev_err(dev, S2255_DRIVER_NAME " - " fmt, ##arg) + #define dprintk(level, fmt, arg...) \ do { \ if (*s2255_debug >= (level)) { \ - printk(KERN_DEBUG "s2255: " fmt, ##arg); \ + printk(KERN_DEBUG S2255_DRIVER_NAME \ + ": " fmt, ##arg); \ } \ } while (0) - static struct usb_driver s2255_driver; @@ -528,14 +533,14 @@ static void s2255_fwchunk_complete(struct urb *urb) int len; dprintk(100, "udev %p urb %p", udev, urb); if (urb->status) { - dev_err(&udev->dev, "URB failed with status %d", urb->status); + dev_err(&udev->dev, "URB failed with status %d\n", urb->status); atomic_set(&data->fw_state, S2255_FW_FAILED); /* wake up anything waiting for the firmware */ wake_up(&data->wait_fw); return; } if (data->fw_urb == NULL) { - dev_err(&udev->dev, "s2255 disconnected\n"); + s2255_dev_err(&udev->dev, "disconnected\n"); atomic_set(&data->fw_state, S2255_FW_FAILED); /* wake up anything waiting for the firmware */ wake_up(&data->wait_fw); @@ -1278,7 +1283,7 @@ static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i) } if (!res_get(dev, fh)) { - dev_err(&dev->udev->dev, "s2255: stream busy\n"); + s2255_dev_err(&dev->udev->dev, "stream busy\n"); return -EBUSY; } @@ -1545,7 +1550,8 @@ static int s2255_open(struct file *file) switch (atomic_read(&dev->fw_data->fw_state)) { case S2255_FW_FAILED: - err("2255 firmware load failed. retrying.\n"); + s2255_dev_err(&dev->udev->dev, + "firmware load failed. retrying.\n"); s2255_fwload_start(dev, 1); wait_event_timeout(dev->fw_data->wait_fw, ((atomic_read(&dev->fw_data->fw_state) @@ -2173,7 +2179,8 @@ static int s2255_board_init(struct s2255_dev *dev) printk(KERN_INFO "2255 usb firmware version %d \n", fw_ver); if (fw_ver < CUR_USB_FWVER) - err("usb firmware not up to date %d\n", fw_ver); + dev_err(&dev->udev->dev, + "usb firmware not up to date %d\n", fw_ver); for (j = 0; j < MAX_CHANNELS; j++) { dev->b_acquire[j] = 0; @@ -2228,13 +2235,13 @@ static void read_pipe_completion(struct urb *purb) dprintk(100, "read pipe completion %p, status %d\n", purb, purb->status); if (pipe_info == NULL) { - err("no context !"); + dev_err(&purb->dev->dev, "no context!\n"); return; } dev = pipe_info->dev; if (dev == NULL) { - err("no context !"); + dev_err(&purb->dev->dev, "no context!\n"); return; } status = purb->status; @@ -2286,7 +2293,7 @@ static int s2255_start_readpipe(struct s2255_dev *dev) pipe_info->stream_urb = usb_alloc_urb(0, GFP_KERNEL); if (!pipe_info->stream_urb) { dev_err(&dev->udev->dev, - "ReadStream: Unable to alloc URB"); + "ReadStream: Unable to alloc URB\n"); return -ENOMEM; } /* transfer buffer allocated in board_init */ @@ -2391,7 +2398,7 @@ static void s2255_stop_readpipe(struct s2255_dev *dev) int j; if (dev == NULL) { - err("s2255: invalid device"); + s2255_dev_err(&dev->udev->dev, "invalid device\n"); return; } dprintk(4, "stop read pipe\n"); @@ -2453,7 +2460,7 @@ static int s2255_probe(struct usb_interface *interface, /* allocate memory for our device state and initialize it to zero */ dev = kzalloc(sizeof(struct s2255_dev), GFP_KERNEL); if (dev == NULL) { - err("s2255: out of memory"); + s2255_dev_err(&interface->dev, "out of memory\n"); goto error; } @@ -2487,7 +2494,7 @@ static int s2255_probe(struct usb_interface *interface, } if (!dev->read_endpoint) { - dev_err(&interface->dev, "Could not find bulk-in endpoint"); + dev_err(&interface->dev, "Could not find bulk-in endpoint\n"); goto error; } @@ -2583,7 +2590,7 @@ static void s2255_disconnect(struct usb_interface *interface) } static struct usb_driver s2255_driver = { - .name = "s2255", + .name = S2255_DRIVER_NAME, .probe = s2255_probe, .disconnect = s2255_disconnect, .id_table = s2255_table, @@ -2597,7 +2604,8 @@ static int __init usb_s2255_init(void) result = usb_register(&s2255_driver); if (result) - err("usb_register failed. Error number %d", result); + pr_err(KBUILD_MODNAME + ": usb_register failed. Error number %d\n", result); dprintk(2, "s2255_init: done\n"); return result; diff --git a/drivers/media/video/usbvision/usbvision-core.c b/drivers/media/video/usbvision/usbvision-core.c index 9e4f50639975..4444e7e3cdf8 100644 --- a/drivers/media/video/usbvision/usbvision-core.c +++ b/drivers/media/video/usbvision/usbvision-core.c @@ -381,8 +381,9 @@ int usbvision_scratch_alloc(struct usb_usbvision *usbvision) usbvision->scratch = vmalloc_32(scratch_buf_size); scratch_reset(usbvision); if(usbvision->scratch == NULL) { - err("%s: unable to allocate %d bytes for scratch", - __func__, scratch_buf_size); + dev_err(&usbvision->dev->dev, + "%s: unable to allocate %d bytes for scratch\n", + __func__, scratch_buf_size); return -ENOMEM; } return 0; @@ -491,8 +492,9 @@ int usbvision_decompress_alloc(struct usb_usbvision *usbvision) int IFB_size = MAX_FRAME_WIDTH * MAX_FRAME_HEIGHT * 3 / 2; usbvision->IntraFrameBuffer = vmalloc_32(IFB_size); if (usbvision->IntraFrameBuffer == NULL) { - err("%s: unable to allocate %d for compr. frame buffer", - __func__, IFB_size); + dev_err(&usbvision->dev->dev, + "%s: unable to allocate %d for compr. frame buffer\n", + __func__, IFB_size); return -ENOMEM; } return 0; @@ -1514,8 +1516,9 @@ static void usbvision_isocIrq(struct urb *urb) errCode = usb_submit_urb (urb, GFP_ATOMIC); if(errCode) { - err("%s: usb_submit_urb failed: error %d", - __func__, errCode); + dev_err(&usbvision->dev->dev, + "%s: usb_submit_urb failed: error %d\n", + __func__, errCode); } return; @@ -1546,7 +1549,8 @@ int usbvision_read_reg(struct usb_usbvision *usbvision, unsigned char reg) 0, (__u16) reg, buffer, 1, HZ); if (errCode < 0) { - err("%s: failed: error %d", __func__, errCode); + dev_err(&usbvision->dev->dev, + "%s: failed: error %d\n", __func__, errCode); return errCode; } return buffer[0]; @@ -1574,7 +1578,8 @@ int usbvision_write_reg(struct usb_usbvision *usbvision, unsigned char reg, USB_RECIP_ENDPOINT, 0, (__u16) reg, &value, 1, HZ); if (errCode < 0) { - err("%s: failed: error %d", __func__, errCode); + dev_err(&usbvision->dev->dev, + "%s: failed: error %d\n", __func__, errCode); } return errCode; } @@ -1850,7 +1855,8 @@ int usbvision_set_output(struct usb_usbvision *usbvision, int width, 0, (__u16) USBVISION_LXSIZE_O, value, 4, HZ); if (errCode < 0) { - err("%s failed: error %d", __func__, errCode); + dev_err(&usbvision->dev->dev, + "%s failed: error %d\n", __func__, errCode); return errCode; } usbvision->curwidth = usbvision->stretch_width * UsbWidth; @@ -2236,7 +2242,7 @@ static int usbvision_set_dram_settings(struct usb_usbvision *usbvision) (__u16) USBVISION_DRM_PRM1, value, 8, HZ); if (rc < 0) { - err("%sERROR=%d", __func__, rc); + dev_err(&usbvision->dev->dev, "%sERROR=%d\n", __func__, rc); return rc; } @@ -2432,8 +2438,9 @@ int usbvision_set_alternate(struct usb_usbvision *dev) PDEBUG(DBG_FUNC,"setting alternate %d with wMaxPacketSize=%u", dev->ifaceAlt,dev->isocPacketSize); errCode = usb_set_interface(dev->dev, dev->iface, dev->ifaceAlt); if (errCode < 0) { - err ("cannot change alternate number to %d (error=%i)", - dev->ifaceAlt, errCode); + dev_err(&dev->dev->dev, + "cannot change alternate number to %d (error=%i)\n", + dev->ifaceAlt, errCode); return errCode; } } @@ -2484,7 +2491,8 @@ int usbvision_init_isoc(struct usb_usbvision *usbvision) urb = usb_alloc_urb(USBVISION_URB_FRAMES, GFP_KERNEL); if (urb == NULL) { - err("%s: usb_alloc_urb() failed", __func__); + dev_err(&usbvision->dev->dev, + "%s: usb_alloc_urb() failed\n", __func__); return -ENOMEM; } usbvision->sbuf[bufIdx].urb = urb; @@ -2516,8 +2524,9 @@ int usbvision_init_isoc(struct usb_usbvision *usbvision) errCode = usb_submit_urb(usbvision->sbuf[bufIdx].urb, GFP_KERNEL); if (errCode) { - err("%s: usb_submit_urb(%d) failed: error %d", - __func__, bufIdx, errCode); + dev_err(&usbvision->dev->dev, + "%s: usb_submit_urb(%d) failed: error %d\n", + __func__, bufIdx, errCode); } } @@ -2566,8 +2575,9 @@ void usbvision_stop_isoc(struct usb_usbvision *usbvision) errCode = usb_set_interface(usbvision->dev, usbvision->iface, usbvision->ifaceAlt); if (errCode < 0) { - err("%s: usb_set_interface() failed: error %d", - __func__, errCode); + dev_err(&usbvision->dev->dev, + "%s: usb_set_interface() failed: error %d\n", + __func__, errCode); usbvision->last_error = errCode; } regValue = (16-usbvision_read_reg(usbvision, USBVISION_ALTER_REG)) & 0x0F; diff --git a/drivers/media/video/usbvision/usbvision-i2c.c b/drivers/media/video/usbvision/usbvision-i2c.c index 6b66ae4f430f..6057098282ca 100644 --- a/drivers/media/video/usbvision/usbvision-i2c.c +++ b/drivers/media/video/usbvision/usbvision-i2c.c @@ -119,7 +119,8 @@ static inline int usb_find_address(struct i2c_adapter *i2c_adap, /* try extended address code... */ ret = try_write_address(i2c_adap, addr, retries); if (ret != 1) { - err("died at extended address code, while writing"); + dev_err(&i2c_adap->dev, + "died at extended address code, while writing\n"); return -EREMOTEIO; } add[0] = addr; @@ -128,7 +129,8 @@ static inline int usb_find_address(struct i2c_adapter *i2c_adap, addr |= 0x01; ret = try_read_address(i2c_adap, addr, retries); if (ret != 1) { - err("died at extended address code, while reading"); + dev_err(&i2c_adap->dev, + "died at extended address code, while reading\n"); return -EREMOTEIO; } } diff --git a/drivers/media/video/usbvision/usbvision-video.c b/drivers/media/video/usbvision/usbvision-video.c index 2622de003a45..47d672da5415 100644 --- a/drivers/media/video/usbvision/usbvision-video.c +++ b/drivers/media/video/usbvision/usbvision-video.c @@ -329,7 +329,7 @@ static void usbvision_create_sysfs(struct video_device *vdev) return; } while (0); - err("%s error: %d\n", __func__, res); + dev_err(&vdev->dev, "%s error: %d\n", __func__, res); } static void usbvision_remove_sysfs(struct video_device *vdev) @@ -487,8 +487,9 @@ static int vidioc_g_register (struct file *file, void *priv, /* NT100x has a 8-bit register space */ errCode = usbvision_read_reg(usbvision, reg->reg&0xff); if (errCode < 0) { - err("%s: VIDIOC_DBG_G_REGISTER failed: error %d", - __func__, errCode); + dev_err(&usbvision->vdev->dev, + "%s: VIDIOC_DBG_G_REGISTER failed: error %d\n", + __func__, errCode); return errCode; } reg->val = errCode; @@ -507,8 +508,9 @@ static int vidioc_s_register (struct file *file, void *priv, /* NT100x has a 8-bit register space */ errCode = usbvision_write_reg(usbvision, reg->reg&0xff, reg->val); if (errCode < 0) { - err("%s: VIDIOC_DBG_S_REGISTER failed: error %d", - __func__, errCode); + dev_err(&usbvision->vdev->dev, + "%s: VIDIOC_DBG_S_REGISTER failed: error %d\n", + __func__, errCode); return errCode; } return 0; @@ -1189,7 +1191,9 @@ static int usbvision_radio_open(struct file *file) mutex_lock(&usbvision->lock); if (usbvision->user) { - err("%s: Someone tried to open an already opened USBVision Radio!", __func__); + dev_err(&usbvision->rdev->dev, + "%s: Someone tried to open an already opened USBVision Radio!\n", + __func__); errCode = -EBUSY; } else { @@ -1413,7 +1417,8 @@ static struct video_device *usbvision_vdev_init(struct usb_usbvision *usbvision, struct video_device *vdev; if (usb_dev == NULL) { - err("%s: usbvision->dev is not set", __func__); + dev_err(&usbvision->dev->dev, + "%s: usbvision->dev is not set\n", __func__); return NULL; } @@ -1524,7 +1529,9 @@ static int __devinit usbvision_register_video(struct usb_usbvision *usbvision) return 0; err_exit: - err("USBVision[%d]: video_register_device() failed", usbvision->nr); + dev_err(&usbvision->dev->dev, + "USBVision[%d]: video_register_device() failed\n", + usbvision->nr); usbvision_unregister_video(usbvision); return -1; } @@ -1675,20 +1682,20 @@ static int __devinit usbvision_probe(struct usb_interface *intf, } endpoint = &interface->endpoint[1].desc; if (!usb_endpoint_xfer_isoc(endpoint)) { - err("%s: interface %d. has non-ISO endpoint!", + dev_err(&intf->dev, "%s: interface %d. has non-ISO endpoint!\n", __func__, ifnum); - err("%s: Endpoint attributes %d", + dev_err(&intf->dev, "%s: Endpoint attributes %d", __func__, endpoint->bmAttributes); return -ENODEV; } if (usb_endpoint_dir_out(endpoint)) { - err("%s: interface %d. has ISO OUT endpoint!", + dev_err(&intf->dev, "%s: interface %d. has ISO OUT endpoint!\n", __func__, ifnum); return -ENODEV; } if ((usbvision = usbvision_alloc(dev)) == NULL) { - err("%s: couldn't allocate USBVision struct", __func__); + dev_err(&intf->dev, "%s: couldn't allocate USBVision struct\n", __func__); return -ENOMEM; } @@ -1711,7 +1718,7 @@ static int __devinit usbvision_probe(struct usb_interface *intf, usbvision->alt_max_pkt_size = kmalloc(32* usbvision->num_alt,GFP_KERNEL); if (usbvision->alt_max_pkt_size == NULL) { - err("usbvision: out of memory!\n"); + dev_err(&intf->dev, "usbvision: out of memory!\n"); mutex_unlock(&usbvision->lock); return -ENOMEM; } @@ -1772,7 +1779,8 @@ static void __devexit usbvision_disconnect(struct usb_interface *intf) PDEBUG(DBG_PROBE, ""); if (usbvision == NULL) { - err("%s: usb_get_intfdata() failed", __func__); + dev_err(&usbvision->dev->dev, + "%s: usb_get_intfdata() failed\n", __func__); return; } usb_set_intfdata (intf, NULL); -- cgit v1.2.3 From ade0815c16734e8c25dbac9faf5b5d63bcccd533 Mon Sep 17 00:00:00 2001 From: Douglas Kosovic Date: Thu, 22 Jan 2009 23:07:26 -0300 Subject: V4L/DVB (10299): bttv: Add support for IVCE-8784 support for V4L2 bttv driver It's a quad Bt878 PCI-e x1 capture board that's basically the same as the IVC-200 (quad Bt878 PCI) capture board that's currently supported in the V4L2 bttv driver. Manufacturer's web page for IVCE-8784 with photo and info: http://www.iei.com.tw/en/product_IPC.asp?model=IVCE-8784 Signed-off-by: Douglas Kosovic Signed-off-by: Mauro Carvalho Chehab --- Documentation/video4linux/CARDLIST.bttv | 1 + drivers/media/video/bt8xx/bttv-cards.c | 17 +++++++++++++++++ drivers/media/video/bt8xx/bttv.h | 1 + 3 files changed, 19 insertions(+) (limited to 'drivers/media/video') diff --git a/Documentation/video4linux/CARDLIST.bttv b/Documentation/video4linux/CARDLIST.bttv index 0d93fa1ac25e..4dfe62641374 100644 --- a/Documentation/video4linux/CARDLIST.bttv +++ b/Documentation/video4linux/CARDLIST.bttv @@ -154,3 +154,4 @@ 153 -> PHYTEC VD-012 (bt878) 154 -> PHYTEC VD-012-X1 (bt878) 155 -> PHYTEC VD-012-X2 (bt878) +156 -> IVCE-8784 [0000:f050,0001:f050,0002:f050,0003:f050] diff --git a/drivers/media/video/bt8xx/bttv-cards.c b/drivers/media/video/bt8xx/bttv-cards.c index d24dcc025e37..9dfd8c70e4fb 100644 --- a/drivers/media/video/bt8xx/bttv-cards.c +++ b/drivers/media/video/bt8xx/bttv-cards.c @@ -246,6 +246,10 @@ static struct CARD { { 0xa182ff0d, BTTV_BOARD_IVC120, "IVC-120G" }, { 0xa182ff0e, BTTV_BOARD_IVC120, "IVC-120G" }, { 0xa182ff0f, BTTV_BOARD_IVC120, "IVC-120G" }, + { 0xf0500000, BTTV_BOARD_IVCE8784, "IVCE-8784" }, + { 0xf0500001, BTTV_BOARD_IVCE8784, "IVCE-8784" }, + { 0xf0500002, BTTV_BOARD_IVCE8784, "IVCE-8784" }, + { 0xf0500003, BTTV_BOARD_IVCE8784, "IVCE-8784" }, { 0x41424344, BTTV_BOARD_GRANDTEC, "GrandTec Multi Capture" }, { 0x01020304, BTTV_BOARD_XGUARD, "Grandtec Grand X-Guard" }, @@ -2162,6 +2166,19 @@ struct tvcard bttv_tvcards[] = { .muxsel = { 2 }, .pll = PLL_28, }, + [BTTV_BOARD_IVCE8784] = { + .name = "IVCE-8784", + .video_inputs = 1, + .audio_inputs = 0, + .tuner = UNSET, + .tuner_type = UNSET, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .svhs = UNSET, + .gpiomask = 0xdf, + .muxsel = { 2 }, + .pll = PLL_28, + }, [BTTV_BOARD_XGUARD] = { .name = "Grand X-Guard / Trust 814PCI", .video_inputs = 16, diff --git a/drivers/media/video/bt8xx/bttv.h b/drivers/media/video/bt8xx/bttv.h index 529bf6cf634d..a7bcad171823 100644 --- a/drivers/media/video/bt8xx/bttv.h +++ b/drivers/media/video/bt8xx/bttv.h @@ -180,6 +180,7 @@ #define BTTV_BOARD_VD012 0x99 #define BTTV_BOARD_VD012_X1 0x9a #define BTTV_BOARD_VD012_X2 0x9b +#define BTTV_BOARD_IVCE8784 0x9c /* more card-specific defines */ -- cgit v1.2.3 From 87e3495c316bf3b63512eb280fd4b2d6d3518755 Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Fri, 23 Jan 2009 01:20:24 -0300 Subject: V4L/DVB (10303): pvrusb2: Use usb_make_path() to determine device bus location Signed-off-by: Mike Isely Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/pvrusb2/pvrusb2-hdw.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/drivers/media/video/pvrusb2/pvrusb2-hdw.c index ac5dad0c5fb0..ed8a4561e086 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-hdw.c +++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.c @@ -2412,10 +2412,7 @@ struct pvr2_hdw *pvr2_hdw_create(struct usb_interface *intf, hdw->usb_intf = intf; hdw->usb_dev = interface_to_usbdev(intf); - scnprintf(hdw->bus_info,sizeof(hdw->bus_info), - "usb %s address %d", - dev_name(&hdw->usb_dev->dev), - hdw->usb_dev->devnum); + usb_make_path(hdw->usb_dev, hdw->bus_info, sizeof(hdw->bus_info)); ifnum = hdw->usb_intf->cur_altsetting->desc.bInterfaceNumber; usb_set_interface(hdw->usb_dev,ifnum,0); -- cgit v1.2.3 From d4db588ccc738528601947d57fd398bb3f55cd31 Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Wed, 10 Dec 2008 01:54:32 -0300 Subject: V4L/DVB (10304): buf-dma-contig: fix USERPTR free handling This patch fixes a free-without-alloc bug for V4L2_MEMORY_USERPTR video buffers. Signed-off-by: Magnus Damm Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/videobuf-dma-contig.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/videobuf-dma-contig.c b/drivers/media/video/videobuf-dma-contig.c index 31944b11e6ea..6109fb5f34e2 100644 --- a/drivers/media/video/videobuf-dma-contig.c +++ b/drivers/media/video/videobuf-dma-contig.c @@ -400,7 +400,7 @@ void videobuf_dma_contig_free(struct videobuf_queue *q, So, it should free memory only if the memory were allocated for read() operation. */ - if ((buf->memory != V4L2_MEMORY_USERPTR) || !buf->baddr) + if ((buf->memory != V4L2_MEMORY_USERPTR) || buf->baddr) return; if (!mem) -- cgit v1.2.3 From 5993a663a96df53f14d9e71abc27bcbd442317df Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 23 Jan 2009 21:35:12 -0300 Subject: V4L/DVB (10305): videobuf-vmalloc: Fix: videobuf memory were never freed videobuf_vmalloc_free() is never freeing the video buffer memory. Due to that, after multiple open/closes, user can suffer a panic: Kernel BUG at mm/slab.c:2650 invalid opcode: 0000 [1] SMP last sysfs file: /class/video4linux/video0/dev CPU 4 Modules linked in: vivi(U) videodev(U) v4l1_compat(U) v4l2_compat_ioctl32(U) videobuf_vmalloc(U) videobuf_core(U) ipv6 xfrm_nalgo autofs4 vmnet(U) vmblock(U) vmci(U) vmmon(U) ip_conntrack_netbios_ns ipt_REJECT xt_state ip_conntrack nfnetlink xt_tcpudp iptable_filter ip_tables x_tables cpufreq_ondemand dm_mirror dm_log dm_multipath scsi_dh dm_mod video backlight sbs i2c_ec button battery asus_acpi acpi_memhotplug ac lp testmgr_cipher testmgr aead crypto_blkcipher crypto_algapi crypto_api arc4 snd_hda_intel nvidia(PFU) snd_seq_dummy snd_seq_oss snd_seq_midi_event rt73usb crc_itu_t snd_seq snd_seq_device snd_pcm_oss snd_mixer_oss tg3 sr_mod snd_pcm snd_timer snd_page_alloc snd_hwdep pcspkr rt2500usb cdrom rt2x00usb rt2x00lib libphy snd parport_pc soundcore shpchp serio_raw i2c_i801 i5400_edac parport ata_piix sg mac80211 edac_mc i2c_core cfg80211 ahci libata sd_mod scsi_mod ext3 jbd uhci_hcd ohci_hcd ehci_hcd Pid: 6215, comm: v4l-stress-buff Tainted: PF 2.6.18-118.el5 #1 RIP: 0010:[] [] cache_grow+0x1e/0x395 RSP: 0018:ffff810128a35d28 EFLAGS: 00010006 RAX: 0000000000000000 RBX: 00000000000080d0 RCX: 00000000ffffffff RDX: 0000000000000000 RSI: 00000000000080d0 RDI: ffff8101042d8340 RBP: ffff8101042ce5e0 R08: ffff81012fc1e8c0 R09: ffff8101042eac00 R10: 0000000000000000 R11: ffffffff882a5139 R12: ffff8101042d8340 R13: ffff8101042ce5c0 R14: 0000000000000000 R15: ffff8101042d8340 FS: 0000000000000000(0000) GS:ffff81012fc24d40(0063) knlGS:00000000f7f706c0 CS: 0010 DS: 002b ES: 002b CR0: 000000008005003b CR2: 00000000f7f9a000 CR3: 0000000117ad0000 CR4: 00000000000006e0 Process v4l-stress-buff (pid: 6215, threadinfo ffff810128a34000, task ffff810128fcb820) Stack: ffffc20012a39000 0000004415173ff8 ffff810000011c10 000280d200000000 0000000000000002 00000000ffffffff ffff8101042ce5e0 ffff81012fc1e8c0 ffff8101042ce5c0 000000000000000c ffff8101042d8340 ffffffff8005bdde Call Trace: [] cache_alloc_refill+0x136/0x186 [] kmem_cache_alloc_node+0x98/0xb2 [] __vmalloc_area_node+0x62/0x153 [] vmalloc_user+0x15/0x50 [] :videobuf_vmalloc:__videobuf_iolock+0xe6/0x155 [] :vivi:buffer_prepare+0xb9/0xe6 [] :videobuf_core:__videobuf_read_start+0xa2/0x10f [] :videobuf_core:videobuf_read_stream+0x9c/0x1f3 [] vfs_read+0xcb/0x171 [] sys_read+0x45/0x6e [] sysenter_do_call+0x1b/0x67 Code: 0f 0b 68 af 1e 2a 80 c2 5a 0a f6 c7 20 0f 85 53 03 00 00 89 RIP [] cache_grow+0x1e/0x395 RSP <0>Kernel panic - not syncing: Fatal exception Thanks to Douglas Schilling Landgraf for writing a stress tool for testing and to Robert Krakora to trace the code and discover the point where the bug were happening. Thanks also to Magnus Damm that provided us a fix for a similar bug on videobuf-dma-contig. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/videobuf-vmalloc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/videobuf-vmalloc.c b/drivers/media/video/videobuf-vmalloc.c index be65a2fb3976..30ae30f99ccc 100644 --- a/drivers/media/video/videobuf-vmalloc.c +++ b/drivers/media/video/videobuf-vmalloc.c @@ -425,7 +425,7 @@ void videobuf_vmalloc_free (struct videobuf_buffer *buf) So, it should free memory only if the memory were allocated for read() operation. */ - if ((buf->memory != V4L2_MEMORY_USERPTR) || (buf->baddr == 0)) + if ((buf->memory != V4L2_MEMORY_USERPTR) || buf->baddr) return; if (!mem) -- cgit v1.2.3 From 6f2a278171bf7fc8153a42baa26b51d1ecb4c83f Mon Sep 17 00:00:00 2001 From: Thierry MERLE Date: Tue, 20 Jan 2009 17:40:44 -0300 Subject: V4L/DVB (10306): usbvision: use usb_make_path to report bus info usb_make_path reports canonical bus info. Use it when reporting bus info in VIDIOC_QUERYCAP. Signed-off-by: Thierry MERLE Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/usbvision/usbvision-video.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/usbvision/usbvision-video.c b/drivers/media/video/usbvision/usbvision-video.c index 47d672da5415..334c77d9116f 100644 --- a/drivers/media/video/usbvision/usbvision-video.c +++ b/drivers/media/video/usbvision/usbvision-video.c @@ -526,8 +526,7 @@ static int vidioc_querycap (struct file *file, void *priv, strlcpy(vc->card, usbvision_device_data[usbvision->DevModel].ModelString, sizeof(vc->card)); - strlcpy(vc->bus_info, dev_name(&usbvision->dev->dev), - sizeof(vc->bus_info)); + usb_make_path(usbvision->dev, vc->bus_info, sizeof(vc->bus_info)); vc->version = USBVISION_DRIVER_VERSION; vc->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_AUDIO | -- cgit v1.2.3 From cb97716f3bcc3710b5dc44c01fd7450d032c74e0 Mon Sep 17 00:00:00 2001 From: Thierry MERLE Date: Tue, 20 Jan 2009 18:01:33 -0300 Subject: V4L/DVB (10307): em28xx: use usb_make_path to report bus info usb_make_path reports canonical bus info. Use it when reporting bus info in VIDIOC_QUERYCAP. Signed-off-by: Thierry MERLE Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/em28xx/em28xx-video.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/em28xx/em28xx-video.c b/drivers/media/video/em28xx/em28xx-video.c index d8b45b5ee041..5b2a19b0cca6 100644 --- a/drivers/media/video/em28xx/em28xx-video.c +++ b/drivers/media/video/em28xx/em28xx-video.c @@ -1350,7 +1350,7 @@ static int vidioc_querycap(struct file *file, void *priv, strlcpy(cap->driver, "em28xx", sizeof(cap->driver)); strlcpy(cap->card, em28xx_boards[dev->model].name, sizeof(cap->card)); - strlcpy(cap->bus_info, dev_name(&dev->udev->dev), sizeof(cap->bus_info)); + usb_make_path(dev->udev, cap->bus_info, sizeof(cap->bus_info)); cap->version = EM28XX_VERSION_CODE; @@ -1501,7 +1501,7 @@ static int radio_querycap(struct file *file, void *priv, strlcpy(cap->driver, "em28xx", sizeof(cap->driver)); strlcpy(cap->card, em28xx_boards[dev->model].name, sizeof(cap->card)); - strlcpy(cap->bus_info, dev_name(&dev->udev->dev), sizeof(cap->bus_info)); + usb_make_path(dev->udev, cap->bus_info, sizeof(cap->bus_info)); cap->version = EM28XX_VERSION_CODE; cap->capabilities = V4L2_CAP_TUNER; -- cgit v1.2.3 From b12049a2c3d31e5a167a50ea842b0e7ed3024b80 Mon Sep 17 00:00:00 2001 From: Thierry MERLE Date: Tue, 27 Jan 2009 16:53:23 -0300 Subject: V4L/DVB (10308): uvcvideo: use usb_make_path to report bus info usb_make_path reports canonical bus info. Use it when reporting bus info in VIDIOC_QUERYCAP. Signed-off-by: Thierry MERLE Acked-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/uvc/uvc_v4l2.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/uvc/uvc_v4l2.c b/drivers/media/video/uvc/uvc_v4l2.c index 011ebd4da44a..30781b82b6b5 100644 --- a/drivers/media/video/uvc/uvc_v4l2.c +++ b/drivers/media/video/uvc/uvc_v4l2.c @@ -488,8 +488,8 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg) memset(cap, 0, sizeof *cap); strlcpy(cap->driver, "uvcvideo", sizeof cap->driver); strlcpy(cap->card, vdev->name, sizeof cap->card); - strlcpy(cap->bus_info, video->dev->udev->bus->bus_name, - sizeof cap->bus_info); + usb_make_path(video->dev->udev, + cap->bus_info, sizeof(cap->bus_info)); cap->version = DRIVER_VERSION_NUMBER; if (video->streaming->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) cap->capabilities = V4L2_CAP_VIDEO_CAPTURE -- cgit v1.2.3 From e22ed887ee18fde79c013825017521ec64eb8ed5 Mon Sep 17 00:00:00 2001 From: Thierry MERLE Date: Tue, 20 Jan 2009 18:19:25 -0300 Subject: V4L/DVB (10309): s2255drv: use usb_make_path to report bus info usb_make_path reports canonical bus info. Use it when reporting bus info in VIDIOC_QUERYCAP. Signed-off-by: Thierry MERLE Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/s2255drv.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/s2255drv.c b/drivers/media/video/s2255drv.c index 31bc94075268..b5be633e3bb0 100644 --- a/drivers/media/video/s2255drv.c +++ b/drivers/media/video/s2255drv.c @@ -846,8 +846,7 @@ static int vidioc_querycap(struct file *file, void *priv, struct s2255_dev *dev = fh->dev; strlcpy(cap->driver, "s2255", sizeof(cap->driver)); strlcpy(cap->card, "s2255", sizeof(cap->card)); - strlcpy(cap->bus_info, dev_name(&dev->udev->dev), - sizeof(cap->bus_info)); + usb_make_path(dev->udev, cap->bus_info, sizeof(cap->bus_info)); cap->version = S2255_VERSION; cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING; return 0; -- cgit v1.2.3 From f7fe3e6f3c3e9ef6ba5ca187b514d225296d18dd Mon Sep 17 00:00:00 2001 From: Douglas Schilling Landgraf Date: Mon, 19 Jan 2009 09:31:55 -0300 Subject: V4L/DVB (10323): em28xx: Add entry for GADMEI TVR200 Added entry for GADMEI TVR200. Thanks to Yohanes Nugroho for testing and data collection. Signed-off-by: Douglas Schilling Landgraf Signed-off-by: Mauro Carvalho Chehab --- Documentation/video4linux/CARDLIST.em28xx | 1 + drivers/media/video/em28xx/em28xx-cards.c | 20 ++++++++++++++++++++ drivers/media/video/em28xx/em28xx.h | 1 + 3 files changed, 22 insertions(+) (limited to 'drivers/media/video') diff --git a/Documentation/video4linux/CARDLIST.em28xx b/Documentation/video4linux/CARDLIST.em28xx index 75bded8a4aa2..f7a7f48f4d74 100644 --- a/Documentation/video4linux/CARDLIST.em28xx +++ b/Documentation/video4linux/CARDLIST.em28xx @@ -58,3 +58,4 @@ 58 -> Compro VideoMate ForYou/Stereo (em2820/em2840) [185b:2041] 60 -> Hauppauge WinTV HVR 850 (em2883) [2040:651f] 61 -> Pixelview PlayTV Box 4 USB 2.0 (em2820/em2840) + 62 -> Gadmei TVR200 (em2820/em2840) diff --git a/drivers/media/video/em28xx/em28xx-cards.c b/drivers/media/video/em28xx/em28xx-cards.c index 3b3ca3f46d52..3beaeeda2eee 100644 --- a/drivers/media/video/em28xx/em28xx-cards.c +++ b/drivers/media/video/em28xx/em28xx-cards.c @@ -183,6 +183,25 @@ struct em28xx_board em28xx_boards[] = { .amux = EM28XX_AMUX_LINE_IN, } }, }, + [EM2820_BOARD_GADMEI_TVR200] = { + .name = "Gadmei TVR200", + .tuner_type = TUNER_LG_PAL_NEW_TAPC, + .tda9887_conf = TDA9887_PRESENT, + .decoder = EM28XX_SAA711X, + .input = { { + .type = EM28XX_VMUX_TELEVISION, + .vmux = SAA7115_COMPOSITE2, + .amux = EM28XX_AMUX_LINE_IN, + }, { + .type = EM28XX_VMUX_COMPOSITE1, + .vmux = SAA7115_COMPOSITE0, + .amux = EM28XX_AMUX_LINE_IN, + }, { + .type = EM28XX_VMUX_SVIDEO, + .vmux = SAA7115_SVIDEO3, + .amux = EM28XX_AMUX_LINE_IN, + } }, + }, [EM2820_BOARD_TERRATEC_CINERGY_250] = { .name = "Terratec Cinergy 250 USB", .tuner_type = TUNER_LG_PAL_NEW_TAPC, @@ -1349,6 +1368,7 @@ static struct em28xx_hash_table em28xx_i2c_hash[] = { {0xb06a32c3, EM2800_BOARD_TERRATEC_CINERGY_200, TUNER_LG_PAL_NEW_TAPC}, {0xf51200e3, EM2800_BOARD_VGEAR_POCKETTV, TUNER_LG_PAL_NEW_TAPC}, {0x1ba50080, EM2860_BOARD_POINTNIX_INTRAORAL_CAMERA, TUNER_ABSENT}, + {0xc51200e3, EM2820_BOARD_GADMEI_TVR200, TUNER_LG_PAL_NEW_TAPC}, }; int em28xx_tuner_callback(void *ptr, int component, int command, int arg) diff --git a/drivers/media/video/em28xx/em28xx.h b/drivers/media/video/em28xx/em28xx.h index dd2cd36fb1bb..989e67fdff3e 100644 --- a/drivers/media/video/em28xx/em28xx.h +++ b/drivers/media/video/em28xx/em28xx.h @@ -98,6 +98,7 @@ #define EM2820_BOARD_COMPRO_VIDEOMATE_FORYOU 58 #define EM2883_BOARD_HAUPPAUGE_WINTV_HVR_850 60 #define EM2820_BOARD_PROLINK_PLAYTV_BOX4_USB2 61 +#define EM2820_BOARD_GADMEI_TVR200 62 /* Limits minimum and default number of buffers */ #define EM28XX_MIN_BUF 4 -- cgit v1.2.3 From 51caf91f5ba4f6c02ba2bd53c3f113b9da544ebb Mon Sep 17 00:00:00 2001 From: Alexey Klimov Date: Sun, 25 Jan 2009 12:53:09 -0300 Subject: V4L/DVB (10324): em28xx: Correct mailing list Move development mail-list to linux-media on vger.kernel.org. Signed-off-by: Alexey Klimov Signed-off-by: Douglas Schilling Landgraf Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/em28xx/em28xx-cards.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/em28xx/em28xx-cards.c b/drivers/media/video/em28xx/em28xx-cards.c index 3beaeeda2eee..369db26cd721 100644 --- a/drivers/media/video/em28xx/em28xx-cards.c +++ b/drivers/media/video/em28xx/em28xx-cards.c @@ -1630,7 +1630,7 @@ static int em28xx_hint_board(struct em28xx *dev) em28xx_errdev("If the board were missdetected, " "please email this log to:\n"); em28xx_errdev("\tV4L Mailing List " - " \n"); + " \n"); em28xx_errdev("Board detected as %s\n", em28xx_boards[dev->model].name); @@ -1662,7 +1662,7 @@ static int em28xx_hint_board(struct em28xx *dev) em28xx_errdev("If the board were missdetected, " "please email this log to:\n"); em28xx_errdev("\tV4L Mailing List " - " \n"); + " \n"); em28xx_errdev("Board detected as %s\n", em28xx_boards[dev->model].name); @@ -1675,7 +1675,7 @@ static int em28xx_hint_board(struct em28xx *dev) em28xx_errdev("You may try to use card= insmod option to " "workaround that.\n"); em28xx_errdev("Please send an email with this log to:\n"); - em28xx_errdev("\tV4L Mailing List \n"); + em28xx_errdev("\tV4L Mailing List \n"); em28xx_errdev("Board eeprom hash is 0x%08lx\n", dev->hash); em28xx_errdev("Board i2c devicelist hash is 0x%08lx\n", dev->i2c_hash); -- cgit v1.2.3 From 00bc0645f02ec0c3486a9f6af9b6167ce5eda62c Mon Sep 17 00:00:00 2001 From: Douglas Schilling Landgraf Date: Sun, 25 Jan 2009 15:12:29 -0300 Subject: V4L/DVB (10326): em28xx: Cleanup: fix bad whitespacing Signed-off-by: Douglas Schilling Landgraf Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/em28xx/em28xx-audio.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/em28xx/em28xx-audio.c b/drivers/media/video/em28xx/em28xx-audio.c index f132e31f6edd..7a62c77b8485 100644 --- a/drivers/media/video/em28xx/em28xx-audio.c +++ b/drivers/media/video/em28xx/em28xx-audio.c @@ -401,9 +401,9 @@ static snd_pcm_uframes_t snd_em28xx_capture_pointer(struct snd_pcm_substream snd_pcm_uframes_t hwptr_done; dev = snd_pcm_substream_chip(substream); - spin_lock_irqsave(&dev->adev.slock, flags); + spin_lock_irqsave(&dev->adev.slock, flags); hwptr_done = dev->adev.hwptr_done_capture; - spin_unlock_irqrestore(&dev->adev.slock, flags); + spin_unlock_irqrestore(&dev->adev.slock, flags); return hwptr_done; } -- cgit v1.2.3 From b124d597496fad3ba1ead7ed3b6c197c5b0a2ee7 Mon Sep 17 00:00:00 2001 From: Douglas Schilling Landgraf Date: Sun, 25 Jan 2009 19:19:23 -0300 Subject: V4L/DVB (10327): em28xx: Add check before call em28xx_isoc_audio_deinit() Just call em28xx_isoc_audio_deinit() if em28xx sent a usb_submit(). Signed-off-by: Douglas Schilling Landgraf Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/em28xx/em28xx-audio.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/em28xx/em28xx-audio.c b/drivers/media/video/em28xx/em28xx-audio.c index 7a62c77b8485..43e8d7d91a96 100644 --- a/drivers/media/video/em28xx/em28xx-audio.c +++ b/drivers/media/video/em28xx/em28xx-audio.c @@ -61,7 +61,7 @@ static int em28xx_isoc_audio_deinit(struct em28xx *dev) int i; dprintk("Stopping isoc\n"); - for (i = 0; i < EM28XX_AUDIO_BUFS; i++) { + for (i = 0; i < dev->isoc_ctl.num_bufs; i++) { if (!irqs_disabled()) usb_kill_urb(dev->adev.urb[i]); else @@ -73,6 +73,7 @@ static int em28xx_isoc_audio_deinit(struct em28xx *dev) dev->adev.transfer_buffer[i] = NULL; } + dev->isoc_ctl.num_bufs = 0; return 0; } @@ -156,6 +157,8 @@ static int em28xx_init_audio_isoc(struct em28xx *dev) dprintk("Starting isoc transfers\n"); + dev->isoc_ctl.num_bufs = 0; + for (i = 0; i < EM28XX_AUDIO_BUFS; i++) { struct urb *urb; int j, k; @@ -197,10 +200,19 @@ static int em28xx_init_audio_isoc(struct em28xx *dev) for (i = 0; i < EM28XX_AUDIO_BUFS; i++) { errCode = usb_submit_urb(dev->adev.urb[i], GFP_ATOMIC); if (errCode) { - em28xx_isoc_audio_deinit(dev); + if (dev->isoc_ctl.num_bufs == 0) { + usb_free_urb(dev->adev.urb[i]); + dev->adev.urb[i] = NULL; + kfree(dev->adev.transfer_buffer[i]); + dev->adev.transfer_buffer[i] = NULL; + } else + em28xx_isoc_audio_deinit(dev); return errCode; } + mutex_lock(&dev->lock); + dev->isoc_ctl.num_bufs++; + mutex_unlock(&dev->lock); } return 0; -- cgit v1.2.3 From afd46291393e20736368e275a6f5f7c44dfe9540 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Wed, 31 Dec 2008 07:27:42 -0300 Subject: V4L/DVB (10332): gspca - main: Version change. Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/gspca.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/gspca/gspca.c b/drivers/media/video/gspca/gspca.c index 65e4901f4db7..9b77ebbd875d 100644 --- a/drivers/media/video/gspca/gspca.c +++ b/drivers/media/video/gspca/gspca.c @@ -44,7 +44,7 @@ MODULE_AUTHOR("Jean-Francois Moine "); MODULE_DESCRIPTION("GSPCA USB Camera Driver"); MODULE_LICENSE("GPL"); -#define DRIVER_VERSION_NUMBER KERNEL_VERSION(2, 4, 0) +#define DRIVER_VERSION_NUMBER KERNEL_VERSION(2, 5, 0) static int video_nr = -1; -- cgit v1.2.3 From 50e06dee958bdb81229cb42486f7fdc4917fa4da Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Wed, 31 Dec 2008 08:13:46 -0300 Subject: V4L/DVB (10333): gspca - main and many subdrivers: Remove the epaddr variable. The transfer endpoint address is now automatically chosen. Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/conex.c | 1 - drivers/media/video/gspca/etoms.c | 1 - drivers/media/video/gspca/finepix.c | 6 ++---- drivers/media/video/gspca/gspca.c | 17 ++++------------- drivers/media/video/gspca/gspca.h | 1 - drivers/media/video/gspca/m5602/m5602_core.c | 1 - drivers/media/video/gspca/mars.c | 1 - drivers/media/video/gspca/ov519.c | 1 - drivers/media/video/gspca/ov534.c | 1 - drivers/media/video/gspca/pac207.c | 1 - drivers/media/video/gspca/pac7311.c | 1 - drivers/media/video/gspca/sonixb.c | 1 - drivers/media/video/gspca/sonixj.c | 1 - drivers/media/video/gspca/spca500.c | 1 - drivers/media/video/gspca/spca501.c | 1 - drivers/media/video/gspca/spca505.c | 1 - drivers/media/video/gspca/spca506.c | 1 - drivers/media/video/gspca/spca508.c | 1 - drivers/media/video/gspca/spca561.c | 1 - drivers/media/video/gspca/stk014.c | 4 +--- drivers/media/video/gspca/stv06xx/stv06xx.c | 1 - drivers/media/video/gspca/sunplus.c | 1 - drivers/media/video/gspca/t613.c | 1 - drivers/media/video/gspca/tv8532.c | 1 - drivers/media/video/gspca/vc032x.c | 1 - drivers/media/video/gspca/zc3xx.c | 1 - 26 files changed, 7 insertions(+), 43 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/gspca/conex.c b/drivers/media/video/gspca/conex.c index 1753f5bb3544..a7088f60bcd0 100644 --- a/drivers/media/video/gspca/conex.c +++ b/drivers/media/video/gspca/conex.c @@ -815,7 +815,6 @@ static int sd_config(struct gspca_dev *gspca_dev, struct cam *cam; cam = &gspca_dev->cam; - cam->epaddr = 0x01; cam->cam_mode = vga_mode; cam->nmodes = sizeof vga_mode / sizeof vga_mode[0]; diff --git a/drivers/media/video/gspca/etoms.c b/drivers/media/video/gspca/etoms.c index f3cd8ff5cc92..ca888ac969d0 100644 --- a/drivers/media/video/gspca/etoms.c +++ b/drivers/media/video/gspca/etoms.c @@ -658,7 +658,6 @@ static int sd_config(struct gspca_dev *gspca_dev, struct cam *cam; cam = &gspca_dev->cam; - cam->epaddr = 1; sd->sensor = id->driver_info; if (sd->sensor == SENSOR_PAS106) { cam->cam_mode = sif_mode; diff --git a/drivers/media/video/gspca/finepix.c b/drivers/media/video/gspca/finepix.c index afc8b2dd307b..76c6e03cb6c9 100644 --- a/drivers/media/video/gspca/finepix.c +++ b/drivers/media/video/gspca/finepix.c @@ -259,7 +259,6 @@ static int sd_config(struct gspca_dev *gspca_dev, cam->cam_mode = fpix_mode; cam->nmodes = 1; - cam->epaddr = 0x01; /* todo: correct for all cams? */ cam->bulk_size = FPIX_MAX_TRANSFER; /* gspca_dev->nbalt = 1; * use bulk transfer */ @@ -335,8 +334,7 @@ static int sd_start(struct gspca_dev *gspca_dev) /* Read the result of the command. Ignore the result, for it * varies with the device. */ ret = usb_bulk_msg(gspca_dev->dev, - usb_rcvbulkpipe(gspca_dev->dev, - gspca_dev->cam.epaddr), + gspca_dev->urb[0]->pipe, gspca_dev->usb_buf, FPIX_MAX_TRANSFER, &size_ret, FPIX_TIMEOUT); if (ret != 0) { @@ -363,7 +361,7 @@ static int sd_start(struct gspca_dev *gspca_dev) } /* Again, reset bulk in endpoint */ - usb_clear_halt(gspca_dev->dev, gspca_dev->cam.epaddr); + usb_clear_halt(gspca_dev->dev, gspca_dev->urb[0]->pipe); /* Allocate a control URB */ dev->control_urb = usb_alloc_urb(0, GFP_KERNEL); diff --git a/drivers/media/video/gspca/gspca.c b/drivers/media/video/gspca/gspca.c index 9b77ebbd875d..e13833b8ed67 100644 --- a/drivers/media/video/gspca/gspca.c +++ b/drivers/media/video/gspca/gspca.c @@ -439,22 +439,16 @@ static void destroy_urbs(struct gspca_dev *gspca_dev) * look for an input transfer endpoint in an alternate setting */ static struct usb_host_endpoint *alt_xfer(struct usb_host_interface *alt, - __u8 epaddr, __u8 xfer) { struct usb_host_endpoint *ep; int i, attr; - epaddr |= USB_DIR_IN; for (i = 0; i < alt->desc.bNumEndpoints; i++) { ep = &alt->endpoint[i]; - if (ep->desc.bEndpointAddress == epaddr) { - attr = ep->desc.bmAttributes - & USB_ENDPOINT_XFERTYPE_MASK; - if (attr == xfer) - return ep; - break; - } + attr = ep->desc.bmAttributes & USB_ENDPOINT_XFERTYPE_MASK; + if (attr == xfer) + return ep; } return NULL; } @@ -480,7 +474,6 @@ static struct usb_host_endpoint *get_ep(struct gspca_dev *gspca_dev) /* try isoc */ while (--i > 0) { /* alt 0 is unusable */ ep = alt_xfer(&intf->altsetting[i], - gspca_dev->cam.epaddr, USB_ENDPOINT_XFER_ISOC); if (ep) break; @@ -489,7 +482,6 @@ static struct usb_host_endpoint *get_ep(struct gspca_dev *gspca_dev) /* if no isoc, try bulk */ if (ep == NULL) { ep = alt_xfer(&intf->altsetting[0], - gspca_dev->cam.epaddr, USB_ENDPOINT_XFER_BULK); if (ep == NULL) { err("no transfer endpoint found"); @@ -618,8 +610,7 @@ static int gspca_init_transfer(struct gspca_dev *gspca_dev) /* clear the bulk endpoint */ if (gspca_dev->alt == 0) /* if bulk transfer */ usb_clear_halt(gspca_dev->dev, - usb_rcvintpipe(gspca_dev->dev, - gspca_dev->cam.epaddr)); + gspca_dev->urb[0]->pipe); /* start the cam */ ret = gspca_dev->sd_desc->start(gspca_dev); diff --git a/drivers/media/video/gspca/gspca.h b/drivers/media/video/gspca/gspca.h index c90af9cb1e07..e5c8eb709036 100644 --- a/drivers/media/video/gspca/gspca.h +++ b/drivers/media/video/gspca/gspca.h @@ -62,7 +62,6 @@ struct cam { * - cannot be > MAX_NURBS * - when 0 and bulk_size != 0 means * 1 URB and submit done by subdriver */ - __u8 epaddr; }; struct gspca_dev; diff --git a/drivers/media/video/gspca/m5602/m5602_core.c b/drivers/media/video/gspca/m5602/m5602_core.c index ed906fe31287..37a47db2903d 100644 --- a/drivers/media/video/gspca/m5602/m5602_core.c +++ b/drivers/media/video/gspca/m5602/m5602_core.c @@ -332,7 +332,6 @@ static int m5602_configure(struct gspca_dev *gspca_dev, int err; cam = &gspca_dev->cam; - cam->epaddr = M5602_ISOC_ENDPOINT_ADDR; sd->desc = &sd_desc; if (dump_bridge) diff --git a/drivers/media/video/gspca/mars.c b/drivers/media/video/gspca/mars.c index 3d2090e67a63..ba79afbf8b39 100644 --- a/drivers/media/video/gspca/mars.c +++ b/drivers/media/video/gspca/mars.c @@ -121,7 +121,6 @@ static int sd_config(struct gspca_dev *gspca_dev, struct cam *cam; cam = &gspca_dev->cam; - cam->epaddr = 0x01; cam->cam_mode = vga_mode; cam->nmodes = ARRAY_SIZE(vga_mode); sd->qindex = 1; /* set the quantization table */ diff --git a/drivers/media/video/gspca/ov519.c b/drivers/media/video/gspca/ov519.c index ee232956c812..ac9b4dc064d6 100644 --- a/drivers/media/video/gspca/ov519.c +++ b/drivers/media/video/gspca/ov519.c @@ -1360,7 +1360,6 @@ static int sd_config(struct gspca_dev *gspca_dev, } cam = &gspca_dev->cam; - cam->epaddr = OV511_ENDPOINT_ADDRESS; if (!sd->sif) { cam->cam_mode = vga_mode; cam->nmodes = ARRAY_SIZE(vga_mode); diff --git a/drivers/media/video/gspca/ov534.c b/drivers/media/video/gspca/ov534.c index 3bf15e401693..01314e9995f0 100644 --- a/drivers/media/video/gspca/ov534.c +++ b/drivers/media/video/gspca/ov534.c @@ -379,7 +379,6 @@ static int sd_config(struct gspca_dev *gspca_dev, cam = &gspca_dev->cam; - cam->epaddr = 0x01; cam->cam_mode = vga_mode; cam->nmodes = ARRAY_SIZE(vga_mode); diff --git a/drivers/media/video/gspca/pac207.c b/drivers/media/video/gspca/pac207.c index c90ac852bac0..546820f52c02 100644 --- a/drivers/media/video/gspca/pac207.c +++ b/drivers/media/video/gspca/pac207.c @@ -256,7 +256,6 @@ static int sd_config(struct gspca_dev *gspca_dev, " (vid/pid 0x%04X:0x%04X)", id->idVendor, id->idProduct); cam = &gspca_dev->cam; - cam->epaddr = 0x05; cam->cam_mode = sif_mode; cam->nmodes = ARRAY_SIZE(sif_mode); sd->brightness = PAC207_BRIGHTNESS_DEFAULT; diff --git a/drivers/media/video/gspca/pac7311.c b/drivers/media/video/gspca/pac7311.c index a9c95cba710e..f34bbc5db501 100644 --- a/drivers/media/video/gspca/pac7311.c +++ b/drivers/media/video/gspca/pac7311.c @@ -498,7 +498,6 @@ static int sd_config(struct gspca_dev *gspca_dev, struct cam *cam; cam = &gspca_dev->cam; - cam->epaddr = 0x05; sd->sensor = id->driver_info; if (sd->sensor == SENSOR_PAC7302) { diff --git a/drivers/media/video/gspca/sonixb.c b/drivers/media/video/gspca/sonixb.c index b3e4e0677b68..5ec361c779be 100644 --- a/drivers/media/video/gspca/sonixb.c +++ b/drivers/media/video/gspca/sonixb.c @@ -870,7 +870,6 @@ static int sd_config(struct gspca_dev *gspca_dev, gspca_dev->ctrl_dis = sensor_data[sd->sensor].ctrl_dis; cam = &gspca_dev->cam; - cam->epaddr = 0x01; if (!(sensor_data[sd->sensor].flags & F_SIF)) { cam->cam_mode = vga_mode; cam->nmodes = ARRAY_SIZE(vga_mode); diff --git a/drivers/media/video/gspca/sonixj.c b/drivers/media/video/gspca/sonixj.c index 3373b8d9d2a8..5c159d89bd82 100644 --- a/drivers/media/video/gspca/sonixj.c +++ b/drivers/media/video/gspca/sonixj.c @@ -1018,7 +1018,6 @@ static int sd_config(struct gspca_dev *gspca_dev, struct cam *cam; cam = &gspca_dev->cam; - cam->epaddr = 0x01; cam->cam_mode = vga_mode; cam->nmodes = ARRAY_SIZE(vga_mode); diff --git a/drivers/media/video/gspca/spca500.c b/drivers/media/video/gspca/spca500.c index 942f04cd44dd..94ed469a3ada 100644 --- a/drivers/media/video/gspca/spca500.c +++ b/drivers/media/video/gspca/spca500.c @@ -629,7 +629,6 @@ static int sd_config(struct gspca_dev *gspca_dev, struct cam *cam; cam = &gspca_dev->cam; - cam->epaddr = 0x01; sd->subtype = id->driver_info; if (sd->subtype != LogitechClickSmart310) { cam->cam_mode = vga_mode; diff --git a/drivers/media/video/gspca/spca501.c b/drivers/media/video/gspca/spca501.c index 82e3e3e2ada1..766da90e6eb7 100644 --- a/drivers/media/video/gspca/spca501.c +++ b/drivers/media/video/gspca/spca501.c @@ -1934,7 +1934,6 @@ static int sd_config(struct gspca_dev *gspca_dev, struct cam *cam; cam = &gspca_dev->cam; - cam->epaddr = 0x01; cam->cam_mode = vga_mode; cam->nmodes = sizeof vga_mode / sizeof vga_mode[0]; sd->subtype = id->driver_info; diff --git a/drivers/media/video/gspca/spca505.c b/drivers/media/video/gspca/spca505.c index 2a33a29010ee..90d555361ae7 100644 --- a/drivers/media/video/gspca/spca505.c +++ b/drivers/media/video/gspca/spca505.c @@ -636,7 +636,6 @@ static int sd_config(struct gspca_dev *gspca_dev, struct cam *cam; cam = &gspca_dev->cam; - cam->epaddr = 0x01; cam->cam_mode = vga_mode; sd->subtype = id->driver_info; if (sd->subtype != IntelPCCameraPro) diff --git a/drivers/media/video/gspca/spca506.c b/drivers/media/video/gspca/spca506.c index 96e2512e0621..99fa3fc1cb62 100644 --- a/drivers/media/video/gspca/spca506.c +++ b/drivers/media/video/gspca/spca506.c @@ -303,7 +303,6 @@ static int sd_config(struct gspca_dev *gspca_dev, struct cam *cam; cam = &gspca_dev->cam; - cam->epaddr = 0x01; cam->cam_mode = vga_mode; cam->nmodes = sizeof vga_mode / sizeof vga_mode[0]; sd->brightness = sd_ctrls[SD_BRIGHTNESS].qctrl.default_value; diff --git a/drivers/media/video/gspca/spca508.c b/drivers/media/video/gspca/spca508.c index be5d740a315d..f5c045967379 100644 --- a/drivers/media/video/gspca/spca508.c +++ b/drivers/media/video/gspca/spca508.c @@ -1487,7 +1487,6 @@ static int sd_config(struct gspca_dev *gspca_dev, PDEBUG(D_PROBE, "Window 1 average luminance: %d", data1); cam = &gspca_dev->cam; - cam->epaddr = 0x01; cam->cam_mode = sif_mode; cam->nmodes = ARRAY_SIZE(sif_mode); diff --git a/drivers/media/video/gspca/spca561.c b/drivers/media/video/gspca/spca561.c index 3c9288019e96..d64e7d64d053 100644 --- a/drivers/media/video/gspca/spca561.c +++ b/drivers/media/video/gspca/spca561.c @@ -541,7 +541,6 @@ static int sd_config(struct gspca_dev *gspca_dev, } cam = &gspca_dev->cam; - cam->epaddr = 0x01; gspca_dev->nbalt = 7 + 1; /* choose alternate 7 first */ sd->chip_revision = id->driver_info; diff --git a/drivers/media/video/gspca/stk014.c b/drivers/media/video/gspca/stk014.c index 60de9af87fbb..cd1fbff0c94c 100644 --- a/drivers/media/video/gspca/stk014.c +++ b/drivers/media/video/gspca/stk014.c @@ -180,7 +180,7 @@ static int rcv_val(struct gspca_dev *gspca_dev, reg_w(gspca_dev, 0x63b, 0); reg_w(gspca_dev, 0x630, 5); ret = usb_bulk_msg(dev, - usb_rcvbulkpipe(dev, 5), + usb_rcvbulkpipe(dev, 0x05), gspca_dev->usb_buf, 4, /* length */ &alen, @@ -294,9 +294,7 @@ static int sd_config(struct gspca_dev *gspca_dev, const struct usb_device_id *id) { struct sd *sd = (struct sd *) gspca_dev; - struct cam *cam = &gspca_dev->cam; - cam->epaddr = 0x02; gspca_dev->cam.cam_mode = vga_mode; gspca_dev->cam.nmodes = ARRAY_SIZE(vga_mode); sd->brightness = BRIGHTNESS_DEF; diff --git a/drivers/media/video/gspca/stv06xx/stv06xx.c b/drivers/media/video/gspca/stv06xx/stv06xx.c index 13a021e3cbb7..c60b163335c5 100644 --- a/drivers/media/video/gspca/stv06xx/stv06xx.c +++ b/drivers/media/video/gspca/stv06xx/stv06xx.c @@ -429,7 +429,6 @@ static int stv06xx_config(struct gspca_dev *gspca_dev, PDEBUG(D_PROBE, "Configuring camera"); cam = &gspca_dev->cam; - cam->epaddr = STV_ISOC_ENDPOINT_ADDR; sd->desc = sd_desc; gspca_dev->sd_desc = &sd->desc; diff --git a/drivers/media/video/gspca/sunplus.c b/drivers/media/video/gspca/sunplus.c index 6d904d5e4c74..1f07476a9905 100644 --- a/drivers/media/video/gspca/sunplus.c +++ b/drivers/media/video/gspca/sunplus.c @@ -812,7 +812,6 @@ static int sd_config(struct gspca_dev *gspca_dev, struct cam *cam; cam = &gspca_dev->cam; - cam->epaddr = 0x01; sd->bridge = id->driver_info >> 8; sd->subtype = id->driver_info; diff --git a/drivers/media/video/gspca/t613.c b/drivers/media/video/gspca/t613.c index 6ee111a3cbd1..74ca17845223 100644 --- a/drivers/media/video/gspca/t613.c +++ b/drivers/media/video/gspca/t613.c @@ -538,7 +538,6 @@ static int sd_config(struct gspca_dev *gspca_dev, struct cam *cam; cam = &gspca_dev->cam; - cam->epaddr = 0x01; cam->cam_mode = vga_mode_t16; cam->nmodes = ARRAY_SIZE(vga_mode_t16); diff --git a/drivers/media/video/gspca/tv8532.c b/drivers/media/video/gspca/tv8532.c index 94163cceb28a..1da292ea1c77 100644 --- a/drivers/media/video/gspca/tv8532.c +++ b/drivers/media/video/gspca/tv8532.c @@ -241,7 +241,6 @@ static int sd_config(struct gspca_dev *gspca_dev, tv_8532WriteEEprom(gspca_dev); cam = &gspca_dev->cam; - cam->epaddr = 1; cam->cam_mode = sif_mode; cam->nmodes = sizeof sif_mode / sizeof sif_mode[0]; diff --git a/drivers/media/video/gspca/vc032x.c b/drivers/media/video/gspca/vc032x.c index 0525ea51a6de..ab5a25cfc69e 100644 --- a/drivers/media/video/gspca/vc032x.c +++ b/drivers/media/video/gspca/vc032x.c @@ -1979,7 +1979,6 @@ static int sd_config(struct gspca_dev *gspca_dev, int sensor; cam = &gspca_dev->cam; - cam->epaddr = 0x02; sd->bridge = id->driver_info; vc0321_reset(gspca_dev); diff --git a/drivers/media/video/gspca/zc3xx.c b/drivers/media/video/gspca/zc3xx.c index ec2a53d53fe2..c32477db3bab 100644 --- a/drivers/media/video/gspca/zc3xx.c +++ b/drivers/media/video/gspca/zc3xx.c @@ -7147,7 +7147,6 @@ static int sd_config(struct gspca_dev *gspca_dev, } cam = &gspca_dev->cam; - cam->epaddr = 0x01; /*fixme:test*/ gspca_dev->nbalt--; if (vga) { -- cgit v1.2.3 From 766231ab859546edd459242c2dbd805bc7fd446e Mon Sep 17 00:00:00 2001 From: Erik Andren Date: Wed, 31 Dec 2008 14:33:53 -0300 Subject: V4L/DVB (10334): gspca - stv06xx: Rework control description. Signed-off-by: Erik Andren Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/stv06xx/stv06xx_hdcs.c | 76 +++++++++-- drivers/media/video/gspca/stv06xx/stv06xx_hdcs.h | 65 ---------- drivers/media/video/gspca/stv06xx/stv06xx_pb0100.c | 141 +++++++++++++++++++-- drivers/media/video/gspca/stv06xx/stv06xx_pb0100.h | 128 ------------------- drivers/media/video/gspca/stv06xx/stv06xx_sensor.h | 8 -- drivers/media/video/gspca/stv06xx/stv06xx_vv6410.c | 61 ++++++++- drivers/media/video/gspca/stv06xx/stv06xx_vv6410.h | 56 -------- 7 files changed, 258 insertions(+), 277 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/gspca/stv06xx/stv06xx_hdcs.c b/drivers/media/video/gspca/stv06xx/stv06xx_hdcs.c index 14335a9e4bb5..b16903814203 100644 --- a/drivers/media/video/gspca/stv06xx/stv06xx_hdcs.c +++ b/drivers/media/video/gspca/stv06xx/stv06xx_hdcs.c @@ -30,6 +30,66 @@ #include "stv06xx_hdcs.h" +static const struct ctrl hdcs1x00_ctrl[] = { + { + { + .id = V4L2_CID_EXPOSURE, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "exposure", + .minimum = 0x00, + .maximum = 0xffff, + .step = 0x1, + .default_value = HDCS_DEFAULT_EXPOSURE, + .flags = V4L2_CTRL_FLAG_SLIDER + }, + .set = hdcs_set_exposure, + .get = hdcs_get_exposure + }, { + { + .id = V4L2_CID_GAIN, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "gain", + .minimum = 0x00, + .maximum = 0xff, + .step = 0x1, + .default_value = HDCS_DEFAULT_GAIN, + .flags = V4L2_CTRL_FLAG_SLIDER + }, + .set = hdcs_set_gain, + .get = hdcs_get_gain + } +}; + +static struct v4l2_pix_format hdcs1x00_mode[] = { + { + HDCS_1X00_DEF_WIDTH, + HDCS_1X00_DEF_HEIGHT, + V4L2_PIX_FMT_SBGGR8, + V4L2_FIELD_NONE, + .sizeimage = + HDCS_1X00_DEF_WIDTH * HDCS_1X00_DEF_HEIGHT, + .bytesperline = HDCS_1X00_DEF_WIDTH, + .colorspace = V4L2_COLORSPACE_SRGB, + .priv = 1 + } +}; + +static const struct ctrl hdcs1020_ctrl[] = {}; + +static struct v4l2_pix_format hdcs1020_mode[] = { + { + HDCS_1020_DEF_WIDTH, + HDCS_1020_DEF_HEIGHT, + V4L2_PIX_FMT_SBGGR8, + V4L2_FIELD_NONE, + .sizeimage = + HDCS_1020_DEF_WIDTH * HDCS_1020_DEF_HEIGHT, + .bytesperline = HDCS_1020_DEF_WIDTH, + .colorspace = V4L2_COLORSPACE_SRGB, + .priv = 1 + } +}; + enum hdcs_power_state { HDCS_STATE_SLEEP, HDCS_STATE_IDLE, @@ -353,10 +413,10 @@ static int hdcs_probe_1x00(struct sd *sd) info("HDCS-1000/1100 sensor detected"); - sd->gspca_dev.cam.cam_mode = stv06xx_sensor_hdcs1x00.modes; - sd->gspca_dev.cam.nmodes = stv06xx_sensor_hdcs1x00.nmodes; - sd->desc.ctrls = stv06xx_sensor_hdcs1x00.ctrls; - sd->desc.nctrls = stv06xx_sensor_hdcs1x00.nctrls; + sd->gspca_dev.cam.cam_mode = hdcs1x00_mode; + sd->gspca_dev.cam.nmodes = ARRAY_SIZE(hdcs1x00_mode); + sd->desc.ctrls = hdcs1x00_ctrl; + sd->desc.nctrls = ARRAY_SIZE(hdcs1x00_ctrl); hdcs = kmalloc(sizeof(struct hdcs), GFP_KERNEL); if (!hdcs) @@ -412,10 +472,10 @@ static int hdcs_probe_1020(struct sd *sd) info("HDCS-1020 sensor detected"); - sd->gspca_dev.cam.cam_mode = stv06xx_sensor_hdcs1020.modes; - sd->gspca_dev.cam.nmodes = stv06xx_sensor_hdcs1020.nmodes; - sd->desc.ctrls = stv06xx_sensor_hdcs1020.ctrls; - sd->desc.nctrls = stv06xx_sensor_hdcs1020.nctrls; + sd->gspca_dev.cam.cam_mode = hdcs1020_mode; + sd->gspca_dev.cam.nmodes = ARRAY_SIZE(hdcs1020_mode); + sd->desc.ctrls = hdcs1020_ctrl; + sd->desc.nctrls = ARRAY_SIZE(hdcs1020_ctrl); hdcs = kmalloc(sizeof(struct hdcs), GFP_KERNEL); if (!hdcs) diff --git a/drivers/media/video/gspca/stv06xx/stv06xx_hdcs.h b/drivers/media/video/gspca/stv06xx/stv06xx_hdcs.h index 9c7279a4cd88..412f06cf3d5c 100644 --- a/drivers/media/video/gspca/stv06xx/stv06xx_hdcs.h +++ b/drivers/media/video/gspca/stv06xx/stv06xx_hdcs.h @@ -152,53 +152,6 @@ const struct stv06xx_sensor stv06xx_sensor_hdcs1x00 = { .stop = hdcs_stop, .disconnect = hdcs_disconnect, .dump = hdcs_dump, - - .nctrls = 2, - .ctrls = { - { - { - .id = V4L2_CID_EXPOSURE, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "exposure", - .minimum = 0x00, - .maximum = 0xffff, - .step = 0x1, - .default_value = HDCS_DEFAULT_EXPOSURE, - .flags = V4L2_CTRL_FLAG_SLIDER - }, - .set = hdcs_set_exposure, - .get = hdcs_get_exposure - }, - { - { - .id = V4L2_CID_GAIN, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "gain", - .minimum = 0x00, - .maximum = 0xff, - .step = 0x1, - .default_value = HDCS_DEFAULT_GAIN, - .flags = V4L2_CTRL_FLAG_SLIDER - }, - .set = hdcs_set_gain, - .get = hdcs_get_gain - } - }, - - .nmodes = 1, - .modes = { - { - HDCS_1X00_DEF_WIDTH, - HDCS_1X00_DEF_HEIGHT, - V4L2_PIX_FMT_SBGGR8, - V4L2_FIELD_NONE, - .sizeimage = - HDCS_1X00_DEF_WIDTH * HDCS_1X00_DEF_HEIGHT, - .bytesperline = HDCS_1X00_DEF_WIDTH, - .colorspace = V4L2_COLORSPACE_SRGB, - .priv = 1 - } - } }; const struct stv06xx_sensor stv06xx_sensor_hdcs1020 = { @@ -207,29 +160,11 @@ const struct stv06xx_sensor stv06xx_sensor_hdcs1020 = { .i2c_addr = (0x55 << 1), .i2c_len = 1, - .nctrls = 0, - .ctrls = {}, - .init = hdcs_init, .probe = hdcs_probe_1020, .start = hdcs_start, .stop = hdcs_stop, .dump = hdcs_dump, - - .nmodes = 1, - .modes = { - { - HDCS_1020_DEF_WIDTH, - HDCS_1020_DEF_HEIGHT, - V4L2_PIX_FMT_SBGGR8, - V4L2_FIELD_NONE, - .sizeimage = - HDCS_1020_DEF_WIDTH * HDCS_1020_DEF_HEIGHT, - .bytesperline = HDCS_1020_DEF_WIDTH, - .colorspace = V4L2_COLORSPACE_SRGB, - .priv = 1 - } - } }; static const u16 stv_bridge_init[][2] = { diff --git a/drivers/media/video/gspca/stv06xx/stv06xx_pb0100.c b/drivers/media/video/gspca/stv06xx/stv06xx_pb0100.c index d0a0f8596454..ae2d04b85604 100644 --- a/drivers/media/video/gspca/stv06xx/stv06xx_pb0100.c +++ b/drivers/media/video/gspca/stv06xx/stv06xx_pb0100.c @@ -46,6 +46,132 @@ #include "stv06xx_pb0100.h" +static const struct ctrl pb0100_ctrl[] = { +#define GAIN_IDX 0 + { + { + .id = V4L2_CID_GAIN, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "Gain", + .minimum = 0, + .maximum = 255, + .step = 1, + .default_value = 128 + }, + .set = pb0100_set_gain, + .get = pb0100_get_gain + }, +#define RED_BALANCE_IDX 1 + { + { + .id = V4L2_CID_RED_BALANCE, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "Red Balance", + .minimum = -255, + .maximum = 255, + .step = 1, + .default_value = 0 + }, + .set = pb0100_set_red_balance, + .get = pb0100_get_red_balance + }, +#define BLUE_BALANCE_IDX 2 + { + { + .id = V4L2_CID_BLUE_BALANCE, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "Blue Balance", + .minimum = -255, + .maximum = 255, + .step = 1, + .default_value = 0 + }, + .set = pb0100_set_blue_balance, + .get = pb0100_get_blue_balance + }, +#define EXPOSURE_IDX 3 + { + { + .id = V4L2_CID_EXPOSURE, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "Exposure", + .minimum = 0, + .maximum = 511, + .step = 1, + .default_value = 12 + }, + .set = pb0100_set_exposure, + .get = pb0100_get_exposure + }, +#define AUTOGAIN_IDX 4 + { + { + .id = V4L2_CID_AUTOGAIN, + .type = V4L2_CTRL_TYPE_BOOLEAN, + .name = "Automatic Gain and Exposure", + .minimum = 0, + .maximum = 1, + .step = 1, + .default_value = 1 + }, + .set = pb0100_set_autogain, + .get = pb0100_get_autogain + }, +#define AUTOGAIN_TARGET_IDX 5 + { + { + .id = V4L2_CTRL_CLASS_USER + 0x1000, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "Automatic Gain Target", + .minimum = 0, + .maximum = 255, + .step = 1, + .default_value = 128 + }, + .set = pb0100_set_autogain_target, + .get = pb0100_get_autogain_target + }, +#define NATURAL_IDX 6 + { + { + .id = V4L2_CTRL_CLASS_USER + 0x1001, + .type = V4L2_CTRL_TYPE_BOOLEAN, + .name = "Natural Light Source", + .minimum = 0, + .maximum = 1, + .step = 1, + .default_value = 1 + }, + .set = pb0100_set_natural, + .get = pb0100_get_natural + } +}; + +static struct v4l2_pix_format pb0100_mode[] = { +/* low res / subsample modes disabled as they are only half res horizontal, + halving the vertical resolution does not seem to work */ + { + 320, + 240, + V4L2_PIX_FMT_SGRBG8, + V4L2_FIELD_NONE, + .sizeimage = 320 * 240, + .bytesperline = 320, + .colorspace = V4L2_COLORSPACE_SRGB, + .priv = PB0100_CROP_TO_VGA + }, + { + 352, + 288, + V4L2_PIX_FMT_SGRBG8, + V4L2_FIELD_NONE, + .sizeimage = 352 * 288, + .bytesperline = 352, + .colorspace = V4L2_COLORSPACE_SRGB, + .priv = 0 + } +}; + static int pb0100_probe(struct sd *sd) { u16 sensor; @@ -59,20 +185,19 @@ static int pb0100_probe(struct sd *sd) if ((sensor >> 8) == 0x64) { sensor_settings = kmalloc( - stv06xx_sensor_pb0100.nctrls * sizeof(s32), + ARRAY_SIZE(pb0100_ctrl) * sizeof(s32), GFP_KERNEL); if (!sensor_settings) return -ENOMEM; info("Photobit pb0100 sensor detected"); - sd->gspca_dev.cam.cam_mode = stv06xx_sensor_pb0100.modes; - sd->gspca_dev.cam.nmodes = stv06xx_sensor_pb0100.nmodes; - sd->desc.ctrls = stv06xx_sensor_pb0100.ctrls; - sd->desc.nctrls = stv06xx_sensor_pb0100.nctrls; - for (i = 0; i < stv06xx_sensor_pb0100.nctrls; i++) - sensor_settings[i] = stv06xx_sensor_pb0100. - ctrls[i].qctrl.default_value; + sd->gspca_dev.cam.cam_mode = pb0100_mode; + sd->gspca_dev.cam.nmodes = ARRAY_SIZE(pb0100_mode); + sd->desc.ctrls = pb0100_ctrl; + sd->desc.nctrls = ARRAY_SIZE(pb0100_ctrl); + for (i = 0; i < sd->desc.nctrls; i++) + sensor_settings[i] = pb0100_ctrl[i].qctrl.default_value; sd->sensor_priv = sensor_settings; return 0; diff --git a/drivers/media/video/gspca/stv06xx/stv06xx_pb0100.h b/drivers/media/video/gspca/stv06xx/stv06xx_pb0100.h index 5ea21a1154c4..da7c13ed8ffb 100644 --- a/drivers/media/video/gspca/stv06xx/stv06xx_pb0100.h +++ b/drivers/media/video/gspca/stv06xx/stv06xx_pb0100.h @@ -137,139 +137,11 @@ const struct stv06xx_sensor stv06xx_sensor_pb0100 = { .i2c_addr = 0xba, .i2c_len = 2, - .nctrls = 7, - .ctrls = { -#define GAIN_IDX 0 - { - { - .id = V4L2_CID_GAIN, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "Gain", - .minimum = 0, - .maximum = 255, - .step = 1, - .default_value = 128 - }, - .set = pb0100_set_gain, - .get = pb0100_get_gain - }, -#define RED_BALANCE_IDX 1 - { - { - .id = V4L2_CID_RED_BALANCE, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "Red Balance", - .minimum = -255, - .maximum = 255, - .step = 1, - .default_value = 0 - }, - .set = pb0100_set_red_balance, - .get = pb0100_get_red_balance - }, -#define BLUE_BALANCE_IDX 2 - { - { - .id = V4L2_CID_BLUE_BALANCE, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "Blue Balance", - .minimum = -255, - .maximum = 255, - .step = 1, - .default_value = 0 - }, - .set = pb0100_set_blue_balance, - .get = pb0100_get_blue_balance - }, -#define EXPOSURE_IDX 3 - { - { - .id = V4L2_CID_EXPOSURE, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "Exposure", - .minimum = 0, - .maximum = 511, - .step = 1, - .default_value = 12 - }, - .set = pb0100_set_exposure, - .get = pb0100_get_exposure - }, -#define AUTOGAIN_IDX 4 - { - { - .id = V4L2_CID_AUTOGAIN, - .type = V4L2_CTRL_TYPE_BOOLEAN, - .name = "Automatic Gain and Exposure", - .minimum = 0, - .maximum = 1, - .step = 1, - .default_value = 1 - }, - .set = pb0100_set_autogain, - .get = pb0100_get_autogain - }, -#define AUTOGAIN_TARGET_IDX 5 - { - { - .id = V4L2_CTRL_CLASS_USER + 0x1000, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "Automatic Gain Target", - .minimum = 0, - .maximum = 255, - .step = 1, - .default_value = 128 - }, - .set = pb0100_set_autogain_target, - .get = pb0100_get_autogain_target - }, -#define NATURAL_IDX 6 - { - { - .id = V4L2_CTRL_CLASS_USER + 0x1001, - .type = V4L2_CTRL_TYPE_BOOLEAN, - .name = "Natural Light Source", - .minimum = 0, - .maximum = 1, - .step = 1, - .default_value = 1 - }, - .set = pb0100_set_natural, - .get = pb0100_get_natural - }, - }, - .init = pb0100_init, .probe = pb0100_probe, .start = pb0100_start, .stop = pb0100_stop, .dump = pb0100_dump, - - .nmodes = 2, - .modes = { -/* low res / subsample modes disabled as they are only half res horizontal, - halving the vertical resolution does not seem to work */ - { - 320, - 240, - V4L2_PIX_FMT_SGRBG8, - V4L2_FIELD_NONE, - .sizeimage = 320 * 240, - .bytesperline = 320, - .colorspace = V4L2_COLORSPACE_SRGB, - .priv = PB0100_CROP_TO_VGA - }, - { - 352, - 288, - V4L2_PIX_FMT_SGRBG8, - V4L2_FIELD_NONE, - .sizeimage = 352 * 288, - .bytesperline = 352, - .colorspace = V4L2_COLORSPACE_SRGB, - .priv = 0 - }, - } }; #endif diff --git a/drivers/media/video/gspca/stv06xx/stv06xx_sensor.h b/drivers/media/video/gspca/stv06xx/stv06xx_sensor.h index c726dacefa1f..e88c42f7d2f8 100644 --- a/drivers/media/video/gspca/stv06xx/stv06xx_sensor.h +++ b/drivers/media/video/gspca/stv06xx/stv06xx_sensor.h @@ -41,8 +41,6 @@ extern const struct stv06xx_sensor stv06xx_sensor_hdcs1x00; extern const struct stv06xx_sensor stv06xx_sensor_hdcs1020; extern const struct stv06xx_sensor stv06xx_sensor_pb0100; -#define STV06XX_MAX_CTRLS (V4L2_CID_LASTP1 - V4L2_CID_BASE + 10) - struct stv06xx_sensor { /* Defines the name of a sensor */ char name[32]; @@ -81,12 +79,6 @@ struct stv06xx_sensor { /* Instructs the sensor to dump all its contents */ int (*dump)(struct sd *sd); - - int nctrls; - struct ctrl ctrls[STV06XX_MAX_CTRLS]; - - char nmodes; - struct v4l2_pix_format modes[]; }; #endif diff --git a/drivers/media/video/gspca/stv06xx/stv06xx_vv6410.c b/drivers/media/video/gspca/stv06xx/stv06xx_vv6410.c index 1ca91f2a6dee..a204b5891f63 100644 --- a/drivers/media/video/gspca/stv06xx/stv06xx_vv6410.c +++ b/drivers/media/video/gspca/stv06xx/stv06xx_vv6410.c @@ -29,6 +29,59 @@ #include "stv06xx_vv6410.h" +static struct v4l2_pix_format vv6410_mode[] = { + { + 356, + 292, + V4L2_PIX_FMT_SGRBG8, + V4L2_FIELD_NONE, + .sizeimage = 356 * 292, + .bytesperline = 356, + .colorspace = V4L2_COLORSPACE_SRGB, + .priv = 0 + } +}; + +static const struct ctrl vv6410_ctrl[] = { + { + { + .id = V4L2_CID_HFLIP, + .type = V4L2_CTRL_TYPE_BOOLEAN, + .name = "horizontal flip", + .minimum = 0, + .maximum = 1, + .step = 1, + .default_value = 0 + }, + .set = vv6410_set_hflip, + .get = vv6410_get_hflip + }, { + { + .id = V4L2_CID_VFLIP, + .type = V4L2_CTRL_TYPE_BOOLEAN, + .name = "vertical flip", + .minimum = 0, + .maximum = 1, + .step = 1, + .default_value = 0 + }, + .set = vv6410_set_vflip, + .get = vv6410_get_vflip + }, { + { + .id = V4L2_CID_GAIN, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "analog gain", + .minimum = 0, + .maximum = 15, + .step = 1, + .default_value = 0 + }, + .set = vv6410_set_analog_gain, + .get = vv6410_get_analog_gain + } +}; + static int vv6410_probe(struct sd *sd) { u16 data; @@ -42,10 +95,10 @@ static int vv6410_probe(struct sd *sd) if (data == 0x19) { info("vv6410 sensor detected"); - sd->gspca_dev.cam.cam_mode = stv06xx_sensor_vv6410.modes; - sd->gspca_dev.cam.nmodes = stv06xx_sensor_vv6410.nmodes; - sd->desc.ctrls = stv06xx_sensor_vv6410.ctrls; - sd->desc.nctrls = stv06xx_sensor_vv6410.nctrls; + sd->gspca_dev.cam.cam_mode = vv6410_mode; + sd->gspca_dev.cam.nmodes = ARRAY_SIZE(vv6410_mode); + sd->desc.ctrls = vv6410_ctrl; + sd->desc.nctrls = ARRAY_SIZE(vv6410_ctrl); return 0; } diff --git a/drivers/media/video/gspca/stv06xx/stv06xx_vv6410.h b/drivers/media/video/gspca/stv06xx/stv06xx_vv6410.h index 3ff8c4ea3362..1cb5f57651bd 100644 --- a/drivers/media/video/gspca/stv06xx/stv06xx_vv6410.h +++ b/drivers/media/video/gspca/stv06xx/stv06xx_vv6410.h @@ -197,62 +197,6 @@ const struct stv06xx_sensor stv06xx_sensor_vv6410 = { .start = vv6410_start, .stop = vv6410_stop, .dump = vv6410_dump, - - .nctrls = 3, - .ctrls = { - { - { - .id = V4L2_CID_HFLIP, - .type = V4L2_CTRL_TYPE_BOOLEAN, - .name = "horizontal flip", - .minimum = 0, - .maximum = 1, - .step = 1, - .default_value = 0 - }, - .set = vv6410_set_hflip, - .get = vv6410_get_hflip - }, { - { - .id = V4L2_CID_VFLIP, - .type = V4L2_CTRL_TYPE_BOOLEAN, - .name = "vertical flip", - .minimum = 0, - .maximum = 1, - .step = 1, - .default_value = 0 - }, - .set = vv6410_set_vflip, - .get = vv6410_get_vflip - }, { - { - .id = V4L2_CID_GAIN, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "analog gain", - .minimum = 0, - .maximum = 15, - .step = 1, - .default_value = 0 - }, - .set = vv6410_set_analog_gain, - .get = vv6410_get_analog_gain - } - }, - - .nmodes = 1, - .modes = { - { - 356, - 292, - V4L2_PIX_FMT_SGRBG8, - V4L2_FIELD_NONE, - .sizeimage = - 356 * 292, - .bytesperline = 356, - .colorspace = V4L2_COLORSPACE_SRGB, - .priv = 0 - } - } }; /* If NULL, only single value to write, stored in len */ -- cgit v1.2.3 From f69e9529ed96ff917096d0b7b3015c8d8ea5750d Mon Sep 17 00:00:00 2001 From: Alexey Klimov Date: Thu, 1 Jan 2009 13:02:07 -0300 Subject: V4L/DVB (10335): gspca - all subdrivers: Fix CodingStyle in sd_mod_init function. Introduce int ret and check it value after call to usb_register(). Signed-off-by: Alexey Klimov Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/conex.c | 4 +++- drivers/media/video/gspca/etoms.c | 4 +++- drivers/media/video/gspca/finepix.c | 4 +++- drivers/media/video/gspca/m5602/m5602_core.c | 4 +++- drivers/media/video/gspca/mars.c | 4 +++- drivers/media/video/gspca/ov519.c | 4 +++- drivers/media/video/gspca/ov534.c | 4 +++- drivers/media/video/gspca/pac207.c | 4 +++- drivers/media/video/gspca/pac7311.c | 4 +++- drivers/media/video/gspca/sonixb.c | 4 +++- drivers/media/video/gspca/sonixj.c | 4 +++- drivers/media/video/gspca/spca500.c | 4 +++- drivers/media/video/gspca/spca501.c | 4 +++- drivers/media/video/gspca/spca505.c | 4 +++- drivers/media/video/gspca/spca506.c | 4 +++- drivers/media/video/gspca/spca508.c | 4 +++- drivers/media/video/gspca/spca561.c | 4 +++- drivers/media/video/gspca/stk014.c | 4 +++- drivers/media/video/gspca/stv06xx/stv06xx.c | 4 +++- drivers/media/video/gspca/sunplus.c | 4 +++- drivers/media/video/gspca/t613.c | 4 +++- drivers/media/video/gspca/tv8532.c | 4 +++- drivers/media/video/gspca/vc032x.c | 4 +++- drivers/media/video/gspca/zc3xx.c | 4 +++- 24 files changed, 72 insertions(+), 24 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/gspca/conex.c b/drivers/media/video/gspca/conex.c index a7088f60bcd0..825342be41fc 100644 --- a/drivers/media/video/gspca/conex.c +++ b/drivers/media/video/gspca/conex.c @@ -1028,7 +1028,9 @@ static struct usb_driver sd_driver = { /* -- module insert / remove -- */ static int __init sd_mod_init(void) { - if (usb_register(&sd_driver) < 0) + int ret; + ret = usb_register(&sd_driver); + if (ret < 0) return -1; PDEBUG(D_PROBE, "registered"); return 0; diff --git a/drivers/media/video/gspca/etoms.c b/drivers/media/video/gspca/etoms.c index ca888ac969d0..c5f8dda42435 100644 --- a/drivers/media/video/gspca/etoms.c +++ b/drivers/media/video/gspca/etoms.c @@ -927,7 +927,9 @@ static struct usb_driver sd_driver = { /* -- module insert / remove -- */ static int __init sd_mod_init(void) { - if (usb_register(&sd_driver) < 0) + int ret; + ret = usb_register(&sd_driver); + if (ret < 0) return -1; PDEBUG(D_PROBE, "registered"); return 0; diff --git a/drivers/media/video/gspca/finepix.c b/drivers/media/video/gspca/finepix.c index 76c6e03cb6c9..96a5ca775b55 100644 --- a/drivers/media/video/gspca/finepix.c +++ b/drivers/media/video/gspca/finepix.c @@ -454,7 +454,9 @@ static struct usb_driver sd_driver = { /* -- module insert / remove -- */ static int __init sd_mod_init(void) { - if (usb_register(&sd_driver) < 0) + int ret; + ret = usb_register(&sd_driver); + if (ret < 0) return -1; PDEBUG(D_PROBE, "registered"); return 0; diff --git a/drivers/media/video/gspca/m5602/m5602_core.c b/drivers/media/video/gspca/m5602/m5602_core.c index 37a47db2903d..e78914d7a1a0 100644 --- a/drivers/media/video/gspca/m5602/m5602_core.c +++ b/drivers/media/video/gspca/m5602/m5602_core.c @@ -373,7 +373,9 @@ static struct usb_driver sd_driver = { /* -- module insert / remove -- */ static int __init mod_m5602_init(void) { - if (usb_register(&sd_driver) < 0) + int ret; + ret = usb_register(&sd_driver); + if (ret < 0) return -1; PDEBUG(D_PROBE, "registered"); return 0; diff --git a/drivers/media/video/gspca/mars.c b/drivers/media/video/gspca/mars.c index ba79afbf8b39..420224afacb1 100644 --- a/drivers/media/video/gspca/mars.c +++ b/drivers/media/video/gspca/mars.c @@ -420,7 +420,9 @@ static struct usb_driver sd_driver = { /* -- module insert / remove -- */ static int __init sd_mod_init(void) { - if (usb_register(&sd_driver) < 0) + int ret; + ret = usb_register(&sd_driver); + if (ret < 0) return -1; PDEBUG(D_PROBE, "registered"); return 0; diff --git a/drivers/media/video/gspca/ov519.c b/drivers/media/video/gspca/ov519.c index ac9b4dc064d6..c78d2d0f43d3 100644 --- a/drivers/media/video/gspca/ov519.c +++ b/drivers/media/video/gspca/ov519.c @@ -2176,7 +2176,9 @@ static struct usb_driver sd_driver = { /* -- module insert / remove -- */ static int __init sd_mod_init(void) { - if (usb_register(&sd_driver) < 0) + int ret; + ret = usb_register(&sd_driver); + if (ret < 0) return -1; PDEBUG(D_PROBE, "registered"); return 0; diff --git a/drivers/media/video/gspca/ov534.c b/drivers/media/video/gspca/ov534.c index 01314e9995f0..e20ec7df34a7 100644 --- a/drivers/media/video/gspca/ov534.c +++ b/drivers/media/video/gspca/ov534.c @@ -584,7 +584,9 @@ static struct usb_driver sd_driver = { /* -- module insert / remove -- */ static int __init sd_mod_init(void) { - if (usb_register(&sd_driver) < 0) + int ret; + ret = usb_register(&sd_driver); + if (ret < 0) return -1; PDEBUG(D_PROBE, "registered"); return 0; diff --git a/drivers/media/video/gspca/pac207.c b/drivers/media/video/gspca/pac207.c index 546820f52c02..10331728f162 100644 --- a/drivers/media/video/gspca/pac207.c +++ b/drivers/media/video/gspca/pac207.c @@ -564,7 +564,9 @@ static struct usb_driver sd_driver = { /* -- module insert / remove -- */ static int __init sd_mod_init(void) { - if (usb_register(&sd_driver) < 0) + int ret; + ret = usb_register(&sd_driver); + if (ret < 0) return -1; PDEBUG(D_PROBE, "registered"); return 0; diff --git a/drivers/media/video/gspca/pac7311.c b/drivers/media/video/gspca/pac7311.c index f34bbc5db501..8a4551ecd0a6 100644 --- a/drivers/media/video/gspca/pac7311.c +++ b/drivers/media/video/gspca/pac7311.c @@ -1096,7 +1096,9 @@ static struct usb_driver sd_driver = { /* -- module insert / remove -- */ static int __init sd_mod_init(void) { - if (usb_register(&sd_driver) < 0) + int ret; + ret = usb_register(&sd_driver); + if (ret < 0) return -1; PDEBUG(D_PROBE, "registered"); return 0; diff --git a/drivers/media/video/gspca/sonixb.c b/drivers/media/video/gspca/sonixb.c index 5ec361c779be..dd9417eea16a 100644 --- a/drivers/media/video/gspca/sonixb.c +++ b/drivers/media/video/gspca/sonixb.c @@ -1271,7 +1271,9 @@ static struct usb_driver sd_driver = { /* -- module insert / remove -- */ static int __init sd_mod_init(void) { - if (usb_register(&sd_driver) < 0) + int ret; + ret = usb_register(&sd_driver); + if (ret < 0) return -1; PDEBUG(D_PROBE, "registered"); return 0; diff --git a/drivers/media/video/gspca/sonixj.c b/drivers/media/video/gspca/sonixj.c index 5c159d89bd82..d1b604c07afd 100644 --- a/drivers/media/video/gspca/sonixj.c +++ b/drivers/media/video/gspca/sonixj.c @@ -1793,7 +1793,9 @@ static struct usb_driver sd_driver = { /* -- module insert / remove -- */ static int __init sd_mod_init(void) { - if (usb_register(&sd_driver) < 0) + int ret; + ret = usb_register(&sd_driver); + if (ret < 0) return -1; info("registered"); return 0; diff --git a/drivers/media/video/gspca/spca500.c b/drivers/media/video/gspca/spca500.c index 94ed469a3ada..75494016515d 100644 --- a/drivers/media/video/gspca/spca500.c +++ b/drivers/media/video/gspca/spca500.c @@ -1092,7 +1092,9 @@ static struct usb_driver sd_driver = { /* -- module insert / remove -- */ static int __init sd_mod_init(void) { - if (usb_register(&sd_driver) < 0) + int ret; + ret = usb_register(&sd_driver); + if (ret < 0) return -1; PDEBUG(D_PROBE, "registered"); return 0; diff --git a/drivers/media/video/gspca/spca501.c b/drivers/media/video/gspca/spca501.c index 766da90e6eb7..9ae62f18f725 100644 --- a/drivers/media/video/gspca/spca501.c +++ b/drivers/media/video/gspca/spca501.c @@ -2210,7 +2210,9 @@ static struct usb_driver sd_driver = { /* -- module insert / remove -- */ static int __init sd_mod_init(void) { - if (usb_register(&sd_driver) < 0) + int ret; + ret = usb_register(&sd_driver); + if (ret < 0) return -1; PDEBUG(D_PROBE, "registered"); return 0; diff --git a/drivers/media/video/gspca/spca505.c b/drivers/media/video/gspca/spca505.c index 90d555361ae7..32ae57e5f7be 100644 --- a/drivers/media/video/gspca/spca505.c +++ b/drivers/media/video/gspca/spca505.c @@ -862,7 +862,9 @@ static struct usb_driver sd_driver = { /* -- module insert / remove -- */ static int __init sd_mod_init(void) { - if (usb_register(&sd_driver) < 0) + int ret; + ret = usb_register(&sd_driver); + if (ret < 0) return -1; PDEBUG(D_PROBE, "registered"); return 0; diff --git a/drivers/media/video/gspca/spca506.c b/drivers/media/video/gspca/spca506.c index 99fa3fc1cb62..aa3ecc8acfa6 100644 --- a/drivers/media/video/gspca/spca506.c +++ b/drivers/media/video/gspca/spca506.c @@ -771,7 +771,9 @@ static struct usb_driver sd_driver = { /* -- module insert / remove -- */ static int __init sd_mod_init(void) { - if (usb_register(&sd_driver) < 0) + int ret; + ret = usb_register(&sd_driver); + if (ret < 0) return -1; PDEBUG(D_PROBE, "registered"); return 0; diff --git a/drivers/media/video/gspca/spca508.c b/drivers/media/video/gspca/spca508.c index f5c045967379..c9d5e6c80912 100644 --- a/drivers/media/video/gspca/spca508.c +++ b/drivers/media/video/gspca/spca508.c @@ -1665,7 +1665,9 @@ static struct usb_driver sd_driver = { /* -- module insert / remove -- */ static int __init sd_mod_init(void) { - if (usb_register(&sd_driver) < 0) + int ret; + ret = usb_register(&sd_driver); + if (ret < 0) return -1; PDEBUG(D_PROBE, "registered"); return 0; diff --git a/drivers/media/video/gspca/spca561.c b/drivers/media/video/gspca/spca561.c index d64e7d64d053..1538350849f9 100644 --- a/drivers/media/video/gspca/spca561.c +++ b/drivers/media/video/gspca/spca561.c @@ -1196,7 +1196,9 @@ static struct usb_driver sd_driver = { /* -- module insert / remove -- */ static int __init sd_mod_init(void) { - if (usb_register(&sd_driver) < 0) + int ret; + ret = usb_register(&sd_driver); + if (ret < 0) return -1; PDEBUG(D_PROBE, "registered"); return 0; diff --git a/drivers/media/video/gspca/stk014.c b/drivers/media/video/gspca/stk014.c index cd1fbff0c94c..8743c03ed4aa 100644 --- a/drivers/media/video/gspca/stk014.c +++ b/drivers/media/video/gspca/stk014.c @@ -560,7 +560,9 @@ static struct usb_driver sd_driver = { /* -- module insert / remove -- */ static int __init sd_mod_init(void) { - if (usb_register(&sd_driver) < 0) + int ret; + ret = usb_register(&sd_driver); + if (ret < 0) return -1; info("registered"); return 0; diff --git a/drivers/media/video/gspca/stv06xx/stv06xx.c b/drivers/media/video/gspca/stv06xx/stv06xx.c index c60b163335c5..c43534db74bb 100644 --- a/drivers/media/video/gspca/stv06xx/stv06xx.c +++ b/drivers/media/video/gspca/stv06xx/stv06xx.c @@ -500,7 +500,9 @@ static struct usb_driver sd_driver = { /* -- module insert / remove -- */ static int __init sd_mod_init(void) { - if (usb_register(&sd_driver) < 0) + int ret; + ret = usb_register(&sd_driver); + if (ret < 0) return -1; PDEBUG(D_PROBE, "registered"); return 0; diff --git a/drivers/media/video/gspca/sunplus.c b/drivers/media/video/gspca/sunplus.c index 1f07476a9905..a7d324cf1a5c 100644 --- a/drivers/media/video/gspca/sunplus.c +++ b/drivers/media/video/gspca/sunplus.c @@ -1464,7 +1464,9 @@ static struct usb_driver sd_driver = { /* -- module insert / remove -- */ static int __init sd_mod_init(void) { - if (usb_register(&sd_driver) < 0) + int ret; + ret = usb_register(&sd_driver); + if (ret < 0) return -1; PDEBUG(D_PROBE, "registered"); return 0; diff --git a/drivers/media/video/gspca/t613.c b/drivers/media/video/gspca/t613.c index 74ca17845223..1dfdbf58526f 100644 --- a/drivers/media/video/gspca/t613.c +++ b/drivers/media/video/gspca/t613.c @@ -1171,7 +1171,9 @@ static struct usb_driver sd_driver = { /* -- module insert / remove -- */ static int __init sd_mod_init(void) { - if (usb_register(&sd_driver) < 0) + int ret; + ret = usb_register(&sd_driver); + if (ret < 0) return -1; PDEBUG(D_PROBE, "registered"); return 0; diff --git a/drivers/media/video/gspca/tv8532.c b/drivers/media/video/gspca/tv8532.c index 1da292ea1c77..0bcbdb22e018 100644 --- a/drivers/media/video/gspca/tv8532.c +++ b/drivers/media/video/gspca/tv8532.c @@ -569,7 +569,9 @@ static struct usb_driver sd_driver = { /* -- module insert / remove -- */ static int __init sd_mod_init(void) { - if (usb_register(&sd_driver) < 0) + int ret; + ret = usb_register(&sd_driver); + if (ret < 0) return -1; PDEBUG(D_PROBE, "registered"); return 0; diff --git a/drivers/media/video/gspca/vc032x.c b/drivers/media/video/gspca/vc032x.c index ab5a25cfc69e..0f475ec2ab93 100644 --- a/drivers/media/video/gspca/vc032x.c +++ b/drivers/media/video/gspca/vc032x.c @@ -2459,7 +2459,9 @@ static struct usb_driver sd_driver = { /* -- module insert / remove -- */ static int __init sd_mod_init(void) { - if (usb_register(&sd_driver) < 0) + int ret; + ret = usb_register(&sd_driver); + if (ret < 0) return -1; PDEBUG(D_PROBE, "registered"); return 0; diff --git a/drivers/media/video/gspca/zc3xx.c b/drivers/media/video/gspca/zc3xx.c index c32477db3bab..afc10a9ac539 100644 --- a/drivers/media/video/gspca/zc3xx.c +++ b/drivers/media/video/gspca/zc3xx.c @@ -7599,7 +7599,9 @@ static struct usb_driver sd_driver = { static int __init sd_mod_init(void) { - if (usb_register(&sd_driver) < 0) + int ret; + ret = usb_register(&sd_driver); + if (ret < 0) return -1; PDEBUG(D_PROBE, "registered"); return 0; -- cgit v1.2.3 From e6b148490f5e9ebb90ecb4a8de930be1b8936a16 Mon Sep 17 00:00:00 2001 From: Alexey Klimov Date: Thu, 1 Jan 2009 13:04:58 -0300 Subject: V4L/DVB (10336): gspca - all subdrivers: Return ret instead of -1 in sd_mod_init. Signed-off-by: Alexey Klimov Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/conex.c | 2 +- drivers/media/video/gspca/etoms.c | 2 +- drivers/media/video/gspca/finepix.c | 2 +- drivers/media/video/gspca/m5602/m5602_core.c | 2 +- drivers/media/video/gspca/mars.c | 2 +- drivers/media/video/gspca/ov519.c | 2 +- drivers/media/video/gspca/ov534.c | 2 +- drivers/media/video/gspca/pac207.c | 2 +- drivers/media/video/gspca/pac7311.c | 2 +- drivers/media/video/gspca/sonixb.c | 2 +- drivers/media/video/gspca/sonixj.c | 2 +- drivers/media/video/gspca/spca500.c | 2 +- drivers/media/video/gspca/spca501.c | 2 +- drivers/media/video/gspca/spca505.c | 2 +- drivers/media/video/gspca/spca506.c | 2 +- drivers/media/video/gspca/spca508.c | 2 +- drivers/media/video/gspca/spca561.c | 2 +- drivers/media/video/gspca/stk014.c | 2 +- drivers/media/video/gspca/stv06xx/stv06xx.c | 2 +- drivers/media/video/gspca/sunplus.c | 2 +- drivers/media/video/gspca/t613.c | 2 +- drivers/media/video/gspca/tv8532.c | 2 +- drivers/media/video/gspca/vc032x.c | 2 +- drivers/media/video/gspca/zc3xx.c | 2 +- 24 files changed, 24 insertions(+), 24 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/gspca/conex.c b/drivers/media/video/gspca/conex.c index 825342be41fc..2de8906e5661 100644 --- a/drivers/media/video/gspca/conex.c +++ b/drivers/media/video/gspca/conex.c @@ -1031,7 +1031,7 @@ static int __init sd_mod_init(void) int ret; ret = usb_register(&sd_driver); if (ret < 0) - return -1; + return ret; PDEBUG(D_PROBE, "registered"); return 0; } diff --git a/drivers/media/video/gspca/etoms.c b/drivers/media/video/gspca/etoms.c index c5f8dda42435..49ab2659a3f6 100644 --- a/drivers/media/video/gspca/etoms.c +++ b/drivers/media/video/gspca/etoms.c @@ -930,7 +930,7 @@ static int __init sd_mod_init(void) int ret; ret = usb_register(&sd_driver); if (ret < 0) - return -1; + return ret; PDEBUG(D_PROBE, "registered"); return 0; } diff --git a/drivers/media/video/gspca/finepix.c b/drivers/media/video/gspca/finepix.c index 96a5ca775b55..dc65c363aa87 100644 --- a/drivers/media/video/gspca/finepix.c +++ b/drivers/media/video/gspca/finepix.c @@ -457,7 +457,7 @@ static int __init sd_mod_init(void) int ret; ret = usb_register(&sd_driver); if (ret < 0) - return -1; + return ret; PDEBUG(D_PROBE, "registered"); return 0; } diff --git a/drivers/media/video/gspca/m5602/m5602_core.c b/drivers/media/video/gspca/m5602/m5602_core.c index e78914d7a1a0..b35e4838a6e5 100644 --- a/drivers/media/video/gspca/m5602/m5602_core.c +++ b/drivers/media/video/gspca/m5602/m5602_core.c @@ -376,7 +376,7 @@ static int __init mod_m5602_init(void) int ret; ret = usb_register(&sd_driver); if (ret < 0) - return -1; + return ret; PDEBUG(D_PROBE, "registered"); return 0; } diff --git a/drivers/media/video/gspca/mars.c b/drivers/media/video/gspca/mars.c index 420224afacb1..477441e22bab 100644 --- a/drivers/media/video/gspca/mars.c +++ b/drivers/media/video/gspca/mars.c @@ -423,7 +423,7 @@ static int __init sd_mod_init(void) int ret; ret = usb_register(&sd_driver); if (ret < 0) - return -1; + return ret; PDEBUG(D_PROBE, "registered"); return 0; } diff --git a/drivers/media/video/gspca/ov519.c b/drivers/media/video/gspca/ov519.c index c78d2d0f43d3..1fff37b79891 100644 --- a/drivers/media/video/gspca/ov519.c +++ b/drivers/media/video/gspca/ov519.c @@ -2179,7 +2179,7 @@ static int __init sd_mod_init(void) int ret; ret = usb_register(&sd_driver); if (ret < 0) - return -1; + return ret; PDEBUG(D_PROBE, "registered"); return 0; } diff --git a/drivers/media/video/gspca/ov534.c b/drivers/media/video/gspca/ov534.c index e20ec7df34a7..55d920caa6bb 100644 --- a/drivers/media/video/gspca/ov534.c +++ b/drivers/media/video/gspca/ov534.c @@ -587,7 +587,7 @@ static int __init sd_mod_init(void) int ret; ret = usb_register(&sd_driver); if (ret < 0) - return -1; + return ret; PDEBUG(D_PROBE, "registered"); return 0; } diff --git a/drivers/media/video/gspca/pac207.c b/drivers/media/video/gspca/pac207.c index 10331728f162..93616cebf360 100644 --- a/drivers/media/video/gspca/pac207.c +++ b/drivers/media/video/gspca/pac207.c @@ -567,7 +567,7 @@ static int __init sd_mod_init(void) int ret; ret = usb_register(&sd_driver); if (ret < 0) - return -1; + return ret; PDEBUG(D_PROBE, "registered"); return 0; } diff --git a/drivers/media/video/gspca/pac7311.c b/drivers/media/video/gspca/pac7311.c index 8a4551ecd0a6..e1e3a3a50484 100644 --- a/drivers/media/video/gspca/pac7311.c +++ b/drivers/media/video/gspca/pac7311.c @@ -1099,7 +1099,7 @@ static int __init sd_mod_init(void) int ret; ret = usb_register(&sd_driver); if (ret < 0) - return -1; + return ret; PDEBUG(D_PROBE, "registered"); return 0; } diff --git a/drivers/media/video/gspca/sonixb.c b/drivers/media/video/gspca/sonixb.c index dd9417eea16a..153d0a91d4b5 100644 --- a/drivers/media/video/gspca/sonixb.c +++ b/drivers/media/video/gspca/sonixb.c @@ -1274,7 +1274,7 @@ static int __init sd_mod_init(void) int ret; ret = usb_register(&sd_driver); if (ret < 0) - return -1; + return ret; PDEBUG(D_PROBE, "registered"); return 0; } diff --git a/drivers/media/video/gspca/sonixj.c b/drivers/media/video/gspca/sonixj.c index d1b604c07afd..755ca302368e 100644 --- a/drivers/media/video/gspca/sonixj.c +++ b/drivers/media/video/gspca/sonixj.c @@ -1796,7 +1796,7 @@ static int __init sd_mod_init(void) int ret; ret = usb_register(&sd_driver); if (ret < 0) - return -1; + return ret; info("registered"); return 0; } diff --git a/drivers/media/video/gspca/spca500.c b/drivers/media/video/gspca/spca500.c index 75494016515d..5450c3c4274b 100644 --- a/drivers/media/video/gspca/spca500.c +++ b/drivers/media/video/gspca/spca500.c @@ -1095,7 +1095,7 @@ static int __init sd_mod_init(void) int ret; ret = usb_register(&sd_driver); if (ret < 0) - return -1; + return ret; PDEBUG(D_PROBE, "registered"); return 0; } diff --git a/drivers/media/video/gspca/spca501.c b/drivers/media/video/gspca/spca501.c index 9ae62f18f725..414b5b8b759f 100644 --- a/drivers/media/video/gspca/spca501.c +++ b/drivers/media/video/gspca/spca501.c @@ -2213,7 +2213,7 @@ static int __init sd_mod_init(void) int ret; ret = usb_register(&sd_driver); if (ret < 0) - return -1; + return ret; PDEBUG(D_PROBE, "registered"); return 0; } diff --git a/drivers/media/video/gspca/spca505.c b/drivers/media/video/gspca/spca505.c index 32ae57e5f7be..b8c855c6a4ec 100644 --- a/drivers/media/video/gspca/spca505.c +++ b/drivers/media/video/gspca/spca505.c @@ -865,7 +865,7 @@ static int __init sd_mod_init(void) int ret; ret = usb_register(&sd_driver); if (ret < 0) - return -1; + return ret; PDEBUG(D_PROBE, "registered"); return 0; } diff --git a/drivers/media/video/gspca/spca506.c b/drivers/media/video/gspca/spca506.c index aa3ecc8acfa6..8cedb00976a4 100644 --- a/drivers/media/video/gspca/spca506.c +++ b/drivers/media/video/gspca/spca506.c @@ -774,7 +774,7 @@ static int __init sd_mod_init(void) int ret; ret = usb_register(&sd_driver); if (ret < 0) - return -1; + return ret; PDEBUG(D_PROBE, "registered"); return 0; } diff --git a/drivers/media/video/gspca/spca508.c b/drivers/media/video/gspca/spca508.c index c9d5e6c80912..34e74004774b 100644 --- a/drivers/media/video/gspca/spca508.c +++ b/drivers/media/video/gspca/spca508.c @@ -1668,7 +1668,7 @@ static int __init sd_mod_init(void) int ret; ret = usb_register(&sd_driver); if (ret < 0) - return -1; + return ret; PDEBUG(D_PROBE, "registered"); return 0; } diff --git a/drivers/media/video/gspca/spca561.c b/drivers/media/video/gspca/spca561.c index 1538350849f9..173c0c43fd1f 100644 --- a/drivers/media/video/gspca/spca561.c +++ b/drivers/media/video/gspca/spca561.c @@ -1199,7 +1199,7 @@ static int __init sd_mod_init(void) int ret; ret = usb_register(&sd_driver); if (ret < 0) - return -1; + return ret; PDEBUG(D_PROBE, "registered"); return 0; } diff --git a/drivers/media/video/gspca/stk014.c b/drivers/media/video/gspca/stk014.c index 8743c03ed4aa..ba31eb318652 100644 --- a/drivers/media/video/gspca/stk014.c +++ b/drivers/media/video/gspca/stk014.c @@ -563,7 +563,7 @@ static int __init sd_mod_init(void) int ret; ret = usb_register(&sd_driver); if (ret < 0) - return -1; + return ret; info("registered"); return 0; } diff --git a/drivers/media/video/gspca/stv06xx/stv06xx.c b/drivers/media/video/gspca/stv06xx/stv06xx.c index c43534db74bb..9dff2e65b116 100644 --- a/drivers/media/video/gspca/stv06xx/stv06xx.c +++ b/drivers/media/video/gspca/stv06xx/stv06xx.c @@ -503,7 +503,7 @@ static int __init sd_mod_init(void) int ret; ret = usb_register(&sd_driver); if (ret < 0) - return -1; + return ret; PDEBUG(D_PROBE, "registered"); return 0; } diff --git a/drivers/media/video/gspca/sunplus.c b/drivers/media/video/gspca/sunplus.c index a7d324cf1a5c..d9c9c440f020 100644 --- a/drivers/media/video/gspca/sunplus.c +++ b/drivers/media/video/gspca/sunplus.c @@ -1467,7 +1467,7 @@ static int __init sd_mod_init(void) int ret; ret = usb_register(&sd_driver); if (ret < 0) - return -1; + return ret; PDEBUG(D_PROBE, "registered"); return 0; } diff --git a/drivers/media/video/gspca/t613.c b/drivers/media/video/gspca/t613.c index 1dfdbf58526f..76ba2c9588d7 100644 --- a/drivers/media/video/gspca/t613.c +++ b/drivers/media/video/gspca/t613.c @@ -1174,7 +1174,7 @@ static int __init sd_mod_init(void) int ret; ret = usb_register(&sd_driver); if (ret < 0) - return -1; + return ret; PDEBUG(D_PROBE, "registered"); return 0; } diff --git a/drivers/media/video/gspca/tv8532.c b/drivers/media/video/gspca/tv8532.c index 0bcbdb22e018..86e4f0e3d917 100644 --- a/drivers/media/video/gspca/tv8532.c +++ b/drivers/media/video/gspca/tv8532.c @@ -572,7 +572,7 @@ static int __init sd_mod_init(void) int ret; ret = usb_register(&sd_driver); if (ret < 0) - return -1; + return ret; PDEBUG(D_PROBE, "registered"); return 0; } diff --git a/drivers/media/video/gspca/vc032x.c b/drivers/media/video/gspca/vc032x.c index 0f475ec2ab93..ab3108000756 100644 --- a/drivers/media/video/gspca/vc032x.c +++ b/drivers/media/video/gspca/vc032x.c @@ -2462,7 +2462,7 @@ static int __init sd_mod_init(void) int ret; ret = usb_register(&sd_driver); if (ret < 0) - return -1; + return ret; PDEBUG(D_PROBE, "registered"); return 0; } diff --git a/drivers/media/video/gspca/zc3xx.c b/drivers/media/video/gspca/zc3xx.c index afc10a9ac539..e0dbbc2b999a 100644 --- a/drivers/media/video/gspca/zc3xx.c +++ b/drivers/media/video/gspca/zc3xx.c @@ -7602,7 +7602,7 @@ static int __init sd_mod_init(void) int ret; ret = usb_register(&sd_driver); if (ret < 0) - return -1; + return ret; PDEBUG(D_PROBE, "registered"); return 0; } -- cgit v1.2.3 From 11fb06bd8da59c0a516e1b5f3d200a484becdf06 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Thu, 1 Jan 2009 13:20:42 -0300 Subject: V4L/DVB (10337): gspca - common: Simplify the debug macros. The err, warning and info redefinitions don't need the use of do {} while. Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/gspca.h | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/gspca/gspca.h b/drivers/media/video/gspca/gspca.h index e5c8eb709036..6f172e9e5fe9 100644 --- a/drivers/media/video/gspca/gspca.h +++ b/drivers/media/video/gspca/gspca.h @@ -33,19 +33,13 @@ extern int gspca_debug; #endif #undef err #define err(fmt, args...) \ - do {\ - printk(KERN_ERR MODULE_NAME ": " fmt "\n", ## args); \ - } while (0) + printk(KERN_ERR MODULE_NAME ": " fmt "\n", ## args) #undef info #define info(fmt, args...) \ - do {\ - printk(KERN_INFO MODULE_NAME ": " fmt "\n", ## args); \ - } while (0) + printk(KERN_INFO MODULE_NAME ": " fmt "\n", ## args) #undef warn #define warn(fmt, args...) \ - do {\ - printk(KERN_WARNING MODULE_NAME ": " fmt "\n", ## args); \ - } while (0) + printk(KERN_WARNING MODULE_NAME ": " fmt "\n", ## args) #define GSPCA_MAX_FRAMES 16 /* maximum number of video frame buffers */ /* image transfers */ -- cgit v1.2.3 From d5b53f467bf5c2d0dbd5b043461275255073886d Mon Sep 17 00:00:00 2001 From: Erik Andren Date: Wed, 7 Jan 2009 06:09:27 -0300 Subject: V4L/DVB (10341): gspca - stv06xx: Plug a memory leak in the pb0100 sensor driver. Signed-off-by: Erik Andren Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/stv06xx/stv06xx_pb0100.c | 6 ++++++ drivers/media/video/gspca/stv06xx/stv06xx_pb0100.h | 2 ++ 2 files changed, 8 insertions(+) (limited to 'drivers/media/video') diff --git a/drivers/media/video/gspca/stv06xx/stv06xx_pb0100.c b/drivers/media/video/gspca/stv06xx/stv06xx_pb0100.c index ae2d04b85604..285221e6b390 100644 --- a/drivers/media/video/gspca/stv06xx/stv06xx_pb0100.c +++ b/drivers/media/video/gspca/stv06xx/stv06xx_pb0100.c @@ -268,6 +268,12 @@ out: return (err < 0) ? err : 0; } +static void pb0100_disconnect(struct sd *sd) +{ + sd->sensor = NULL; + kfree(sd->sensor_priv); +} + /* FIXME: Sort the init commands out and put them into tables, this is only for getting the camera to work */ /* FIXME: No error handling for now, diff --git a/drivers/media/video/gspca/stv06xx/stv06xx_pb0100.h b/drivers/media/video/gspca/stv06xx/stv06xx_pb0100.h index da7c13ed8ffb..4de4fa5ebc57 100644 --- a/drivers/media/video/gspca/stv06xx/stv06xx_pb0100.h +++ b/drivers/media/video/gspca/stv06xx/stv06xx_pb0100.h @@ -114,6 +114,7 @@ static int pb0100_start(struct sd *sd); static int pb0100_init(struct sd *sd); static int pb0100_stop(struct sd *sd); static int pb0100_dump(struct sd *sd); +static void pb0100_disconnect(struct sd *sd); /* V4L2 controls supported by the driver */ static int pb0100_get_gain(struct gspca_dev *gspca_dev, __s32 *val); @@ -142,6 +143,7 @@ const struct stv06xx_sensor stv06xx_sensor_pb0100 = { .start = pb0100_start, .stop = pb0100_stop, .dump = pb0100_dump, + .disconnect = pb0100_disconnect, }; #endif -- cgit v1.2.3 From 5658ae9007490c18853fbf112f1b3516f5949e62 Mon Sep 17 00:00:00 2001 From: Erik Andren Date: Wed, 7 Jan 2009 06:11:50 -0300 Subject: V4L/DVB (10342): gspca - stv06xx: Add ctrl caching to the vv6410. Signed-off-by: Erik Andren Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/stv06xx/stv06xx_vv6410.c | 66 ++++++++++++++-------- drivers/media/video/gspca/stv06xx/stv06xx_vv6410.h | 2 + 2 files changed, 43 insertions(+), 25 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/gspca/stv06xx/stv06xx_vv6410.c b/drivers/media/video/gspca/stv06xx/stv06xx_vv6410.c index a204b5891f63..69c77c932fc0 100644 --- a/drivers/media/video/gspca/stv06xx/stv06xx_vv6410.c +++ b/drivers/media/video/gspca/stv06xx/stv06xx_vv6410.c @@ -43,6 +43,7 @@ static struct v4l2_pix_format vv6410_mode[] = { }; static const struct ctrl vv6410_ctrl[] = { +#define HFLIP_IDX 0 { { .id = V4L2_CID_HFLIP, @@ -55,7 +56,9 @@ static const struct ctrl vv6410_ctrl[] = { }, .set = vv6410_set_hflip, .get = vv6410_get_hflip - }, { + }, +#define VFLIP_IDX 1 + { { .id = V4L2_CID_VFLIP, .type = V4L2_CTRL_TYPE_BOOLEAN, @@ -67,7 +70,9 @@ static const struct ctrl vv6410_ctrl[] = { }, .set = vv6410_set_vflip, .get = vv6410_get_vflip - }, { + }, +#define GAIN_IDX 2 + { { .id = V4L2_CID_GAIN, .type = V4L2_CTRL_TYPE_INTEGER, @@ -85,23 +90,31 @@ static const struct ctrl vv6410_ctrl[] = { static int vv6410_probe(struct sd *sd) { u16 data; - int err; + int err, i; + s32 *sensor_settings; err = stv06xx_read_sensor(sd, VV6410_DEVICEH, &data); - if (err < 0) return -ENODEV; if (data == 0x19) { info("vv6410 sensor detected"); + sensor_settings = kmalloc(ARRAY_SIZE(vv6410_ctrl) * sizeof(s32), + GFP_KERNEL); + if (!sensor_settings) + return -ENOMEM; + sd->gspca_dev.cam.cam_mode = vv6410_mode; sd->gspca_dev.cam.nmodes = ARRAY_SIZE(vv6410_mode); sd->desc.ctrls = vv6410_ctrl; sd->desc.nctrls = ARRAY_SIZE(vv6410_ctrl); + + for (i = 0; i < sd->desc.nctrls; i++) + sensor_settings[i] = vv6410_ctrl[i].qctrl.default_value; + sd->sensor_priv = sensor_settings; return 0; } - return -ENODEV; } @@ -133,6 +146,12 @@ static int vv6410_init(struct sd *sd) return (err < 0) ? err : 0; } +static void vv6410_disconnect(struct sd *sd) +{ + sd->sensor = NULL; + kfree(sd->sensor_priv); +} + static int vv6410_start(struct sd *sd) { int err; @@ -209,17 +228,13 @@ static int vv6410_dump(struct sd *sd) static int vv6410_get_hflip(struct gspca_dev *gspca_dev, __s32 *val) { - int err; - u16 i2c_data; struct sd *sd = (struct sd *) gspca_dev; + s32 *sensor_settings = sd->sensor_priv; - err = stv06xx_read_sensor(sd, VV6410_DATAFORMAT, &i2c_data); - - *val = (i2c_data & VV6410_HFLIP) ? 1 : 0; - + *val = sensor_settings[HFLIP_IDX]; PDEBUG(D_V4L2, "Read horizontal flip %d", *val); - return (err < 0) ? err : 0; + return 0; } static int vv6410_set_hflip(struct gspca_dev *gspca_dev, __s32 val) @@ -227,6 +242,9 @@ static int vv6410_set_hflip(struct gspca_dev *gspca_dev, __s32 val) int err; u16 i2c_data; struct sd *sd = (struct sd *) gspca_dev; + s32 *sensor_settings = sd->sensor_priv; + + sensor_settings[HFLIP_IDX] = val; err = stv06xx_read_sensor(sd, VV6410_DATAFORMAT, &i2c_data); if (err < 0) return err; @@ -244,17 +262,13 @@ static int vv6410_set_hflip(struct gspca_dev *gspca_dev, __s32 val) static int vv6410_get_vflip(struct gspca_dev *gspca_dev, __s32 *val) { - int err; - u16 i2c_data; struct sd *sd = (struct sd *) gspca_dev; + s32 *sensor_settings = sd->sensor_priv; - err = stv06xx_read_sensor(sd, VV6410_DATAFORMAT, &i2c_data); - - *val = (i2c_data & VV6410_VFLIP) ? 1 : 0; - + *val = sensor_settings[VFLIP_IDX]; PDEBUG(D_V4L2, "Read vertical flip %d", *val); - return (err < 0) ? err : 0; + return 0; } static int vv6410_set_vflip(struct gspca_dev *gspca_dev, __s32 val) @@ -262,6 +276,9 @@ static int vv6410_set_vflip(struct gspca_dev *gspca_dev, __s32 val) int err; u16 i2c_data; struct sd *sd = (struct sd *) gspca_dev; + s32 *sensor_settings = sd->sensor_priv; + + sensor_settings[VFLIP_IDX] = val; err = stv06xx_read_sensor(sd, VV6410_DATAFORMAT, &i2c_data); if (err < 0) return err; @@ -279,24 +296,23 @@ static int vv6410_set_vflip(struct gspca_dev *gspca_dev, __s32 val) static int vv6410_get_analog_gain(struct gspca_dev *gspca_dev, __s32 *val) { - int err; - u16 i2c_data; struct sd *sd = (struct sd *) gspca_dev; + s32 *sensor_settings = sd->sensor_priv; - err = stv06xx_read_sensor(sd, VV6410_ANALOGGAIN, &i2c_data); - - *val = i2c_data & 0xf; + *val = sensor_settings[GAIN_IDX]; PDEBUG(D_V4L2, "Read analog gain %d", *val); - return (err < 0) ? err : 0; + return 0; } static int vv6410_set_analog_gain(struct gspca_dev *gspca_dev, __s32 val) { int err; struct sd *sd = (struct sd *) gspca_dev; + s32 *sensor_settings = sd->sensor_priv; + sensor_settings[GAIN_IDX] = val; PDEBUG(D_V4L2, "Set analog gain to %d", val); err = stv06xx_write_sensor(sd, VV6410_ANALOGGAIN, 0xf0 | (val & 0xf)); diff --git a/drivers/media/video/gspca/stv06xx/stv06xx_vv6410.h b/drivers/media/video/gspca/stv06xx/stv06xx_vv6410.h index 1cb5f57651bd..95ac55891bd4 100644 --- a/drivers/media/video/gspca/stv06xx/stv06xx_vv6410.h +++ b/drivers/media/video/gspca/stv06xx/stv06xx_vv6410.h @@ -178,6 +178,7 @@ static int vv6410_start(struct sd *sd); static int vv6410_init(struct sd *sd); static int vv6410_stop(struct sd *sd); static int vv6410_dump(struct sd *sd); +static void vv6410_disconnect(struct sd *sd); /* V4L2 controls supported by the driver */ static int vv6410_get_hflip(struct gspca_dev *gspca_dev, __s32 *val); @@ -197,6 +198,7 @@ const struct stv06xx_sensor stv06xx_sensor_vv6410 = { .start = vv6410_start, .stop = vv6410_stop, .dump = vv6410_dump, + .disconnect = vv6410_disconnect, }; /* If NULL, only single value to write, stored in len */ -- cgit v1.2.3 From ef6bc5aec2d8bd53dcc851a5cd2fc8e918db239b Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Wed, 7 Jan 2009 08:00:18 -0300 Subject: V4L/DVB (10343): gspca - zc3xx / zc0301: Handle the 0ac8:303b instead of zc0301. This webcam is generic and some sensors are not treated by the driver zc0301. Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/zc3xx.c | 2 -- drivers/media/video/zc0301/zc0301_sensor.h | 8 ++++++++ 2 files changed, 8 insertions(+), 2 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/gspca/zc3xx.c b/drivers/media/video/gspca/zc3xx.c index e0dbbc2b999a..2482f9163adb 100644 --- a/drivers/media/video/gspca/zc3xx.c +++ b/drivers/media/video/gspca/zc3xx.c @@ -7564,9 +7564,7 @@ static const __devinitdata struct usb_device_id device_table[] = { {USB_DEVICE(0x0ac8, 0x0301), .driver_info = SENSOR_PAS106}, {USB_DEVICE(0x0ac8, 0x0302)}, {USB_DEVICE(0x0ac8, 0x301b)}, -#if !defined CONFIG_USB_ZC0301 && !defined CONFIG_USB_ZC0301_MODULE {USB_DEVICE(0x0ac8, 0x303b)}, -#endif {USB_DEVICE(0x0ac8, 0x305b), .driver_info = SENSOR_TAS5130C_VF0250}, {USB_DEVICE(0x0ac8, 0x307b)}, {USB_DEVICE(0x10fd, 0x0128)}, diff --git a/drivers/media/video/zc0301/zc0301_sensor.h b/drivers/media/video/zc0301/zc0301_sensor.h index b0cd49c438a3..3a408de91b9c 100644 --- a/drivers/media/video/zc0301/zc0301_sensor.h +++ b/drivers/media/video/zc0301/zc0301_sensor.h @@ -58,12 +58,20 @@ zc0301_attach_sensor(struct zc0301_device* cam, struct zc0301_sensor* sensor); .idProduct = (prod), \ .bInterfaceClass = (intclass) +#if !defined CONFIG_USB_GSPCA && !defined CONFIG_USB_GSPCA_MODULE #define ZC0301_ID_TABLE \ static const struct usb_device_id zc0301_id_table[] = { \ { ZC0301_USB_DEVICE(0x046d, 0x08ae, 0xff), }, /* PAS202 */ \ { ZC0301_USB_DEVICE(0x0ac8, 0x303b, 0xff), }, /* PB-0330 */ \ { } \ }; +#else +#define ZC0301_ID_TABLE \ +static const struct usb_device_id zc0301_id_table[] = { \ + { ZC0301_USB_DEVICE(0x046d, 0x08ae, 0xff), }, /* PAS202 */ \ + { } \ +}; +#endif /*****************************************************************************/ -- cgit v1.2.3 From 96ff65144c3e302698d6c53b8d05098844c6b064 Mon Sep 17 00:00:00 2001 From: Antonio Ospite Date: Wed, 7 Jan 2009 09:09:36 -0300 Subject: V4L/DVB (10344): gspca - ov534: Disable the Hercules webcams. The Hercules webcam based on ov534 use different sensor than Playstation Eye, disable them until full support is provided. Signed-off-by: Antonio Ospite Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/ov534.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/gspca/ov534.c b/drivers/media/video/gspca/ov534.c index 55d920caa6bb..054bdf02c386 100644 --- a/drivers/media/video/gspca/ov534.c +++ b/drivers/media/video/gspca/ov534.c @@ -555,8 +555,6 @@ static const struct sd_desc sd_desc = { /* -- module initialisation -- */ static const __devinitdata struct usb_device_id device_table[] = { - {USB_DEVICE(0x06f8, 0x3002)}, /* Hercules Blog Webcam */ - {USB_DEVICE(0x06f8, 0x3003)}, /* Hercules Dualpix HD Weblog */ {USB_DEVICE(0x1415, 0x2000)}, /* Sony HD Eye for PS3 (SLEH 00201) */ {} }; -- cgit v1.2.3 From 36e819db435a61819d50c57c424a5ab2b9634e59 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Wed, 7 Jan 2009 16:49:57 -0300 Subject: V4L/DVB (10345): gspca - jpeg subdrivers: One quantization table per subdriver. Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/conex.c | 8 +- drivers/media/video/gspca/jpeg.h | 283 ++++++++++++++++++++---------------- drivers/media/video/gspca/mars.c | 9 +- drivers/media/video/gspca/sonixj.c | 5 +- drivers/media/video/gspca/spca500.c | 5 +- drivers/media/video/gspca/stk014.c | 10 +- drivers/media/video/gspca/sunplus.c | 7 +- drivers/media/video/gspca/zc3xx.c | 36 ++--- 8 files changed, 183 insertions(+), 180 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/gspca/conex.c b/drivers/media/video/gspca/conex.c index 2de8906e5661..de2e608bf5ba 100644 --- a/drivers/media/video/gspca/conex.c +++ b/drivers/media/video/gspca/conex.c @@ -23,6 +23,7 @@ #include "gspca.h" #define CONEX_CAM 1 /* special JPEG header */ +#define QUANT_VAL 0 /* quantization table */ #include "jpeg.h" MODULE_AUTHOR("Michel Xhaard "); @@ -36,8 +37,6 @@ struct sd { unsigned char brightness; unsigned char contrast; unsigned char colors; - - unsigned char qindex; }; /* V4L2 controls supported by the driver */ @@ -818,7 +817,6 @@ static int sd_config(struct gspca_dev *gspca_dev, cam->cam_mode = vga_mode; cam->nmodes = sizeof vga_mode / sizeof vga_mode[0]; - sd->qindex = 0; /* set the quantization */ sd->brightness = BRIGHTNESS_DEF; sd->contrast = CONTRAST_DEF; sd->colors = COLOR_DEF; @@ -882,9 +880,7 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, data, 0); /* put the JPEG header in the new frame */ - jpeg_put_header(gspca_dev, frame, - ((struct sd *) gspca_dev)->qindex, - 0x22); + jpeg_put_header(gspca_dev, frame, 0x22); data += 2; len -= 2; } diff --git a/drivers/media/video/gspca/jpeg.h b/drivers/media/video/gspca/jpeg.h index d823b47bd4e6..7d2df9720025 100644 --- a/drivers/media/video/gspca/jpeg.h +++ b/drivers/media/video/gspca/jpeg.h @@ -24,171 +24,207 @@ * */ -/* start of jpeg frame + quantization table */ -static const unsigned char quant[][0x88] = { -/* index 0 - Q40*/ - { +/* + * generation options + * CONEX_CAM Conexant if present + * QUANT_VAL quantization table (0..8) + */ + +/* + * JPEG header: + * - start of jpeg frame + * - quantization table + * - huffman table + * - start of SOF0 + */ +static const u8 jpeg_head[] = { 0xff, 0xd8, /* jpeg */ 0xff, 0xdb, 0x00, 0x84, /* DQT */ +#if QUANT_VAL == 0 +/* index 0 - Q40*/ 0, /* quantization table part 1 */ - 20, 14, 15, 18, 15, 13, 20, 18, 16, 18, 23, 21, 20, 24, 30, 50, - 33, 30, 28, 28, 30, 61, 44, 46, 36, 50, 73, 64, 76, 75, 71, 64, - 70, 69, 80, 90, 115, 98, 80, 85, 109, 86, 69, 70, 100, 136, 101, - 109, - 119, 123, 129, 130, 129, 78, 96, 141, 151, 140, 125, 150, 115, - 126, 129, 124, + 0x14, 0x0e, 0x0f, 0x12, 0x0f, 0x0d, 0x14, 0x12, + 0x10, 0x12, 0x17, 0x15, 0x14, 0x18, 0x1e, 0x32, + 0x21, 0x1e, 0x1c, 0x1c, 0x1e, 0x3d, 0x2c, 0x2e, + 0x24, 0x32, 0x49, 0x40, 0x4c, 0x4b, 0x47, 0x40, + 0x46, 0x45, 0x50, 0x5a, 0x73, 0x62, 0x50, 0x55, + 0x6d, 0x56, 0x45, 0x46, 0x64, 0x88, 0x65, 0x6d, + 0x77, 0x7b, 0x81, 0x82, 0x81, 0x4e, 0x60, 0x8d, + 0x97, 0x8c, 0x7d, 0x96, 0x73, 0x7e, 0x81, 0x7c, 1, /* quantization table part 2 */ - 21, 23, 23, 30, 26, 30, 59, 33, 33, 59, 124, 83, 70, 83, 124, 124, - 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, - 124, 124, 124, - 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, - 124, 124, 124, - 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, - 124, 124, 124}, + 0x15, 0x17, 0x17, 0x1e, 0x1a, 0x1e, 0x3b, 0x21, + 0x21, 0x3b, 0x7c, 0x53, 0x46, 0x53, 0x7c, 0x0c, + 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, + 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, + 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, + 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, + 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, + 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, +#elif QUANT_VAL == 1 /* index 1 - Q50 */ - { - 0xff, 0xd8, - 0xff, 0xdb, 0x00, 0x84, /* DQT */ 0, - 16, 11, 12, 14, 12, 10, 16, 14, 13, 14, 18, 17, 16, 19, 24, 40, - 26, 24, 22, 22, 24, 49, 35, 37, 29, 40, 58, 51, 61, 60, 57, 51, - 56, 55, 64, 72, 92, 78, 64, 68, 87, 69, 55, 56, 80, 109, 81, 87, - 95, 98, 103, 104, 103, 62, 77, 113, 121, 112, 100, 120, 92, 101, - 103, 99, + 0x10, 0x0b, 0x0c, 0x0e, 0x0c, 0x0a, 0x10, 0x0e, + 0x0d, 0x0e, 0x12, 0x11, 0x10, 0x13, 0x18, 0x28, + 0x1a, 0x18, 0x16, 0x16, 0x18, 0x31, 0x23, 0x25, + 0x1d, 0x28, 0x3a, 0x33, 0x3d, 0x3c, 0x39, 0x33, + 0x38, 0x37, 0x40, 0x48, 0x5c, 0x4e, 0x40, 0x44, + 0x57, 0x45, 0x37, 0x38, 0x50, 0x6d, 0x51, 0x57, + 0x5f, 0x62, 0x67, 0x68, 0x67, 0x3e, 0x4d, 0x71, + 0x79, 0x70, 0x64, 0x78, 0x5c, 0x65, 0x67, 0x63, 1, - 17, 18, 18, 24, 21, 24, 47, 26, 26, 47, 99, 66, 56, 66, 99, 99, - 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, - 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, - 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99}, + 0x11, 0x12, 0x12, 0x18, 0x15, 0x18, 0x2f, 0x1a, + 0x1a, 0x2f, 0x63, 0x42, 0x38, 0x42, 0x63, 0x63, + 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, + 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, + 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, + 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, + 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, + 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, +#elif QUANT_VAL == 2 /* index 2 Q60 */ - { - 0xff, 0xd8, - 0xff, 0xdb, 0x00, 0x84, /* DQT */ 0, - 13, 9, 10, 11, 10, 8, 13, 11, 10, 11, 14, 14, 13, 15, 19, 32, - 21, 19, 18, 18, 19, 39, 28, 30, 23, 32, 46, 41, 49, 48, 46, 41, - 45, 44, 51, 58, 74, 62, 51, 54, 70, 55, 44, 45, 64, 87, 65, 70, - 76, 78, 82, 83, 82, 50, 62, 90, 97, 90, 80, 96, 74, 81, 82, 79, + 0x0d, 0x09, 0x0a, 0x0b, 0x0a, 0x08, 0x0d, 0x0b, + 0x0a, 0x0b, 0x0e, 0x0e, 0x0d, 0x0f, 0x13, 0x20, + 0x15, 0x13, 0x12, 0x12, 0x13, 0x27, 0x1c, 0x1e, + 0x17, 0x20, 0x2e, 0x29, 0x31, 0x30, 0x2e, 0x29, + 0x2d, 0x2c, 0x33, 0x3a, 0x4a, 0x3e, 0x33, 0x36, + 0x46, 0x37, 0x2c, 0x2d, 0x40, 0x57, 0x41, 0x46, + 0x4c, 0x4e, 0x52, 0x53, 0x52, 0x32, 0x3e, 0x5a, + 0x61, 0x5a, 0x50, 0x60, 0x4a, 0x51, 0x52, 0x4f, 1, - 14, 14, 14, 19, 17, 19, 38, 21, 21, 38, 79, 53, 45, 53, 79, 79, - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79}, + 0x0e, 0x0e, 0x0e, 0x13, 0x11, 0x13, 0x26, 0x15, + 0x15, 0x26, 0x4f, 0x35, 0x2d, 0x35, 0x4f, 0x4f, + 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, + 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, + 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, + 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, + 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, + 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, +#elif QUANT_VAL == 3 /* index 3 - Q70 */ - { - 0xff, 0xd8, - 0xff, 0xdb, 0x00, 0x84, /* DQT */ 0, - 10, 7, 7, 8, 7, 6, 10, 8, 8, 8, 11, 10, 10, 11, 14, 24, - 16, 14, 13, 13, 14, 29, 21, 22, 17, 24, 35, 31, 37, 36, 34, 31, - 34, 33, 38, 43, 55, 47, 38, 41, 52, 41, 33, 34, 48, 65, 49, 52, - 57, 59, 62, 62, 62, 37, 46, 68, 73, 67, 60, 72, 55, 61, 62, 59, + 0x0a, 0x07, 0x07, 0x08, 0x07, 0x06, 0x0a, 0x08, + 0x08, 0x08, 0x0b, 0x0a, 0x0a, 0x0b, 0x0e, 0x18, + 0x10, 0x0e, 0x0d, 0x0d, 0x0e, 0x1d, 0x15, 0x16, + 0x11, 0x18, 0x23, 0x1f, 0x25, 0x24, 0x22, 0x1f, + 0x22, 0x21, 0x26, 0x2b, 0x37, 0x2f, 0x26, 0x29, + 0x34, 0x29, 0x21, 0x22, 0x30, 0x41, 0x31, 0x34, + 0x39, 0x3b, 0x3e, 0x3e, 0x3e, 0x25, 0x2e, 0x44, + 0x49, 0x43, 0x3c, 0x48, 0x37, 0x3d, 0x3e, 0x3b, 1, - 10, 11, 11, 14, 13, 14, 28, 16, 16, 28, 59, 40, 34, 40, 59, 59, - 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, - 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, - 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59}, + 0x0a, 0x0b, 0x0b, 0x0e, 0x0d, 0x0e, 0x1c, 0x10, + 0x10, 0x1c, 0x3b, 0x28, 0x22, 0x28, 0x3b, 0x3b, + 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, + 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, + 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, + 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, + 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, + 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, +#elif QUANT_VAL == 4 /* index 4 - Q80 */ - { - 0xff, 0xd8, - 0xff, 0xdb, 0x00, 0x84, /* DQT */ 0, - 6, 4, 5, 6, 5, 4, 6, 6, 5, 6, 7, 7, 6, 8, 10, 16, - 10, 10, 9, 9, 10, 20, 14, 15, 12, 16, 23, 20, 24, 24, 23, 20, - 22, 22, 26, 29, 37, 31, 26, 27, 35, 28, 22, 22, 32, 44, 32, 35, - 38, 39, 41, 42, 41, 25, 31, 45, 48, 45, 40, 48, 37, 40, 41, 40, + 0x06, 0x04, 0x05, 0x06, 0x05, 0x04, 0x06, 0x06, + 0x05, 0x06, 0x07, 0x07, 0x06, 0x08, 0x0a, 0x10, + 0x0a, 0x0a, 0x09, 0x09, 0x0a, 0x14, 0x0e, 0x0f, + 0x0c, 0x10, 0x17, 0x14, 0x18, 0x18, 0x17, 0x14, + 0x16, 0x16, 0x1a, 0x1d, 0x25, 0x1f, 0x1a, 0x1b, + 0x23, 0x1c, 0x16, 0x16, 0x20, 0x2c, 0x20, 0x23, + 0x26, 0x27, 0x29, 0x2a, 0x29, 0x19, 0x1f, 0x2d, + 0x30, 0x2d, 0x28, 0x30, 0x25, 0x28, 0x29, 0x28, 1, - 7, 7, 7, 10, 8, 10, 19, 10, 10, 19, 40, 26, 22, 26, 40, 40, - 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, - 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, - 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40}, + 0x07, 0x07, 0x07, 0x0a, 0x08, 0x0a, 0x13, 0x0a, + 0x0a, 0x13, 0x28, 0x1a, 0x16, 0x1a, 0x28, 0x28, + 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, + 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, + 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, + 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, + 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, + 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, +#elif QUANT_VAL == 5 /* index 5 - Q85 */ - { - 0xff, 0xd8, - 0xff, 0xdb, 0x00, 0x84, /* DQT */ 0, - 5, 3, 4, 4, 4, 3, 5, 4, 4, 4, 5, 5, 5, 6, 7, 12, - 8, 7, 7, 7, 7, 15, 11, 11, 9, 12, 17, 15, 18, 18, 17, 15, - 17, 17, 19, 22, 28, 23, 19, 20, 26, 21, 17, 17, 24, 33, 24, 26, - 29, 29, 31, 31, 31, 19, 23, 34, 36, 34, 30, 36, 28, 30, 31, 30, + 0x05, 0x03, 0x04, 0x04, 0x04, 0x03, 0x05, 0x04, + 0x04, 0x04, 0x05, 0x05, 0x05, 0x06, 0x07, 0x0c, + 0x08, 0x07, 0x07, 0x07, 0x07, 0x0f, 0x0b, 0x0b, + 0x09, 0x0c, 0x11, 0x0f, 0x12, 0x12, 0x11, 0x0f, + 0x11, 0x11, 0x13, 0x16, 0x1c, 0x17, 0x13, 0x14, + 0x1a, 0x15, 0x11, 0x11, 0x18, 0x21, 0x18, 0x1a, + 0x1d, 0x1d, 0x1f, 0x1f, 0x1f, 0x13, 0x17, 0x22, + 0x24, 0x22, 0x1e, 0x24, 0x1c, 0x1e, 0x1f, 0x1e, 1, - 5, 5, 5, 7, 6, 7, 14, 8, 8, 14, 30, 20, 17, 20, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30}, + 0x05, 0x05, 0x05, 0x07, 0x06, 0x07, 0x0e, 0x08, + 0x08, 0x0e, 0x1e, 0x14, 0x11, 0x14, 0x1e, 0x1e, + 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, + 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, + 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, + 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, + 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, + 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, +#elif QUANT_VAL == 6 /* index 6 - 86 */ -{ - 0xff, 0xd8, - 0xff, 0xdb, 0x00, 0x84, /* DQT */ 0, 0x04, 0x03, 0x03, 0x04, 0x03, 0x03, 0x04, 0x04, 0x04, 0x04, 0x05, 0x05, 0x04, 0x05, 0x07, 0x0B, - 0x07, 0x07, 0x06, 0x06, 0x07, 0x0E, 0x0A, 0x0A, - 0x08, 0x0B, 0x10, 0x0E, 0x11, 0x11, 0x10, 0x0E, - 0x10, 0x0F, 0x12, 0x14, 0x1A, 0x16, 0x12, 0x13, - 0x18, 0x13, 0x0F, 0x10, 0x16, 0x1F, 0x17, 0x18, - 0x1B, 0x1B, 0x1D, 0x1D, 0x1D, 0x11, 0x16, 0x20, - 0x22, 0x1F, 0x1C, 0x22, 0x1A, 0x1C, 0x1D, 0x1C, + 0x07, 0x07, 0x06, 0x06, 0x07, 0x0e, 0x0a, 0x0a, + 0x08, 0x0B, 0x10, 0x0e, 0x11, 0x11, 0x10, 0x0e, + 0x10, 0x0f, 0x12, 0x14, 0x1a, 0x16, 0x12, 0x13, + 0x18, 0x13, 0x0f, 0x10, 0x16, 0x1f, 0x17, 0x18, + 0x1b, 0x1b, 0x1d, 0x1d, 0x1d, 0x11, 0x16, 0x20, + 0x22, 0x1f, 0x1c, 0x22, 0x1a, 0x1c, 0x1d, 0x1c, 1, 0x05, 0x05, 0x05, 0x07, 0x06, 0x07, 0x0D, 0x07, - 0x07, 0x0D, 0x1C, 0x12, 0x10, 0x12, 0x1C, 0x1C, - 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, - 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, - 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, - 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, - 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, - 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, - }, + 0x07, 0x0D, 0x1c, 0x12, 0x10, 0x12, 0x1c, 0x1c, + 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, + 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, + 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, + 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, + 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, + 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, +#elif QUANT_VAL == 7 /* index 7 - 88 */ -{ - 0xff, 0xd8, - 0xff, 0xdb, 0x00, 0x84, /* DQT */ 0, 0x04, 0x03, 0x03, 0x03, 0x03, 0x02, 0x04, 0x03, - 0x03, 0x03, 0x04, 0x04, 0x04, 0x05, 0x06, 0x0A, + 0x03, 0x03, 0x04, 0x04, 0x04, 0x05, 0x06, 0x0a, 0x06, 0x06, 0x05, 0x05, 0x06, 0x0C, 0x08, 0x09, - 0x07, 0x0A, 0x0E, 0x0C, 0x0F, 0x0E, 0x0E, 0x0C, - 0x0D, 0x0D, 0x0F, 0x11, 0x16, 0x13, 0x0F, 0x10, - 0x15, 0x11, 0x0D, 0x0D, 0x13, 0x1A, 0x13, 0x15, - 0x17, 0x18, 0x19, 0x19, 0x19, 0x0F, 0x12, 0x1B, - 0x1D, 0x1B, 0x18, 0x1D, 0x16, 0x18, 0x19, 0x18, + 0x07, 0x0a, 0x0e, 0x0c, 0x0f, 0x0e, 0x0e, 0x0c, + 0x0d, 0x0d, 0x0f, 0x11, 0x16, 0x13, 0x0f, 0x10, + 0x15, 0x11, 0x0d, 0x0d, 0x13, 0x1a, 0x13, 0x15, + 0x17, 0x18, 0x19, 0x19, 0x19, 0x0f, 0x12, 0x1b, + 0x1d, 0x1b, 0x18, 0x1d, 0x16, 0x18, 0x19, 0x18, 1, 0x04, 0x04, 0x04, 0x06, 0x05, 0x06, 0x0B, 0x06, - 0x06, 0x0B, 0x18, 0x10, 0x0D, 0x10, 0x18, 0x18, + 0x06, 0x0B, 0x18, 0x10, 0x0d, 0x10, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, -}, +#elif QUANT_VAL == 8 /* index 8 - ?? */ -{ - 0xff, 0xd8, - 0xff, 0xdb, 0x00, 0x84, /* DQT */ 0, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x03, 0x05, 0x03, 0x03, 0x03, 0x03, 0x03, 0x06, 0x04, 0x05, 0x04, 0x05, 0x07, 0x06, 0x08, 0x08, 0x07, 0x06, - 0x07, 0x07, 0x08, 0x09, 0x0C, 0x0A, 0x08, 0x09, - 0x0B, 0x09, 0x07, 0x07, 0x0A, 0x0E, 0x0A, 0x0B, - 0x0C, 0x0C, 0x0D, 0x0D, 0x0D, 0x08, 0x0A, 0x0E, - 0x0F, 0x0E, 0x0D, 0x0F, 0x0C, 0x0D, 0x0D, 0x0C, + 0x07, 0x07, 0x08, 0x09, 0x0c, 0x0a, 0x08, 0x09, + 0x0B, 0x09, 0x07, 0x07, 0x0a, 0x0e, 0x0a, 0x0b, + 0x0c, 0x0c, 0x0d, 0x0d, 0x0d, 0x08, 0x0a, 0x0e, + 0x0f, 0x0e, 0x0d, 0x0f, 0x0c, 0x0d, 0x0d, 0x0c, 1, 0x02, 0x02, 0x02, 0x03, 0x03, 0x03, 0x06, 0x03, - 0x03, 0x06, 0x0C, 0x08, 0x07, 0x08, 0x0C, 0x0C, - 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, - 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, - 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, - 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, - 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, - 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C -} -}; + 0x03, 0x06, 0x0c, 0x08, 0x07, 0x08, 0x0c, 0x0c, + 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, + 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, + 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, + 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, + 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, + 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, +#else +#error "Invalid quantization table" +#endif -/* huffman table + start of SOF0 */ -static unsigned char huffman[] = { +/* huffman table */ 0xff, 0xc4, 0x01, 0xa2, 0x00, 0x00, 0x01, 0x05, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, @@ -260,7 +296,7 @@ static unsigned char huffman[] = { */ /* end of header */ -static unsigned char eoh[] = { +static u8 eoh[] = { 0x00, /* quant Y */ 0x02, 0x11, 0x01, /* samples CbCr - quant CbCr */ 0x03, 0x11, 0x01, @@ -273,17 +309,14 @@ static unsigned char eoh[] = { /* -- output the JPEG header -- */ static void jpeg_put_header(struct gspca_dev *gspca_dev, struct gspca_frame *frame, - int qindex, int samplesY) { #ifndef CONEX_CAM - unsigned char tmpbuf[8]; + u8 tmpbuf[8]; #endif gspca_frame_add(gspca_dev, FIRST_PACKET, frame, - (unsigned char *) quant[qindex], sizeof quant[0]); - gspca_frame_add(gspca_dev, INTER_PACKET, frame, - (unsigned char *) huffman, sizeof huffman); + jpeg_head, sizeof jpeg_head); #ifndef CONEX_CAM tmpbuf[0] = gspca_dev->height >> 8; tmpbuf[1] = gspca_dev->height & 0xff; diff --git a/drivers/media/video/gspca/mars.c b/drivers/media/video/gspca/mars.c index 477441e22bab..54c68ea7e546 100644 --- a/drivers/media/video/gspca/mars.c +++ b/drivers/media/video/gspca/mars.c @@ -22,6 +22,7 @@ #define MODULE_NAME "mars" #include "gspca.h" +#define QUANT_VAL 1 /* quantization table */ #include "jpeg.h" MODULE_AUTHOR("Michel Xhaard "); @@ -31,8 +32,6 @@ MODULE_LICENSE("GPL"); /* specific webcam descriptor */ struct sd { struct gspca_dev gspca_dev; /* !! must be the first item */ - - char qindex; }; /* V4L2 controls supported by the driver */ @@ -117,13 +116,11 @@ static void bulk_w(struct gspca_dev *gspca_dev, static int sd_config(struct gspca_dev *gspca_dev, const struct usb_device_id *id) { - struct sd *sd = (struct sd *) gspca_dev; struct cam *cam; cam = &gspca_dev->cam; cam->cam_mode = vga_mode; cam->nmodes = ARRAY_SIZE(vga_mode); - sd->qindex = 1; /* set the quantization table */ return 0; } @@ -345,7 +342,6 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, __u8 *data, /* isoc packet */ int len) /* iso packet length */ { - struct sd *sd = (struct sd *) gspca_dev; int p; if (len < 6) { @@ -368,8 +364,7 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, frame, data, 0); /* put the JPEG header */ - jpeg_put_header(gspca_dev, frame, - sd->qindex, 0x21); + jpeg_put_header(gspca_dev, frame, 0x21); data += 16; len -= 16; break; diff --git a/drivers/media/video/gspca/sonixj.c b/drivers/media/video/gspca/sonixj.c index 755ca302368e..51d68d35aa73 100644 --- a/drivers/media/video/gspca/sonixj.c +++ b/drivers/media/video/gspca/sonixj.c @@ -22,6 +22,7 @@ #define MODULE_NAME "sonixj" #include "gspca.h" +#define QUANT_VAL 4 /* quantization table */ #include "jpeg.h" #define V4L2_CID_INFRARED (V4L2_CID_PRIVATE_BASE + 0) @@ -49,7 +50,6 @@ struct sd { __s8 ag_cnt; #define AG_CNT_START 13 - __u8 qindex; __u8 bridge; #define BRIDGE_SN9C102P 0 #define BRIDGE_SN9C105 1 @@ -1025,7 +1025,6 @@ static int sd_config(struct gspca_dev *gspca_dev, sd->sensor = id->driver_info >> 8; sd->i2c_base = id->driver_info; - sd->qindex = 4; /* set the quantization table */ sd->brightness = BRIGHTNESS_DEF; sd->contrast = CONTRAST_DEF; sd->colors = COLOR_DEF; @@ -1549,7 +1548,7 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, if (gspca_dev->last_packet_type == LAST_PACKET) { /* put the JPEG 422 header */ - jpeg_put_header(gspca_dev, frame, sd->qindex, 0x21); + jpeg_put_header(gspca_dev, frame, 0x21); } gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len); } diff --git a/drivers/media/video/gspca/spca500.c b/drivers/media/video/gspca/spca500.c index 5450c3c4274b..e00f3b53bdff 100644 --- a/drivers/media/video/gspca/spca500.c +++ b/drivers/media/video/gspca/spca500.c @@ -22,6 +22,7 @@ #define MODULE_NAME "spca500" #include "gspca.h" +#define QUANT_VAL 5 /* quantization table */ #include "jpeg.h" MODULE_AUTHOR("Michel Xhaard "); @@ -39,7 +40,6 @@ struct sd { unsigned char contrast; unsigned char colors; - char qindex; char subtype; #define AgfaCl20 0 #define AiptekPocketDV 1 @@ -637,7 +637,6 @@ static int sd_config(struct gspca_dev *gspca_dev, cam->cam_mode = sif_mode; cam->nmodes = ARRAY_SIZE(sif_mode); } - sd->qindex = 5; sd->brightness = BRIGHTNESS_DEF; sd->contrast = CONTRAST_DEF; sd->colors = COLOR_DEF; @@ -900,7 +899,7 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, ffd9, 2); /* put the JPEG header in the new frame */ - jpeg_put_header(gspca_dev, frame, sd->qindex, 0x22); + jpeg_put_header(gspca_dev, frame, 0x22); data += SPCA500_OFFSET_DATA; len -= SPCA500_OFFSET_DATA; diff --git a/drivers/media/video/gspca/stk014.c b/drivers/media/video/gspca/stk014.c index ba31eb318652..d1d54edd80bd 100644 --- a/drivers/media/video/gspca/stk014.c +++ b/drivers/media/video/gspca/stk014.c @@ -21,6 +21,8 @@ #define MODULE_NAME "stk014" #include "gspca.h" +#define QUANT_VAL 7 /* quantization table */ + /* <= 4 KO - 7: good (enough!) */ #include "jpeg.h" MODULE_AUTHOR("Jean-Francois Moine "); @@ -37,9 +39,6 @@ struct sd { unsigned char lightfreq; }; -/* global parameters */ -static int sd_quant = 7; /* <= 4 KO - 7: good (enough!) */ - /* V4L2 controls supported by the driver */ static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val); static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val); @@ -418,7 +417,7 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, ffd9, 2); /* put the JPEG 411 header */ - jpeg_put_header(gspca_dev, frame, sd_quant, 0x22); + jpeg_put_header(gspca_dev, frame, 0x22); /* beginning of the frame */ #define STKHDRSZ 12 @@ -575,6 +574,3 @@ static void __exit sd_mod_exit(void) module_init(sd_mod_init); module_exit(sd_mod_exit); - -module_param_named(quant, sd_quant, int, 0644); -MODULE_PARM_DESC(quant, "Quantization index (0..8)"); diff --git a/drivers/media/video/gspca/sunplus.c b/drivers/media/video/gspca/sunplus.c index d9c9c440f020..2c0b6c3c8760 100644 --- a/drivers/media/video/gspca/sunplus.c +++ b/drivers/media/video/gspca/sunplus.c @@ -22,6 +22,7 @@ #define MODULE_NAME "sunplus" #include "gspca.h" +#define QUANT_VAL 5 /* quantization table */ #include "jpeg.h" MODULE_AUTHOR("Michel Xhaard "); @@ -40,7 +41,6 @@ struct sd { unsigned char colors; unsigned char autogain; - char qindex; char bridge; #define BRIDGE_SPCA504 0 #define BRIDGE_SPCA504B 1 @@ -849,7 +849,6 @@ static int sd_config(struct gspca_dev *gspca_dev, cam->nmodes = sizeof vga_mode2 / sizeof vga_mode2[0]; break; } - sd->qindex = 5; /* set the quantization table */ sd->brightness = sd_ctrls[SD_BRIGHTNESS].qctrl.default_value; sd->contrast = sd_ctrls[SD_CONTRAST].qctrl.default_value; sd->colors = sd_ctrls[SD_COLOR].qctrl.default_value; @@ -1154,9 +1153,7 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, ffd9, 2); /* put the JPEG header in the new frame */ - jpeg_put_header(gspca_dev, frame, - ((struct sd *) gspca_dev)->qindex, - 0x22); + jpeg_put_header(gspca_dev, frame, 0x22); } /* add 0x00 after 0xff */ diff --git a/drivers/media/video/gspca/zc3xx.c b/drivers/media/video/gspca/zc3xx.c index 2482f9163adb..226aafc9688d 100644 --- a/drivers/media/video/gspca/zc3xx.c +++ b/drivers/media/video/gspca/zc3xx.c @@ -31,6 +31,7 @@ MODULE_LICENSE("GPL"); static int force_sensor = -1; +#define QUANT_VAL 1 /* quantization table */ #include "jpeg.h" #include "zc3xx-reg.h" @@ -45,7 +46,6 @@ struct sd { __u8 lightfreq; __u8 sharpness; - char qindex; signed char sensor; /* Type of image sensor chip */ /* !! values used in different tables */ #define SENSOR_CS2102 0 @@ -6536,7 +6536,6 @@ static void setquality(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; struct usb_device *dev = gspca_dev->dev; - __u8 quality; __u8 frxt; switch (sd->sensor) { @@ -6547,26 +6546,18 @@ static void setquality(struct gspca_dev *gspca_dev) return; } /*fixme: is it really 0008 0007 0018 for all other sensors? */ - quality = sd->qindex; - reg_w(dev, quality, 0x0008); + reg_w(dev, QUANT_VAL, 0x0008); frxt = 0x30; reg_w(dev, frxt, 0x0007); - switch (quality) { - case 0: - case 1: - case 2: - frxt = 0xff; - break; - case 3: - frxt = 0xf0; - break; - case 4: - frxt = 0xe0; - break; - case 5: - frxt = 0x20; - break; - } +#if QUANT_VAL == 0 || QUANT_VAL == 1 || QUANT_VAL == 2 + frxt = 0xff; +#elif QUANT_VAL == 3 + frxt = 0xf0; +#elif QUANT_VAL == 4 + frxt = 0xe0; +#else + frxt = 0x20; +#endif reg_w(dev, frxt, 0x0018); } @@ -7156,7 +7147,6 @@ static int sd_config(struct gspca_dev *gspca_dev, cam->cam_mode = sif_mode; cam->nmodes = ARRAY_SIZE(sif_mode); } - sd->qindex = 1; sd->brightness = sd_ctrls[SD_BRIGHTNESS].qctrl.default_value; sd->contrast = sd_ctrls[SD_CONTRAST].qctrl.default_value; sd->gamma = gamma[(int) sd->sensor]; @@ -7358,9 +7348,7 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame, data, 0); /* put the JPEG header in the new frame */ - jpeg_put_header(gspca_dev, frame, - ((struct sd *) gspca_dev)->qindex, - 0x21); + jpeg_put_header(gspca_dev, frame, 0x21); /* remove the webcam's header: * ff d8 ff fe 00 0e 00 00 ss ss 00 01 ww ww hh hh pp pp * - 'ss ss' is the frame sequence number (BE) -- cgit v1.2.3 From 3ab67baf36c1f5356afb6424aca77866d91a6b5b Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Thu, 8 Jan 2009 09:38:45 -0300 Subject: V4L/DVB (10346): gspca - zc3xx: Fix bad variable type with i2c read. The returned value of i2c read is a 16 bits word. It was stored in a 8 bits variable, preventing a sensor to be detected. Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/zc3xx.c | 125 ++++++++++++++++++-------------------- 1 file changed, 59 insertions(+), 66 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/gspca/zc3xx.c b/drivers/media/video/gspca/zc3xx.c index 226aafc9688d..74eabce7b4ae 100644 --- a/drivers/media/video/gspca/zc3xx.c +++ b/drivers/media/video/gspca/zc3xx.c @@ -6237,7 +6237,7 @@ static const struct usb_action tas5130c_vf0250_NoFlikerScale[] = { {} }; -static int reg_r_i(struct gspca_dev *gspca_dev, +static u8 reg_r_i(struct gspca_dev *gspca_dev, __u16 index) { usb_control_msg(gspca_dev->dev, @@ -6250,10 +6250,10 @@ static int reg_r_i(struct gspca_dev *gspca_dev, return gspca_dev->usb_buf[0]; } -static int reg_r(struct gspca_dev *gspca_dev, +static u8 reg_r(struct gspca_dev *gspca_dev, __u16 index) { - int ret; + u8 ret; ret = reg_r_i(gspca_dev, index); PDEBUG(D_USBI, "reg r [%04x] -> %02x", index, ret); @@ -6734,26 +6734,25 @@ static int sif_probe(struct gspca_dev *gspca_dev) static int vga_2wr_probe(struct gspca_dev *gspca_dev) { struct usb_device *dev = gspca_dev->dev; - __u8 retbyte; - __u16 checkword; + u16 retword; start_2wr_probe(dev, 0x00); /* HV7131B */ i2c_write(gspca_dev, 0x01, 0xaa, 0x00); - retbyte = i2c_read(gspca_dev, 0x01); - if (retbyte != 0) + retword = i2c_read(gspca_dev, 0x01); + if (retword != 0) return 0x00; /* HV7131B */ start_2wr_probe(dev, 0x04); /* CS2102 */ i2c_write(gspca_dev, 0x01, 0xaa, 0x00); - retbyte = i2c_read(gspca_dev, 0x01); - if (retbyte != 0) + retword = i2c_read(gspca_dev, 0x01); + if (retword != 0) return 0x04; /* CS2102 */ start_2wr_probe(dev, 0x06); /* OmniVision */ reg_w(dev, 0x08, 0x008d); i2c_write(gspca_dev, 0x11, 0xaa, 0x00); - retbyte = i2c_read(gspca_dev, 0x11); - if (retbyte != 0) { + retword = i2c_read(gspca_dev, 0x11); + if (retword != 0) { /* (should have returned 0xaa) --> Omnivision? */ /* reg_r 0x10 -> 0x06 --> */ goto ov_check; @@ -6761,40 +6760,40 @@ static int vga_2wr_probe(struct gspca_dev *gspca_dev) start_2wr_probe(dev, 0x08); /* HDCS2020 */ i2c_write(gspca_dev, 0x15, 0xaa, 0x00); - retbyte = i2c_read(gspca_dev, 0x15); - if (retbyte != 0) + retword = i2c_read(gspca_dev, 0x15); + if (retword != 0) return 0x08; /* HDCS2020 */ start_2wr_probe(dev, 0x0a); /* PB0330 */ i2c_write(gspca_dev, 0x07, 0xaa, 0xaa); - retbyte = i2c_read(gspca_dev, 0x07); - if (retbyte != 0) + retword = i2c_read(gspca_dev, 0x07); + if (retword != 0) return 0x0a; /* PB0330 */ - retbyte = i2c_read(gspca_dev, 0x03); - if (retbyte != 0) + retword = i2c_read(gspca_dev, 0x03); + if (retword != 0) return 0x0a; /* PB0330 ?? */ - retbyte = i2c_read(gspca_dev, 0x04); - if (retbyte != 0) + retword = i2c_read(gspca_dev, 0x04); + if (retword != 0) return 0x0a; /* PB0330 ?? */ start_2wr_probe(dev, 0x0c); /* ICM105A */ i2c_write(gspca_dev, 0x01, 0x11, 0x00); - retbyte = i2c_read(gspca_dev, 0x01); - if (retbyte != 0) + retword = i2c_read(gspca_dev, 0x01); + if (retword != 0) return 0x0c; /* ICM105A */ start_2wr_probe(dev, 0x0e); /* PAS202BCB */ reg_w(dev, 0x08, 0x008d); i2c_write(gspca_dev, 0x03, 0xaa, 0x00); msleep(500); - retbyte = i2c_read(gspca_dev, 0x03); - if (retbyte != 0) + retword = i2c_read(gspca_dev, 0x03); + if (retword != 0) return 0x0e; /* PAS202BCB */ start_2wr_probe(dev, 0x02); /* ?? */ i2c_write(gspca_dev, 0x01, 0xaa, 0x00); - retbyte = i2c_read(gspca_dev, 0x01); - if (retbyte != 0) + retword = i2c_read(gspca_dev, 0x01); + if (retword != 0) return 0x02; /* ?? */ ov_check: reg_r(gspca_dev, 0x0010); /* ?? */ @@ -6808,12 +6807,10 @@ ov_check: msleep(500); reg_w(dev, 0x01, 0x0012); i2c_write(gspca_dev, 0x12, 0x80, 0x00); /* sensor reset */ - retbyte = i2c_read(gspca_dev, 0x0a); - checkword = retbyte << 8; - retbyte = i2c_read(gspca_dev, 0x0b); - checkword |= retbyte; - PDEBUG(D_PROBE, "probe 2wr ov vga 0x%04x", checkword); - switch (checkword) { + retword = i2c_read(gspca_dev, 0x0a) << 8; + retword |= i2c_read(gspca_dev, 0x0b); + PDEBUG(D_PROBE, "probe 2wr ov vga 0x%04x", retword); + switch (retword) { case 0x7631: /* OV7630C */ reg_w(dev, 0x06, 0x0010); break; @@ -6823,7 +6820,7 @@ ov_check: default: return -1; /* not OmniVision */ } - return checkword; + return retword; } struct sensor_by_chipset_revision { @@ -6844,7 +6841,7 @@ static int vga_3wr_probe(struct gspca_dev *gspca_dev) struct usb_device *dev = gspca_dev->dev; int i; __u8 retbyte; - __u16 checkword; + u16 retword; /*fixme: lack of 8b=b3 (11,12)-> 10, 8b=e0 (14,15,16)-> 12 found in gspcav1*/ reg_w(dev, 0x02, 0x0010); @@ -6856,27 +6853,25 @@ static int vga_3wr_probe(struct gspca_dev *gspca_dev) reg_w(dev, 0x03, 0x0012); reg_w(dev, 0x01, 0x0012); reg_w(dev, 0x05, 0x0012); - retbyte = i2c_read(gspca_dev, 0x14); - if (retbyte != 0) + retword = i2c_read(gspca_dev, 0x14); + if (retword != 0) return 0x11; /* HV7131R */ - retbyte = i2c_read(gspca_dev, 0x15); - if (retbyte != 0) + retword = i2c_read(gspca_dev, 0x15); + if (retword != 0) return 0x11; /* HV7131R */ - retbyte = i2c_read(gspca_dev, 0x16); - if (retbyte != 0) + retword = i2c_read(gspca_dev, 0x16); + if (retword != 0) return 0x11; /* HV7131R */ reg_w(dev, 0x02, 0x0010); - retbyte = reg_r(gspca_dev, 0x000b); - checkword = retbyte << 8; - retbyte = reg_r(gspca_dev, 0x000a); - checkword |= retbyte; - PDEBUG(D_PROBE, "probe 3wr vga 1 0x%04x", checkword); + retword = reg_r(gspca_dev, 0x000b) << 8; + retword |= reg_r(gspca_dev, 0x000a); + PDEBUG(D_PROBE, "probe 3wr vga 1 0x%04x", retword); reg_r(gspca_dev, 0x0010); /* this is tested only once anyway */ for (i = 0; i < ARRAY_SIZE(chipset_revision_sensor); i++) { - if (chipset_revision_sensor[i].revision == checkword) { - sd->chip_revision = checkword; + if (chipset_revision_sensor[i].revision == retword) { + sd->chip_revision = retword; send_unknown(dev, SENSOR_PB0330); return chipset_revision_sensor[i].internal_sensor_id; } @@ -6888,8 +6883,8 @@ static int vga_3wr_probe(struct gspca_dev *gspca_dev) reg_w(dev, 0x0a, 0x0010); reg_w(dev, 0x03, 0x0012); reg_w(dev, 0x01, 0x0012); - retbyte = i2c_read(gspca_dev, 0x00); - if (retbyte != 0) { + retword = i2c_read(gspca_dev, 0x00); + if (retword != 0) { PDEBUG(D_PROBE, "probe 3wr vga type 0a ?"); return 0x0a; /* ?? */ } @@ -6901,14 +6896,14 @@ static int vga_3wr_probe(struct gspca_dev *gspca_dev) reg_w(dev, 0x03, 0x0012); msleep(2); reg_w(dev, 0x01, 0x0012); - retbyte = i2c_read(gspca_dev, 0x00); - if (retbyte != 0) { - PDEBUG(D_PROBE, "probe 3wr vga type %02x", retbyte); - if (retbyte == 0x11) /* VF0250 */ + retword = i2c_read(gspca_dev, 0x00); + if (retword != 0) { + PDEBUG(D_PROBE, "probe 3wr vga type %02x", retword); + if (retword == 0x0011) /* VF0250 */ return 0x0250; - if (retbyte == 0x29) /* gc0305 */ + if (retword == 0x0029) /* gc0305 */ send_unknown(dev, SENSOR_GC0305); - return retbyte; + return retword; } reg_w(dev, 0x01, 0x0000); /* check OmniVision */ @@ -6918,8 +6913,8 @@ static int vga_3wr_probe(struct gspca_dev *gspca_dev) reg_w(dev, 0x06, 0x0010); reg_w(dev, 0x01, 0x0012); reg_w(dev, 0x05, 0x0012); - if (i2c_read(gspca_dev, 0x1c) == 0x7f /* OV7610 - manufacturer ID */ - && i2c_read(gspca_dev, 0x1d) == 0xa2) { + if (i2c_read(gspca_dev, 0x1c) == 0x007f /* OV7610 - manufacturer ID */ + && i2c_read(gspca_dev, 0x1d) == 0x00a2) { send_unknown(dev, SENSOR_OV7620); return 0x06; /* OmniVision confirm ? */ } @@ -6933,16 +6928,14 @@ static int vga_3wr_probe(struct gspca_dev *gspca_dev) /* msleep(150); */ reg_w(dev, 0x01, 0x0012); reg_w(dev, 0x05, 0x0012); - retbyte = i2c_read(gspca_dev, 0x0000); /* ID 0 */ - checkword = retbyte << 8; - retbyte = i2c_read(gspca_dev, 0x0001); /* ID 1 */ - checkword |= retbyte; - PDEBUG(D_PROBE, "probe 3wr vga 2 0x%04x", checkword); - if (checkword == 0x2030) { + retword = i2c_read(gspca_dev, 0x00) << 8; /* ID 0 */ + retword |= i2c_read(gspca_dev, 0x01); /* ID 1 */ + PDEBUG(D_PROBE, "probe 3wr vga 2 0x%04x", retword); + if (retword == 0x2030) { retbyte = i2c_read(gspca_dev, 0x02); /* revision number */ PDEBUG(D_PROBE, "sensor PO2030 rev 0x%02x", retbyte); send_unknown(dev, SENSOR_PO2030); - return checkword; + return retword; } reg_w(dev, 0x01, 0x0000); @@ -6953,9 +6946,9 @@ static int vga_3wr_probe(struct gspca_dev *gspca_dev) reg_w(dev, 0x01, 0x0012); reg_w(dev, 0x05, 0x0001); reg_w(dev, 0xd3, 0x008b); - retbyte = i2c_read(gspca_dev, 0x01); - if (retbyte != 0) { - PDEBUG(D_PROBE, "probe 3wr vga type 0a ?"); + retword = i2c_read(gspca_dev, 0x01); + if (retword != 0) { + PDEBUG(D_PROBE, "probe 3wr vga type 0a ? ret: %04x", retword); return 0x0a; /* ?? */ } return -1; -- cgit v1.2.3 From a0306bfa011d86899f3e88d35b6ffe525271bafc Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Thu, 8 Jan 2009 16:29:38 -0300 Subject: V4L/DVB (10347): gspca - mars: Optimize, rewrite initialization and add controls. Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/mars.c | 435 ++++++++++++++++++++++----------------- 1 file changed, 243 insertions(+), 192 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/gspca/mars.c b/drivers/media/video/gspca/mars.c index 54c68ea7e546..e85ba1aa8bd3 100644 --- a/drivers/media/video/gspca/mars.c +++ b/drivers/media/video/gspca/mars.c @@ -32,16 +32,86 @@ MODULE_LICENSE("GPL"); /* specific webcam descriptor */ struct sd { struct gspca_dev gspca_dev; /* !! must be the first item */ + + u8 brightness; + u8 colors; + u8 gamma; + u8 sharpness; }; /* V4L2 controls supported by the driver */ +static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val); +static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val); +static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val); +static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val); +static int sd_setgamma(struct gspca_dev *gspca_dev, __s32 val); +static int sd_getgamma(struct gspca_dev *gspca_dev, __s32 *val); +static int sd_setsharpness(struct gspca_dev *gspca_dev, __s32 val); +static int sd_getsharpness(struct gspca_dev *gspca_dev, __s32 *val); + static struct ctrl sd_ctrls[] = { + { + { + .id = V4L2_CID_BRIGHTNESS, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "Brightness", + .minimum = 0, + .maximum = 30, + .step = 1, +#define BRIGHTNESS_DEF 15 + .default_value = BRIGHTNESS_DEF, + }, + .set = sd_setbrightness, + .get = sd_getbrightness, + }, + { + { + .id = V4L2_CID_SATURATION, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "Color", + .minimum = 0, + .maximum = 220, + .step = 1, +#define COLOR_DEF 190 + .default_value = COLOR_DEF, + }, + .set = sd_setcolors, + .get = sd_getcolors, + }, + { + { + .id = V4L2_CID_GAMMA, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "Gamma", + .minimum = 0, + .maximum = 3, + .step = 1, +#define GAMMA_DEF 1 + .default_value = GAMMA_DEF, + }, + .set = sd_setgamma, + .get = sd_getgamma, + }, + { + { + .id = V4L2_CID_SHARPNESS, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "Sharpness", + .minimum = 0, + .maximum = 2, + .step = 1, +#define SHARPNESS_DEF 1 + .default_value = SHARPNESS_DEF, + }, + .set = sd_setsharpness, + .get = sd_getsharpness, + }, }; static const struct v4l2_pix_format vga_mode[] = { {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, .bytesperline = 320, - .sizeimage = 320 * 240 * 3 / 8 + 589, + .sizeimage = 320 * 240 * 3 / 8 + 590, .colorspace = V4L2_COLORSPACE_JPEG, .priv = 2}, {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, @@ -51,76 +121,62 @@ static const struct v4l2_pix_format vga_mode[] = { .priv = 1}, }; -/* MI Register table //elvis */ -enum { - REG_HW_MI_0, - REG_HW_MI_1, - REG_HW_MI_2, - REG_HW_MI_3, - REG_HW_MI_4, - REG_HW_MI_5, - REG_HW_MI_6, - REG_HW_MI_7, - REG_HW_MI_9 = 0x09, - REG_HW_MI_B = 0x0B, - REG_HW_MI_C, - REG_HW_MI_D, - REG_HW_MI_1E = 0x1E, - REG_HW_MI_20 = 0x20, - REG_HW_MI_2B = 0x2B, - REG_HW_MI_2C, - REG_HW_MI_2D, - REG_HW_MI_2E, - REG_HW_MI_35 = 0x35, - REG_HW_MI_5F = 0x5f, - REG_HW_MI_60, - REG_HW_MI_61, - REG_HW_MI_62, - REG_HW_MI_63, - REG_HW_MI_64, - REG_HW_MI_F1 = 0xf1, - ATTR_TOTAL_MI_REG = 0xf2 +static const __u8 mi_data[0x20] = { +/* 01 02 03 04 05 06 07 08 */ + 0x48, 0x22, 0x01, 0x47, 0x10, 0x00, 0x00, 0x00, +/* 09 0a 0b 0c 0d 0e 0f 10 */ + 0x00, 0x01, 0x30, 0x01, 0x30, 0x01, 0x30, 0x01, +/* 11 12 13 14 15 16 17 18 */ + 0x30, 0x00, 0x04, 0x00, 0x06, 0x01, 0xe2, 0x02, +/* 19 1a 1b 1c 1d 1e 1f 20 */ + 0x82, 0x00, 0x20, 0x17, 0x80, 0x08, 0x0c, 0x00 }; -/* the bytes to write are in gspca_dev->usb_buf */ +/* write bytes from gspca_dev->usb_buf */ static int reg_w(struct gspca_dev *gspca_dev, - __u16 index, int len) + int len) { - int rc; - - rc = usb_control_msg(gspca_dev->dev, - usb_sndbulkpipe(gspca_dev->dev, 4), - 0x12, - 0xc8, /* ?? */ - 0, /* value */ - index, gspca_dev->usb_buf, len, 500); - if (rc < 0) - PDEBUG(D_ERR, "reg write [%02x] error %d", index, rc); - return rc; + int alen, ret; + + ret = usb_bulk_msg(gspca_dev->dev, + usb_sndbulkpipe(gspca_dev->dev, 4), + gspca_dev->usb_buf, + len, + &alen, + 500); /* timeout in milliseconds */ + if (ret < 0) + PDEBUG(D_ERR, "reg write [%02x] error %d", + gspca_dev->usb_buf[0], ret); + return ret; } -static void bulk_w(struct gspca_dev *gspca_dev, - __u16 *pch, - __u16 Address) +static void mi_w(struct gspca_dev *gspca_dev, + u8 addr, + u8 value) { gspca_dev->usb_buf[0] = 0x1f; gspca_dev->usb_buf[1] = 0; /* control byte */ - gspca_dev->usb_buf[2] = Address; - gspca_dev->usb_buf[3] = *pch >> 8; /* high byte */ - gspca_dev->usb_buf[4] = *pch; /* low byte */ + gspca_dev->usb_buf[2] = addr; + gspca_dev->usb_buf[3] = value; - reg_w(gspca_dev, Address, 5); + reg_w(gspca_dev, 4); } /* this function is called at probe time */ static int sd_config(struct gspca_dev *gspca_dev, const struct usb_device_id *id) { + struct sd *sd = (struct sd *) gspca_dev; struct cam *cam; cam = &gspca_dev->cam; cam->cam_mode = vga_mode; cam->nmodes = ARRAY_SIZE(vga_mode); + sd->brightness = BRIGHTNESS_DEF; + sd->colors = COLOR_DEF; + sd->gamma = GAMMA_DEF; + sd->sharpness = SHARPNESS_DEF; + gspca_dev->iface = 9; /* use the altsetting 08 */ return 0; } @@ -132,24 +188,16 @@ static int sd_init(struct gspca_dev *gspca_dev) static int sd_start(struct gspca_dev *gspca_dev) { + struct sd *sd = (struct sd *) gspca_dev; int err_code; - __u8 *data; - __u16 *MI_buf; - int h_size, v_size; - int intpipe; - - PDEBUG(D_STREAM, "camera start, iface %d, alt 8", gspca_dev->iface); - err_code = usb_set_interface(gspca_dev->dev, gspca_dev->iface, 8); - if (err_code < 0) { - PDEBUG(D_ERR|D_STREAM, "Set packet size: set interface error"); - return err_code; - } + u8 *data; + int i, val; data = gspca_dev->usb_buf; + data[0] = 0x01; /* address */ data[1] = 0x01; - - err_code = reg_w(gspca_dev, data[0], 2); + err_code = reg_w(gspca_dev, 2); if (err_code < 0) return err_code; @@ -159,30 +207,28 @@ static int sd_start(struct gspca_dev *gspca_dev) data[0] = 0x00; /* address */ data[1] = 0x0c | 0x01; /* reg 0 */ data[2] = 0x01; /* reg 1 */ - h_size = gspca_dev->width; - v_size = gspca_dev->height; - data[3] = h_size / 8; /* h_size , reg 2 */ - data[4] = v_size / 8; /* v_size , reg 3 */ + data[3] = gspca_dev->width / 8; /* h_size , reg 2 */ + data[4] = gspca_dev->height / 8; /* v_size , reg 3 */ data[5] = 0x30; /* reg 4, MI, PAS5101 : * 0x30 for 24mhz , 0x28 for 12mhz */ - data[6] = 4; /* reg 5, H start */ - data[7] = 0xc0; /* reg 6, gamma 1.5 */ - data[8] = 3; /* reg 7, V start */ + data[6] = 0x02; /* reg 5, H start - was 0x04 */ + data[7] = sd->gamma * 0x40; /* reg 0x06: gamma */ + data[8] = 0x01; /* reg 7, V start - was 0x03 */ /* if (h_size == 320 ) */ /* data[9]= 0x56; * reg 8, 24MHz, 2:1 scale down */ /* else */ data[9] = 0x52; /* reg 8, 24MHz, no scale down */ - data[10] = 0x5d; /* reg 9, I2C device address - * [for PAS5101 (0x40)] [for MI (0x5d)] */ +/*jfm: from win trace*/ + data[10] = 0x18; - err_code = reg_w(gspca_dev, data[0], 11); + err_code = reg_w(gspca_dev, 11); if (err_code < 0) return err_code; data[0] = 0x23; /* address */ data[1] = 0x09; /* reg 35, append frame header */ - err_code = reg_w(gspca_dev, data[0], 2); + err_code = reg_w(gspca_dev, 2); if (err_code < 0) return err_code; @@ -193,137 +239,55 @@ static int sd_start(struct gspca_dev *gspca_dev) /* else */ data[1] = 50; /* 50 reg 60, pc-cam frame size * (unit: 4KB) 200KB */ - err_code = reg_w(gspca_dev, data[0], 2); + err_code = reg_w(gspca_dev, 2); if (err_code < 0) return err_code; - if (0) { /* fixed dark-gain */ - data[1] = 0; /* reg 94, Y Gain (1.75) */ - data[2] = 0; /* reg 95, UV Gain (1.75) */ - data[3] = 0x3f; /* reg 96, Y Gain/UV Gain/disable - * auto dark-gain */ - data[4] = 0; /* reg 97, set fixed dark level */ - data[5] = 0; /* reg 98, don't care */ - } else { /* auto dark-gain */ - data[1] = 0; /* reg 94, Y Gain (auto) */ - data[2] = 0; /* reg 95, UV Gain (1.75) */ - data[3] = 0x78; /* reg 96, Y Gain/UV Gain/disable - * auto dark-gain */ - switch (gspca_dev->width) { -/* case 1280: */ -/* data[4] = 154; - * reg 97, %3 shadow point (unit: 256 pixel) */ -/* data[5] = 51; - * reg 98, %1 highlight point - * (uint: 256 pixel) */ -/* break; */ - default: -/* case 640: */ - data[4] = 36; /* reg 97, %3 shadow point - * (unit: 256 pixel) */ - data[5] = 12; /* reg 98, %1 highlight point - * (uint: 256 pixel) */ - break; - case 320: - data[4] = 9; /* reg 97, %3 shadow point - * (unit: 256 pixel) */ - data[5] = 3; /* reg 98, %1 highlight point - * (uint: 256 pixel) */ - break; - } - } /* auto dark-gain */ data[0] = 0x5e; /* address */ - - err_code = reg_w(gspca_dev, data[0], 6); + data[1] = 0; /* reg 94, Y Gain (auto) */ +/*jfm: from win trace*/ + val = sd->colors * 0x40 + 0x400; + data[2] = val; /* reg 0x5f/0x60 (LE) = saturation */ + data[3] = val >> 8; + data[4] = sd->brightness; /* reg 0x61 = brightness */ + data[5] = 0x00; + + err_code = reg_w(gspca_dev, 6); if (err_code < 0) return err_code; data[0] = 0x67; - data[1] = 0x13; /* reg 103, first pixel B, disable sharpness */ - err_code = reg_w(gspca_dev, data[0], 2); +/*jfm: from win trace*/ + data[1] = sd->sharpness * 4 + 3; + data[2] = 0x14; + err_code = reg_w(gspca_dev, 3); if (err_code < 0) return err_code; - /* - * initialize the value of MI sensor... - */ - MI_buf = kzalloc(ATTR_TOTAL_MI_REG * sizeof *MI_buf, GFP_KERNEL); - MI_buf[REG_HW_MI_1] = 0x000a; - MI_buf[REG_HW_MI_2] = 0x000c; - MI_buf[REG_HW_MI_3] = 0x0405; - MI_buf[REG_HW_MI_4] = 0x0507; - /* mi_Attr_Reg_[REG_HW_MI_5] = 0x01ff;//13 */ - MI_buf[REG_HW_MI_5] = 0x0013; /* 13 */ - MI_buf[REG_HW_MI_6] = 0x001f; /* vertical blanking */ - /* mi_Attr_Reg_[REG_HW_MI_6] = 0x0400; // vertical blanking */ - MI_buf[REG_HW_MI_7] = 0x0002; - /* mi_Attr_Reg_[REG_HW_MI_9] = 0x015f; */ - /* mi_Attr_Reg_[REG_HW_MI_9] = 0x030f; */ - MI_buf[REG_HW_MI_9] = 0x0374; - MI_buf[REG_HW_MI_B] = 0x0000; - MI_buf[REG_HW_MI_C] = 0x0000; - MI_buf[REG_HW_MI_D] = 0x0000; - MI_buf[REG_HW_MI_1E] = 0x8000; -/* mi_Attr_Reg_[REG_HW_MI_20] = 0x1104; */ - MI_buf[REG_HW_MI_20] = 0x1104; /* 0x111c; */ - MI_buf[REG_HW_MI_2B] = 0x0008; -/* mi_Attr_Reg_[REG_HW_MI_2C] = 0x000f; */ - MI_buf[REG_HW_MI_2C] = 0x001f; /* lita suggest */ - MI_buf[REG_HW_MI_2D] = 0x0008; - MI_buf[REG_HW_MI_2E] = 0x0008; - MI_buf[REG_HW_MI_35] = 0x0051; - MI_buf[REG_HW_MI_5F] = 0x0904; /* fail to write */ - MI_buf[REG_HW_MI_60] = 0x0000; - MI_buf[REG_HW_MI_61] = 0x0000; - MI_buf[REG_HW_MI_62] = 0x0498; - MI_buf[REG_HW_MI_63] = 0x0000; - MI_buf[REG_HW_MI_64] = 0x0000; - MI_buf[REG_HW_MI_F1] = 0x0001; - /* changing while setting up the different value of dx/dy */ - - if (gspca_dev->width != 1280) { - MI_buf[0x01] = 0x010a; - MI_buf[0x02] = 0x014c; - MI_buf[0x03] = 0x01e5; - MI_buf[0x04] = 0x0287; - } - MI_buf[0x20] = 0x1104; - - bulk_w(gspca_dev, MI_buf + 1, 1); - bulk_w(gspca_dev, MI_buf + 2, 2); - bulk_w(gspca_dev, MI_buf + 3, 3); - bulk_w(gspca_dev, MI_buf + 4, 4); - bulk_w(gspca_dev, MI_buf + 5, 5); - bulk_w(gspca_dev, MI_buf + 6, 6); - bulk_w(gspca_dev, MI_buf + 7, 7); - bulk_w(gspca_dev, MI_buf + 9, 9); - bulk_w(gspca_dev, MI_buf + 0x0b, 0x0b); - bulk_w(gspca_dev, MI_buf + 0x0c, 0x0c); - bulk_w(gspca_dev, MI_buf + 0x0d, 0x0d); - bulk_w(gspca_dev, MI_buf + 0x1e, 0x1e); - bulk_w(gspca_dev, MI_buf + 0x20, 0x20); - bulk_w(gspca_dev, MI_buf + 0x2b, 0x2b); - bulk_w(gspca_dev, MI_buf + 0x2c, 0x2c); - bulk_w(gspca_dev, MI_buf + 0x2d, 0x2d); - bulk_w(gspca_dev, MI_buf + 0x2e, 0x2e); - bulk_w(gspca_dev, MI_buf + 0x35, 0x35); - bulk_w(gspca_dev, MI_buf + 0x5f, 0x5f); - bulk_w(gspca_dev, MI_buf + 0x60, 0x60); - bulk_w(gspca_dev, MI_buf + 0x61, 0x61); - bulk_w(gspca_dev, MI_buf + 0x62, 0x62); - bulk_w(gspca_dev, MI_buf + 0x63, 0x63); - bulk_w(gspca_dev, MI_buf + 0x64, 0x64); - bulk_w(gspca_dev, MI_buf + 0xf1, 0xf1); - kfree(MI_buf); - - intpipe = usb_sndintpipe(gspca_dev->dev, 0); - err_code = usb_clear_halt(gspca_dev->dev, intpipe); + data[0] = 0x69; + data[1] = 0x2f; + data[2] = 0x28; + data[3] = 0x42; + err_code = reg_w(gspca_dev, 4); + if (err_code < 0) + return err_code; + + data[0] = 0x63; + data[1] = 0x07; + err_code = reg_w(gspca_dev, 2); +/*jfm: win trace - many writes here to reg 0x64*/ + if (err_code < 0) + return err_code; + + /* initialize the MI sensor */ + for (i = 0; i < sizeof mi_data; i++) + mi_w(gspca_dev, i + 1, mi_data[i]); data[0] = 0x00; data[1] = 0x4d; /* ISOC transfering enable... */ - reg_w(gspca_dev, data[0], 2); - return err_code; + reg_w(gspca_dev, 2); + return 0; } static void sd_stopN(struct gspca_dev *gspca_dev) @@ -332,7 +296,7 @@ static void sd_stopN(struct gspca_dev *gspca_dev) gspca_dev->usb_buf[0] = 1; gspca_dev->usb_buf[1] = 0; - result = reg_w(gspca_dev, gspca_dev->usb_buf[0], 2); + result = reg_w(gspca_dev, 2); if (result < 0) PDEBUG(D_ERR, "Camera Stop failed"); } @@ -358,7 +322,7 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, || data[5 + p] == 0x65 || data[5 + p] == 0x66 || data[5 + p] == 0x67) { - PDEBUG(D_PACK, "sof offset: %d leng: %d", + PDEBUG(D_PACK, "sof offset: %d len: %d", p, len); frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame, data, 0); @@ -374,6 +338,92 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len); } +static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val) +{ + struct sd *sd = (struct sd *) gspca_dev; + + sd->brightness = val; + if (gspca_dev->streaming) { + gspca_dev->usb_buf[0] = 0x61; + gspca_dev->usb_buf[1] = val; + reg_w(gspca_dev, 2); + } + return 0; +} + +static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val) +{ + struct sd *sd = (struct sd *) gspca_dev; + + *val = sd->brightness; + return 0; +} + +static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val) +{ + struct sd *sd = (struct sd *) gspca_dev; + + sd->colors = val; + if (gspca_dev->streaming) { + val = val * 0x40 + 0x400; + gspca_dev->usb_buf[0] = 0x5f; + gspca_dev->usb_buf[1] = val; + gspca_dev->usb_buf[2] = val >> 8; + reg_w(gspca_dev, 3); + } + return 0; +} + +static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val) +{ + struct sd *sd = (struct sd *) gspca_dev; + + *val = sd->colors; + return 0; +} + +static int sd_setgamma(struct gspca_dev *gspca_dev, __s32 val) +{ + struct sd *sd = (struct sd *) gspca_dev; + + sd->gamma = val; + if (gspca_dev->streaming) { + gspca_dev->usb_buf[0] = 0x06; + gspca_dev->usb_buf[1] = val * 0x40; + reg_w(gspca_dev, 2); + } + return 0; +} + +static int sd_getgamma(struct gspca_dev *gspca_dev, __s32 *val) +{ + struct sd *sd = (struct sd *) gspca_dev; + + *val = sd->gamma; + return 0; +} + +static int sd_setsharpness(struct gspca_dev *gspca_dev, __s32 val) +{ + struct sd *sd = (struct sd *) gspca_dev; + + sd->sharpness = val; + if (gspca_dev->streaming) { + gspca_dev->usb_buf[0] = 0x67; + gspca_dev->usb_buf[1] = val * 4 + 3; + reg_w(gspca_dev, 2); + } + return 0; +} + +static int sd_getsharpness(struct gspca_dev *gspca_dev, __s32 *val) +{ + struct sd *sd = (struct sd *) gspca_dev; + + *val = sd->sharpness; + return 0; +} + /* sub-driver description */ static const struct sd_desc sd_desc = { .name = MODULE_NAME, @@ -416,6 +466,7 @@ static struct usb_driver sd_driver = { static int __init sd_mod_init(void) { int ret; + ret = usb_register(&sd_driver); if (ret < 0) return ret; -- cgit v1.2.3 From 0a32ef3fc81fcebf679139534a9f806cb9ff538c Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Thu, 8 Jan 2009 16:30:58 -0300 Subject: V4L/DVB (10348): gspca - mars: Bad isoc packet scanning. Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/mars.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/gspca/mars.c b/drivers/media/video/gspca/mars.c index e85ba1aa8bd3..1eeac4041a61 100644 --- a/drivers/media/video/gspca/mars.c +++ b/drivers/media/video/gspca/mars.c @@ -325,12 +325,12 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, PDEBUG(D_PACK, "sof offset: %d len: %d", p, len); frame = gspca_frame_add(gspca_dev, LAST_PACKET, - frame, data, 0); + frame, data, p); /* put the JPEG header */ jpeg_put_header(gspca_dev, frame, 0x21); - data += 16; - len -= 16; + data += p + 16; + len -= p + 16; break; } } -- cgit v1.2.3 From ca5e578f503133a580fbd5bed39cecf1e3c6e3a2 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Fri, 9 Jan 2009 09:13:26 -0300 Subject: V4L/DVB (10350): gspca - tv8532: Cleanup code. Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/tv8532.c | 474 ++++++++++++++++--------------------- 1 file changed, 199 insertions(+), 275 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/gspca/tv8532.c b/drivers/media/video/gspca/tv8532.c index 86e4f0e3d917..97ffaa7f933c 100644 --- a/drivers/media/video/gspca/tv8532.c +++ b/drivers/media/video/gspca/tv8532.c @@ -31,7 +31,6 @@ struct sd { struct gspca_dev gspca_dev; /* !! must be the first item */ __u16 brightness; - __u16 contrast; __u8 packet; }; @@ -39,11 +38,8 @@ struct sd { /* V4L2 controls supported by the driver */ static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val); static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val); -static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val); -static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val); static struct ctrl sd_ctrls[] = { -#define SD_BRIGHTNESS 0 { { .id = V4L2_CID_BRIGHTNESS, @@ -52,25 +48,12 @@ static struct ctrl sd_ctrls[] = { .minimum = 1, .maximum = 0x2ff, .step = 1, - .default_value = 0x18f, +#define BRIGHTNESS_DEF 0x18f + .default_value = BRIGHTNESS_DEF, }, .set = sd_setbrightness, .get = sd_getbrightness, }, -#define SD_CONTRAST 1 - { - { - .id = V4L2_CID_CONTRAST, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "Contrast", - .minimum = 0, - .maximum = 0xffff, - .step = 1, - .default_value = 0x7fff, - }, - .set = sd_setcontrast, - .get = sd_getcontrast, - }, }; static const struct v4l2_pix_format sif_mode[] = { @@ -86,78 +69,64 @@ static const struct v4l2_pix_format sif_mode[] = { .priv = 0}, }; -/* - * Initialization data: this is the first set-up data written to the - * device (before the open data). - */ -#define TESTCLK 0x10 /* reg 0x2c -> 0x12 //10 */ -#define TESTCOMP 0x90 /* reg 0x28 -> 0x80 */ -#define TESTLINE 0x81 /* reg 0x29 -> 0x81 */ -#define QCIFLINE 0x41 /* reg 0x29 -> 0x81 */ -#define TESTPTL 0x14 /* reg 0x2D -> 0x14 */ -#define TESTPTH 0x01 /* reg 0x2E -> 0x01 */ -#define TESTPTBL 0x12 /* reg 0x2F -> 0x0a */ -#define TESTPTBH 0x01 /* reg 0x30 -> 0x01 */ -#define ADWIDTHL 0xe8 /* reg 0x0c -> 0xe8 */ -#define ADWIDTHH 0x03 /* reg 0x0d -> 0x03 */ -#define ADHEIGHL 0x90 /* reg 0x0e -> 0x91 //93 */ -#define ADHEIGHH 0x01 /* reg 0x0f -> 0x01 */ -#define EXPOL 0x8f /* reg 0x1c -> 0x8f */ -#define EXPOH 0x01 /* reg 0x1d -> 0x01 */ -#define ADCBEGINL 0x44 /* reg 0x10 -> 0x46 //47 */ -#define ADCBEGINH 0x00 /* reg 0x11 -> 0x00 */ -#define ADRBEGINL 0x0a /* reg 0x14 -> 0x0b //0x0c */ -#define ADRBEGINH 0x00 /* reg 0x15 -> 0x00 */ -#define TV8532_CMD_UPDATE 0x84 - -#define TV8532_EEprom_Add 0x03 -#define TV8532_EEprom_DataL 0x04 -#define TV8532_EEprom_DataM 0x05 -#define TV8532_EEprom_DataH 0x06 -#define TV8532_EEprom_TableLength 0x07 -#define TV8532_EEprom_Write 0x08 -#define TV8532_PART_CTRL 0x00 -#define TV8532_CTRL 0x01 -#define TV8532_CMD_EEprom_Open 0x30 -#define TV8532_CMD_EEprom_Close 0x29 -#define TV8532_UDP_UPDATE 0x31 -#define TV8532_GPIO 0x39 -#define TV8532_GPIO_OE 0x3B -#define TV8532_REQ_RegWrite 0x02 -#define TV8532_REQ_RegRead 0x03 - -#define TV8532_ADWIDTH_L 0x0C -#define TV8532_ADWIDTH_H 0x0D -#define TV8532_ADHEIGHT_L 0x0E -#define TV8532_ADHEIGHT_H 0x0F -#define TV8532_EXPOSURE 0x1C -#define TV8532_QUANT_COMP 0x28 -#define TV8532_MODE_PACKET 0x29 -#define TV8532_SETCLK 0x2C -#define TV8532_POINT_L 0x2D -#define TV8532_POINT_H 0x2E -#define TV8532_POINTB_L 0x2F -#define TV8532_POINTB_H 0x30 -#define TV8532_BUDGET_L 0x2A -#define TV8532_BUDGET_H 0x2B -#define TV8532_VID_L 0x34 -#define TV8532_VID_H 0x35 -#define TV8532_PID_L 0x36 -#define TV8532_PID_H 0x37 -#define TV8532_DeviceID 0x83 -#define TV8532_AD_SLOPE 0x91 -#define TV8532_AD_BITCTRL 0x94 -#define TV8532_AD_COLBEGIN_L 0x10 -#define TV8532_AD_COLBEGIN_H 0x11 -#define TV8532_AD_ROWBEGIN_L 0x14 -#define TV8532_AD_ROWBEGIN_H 0x15 - -static const __u32 tv_8532_eeprom_data[] = { -/* add dataL dataM dataH */ - 0x00010001, 0x01018011, 0x02050014, 0x0305001c, - 0x040d001e, 0x0505001f, 0x06050519, 0x0705011b, - 0x0805091e, 0x090d892e, 0x0a05892f, 0x0b050dd9, - 0x0c0509f1, 0 +/* TV-8532A (ICM532A) registers (LE) */ +#define R00_PART_CONTROL 0x00 +#define LATENT_CHANGE 0x80 +#define EXPO_CHANGE 0x04 +#define R01_TIMING_CONTROL_LOW 0x01 +#define CMD_EEprom_Open 0x30 +#define CMD_EEprom_Close 0x29 +#define R03_TABLE_ADDR 0x03 +#define R04_WTRAM_DATA_L 0x04 +#define R05_WTRAM_DATA_M 0x05 +#define R06_WTRAM_DATA_H 0x06 +#define R07_TABLE_LEN 0x07 +#define R08_RAM_WRITE_ACTION 0x08 +#define R0C_AD_WIDTHL 0x0c +#define R0D_AD_WIDTHH 0x0d +#define R0E_AD_HEIGHTL 0x0e +#define R0F_AD_HEIGHTH 0x0f +#define R10_AD_COL_BEGINL 0x10 +#define R11_AD_COL_BEGINH 0x11 +#define MIRROR 0x04 /* [10] */ +#define R14_AD_ROW_BEGINL 0x14 +#define R15_AD_ROWBEGINH 0x15 +#define R1C_AD_EXPOSE_TIMEL 0x1c +#define R28_QUANT 0x28 +#define R29_LINE 0x29 +#define R2C_POLARITY 0x2c +#define R2D_POINT 0x2d +#define R2E_POINTH 0x2e +#define R2F_POINTB 0x2f +#define R30_POINTBH 0x30 +#define R31_UPD 0x31 +#define R2A_HIGH_BUDGET 0x2a +#define R2B_LOW_BUDGET 0x2b +#define R34_VID 0x34 +#define R35_VIDH 0x35 +#define R36_PID 0x36 +#define R37_PIDH 0x37 +#define R39_Test1 0x39 /* GPIO */ +#define R3B_Test3 0x3B /* GPIO */ +#define R83_AD_IDH 0x83 +#define R91_AD_SLOPEREG 0x91 +#define R94_AD_BITCONTROL 0x94 + +static const u8 eeprom_data[][3] = { +/* dataH dataM dataL */ + {0x01, 0x00, 0x01}, + {0x01, 0x80, 0x11}, + {0x05, 0x00, 0x14}, + {0x05, 0x00, 0x1c}, + {0x0d, 0x00, 0x1e}, + {0x05, 0x00, 0x1f}, + {0x05, 0x05, 0x19}, + {0x05, 0x01, 0x1b}, + {0x05, 0x09, 0x1e}, + {0x0d, 0x89, 0x2e}, + {0x05, 0x89, 0x2f}, + {0x05, 0x0d, 0xd9}, + {0x05, 0x09, 0xf1}, }; static int reg_r(struct gspca_dev *gspca_dev, @@ -165,7 +134,7 @@ static int reg_r(struct gspca_dev *gspca_dev, { usb_control_msg(gspca_dev->dev, usb_rcvctrlpipe(gspca_dev->dev, 0), - TV8532_REQ_RegRead, + 0x03, USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 0, /* value */ index, gspca_dev->usb_buf, 1, @@ -174,27 +143,27 @@ static int reg_r(struct gspca_dev *gspca_dev, } /* write 1 byte */ -static void reg_w_1(struct gspca_dev *gspca_dev, +static void reg_w1(struct gspca_dev *gspca_dev, __u16 index, __u8 value) { gspca_dev->usb_buf[0] = value; usb_control_msg(gspca_dev->dev, usb_sndctrlpipe(gspca_dev->dev, 0), - TV8532_REQ_RegWrite, + 0x02, USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 0, /* value */ index, gspca_dev->usb_buf, 1, 500); } /* write 2 bytes */ -static void reg_w_2(struct gspca_dev *gspca_dev, - __u16 index, __u8 val1, __u8 val2) +static void reg_w2(struct gspca_dev *gspca_dev, + u16 index, u16 value) { - gspca_dev->usb_buf[0] = val1; - gspca_dev->usb_buf[1] = val2; + gspca_dev->usb_buf[0] = value; + gspca_dev->usb_buf[1] = value >> 8; usb_control_msg(gspca_dev->dev, usb_sndctrlpipe(gspca_dev->dev, 0), - TV8532_REQ_RegWrite, + 0x02, USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 0, /* value */ index, gspca_dev->usb_buf, 2, 500); @@ -202,32 +171,18 @@ static void reg_w_2(struct gspca_dev *gspca_dev, static void tv_8532WriteEEprom(struct gspca_dev *gspca_dev) { - int i = 0; - __u8 reg, data0, data1, data2; - - reg_w_1(gspca_dev, TV8532_GPIO, 0xb0); - reg_w_1(gspca_dev, TV8532_CTRL, TV8532_CMD_EEprom_Open); -/* msleep(1); */ - while (tv_8532_eeprom_data[i]) { - reg = (tv_8532_eeprom_data[i] & 0xff000000) >> 24; - reg_w_1(gspca_dev, TV8532_EEprom_Add, reg); - /* msleep(1); */ - data0 = (tv_8532_eeprom_data[i] & 0x000000ff); - reg_w_1(gspca_dev, TV8532_EEprom_DataL, data0); - /* msleep(1); */ - data1 = (tv_8532_eeprom_data[i] & 0x0000ff00) >> 8; - reg_w_1(gspca_dev, TV8532_EEprom_DataM, data1); - /* msleep(1); */ - data2 = (tv_8532_eeprom_data[i] & 0x00ff0000) >> 16; - reg_w_1(gspca_dev, TV8532_EEprom_DataH, data2); - /* msleep(1); */ - reg_w_1(gspca_dev, TV8532_EEprom_Write, 0); - /* msleep(10); */ - i++; + int i; + + reg_w1(gspca_dev, R01_TIMING_CONTROL_LOW, CMD_EEprom_Open); + for (i = 0; i < ARRAY_SIZE(eeprom_data); i++) { + reg_w1(gspca_dev, R03_TABLE_ADDR, i); + reg_w1(gspca_dev, R04_WTRAM_DATA_L, eeprom_data[i][2]); + reg_w1(gspca_dev, R05_WTRAM_DATA_M, eeprom_data[i][1]); + reg_w1(gspca_dev, R06_WTRAM_DATA_H, eeprom_data[i][0]); + reg_w1(gspca_dev, R08_RAM_WRITE_ACTION, 0); } - reg_w_1(gspca_dev, TV8532_EEprom_TableLength, i); -/* msleep(1); */ - reg_w_1(gspca_dev, TV8532_CTRL, TV8532_CMD_EEprom_Close); + reg_w1(gspca_dev, R07_TABLE_LEN, i); + reg_w1(gspca_dev, R01_TIMING_CONTROL_LOW, CMD_EEprom_Close); msleep(10); } @@ -238,78 +193,76 @@ static int sd_config(struct gspca_dev *gspca_dev, struct sd *sd = (struct sd *) gspca_dev; struct cam *cam; - tv_8532WriteEEprom(gspca_dev); - cam = &gspca_dev->cam; cam->cam_mode = sif_mode; - cam->nmodes = sizeof sif_mode / sizeof sif_mode[0]; + cam->nmodes = ARRAY_SIZE(sif_mode); - sd->brightness = sd_ctrls[SD_BRIGHTNESS].qctrl.default_value; - sd->contrast = sd_ctrls[SD_CONTRAST].qctrl.default_value; + sd->brightness = BRIGHTNESS_DEF; return 0; } static void tv_8532ReadRegisters(struct gspca_dev *gspca_dev) { - __u8 data; - - data = reg_r(gspca_dev, 0x0001); - PDEBUG(D_USBI, "register 0x01-> %x", data); - data = reg_r(gspca_dev, 0x0002); - PDEBUG(D_USBI, "register 0x02-> %x", data); - reg_r(gspca_dev, TV8532_ADWIDTH_L); - reg_r(gspca_dev, TV8532_ADWIDTH_H); - reg_r(gspca_dev, TV8532_QUANT_COMP); - reg_r(gspca_dev, TV8532_MODE_PACKET); - reg_r(gspca_dev, TV8532_SETCLK); - reg_r(gspca_dev, TV8532_POINT_L); - reg_r(gspca_dev, TV8532_POINT_H); - reg_r(gspca_dev, TV8532_POINTB_L); - reg_r(gspca_dev, TV8532_POINTB_H); - reg_r(gspca_dev, TV8532_BUDGET_L); - reg_r(gspca_dev, TV8532_BUDGET_H); - reg_r(gspca_dev, TV8532_VID_L); - reg_r(gspca_dev, TV8532_VID_H); - reg_r(gspca_dev, TV8532_PID_L); - reg_r(gspca_dev, TV8532_PID_H); - reg_r(gspca_dev, TV8532_DeviceID); - reg_r(gspca_dev, TV8532_AD_COLBEGIN_L); - reg_r(gspca_dev, TV8532_AD_COLBEGIN_H); - reg_r(gspca_dev, TV8532_AD_ROWBEGIN_L); - reg_r(gspca_dev, TV8532_AD_ROWBEGIN_H); + int i; + static u8 reg_tb[] = { + R0C_AD_WIDTHL, + R0D_AD_WIDTHH, + R28_QUANT, + R29_LINE, + R2C_POLARITY, + R2D_POINT, + R2E_POINTH, + R2F_POINTB, + R30_POINTBH, + R2A_HIGH_BUDGET, + R2B_LOW_BUDGET, + R34_VID, + R35_VIDH, + R36_PID, + R37_PIDH, + R83_AD_IDH, + R10_AD_COL_BEGINL, + R11_AD_COL_BEGINH, + R14_AD_ROW_BEGINL, + R15_AD_ROWBEGINH, + 0 + }; + + i = 0; + do { + reg_r(gspca_dev, reg_tb[i]); + i++; + } while (reg_tb[i] != 0); } static void tv_8532_setReg(struct gspca_dev *gspca_dev) { - reg_w_1(gspca_dev, TV8532_AD_COLBEGIN_L, - ADCBEGINL); /* 0x10 */ - reg_w_1(gspca_dev, TV8532_AD_COLBEGIN_H, - ADCBEGINH); /* also digital gain */ - reg_w_1(gspca_dev, TV8532_PART_CTRL, - TV8532_CMD_UPDATE); /* 0x00<-0x84 */ - - reg_w_1(gspca_dev, TV8532_GPIO_OE, 0x0a); + reg_w1(gspca_dev, R10_AD_COL_BEGINL, 0x44); + /* begin active line */ + reg_w1(gspca_dev, R11_AD_COL_BEGINH, 0x00); + /* mirror and digital gain */ + reg_w1(gspca_dev, R00_PART_CONTROL, LATENT_CHANGE | EXPO_CHANGE); + /* = 0x84 */ + + reg_w1(gspca_dev, R3B_Test3, 0x0a); /* Test0Sel = 10 */ /******************************************************/ - reg_w_1(gspca_dev, TV8532_ADHEIGHT_L, ADHEIGHL); /* 0e */ - reg_w_1(gspca_dev, TV8532_ADHEIGHT_H, ADHEIGHH); /* 0f */ - reg_w_2(gspca_dev, TV8532_EXPOSURE, - EXPOL, EXPOH); /* 350d 0x014c; 1c */ - reg_w_1(gspca_dev, TV8532_AD_COLBEGIN_L, - ADCBEGINL); /* 0x10 */ - reg_w_1(gspca_dev, TV8532_AD_COLBEGIN_H, - ADCBEGINH); /* also digital gain */ - reg_w_1(gspca_dev, TV8532_AD_ROWBEGIN_L, - ADRBEGINL); /* 0x14 */ - - reg_w_1(gspca_dev, TV8532_AD_SLOPE, 0x00); /* 0x91 */ - reg_w_1(gspca_dev, TV8532_AD_BITCTRL, 0x02); /* 0x94 */ - - reg_w_1(gspca_dev, TV8532_CTRL, - TV8532_CMD_EEprom_Close); /* 0x01 */ - - reg_w_1(gspca_dev, TV8532_AD_SLOPE, 0x00); /* 0x91 */ - reg_w_1(gspca_dev, TV8532_PART_CTRL, - TV8532_CMD_UPDATE); /* 0x00<-0x84 */ + reg_w1(gspca_dev, R0E_AD_HEIGHTL, 0x90); + reg_w1(gspca_dev, R0F_AD_HEIGHTH, 0x01); + reg_w2(gspca_dev, R1C_AD_EXPOSE_TIMEL, 0x018f); + reg_w1(gspca_dev, R10_AD_COL_BEGINL, 0x44); + /* begin active line */ + reg_w1(gspca_dev, R11_AD_COL_BEGINH, 0x00); + /* mirror and digital gain */ + reg_w1(gspca_dev, R14_AD_ROW_BEGINL, 0x0a); + + reg_w1(gspca_dev, R91_AD_SLOPEREG, 0x00); + reg_w1(gspca_dev, R94_AD_BITCONTROL, 0x02); + + reg_w1(gspca_dev, R01_TIMING_CONTROL_LOW, CMD_EEprom_Close); + + reg_w1(gspca_dev, R91_AD_SLOPEREG, 0x00); + reg_w1(gspca_dev, R00_PART_CONTROL, LATENT_CHANGE | EXPO_CHANGE); + /* = 0x84 */ } static void tv_8532_PollReg(struct gspca_dev *gspca_dev) @@ -318,54 +271,55 @@ static void tv_8532_PollReg(struct gspca_dev *gspca_dev) /* strange polling from tgc */ for (i = 0; i < 10; i++) { - reg_w_1(gspca_dev, TV8532_SETCLK, - TESTCLK); /* 0x48; //0x08; 0x2c */ - reg_w_1(gspca_dev, TV8532_PART_CTRL, TV8532_CMD_UPDATE); - reg_w_1(gspca_dev, TV8532_UDP_UPDATE, 0x01); /* 0x31 */ + reg_w1(gspca_dev, R2C_POLARITY, 0x10); + reg_w1(gspca_dev, R00_PART_CONTROL, + LATENT_CHANGE | EXPO_CHANGE); + reg_w1(gspca_dev, R31_UPD, 0x01); } } /* this function is called at probe and resume time */ static int sd_init(struct gspca_dev *gspca_dev) { - reg_w_1(gspca_dev, TV8532_AD_SLOPE, 0x32); - reg_w_1(gspca_dev, TV8532_AD_BITCTRL, 0x00); + tv_8532WriteEEprom(gspca_dev); + + reg_w1(gspca_dev, R91_AD_SLOPEREG, 0x32); /* slope begin 1,7V, + * slope rate 2 */ + reg_w1(gspca_dev, R94_AD_BITCONTROL, 0x00); tv_8532ReadRegisters(gspca_dev); - reg_w_1(gspca_dev, TV8532_GPIO_OE, 0x0b); - reg_w_2(gspca_dev, TV8532_ADHEIGHT_L, ADHEIGHL, - ADHEIGHH); /* 401d 0x0169; 0e */ - reg_w_2(gspca_dev, TV8532_EXPOSURE, EXPOL, - EXPOH); /* 350d 0x014c; 1c */ - reg_w_1(gspca_dev, TV8532_ADWIDTH_L, ADWIDTHL); /* 0x20; 0x0c */ - reg_w_1(gspca_dev, TV8532_ADWIDTH_H, ADWIDTHH); /* 0x0d */ + reg_w1(gspca_dev, R3B_Test3, 0x0b); + reg_w2(gspca_dev, R0E_AD_HEIGHTL, 0x0190); + reg_w2(gspca_dev, R1C_AD_EXPOSE_TIMEL, 0x018f); + reg_w1(gspca_dev, R0C_AD_WIDTHL, 0xe8); + reg_w1(gspca_dev, R0D_AD_WIDTHH, 0x03); /*******************************************************************/ - reg_w_1(gspca_dev, TV8532_QUANT_COMP, - TESTCOMP); /* 0x72 compressed mode 0x28 */ - reg_w_1(gspca_dev, TV8532_MODE_PACKET, - TESTLINE); /* 0x84; // CIF | 4 packet 0x29 */ + reg_w1(gspca_dev, R28_QUANT, 0x90); + /* no compress - fixed Q - quant 0 */ + reg_w1(gspca_dev, R29_LINE, 0x81); + /* 0x84; // CIF | 4 packet 0x29 */ /************************************************/ - reg_w_1(gspca_dev, TV8532_SETCLK, - TESTCLK); /* 0x48; //0x08; 0x2c */ - reg_w_1(gspca_dev, TV8532_POINT_L, - TESTPTL); /* 0x38; 0x2d */ - reg_w_1(gspca_dev, TV8532_POINT_H, - TESTPTH); /* 0x04; 0x2e */ - reg_w_1(gspca_dev, TV8532_POINTB_L, - TESTPTBL); /* 0x04; 0x2f */ - reg_w_1(gspca_dev, TV8532_POINTB_H, - TESTPTBH); /* 0x04; 0x30 */ - reg_w_1(gspca_dev, TV8532_PART_CTRL, - TV8532_CMD_UPDATE); /* 0x00<-0x84 */ + reg_w1(gspca_dev, R2C_POLARITY, 0x10); + /* 0x48; //0x08; 0x2c */ + reg_w1(gspca_dev, R2D_POINT, 0x14); + /* 0x38; 0x2d */ + reg_w1(gspca_dev, R2E_POINTH, 0x01); + /* 0x04; 0x2e */ + reg_w1(gspca_dev, R2F_POINTB, 0x12); + /* 0x04; 0x2f */ + reg_w1(gspca_dev, R30_POINTBH, 0x01); + /* 0x04; 0x30 */ + reg_w1(gspca_dev, R00_PART_CONTROL, LATENT_CHANGE | EXPO_CHANGE); + /* 0x00<-0x84 */ /*************************************************/ - reg_w_1(gspca_dev, TV8532_UDP_UPDATE, 0x01); /* 0x31 */ + reg_w1(gspca_dev, R31_UPD, 0x01); /* update registers */ msleep(200); - reg_w_1(gspca_dev, TV8532_UDP_UPDATE, 0x00); /* 0x31 */ + reg_w1(gspca_dev, R31_UPD, 0x00); /* end update */ /*************************************************/ tv_8532_setReg(gspca_dev); /*************************************************/ - reg_w_1(gspca_dev, TV8532_GPIO_OE, 0x0b); + reg_w1(gspca_dev, R3B_Test3, 0x0b); /* Test0Sel = 11 = GPIO */ /*************************************************/ tv_8532_setReg(gspca_dev); /*************************************************/ @@ -376,11 +330,10 @@ static int sd_init(struct gspca_dev *gspca_dev) static void setbrightness(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; - int brightness = sd->brightness; - reg_w_2(gspca_dev, TV8532_EXPOSURE, - brightness >> 8, brightness); /* 1c */ - reg_w_1(gspca_dev, TV8532_PART_CTRL, TV8532_CMD_UPDATE); + reg_w2(gspca_dev, R1C_AD_EXPOSE_TIMEL, sd->brightness); + reg_w1(gspca_dev, R00_PART_CONTROL, LATENT_CHANGE | EXPO_CHANGE); + /* 0x84 */ } /* -- start the camera -- */ @@ -388,57 +341,50 @@ static int sd_start(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; - reg_w_1(gspca_dev, TV8532_AD_SLOPE, 0x32); - reg_w_1(gspca_dev, TV8532_AD_BITCTRL, 0x00); + reg_w1(gspca_dev, R91_AD_SLOPEREG, 0x32); /* slope begin 1,7V, + * slope rate 2 */ + reg_w1(gspca_dev, R94_AD_BITCONTROL, 0x00); tv_8532ReadRegisters(gspca_dev); - reg_w_1(gspca_dev, TV8532_GPIO_OE, 0x0b); - reg_w_2(gspca_dev, TV8532_ADHEIGHT_L, - ADHEIGHL, ADHEIGHH); /* 401d 0x0169; 0e */ -/* reg_w_2(gspca_dev, TV8532_EXPOSURE, - EXPOL, EXPOH); * 350d 0x014c; 1c */ + reg_w1(gspca_dev, R3B_Test3, 0x0b); + + reg_w2(gspca_dev, R0E_AD_HEIGHTL, 0x0190); setbrightness(gspca_dev); - reg_w_1(gspca_dev, TV8532_ADWIDTH_L, ADWIDTHL); /* 0x20; 0x0c */ - reg_w_1(gspca_dev, TV8532_ADWIDTH_H, ADWIDTHH); /* 0x0d */ + reg_w1(gspca_dev, R0C_AD_WIDTHL, 0xe8); /* 0x20; 0x0c */ + reg_w1(gspca_dev, R0D_AD_WIDTHH, 0x03); /************************************************/ - reg_w_1(gspca_dev, TV8532_QUANT_COMP, - TESTCOMP); /* 0x72 compressed mode 0x28 */ + reg_w1(gspca_dev, R28_QUANT, 0x90); + /* 0x72 compressed mode 0x28 */ if (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv) { /* 176x144 */ - reg_w_1(gspca_dev, TV8532_MODE_PACKET, - QCIFLINE); /* 0x84; // CIF | 4 packet 0x29 */ + reg_w1(gspca_dev, R29_LINE, 0x41); + /* CIF - 2 lines/packet */ } else { /* 352x288 */ - reg_w_1(gspca_dev, TV8532_MODE_PACKET, - TESTLINE); /* 0x84; // CIF | 4 packet 0x29 */ + reg_w1(gspca_dev, R29_LINE, 0x81); + /* CIF - 2 lines/packet */ } /************************************************/ - reg_w_1(gspca_dev, TV8532_SETCLK, - TESTCLK); /* 0x48; //0x08; 0x2c */ - reg_w_1(gspca_dev, TV8532_POINT_L, - TESTPTL); /* 0x38; 0x2d */ - reg_w_1(gspca_dev, TV8532_POINT_H, - TESTPTH); /* 0x04; 0x2e */ - reg_w_1(gspca_dev, TV8532_POINTB_L, - TESTPTBL); /* 0x04; 0x2f */ - reg_w_1(gspca_dev, TV8532_POINTB_H, - TESTPTBH); /* 0x04; 0x30 */ - reg_w_1(gspca_dev, TV8532_PART_CTRL, - TV8532_CMD_UPDATE); /* 0x00<-0x84 */ + reg_w1(gspca_dev, R2C_POLARITY, 0x10); /* slow clock */ + reg_w1(gspca_dev, R2D_POINT, 0x14); + reg_w1(gspca_dev, R2E_POINTH, 0x01); + reg_w1(gspca_dev, R2F_POINTB, 0x12); + reg_w1(gspca_dev, R30_POINTBH, 0x01); + reg_w1(gspca_dev, R00_PART_CONTROL, LATENT_CHANGE | EXPO_CHANGE); /************************************************/ - reg_w_1(gspca_dev, TV8532_UDP_UPDATE, 0x01); /* 0x31 */ + reg_w1(gspca_dev, R31_UPD, 0x01); /* update registers */ msleep(200); - reg_w_1(gspca_dev, TV8532_UDP_UPDATE, 0x00); /* 0x31 */ + reg_w1(gspca_dev, R31_UPD, 0x00); /* end update */ /************************************************/ tv_8532_setReg(gspca_dev); /************************************************/ - reg_w_1(gspca_dev, TV8532_GPIO_OE, 0x0b); + reg_w1(gspca_dev, R3B_Test3, 0x0b); /* Test0Sel = 11 = GPIO */ /************************************************/ tv_8532_setReg(gspca_dev); /************************************************/ tv_8532_PollReg(gspca_dev); - reg_w_1(gspca_dev, TV8532_UDP_UPDATE, 0x00); /* 0x31 */ + reg_w1(gspca_dev, R31_UPD, 0x00); /* end update */ gspca_dev->empty_packet = 0; /* check the empty packets */ sd->packet = 0; /* ignore the first packets */ @@ -448,7 +394,7 @@ static int sd_start(struct gspca_dev *gspca_dev) static void sd_stopN(struct gspca_dev *gspca_dev) { - reg_w_1(gspca_dev, TV8532_GPIO_OE, 0x0b); + reg_w1(gspca_dev, R3B_Test3, 0x0b); /* Test0Sel = 11 = GPIO */ } static void sd_pkt_scan(struct gspca_dev *gspca_dev, @@ -472,9 +418,9 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, /* each packet contains: * - header 2 bytes - * - RG line + * - RGRG line * - 4 bytes - * - GB line + * - GBGB line * - 4 bytes */ gspca_frame_add(gspca_dev, packet_type0, @@ -483,10 +429,6 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, frame, data + gspca_dev->width + 6, gspca_dev->width); } -static void setcontrast(struct gspca_dev *gspca_dev) -{ -} - static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val) { struct sd *sd = (struct sd *) gspca_dev; @@ -505,24 +447,6 @@ static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val) return 0; } -static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val) -{ - struct sd *sd = (struct sd *) gspca_dev; - - sd->contrast = val; - if (gspca_dev->streaming) - setcontrast(gspca_dev); - return 0; -} - -static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val) -{ - struct sd *sd = (struct sd *) gspca_dev; - - *val = sd->contrast; - return 0; -} - /* sub-driver description */ static const struct sd_desc sd_desc = { .name = MODULE_NAME, -- cgit v1.2.3 From b3f5dbd0e1d4a1f9ed17cb40b9f789c606c44206 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Sat, 10 Jan 2009 15:54:44 -0300 Subject: V4L/DVB (10352): gspca - spca508: Cleanup code. Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/spca508.c | 113 ++++++++++++++++++------------------ 1 file changed, 56 insertions(+), 57 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/gspca/spca508.c b/drivers/media/video/gspca/spca508.c index 34e74004774b..bf7979da664a 100644 --- a/drivers/media/video/gspca/spca508.c +++ b/drivers/media/video/gspca/spca508.c @@ -101,8 +101,7 @@ static const struct v4l2_pix_format sif_mode[] = { * Initialization data: this is the first set-up data written to the * device (before the open data). */ -static const __u16 spca508_init_data[][3] = -#define IGN(x) /* nothing */ +static const u16 spca508_init_data[][2] = { /* line URB value, index */ /* 44274 1804 */ {0x0000, 0x870b}, @@ -589,11 +588,10 @@ static const __u16 spca508_init_data[][3] = {} }; - /* * Initialization data for Intel EasyPC Camera CS110 */ -static const __u16 spca508cs110_init_data[][3] = { +static const u16 spca508cs110_init_data[][2] = { {0x0000, 0x870b}, /* Reset CTL3 */ {0x0003, 0x8111}, /* Soft Reset compression, memory, TG & CDSP */ {0x0000, 0x8111}, /* Normal operation on reset */ @@ -677,7 +675,7 @@ static const __u16 spca508cs110_init_data[][3] = { {} }; -static const __u16 spca508_sightcam_init_data[][3] = { +static const u16 spca508_sightcam_init_data[][2] = { /* This line seems to setup the frame/canvas */ /*368 */ {0x000f, 0x8402}, @@ -760,7 +758,7 @@ static const __u16 spca508_sightcam_init_data[][3] = { {} }; -static const __u16 spca508_sightcam2_init_data[][3] = { +static const u16 spca508_sightcam2_init_data[][2] = { /* 35 */ {0x0020, 0x8112}, /* 36 */ {0x000f, 0x8402}, @@ -1107,7 +1105,7 @@ static const __u16 spca508_sightcam2_init_data[][3] = { /* * Initialization data for Creative Webcam Vista */ -static const __u16 spca508_vista_init_data[][3] = { +static const u16 spca508_vista_init_data[][2] = { {0x0008, 0x8200}, /* Clear register */ {0x0000, 0x870b}, /* Reset CTL3 */ {0x0020, 0x8112}, /* Video Drop packet enable */ @@ -1309,18 +1307,18 @@ static const __u16 spca508_vista_init_data[][3] = { {0x0050, 0x8703}, {0x0002, 0x8704}, /* External input CKIx1 */ - {0x0001, 0x870C}, /* Select CKOx2 output */ - {0x009A, 0x8600}, /* Line memory Read Counter (L) */ + {0x0001, 0x870c}, /* Select CKOx2 output */ + {0x009a, 0x8600}, /* Line memory Read Counter (L) */ {0x0001, 0x8606}, /* 1 Line memory Read Counter (H) Result: (d)410 */ {0x0023, 0x8601}, {0x0010, 0x8602}, - {0x000A, 0x8603}, + {0x000a, 0x8603}, {0x009A, 0x8600}, - {0x0001, 0x865B}, /* 1 Horizontal Offset for Valid Pixel(L) */ - {0x0003, 0x865C}, /* Vertical offset for valid lines (L) */ - {0x0058, 0x865D}, /* Horizontal valid pixels window (L) */ - {0x0048, 0x865E}, /* Vertical valid lines window (L) */ - {0x0000, 0x865F}, + {0x0001, 0x865b}, /* 1 Horizontal Offset for Valid Pixel(L) */ + {0x0003, 0x865c}, /* Vertical offset for valid lines (L) */ + {0x0058, 0x865d}, /* Horizontal valid pixels window (L) */ + {0x0048, 0x865e}, /* Vertical valid lines window (L) */ + {0x0000, 0x865f}, {0x0006, 0x8660}, /* Enable nibble data input, select nibble input order */ @@ -1328,63 +1326,63 @@ static const __u16 spca508_vista_init_data[][3] = { {0x0013, 0x8608}, /* A11 Coeficients for color correction */ {0x0028, 0x8609}, /* Note: these values are confirmed at the end of array */ - {0x0005, 0x860A}, /* ... */ - {0x0025, 0x860B}, - {0x00E1, 0x860C}, - {0x00FA, 0x860D}, - {0x00F4, 0x860E}, - {0x00E8, 0x860F}, + {0x0005, 0x860a}, /* ... */ + {0x0025, 0x860b}, + {0x00e1, 0x860c}, + {0x00fa, 0x860D}, + {0x00f4, 0x860e}, + {0x00e8, 0x860f}, {0x0025, 0x8610}, /* A33 Coef. */ - {0x00FC, 0x8611}, /* White balance offset: R */ + {0x00fc, 0x8611}, /* White balance offset: R */ {0x0001, 0x8612}, /* White balance offset: Gr */ - {0x00FE, 0x8613}, /* White balance offset: B */ + {0x00fe, 0x8613}, /* White balance offset: B */ {0x0000, 0x8614}, /* White balance offset: Gb */ {0x0064, 0x8651}, /* R gain for white balance (L) */ {0x0040, 0x8652}, /* Gr gain for white balance (L) */ {0x0066, 0x8653}, /* B gain for white balance (L) */ {0x0040, 0x8654}, /* Gb gain for white balance (L) */ - {0x0001, 0x863F}, /* Enable fixed gamma correction */ + {0x0001, 0x863f}, /* Enable fixed gamma correction */ - {0x00A1, 0x8656}, /* Size - Window1: 256x256, Window2: 128x128 */ + {0x00a1, 0x8656}, /* Size - Window1: 256x256, Window2: 128x128 */ /* UV division: UV no change, Enable New edge enhancement */ {0x0018, 0x8657}, /* Edge gain high threshold */ {0x0020, 0x8658}, /* Edge gain low threshold */ {0x000A, 0x8659}, /* Edge bandwidth high threshold */ - {0x0005, 0x865A}, /* Edge bandwidth low threshold */ + {0x0005, 0x865a}, /* Edge bandwidth low threshold */ {0x0064, 0x8607}, /* UV filter enable */ {0x0016, 0x8660}, - {0x0000, 0x86B0}, /* Bad pixels compensation address */ - {0x00DC, 0x86B1}, /* X coord for bad pixels compensation (L) */ - {0x0000, 0x86B2}, - {0x0009, 0x86B3}, /* Y coord for bad pixels compensation (L) */ - {0x0000, 0x86B4}, - - {0x0001, 0x86B0}, - {0x00F5, 0x86B1}, - {0x0000, 0x86B2}, - {0x00C6, 0x86B3}, - {0x0000, 0x86B4}, - - {0x0002, 0x86B0}, - {0x001C, 0x86B1}, - {0x0001, 0x86B2}, - {0x00D7, 0x86B3}, - {0x0000, 0x86B4}, - - {0x0003, 0x86B0}, - {0x001C, 0x86B1}, - {0x0001, 0x86B2}, - {0x00D8, 0x86B3}, - {0x0000, 0x86B4}, - - {0x0004, 0x86B0}, - {0x001D, 0x86B1}, - {0x0001, 0x86B2}, - {0x00D8, 0x86B3}, - {0x0000, 0x86B4}, - {0x001E, 0x8660}, + {0x0000, 0x86b0}, /* Bad pixels compensation address */ + {0x00dc, 0x86b1}, /* X coord for bad pixels compensation (L) */ + {0x0000, 0x86b2}, + {0x0009, 0x86b3}, /* Y coord for bad pixels compensation (L) */ + {0x0000, 0x86b4}, + + {0x0001, 0x86b0}, + {0x00f5, 0x86b1}, + {0x0000, 0x86b2}, + {0x00c6, 0x86b3}, + {0x0000, 0x86b4}, + + {0x0002, 0x86b0}, + {0x001c, 0x86b1}, + {0x0001, 0x86b2}, + {0x00d7, 0x86b3}, + {0x0000, 0x86b4}, + + {0x0003, 0x86b0}, + {0x001c, 0x86b1}, + {0x0001, 0x86b2}, + {0x00d8, 0x86b3}, + {0x0000, 0x86b4}, + + {0x0004, 0x86b0}, + {0x001d, 0x86b1}, + {0x0001, 0x86b2}, + {0x00d8, 0x86b3}, + {0x0000, 0x86b4}, + {0x001e, 0x8660}, /* READ { 0, 0x0000, 0x8608 } -> 0000: 13 */ @@ -1449,7 +1447,7 @@ static int reg_read(struct gspca_dev *gspca_dev, } static int write_vector(struct gspca_dev *gspca_dev, - const __u16 data[][3]) + const u16 data[][2]) { struct usb_device *dev = gspca_dev->dev; int ret, i = 0; @@ -1666,6 +1664,7 @@ static struct usb_driver sd_driver = { static int __init sd_mod_init(void) { int ret; + ret = usb_register(&sd_driver); if (ret < 0) return ret; -- cgit v1.2.3 From 8789d810f104a3e9f4289382968cf5482934b9fd Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Sat, 10 Jan 2009 16:11:25 -0300 Subject: V4L/DVB (10353): gspca - some subdrivers: Don't get the control values from the webcam. Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/etoms.c | 29 ------------------ drivers/media/video/gspca/spca500.c | 33 --------------------- drivers/media/video/gspca/spca501.c | 15 ---------- drivers/media/video/gspca/spca505.c | 9 ------ drivers/media/video/gspca/spca506.c | 50 ------------------------------- drivers/media/video/gspca/spca508.c | 8 ----- drivers/media/video/gspca/sunplus.c | 59 ------------------------------------- 7 files changed, 203 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/gspca/etoms.c b/drivers/media/video/gspca/etoms.c index 49ab2659a3f6..2c20d06a03e8 100644 --- a/drivers/media/video/gspca/etoms.c +++ b/drivers/media/video/gspca/etoms.c @@ -472,19 +472,6 @@ static void setbrightness(struct gspca_dev *gspca_dev) reg_w_val(gspca_dev, ET_O_RED + i, brightness); } -static void getbrightness(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - int i; - int brightness = 0; - - for (i = 0; i < 4; i++) { - reg_r(gspca_dev, ET_O_RED + i, 1); - brightness += gspca_dev->usb_buf[0]; - } - sd->brightness = brightness >> 3; -} - static void setcontrast(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; @@ -495,19 +482,6 @@ static void setcontrast(struct gspca_dev *gspca_dev) reg_w(gspca_dev, ET_G_RED, RGBG, 6); } -static void getcontrast(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - int i; - int contrast = 0; - - for (i = 0; i < 4; i++) { - reg_r(gspca_dev, ET_G_RED + i, 1); - contrast += gspca_dev->usb_buf[0]; - } - sd->contrast = contrast >> 2; -} - static void setcolors(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; @@ -820,7 +794,6 @@ static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val) { struct sd *sd = (struct sd *) gspca_dev; - getbrightness(gspca_dev); *val = sd->brightness; return 0; } @@ -839,7 +812,6 @@ static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val) { struct sd *sd = (struct sd *) gspca_dev; - getcontrast(gspca_dev); *val = sd->contrast; return 0; } @@ -858,7 +830,6 @@ static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val) { struct sd *sd = (struct sd *) gspca_dev; - getcolors(gspca_dev); *val = sd->colors; return 0; } diff --git a/drivers/media/video/gspca/spca500.c b/drivers/media/video/gspca/spca500.c index e00f3b53bdff..62c12fa10570 100644 --- a/drivers/media/video/gspca/spca500.c +++ b/drivers/media/video/gspca/spca500.c @@ -935,16 +935,6 @@ static void setbrightness(struct gspca_dev *gspca_dev) (__u8) (sd->brightness - 128)); } -static void getbrightness(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - int ret; - - ret = reg_r_12(gspca_dev, 0x00, 0x8167, 1); - if (ret >= 0) - sd->brightness = ret + 128; -} - static void setcontrast(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; @@ -952,16 +942,6 @@ static void setcontrast(struct gspca_dev *gspca_dev) reg_w(gspca_dev, 0x00, 0x8168, sd->contrast); } -static void getcontrast(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - int ret; - - ret = reg_r_12(gspca_dev, 0x0, 0x8168, 1); - if (ret >= 0) - sd->contrast = ret; -} - static void setcolors(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; @@ -969,16 +949,6 @@ static void setcolors(struct gspca_dev *gspca_dev) reg_w(gspca_dev, 0x00, 0x8169, sd->colors); } -static void getcolors(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - int ret; - - ret = reg_r_12(gspca_dev, 0x0, 0x8169, 1); - if (ret >= 0) - sd->colors = ret; -} - static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val) { struct sd *sd = (struct sd *) gspca_dev; @@ -993,7 +963,6 @@ static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val) { struct sd *sd = (struct sd *) gspca_dev; - getbrightness(gspca_dev); *val = sd->brightness; return 0; } @@ -1012,7 +981,6 @@ static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val) { struct sd *sd = (struct sd *) gspca_dev; - getcontrast(gspca_dev); *val = sd->contrast; return 0; } @@ -1031,7 +999,6 @@ static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val) { struct sd *sd = (struct sd *) gspca_dev; - getcolors(gspca_dev); *val = sd->colors; return 0; } diff --git a/drivers/media/video/gspca/spca501.c b/drivers/media/video/gspca/spca501.c index 414b5b8b759f..d48b27c648ca 100644 --- a/drivers/media/video/gspca/spca501.c +++ b/drivers/media/video/gspca/spca501.c @@ -1883,10 +1883,6 @@ static void setbrightness(struct gspca_dev *gspca_dev) reg_write(gspca_dev->dev, SPCA501_REG_CCDSP, 0x12, sd->brightness); } -static void getbrightness(struct gspca_dev *gspca_dev) -{ -} - static void setcontrast(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; @@ -1897,10 +1893,6 @@ static void setcontrast(struct gspca_dev *gspca_dev) sd->contrast & 0xff); } -static void getcontrast(struct gspca_dev *gspca_dev) -{ -} - static void setcolors(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; @@ -1908,10 +1900,6 @@ static void setcolors(struct gspca_dev *gspca_dev) reg_write(gspca_dev->dev, SPCA501_REG_CCDSP, 0x0c, sd->colors); } -static void getcolors(struct gspca_dev *gspca_dev) -{ -} - static void setblue_balance(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; @@ -2083,7 +2071,6 @@ static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val) { struct sd *sd = (struct sd *) gspca_dev; - getbrightness(gspca_dev); *val = sd->brightness; return 0; } @@ -2102,7 +2089,6 @@ static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val) { struct sd *sd = (struct sd *) gspca_dev; - getcontrast(gspca_dev); *val = sd->contrast; return 0; } @@ -2121,7 +2107,6 @@ static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val) { struct sd *sd = (struct sd *) gspca_dev; - getcolors(gspca_dev); *val = sd->colors; return 0; } diff --git a/drivers/media/video/gspca/spca505.c b/drivers/media/video/gspca/spca505.c index b8c855c6a4ec..25e2bec9dc52 100644 --- a/drivers/media/video/gspca/spca505.c +++ b/drivers/media/video/gspca/spca505.c @@ -790,14 +790,6 @@ static void setbrightness(struct gspca_dev *gspca_dev) reg_write(gspca_dev->dev, 5, 0x01, (255 - brightness) << 2); } -static void getbrightness(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - - sd->brightness = 255 - - ((reg_read(gspca_dev, 5, 0x01, 1) >> 2) - + (reg_read(gspca_dev, 5, 0x0, 1) << 6)); -} static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val) { @@ -813,7 +805,6 @@ static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val) { struct sd *sd = (struct sd *) gspca_dev; - getbrightness(gspca_dev); *val = sd->brightness; return 0; } diff --git a/drivers/media/video/gspca/spca506.c b/drivers/media/video/gspca/spca506.c index 8cedb00976a4..3a0c893f942d 100644 --- a/drivers/media/video/gspca/spca506.c +++ b/drivers/media/video/gspca/spca506.c @@ -193,24 +193,6 @@ static void spca506_WriteI2c(struct gspca_dev *gspca_dev, __u16 valeur, } } -static int spca506_ReadI2c(struct gspca_dev *gspca_dev, __u16 reg) -{ - int retry = 60; - - reg_w(gspca_dev->dev, 0x07, SAA7113_I2C_BASE_WRITE, 0x0004); - reg_w(gspca_dev->dev, 0x07, reg, 0x0001); - reg_w(gspca_dev->dev, 0x07, 0x01, 0x0002); - while (--retry) { - reg_r(gspca_dev, 0x07, 0x0003, 2); - if ((gspca_dev->usb_buf[0] | gspca_dev->usb_buf[1]) == 0x00) - break; - } - if (retry == 0) - return -1; - reg_r(gspca_dev, 0x07, 0x0000, 1); - return gspca_dev->usb_buf[0]; -} - static void spca506_SetNormeInput(struct gspca_dev *gspca_dev, __u16 norme, __u16 channel) @@ -595,13 +577,6 @@ static void setbrightness(struct gspca_dev *gspca_dev) spca506_WriteI2c(gspca_dev, 0x01, 0x09); } -static void getbrightness(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - - sd->brightness = spca506_ReadI2c(gspca_dev, SAA7113_bright); -} - static void setcontrast(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; @@ -611,13 +586,6 @@ static void setcontrast(struct gspca_dev *gspca_dev) spca506_WriteI2c(gspca_dev, 0x01, 0x09); } -static void getcontrast(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - - sd->contrast = spca506_ReadI2c(gspca_dev, SAA7113_contrast); -} - static void setcolors(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; @@ -627,13 +595,6 @@ static void setcolors(struct gspca_dev *gspca_dev) spca506_WriteI2c(gspca_dev, 0x01, 0x09); } -static void getcolors(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - - sd->colors = spca506_ReadI2c(gspca_dev, SAA7113_saturation); -} - static void sethue(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; @@ -643,13 +604,6 @@ static void sethue(struct gspca_dev *gspca_dev) spca506_WriteI2c(gspca_dev, 0x01, 0x09); } -static void gethue(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - - sd->hue = spca506_ReadI2c(gspca_dev, SAA7113_hue); -} - static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val) { struct sd *sd = (struct sd *) gspca_dev; @@ -664,7 +618,6 @@ static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val) { struct sd *sd = (struct sd *) gspca_dev; - getbrightness(gspca_dev); *val = sd->brightness; return 0; } @@ -683,7 +636,6 @@ static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val) { struct sd *sd = (struct sd *) gspca_dev; - getcontrast(gspca_dev); *val = sd->contrast; return 0; } @@ -702,7 +654,6 @@ static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val) { struct sd *sd = (struct sd *) gspca_dev; - getcolors(gspca_dev); *val = sd->colors; return 0; } @@ -721,7 +672,6 @@ static int sd_gethue(struct gspca_dev *gspca_dev, __s32 *val) { struct sd *sd = (struct sd *) gspca_dev; - gethue(gspca_dev); *val = sd->hue; return 0; } diff --git a/drivers/media/video/gspca/spca508.c b/drivers/media/video/gspca/spca508.c index bf7979da664a..adacf8437661 100644 --- a/drivers/media/video/gspca/spca508.c +++ b/drivers/media/video/gspca/spca508.c @@ -1590,13 +1590,6 @@ static void setbrightness(struct gspca_dev *gspca_dev) reg_write(gspca_dev->dev, 0x8654, brightness); } -static void getbrightness(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - - sd->brightness = reg_read(gspca_dev, 0x8651); -} - static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val) { struct sd *sd = (struct sd *) gspca_dev; @@ -1611,7 +1604,6 @@ static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val) { struct sd *sd = (struct sd *) gspca_dev; - getbrightness(gspca_dev); *val = sd->brightness; return 0; } diff --git a/drivers/media/video/gspca/sunplus.c b/drivers/media/video/gspca/sunplus.c index 2c0b6c3c8760..9d08a66fe23d 100644 --- a/drivers/media/video/gspca/sunplus.c +++ b/drivers/media/video/gspca/sunplus.c @@ -1194,26 +1194,6 @@ static void setbrightness(struct gspca_dev *gspca_dev) } } -static void getbrightness(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - __u16 brightness = 0; - - switch (sd->bridge) { - default: -/* case BRIDGE_SPCA533: */ -/* case BRIDGE_SPCA504B: */ -/* case BRIDGE_SPCA504: */ -/* case BRIDGE_SPCA504C: */ - brightness = reg_r_12(gspca_dev, 0x00, 0x21a7, 2); - break; - case BRIDGE_SPCA536: - brightness = reg_r_12(gspca_dev, 0x00, 0x20f0, 2); - break; - } - sd->brightness = ((brightness & 0xff) - 128) % 255; -} - static void setcontrast(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; @@ -1233,24 +1213,6 @@ static void setcontrast(struct gspca_dev *gspca_dev) } } -static void getcontrast(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - - switch (sd->bridge) { - default: -/* case BRIDGE_SPCA533: */ -/* case BRIDGE_SPCA504B: */ -/* case BRIDGE_SPCA504: */ -/* case BRIDGE_SPCA504C: */ - sd->contrast = reg_r_12(gspca_dev, 0x00, 0x21a8, 2); - break; - case BRIDGE_SPCA536: - sd->contrast = reg_r_12(gspca_dev, 0x00, 0x20f1, 2); - break; - } -} - static void setcolors(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; @@ -1270,24 +1232,6 @@ static void setcolors(struct gspca_dev *gspca_dev) } } -static void getcolors(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - - switch (sd->bridge) { - default: -/* case BRIDGE_SPCA533: */ -/* case BRIDGE_SPCA504B: */ -/* case BRIDGE_SPCA504: */ -/* case BRIDGE_SPCA504C: */ - sd->colors = reg_r_12(gspca_dev, 0x00, 0x21ae, 2) >> 1; - break; - case BRIDGE_SPCA536: - sd->colors = reg_r_12(gspca_dev, 0x00, 0x20f6, 2) >> 1; - break; - } -} - static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val) { struct sd *sd = (struct sd *) gspca_dev; @@ -1302,7 +1246,6 @@ static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val) { struct sd *sd = (struct sd *) gspca_dev; - getbrightness(gspca_dev); *val = sd->brightness; return 0; } @@ -1321,7 +1264,6 @@ static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val) { struct sd *sd = (struct sd *) gspca_dev; - getcontrast(gspca_dev); *val = sd->contrast; return 0; } @@ -1340,7 +1282,6 @@ static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val) { struct sd *sd = (struct sd *) gspca_dev; - getcolors(gspca_dev); *val = sd->colors; return 0; } -- cgit v1.2.3 From b505cbcb095b8f55a7c594a78863f45ec28f59c9 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Sat, 10 Jan 2009 16:14:12 -0300 Subject: V4L/DVB (10354): gspca - tv8532: Change the max brightness. Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/tv8532.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/gspca/tv8532.c b/drivers/media/video/gspca/tv8532.c index 97ffaa7f933c..9f243d7e3110 100644 --- a/drivers/media/video/gspca/tv8532.c +++ b/drivers/media/video/gspca/tv8532.c @@ -46,9 +46,9 @@ static struct ctrl sd_ctrls[] = { .type = V4L2_CTRL_TYPE_INTEGER, .name = "Brightness", .minimum = 1, - .maximum = 0x2ff, + .maximum = 0x15f, /* = 352 - 1 */ .step = 1, -#define BRIGHTNESS_DEF 0x18f +#define BRIGHTNESS_DEF 0x14c .default_value = BRIGHTNESS_DEF, }, .set = sd_setbrightness, -- cgit v1.2.3 From 8c2ba44106a8693c7f5d2da93c3ab135254d86af Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Tue, 13 Jan 2009 05:55:40 -0300 Subject: V4L/DVB (10356): gspca - sonixj: Cleanup code. Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/sonixj.c | 225 ++++++++++++++++++------------------- 1 file changed, 111 insertions(+), 114 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/gspca/sonixj.c b/drivers/media/video/gspca/sonixj.c index 51d68d35aa73..d1c85ce39e56 100644 --- a/drivers/media/video/gspca/sonixj.c +++ b/drivers/media/video/gspca/sonixj.c @@ -243,89 +243,86 @@ static const struct v4l2_pix_format vga_mode[] = { .priv = 0}, }; -/*Data from sn9c102p+hv71331r */ -static const __u8 sn_hv7131[] = { +/*Data from sn9c102p+hv7131r */ +static const u8 sn_hv7131[0x1c] = { /* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */ 0x00, 0x03, 0x64, 0x00, 0x1a, 0x20, 0x20, 0x20, /* reg8 reg9 rega regb regc regd rege regf */ 0xa1, 0x11, 0x02, 0x09, 0x00, 0x00, 0x00, 0x10, /* reg10 reg11 reg12 reg13 reg14 reg15 reg16 reg17 */ 0x03, 0x00, 0x00, 0x01, 0x03, 0x28, 0x1e, 0x41, -/* reg18 reg19 reg1a reg1b reg1c reg1d reg1e reg1f */ - 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +/* reg18 reg19 reg1a reg1b */ + 0x0a, 0x00, 0x00, 0x00 }; -static const __u8 sn_mi0360[] = { +static const u8 sn_mi0360[0x1c] = { /* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */ 0x00, 0x61, 0x44, 0x00, 0x1a, 0x20, 0x20, 0x20, /* reg8 reg9 rega regb regc regd rege regf */ 0xb1, 0x5d, 0x07, 0x00, 0x00, 0x00, 0x00, 0x10, /* reg10 reg11 reg12 reg13 reg14 reg15 reg16 reg17 */ 0x03, 0x00, 0x00, 0x02, 0x0a, 0x28, 0x1e, 0x61, -/* reg18 reg19 reg1a reg1b reg1c reg1d reg1e reg1f */ - 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +/* reg18 reg19 reg1a reg1b */ + 0x06, 0x00, 0x00, 0x00 }; -static const __u8 sn_mo4000[] = { +static const u8 sn_mo4000[0x1c] = { /* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */ - 0x12, 0x23, 0x60, 0x00, 0x1a, 0x00, 0x20, 0x18, + 0x00, 0x23, 0x60, 0x00, 0x1a, 0x00, 0x20, 0x18, /* reg8 reg9 rega regb regc regd rege regf */ 0x81, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* reg10 reg11 reg12 reg13 reg14 reg15 reg16 reg17 */ 0x03, 0x00, 0x0b, 0x0f, 0x14, 0x28, 0x1e, 0x40, -/* reg18 reg19 reg1a reg1b reg1c reg1d reg1e reg1f */ - 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +/* reg18 reg19 reg1a reg1b */ + 0x08, 0x00, 0x00, 0x00 }; -static const __u8 sn_om6802[] = { +static const u8 sn_om6802[0x1c] = { /* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */ 0x00, 0x23, 0x72, 0x00, 0x1a, 0x34, 0x27, 0x20, /* reg8 reg9 rega regb regc regd rege regf */ 0x80, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* reg10 reg11 reg12 reg13 reg14 reg15 reg16 reg17 */ 0x03, 0x00, 0x51, 0x01, 0x00, 0x28, 0x1e, 0x40, -/* reg18 reg19 reg1a reg1b reg1c reg1d reg1e reg1f */ - 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x08, 0x22, 0x44, 0x63, 0x7d, 0x92, 0xa3, 0xaf, - 0xbc, 0xc4, 0xcd, 0xd5, 0xdc, 0xe1, 0xe8, 0xef, - 0xf7 +/* reg18 reg19 reg1a reg1b */ + 0x05, 0x00, 0x00, 0x00 }; -static const __u8 sn_ov7630[] = { +static const u8 sn_ov7630[0x1c] = { /* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */ 0x00, 0x21, 0x40, 0x00, 0x1a, 0x20, 0x1f, 0x20, /* reg8 reg9 rega regb regc regd rege regf */ 0xa1, 0x21, 0x76, 0x21, 0x00, 0x00, 0x00, 0x10, /* reg10 reg11 reg12 reg13 reg14 reg15 reg16 reg17 */ 0x03, 0x00, 0x04, 0x01, 0x0a, 0x28, 0x1e, 0xc2, -/* reg18 reg19 reg1a reg1b reg1c reg1d reg1e reg1f */ - 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00 +/* reg18 reg19 reg1a reg1b */ + 0x0b, 0x00, 0x00, 0x00 }; -static const __u8 sn_ov7648[] = { +static const u8 sn_ov7648[0x1c] = { /* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */ 0x00, 0x63, 0x40, 0x00, 0x1a, 0x20, 0x20, 0x20, /* reg8 reg9 rega regb regc regd rege regf */ 0x81, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, /* reg10 reg11 reg12 reg13 reg14 reg15 reg16 reg17 */ 0x03, 0x00, 0x00, 0x01, 0x00, 0x28, 0x1e, 0x00, -/* reg18 reg19 reg1a reg1b reg1c reg1d reg1e reg1f */ - 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00 +/* reg18 reg19 reg1a reg1b */ + 0x0b, 0x00, 0x00, 0x00 }; -static const __u8 sn_ov7660[] = { +static const u8 sn_ov7660[0x1c] = { /* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */ 0x00, 0x61, 0x40, 0x00, 0x1a, 0x20, 0x20, 0x20, /* reg8 reg9 rega regb regc regd rege regf */ 0x81, 0x21, 0x07, 0x00, 0x00, 0x00, 0x00, 0x10, /* reg10 reg11 reg12 reg13 reg14 reg15 reg16 reg17 */ 0x03, 0x00, 0x01, 0x01, 0x08, 0x28, 0x1e, 0x20, -/* reg18 reg19 reg1a reg1b reg1c reg1d reg1e reg1f */ - 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +/* reg18 reg19 reg1a reg1b */ + 0x07, 0x00, 0x00, 0x00 }; /* sequence specific to the sensors - !! index = SENSOR_xxx */ -static const __u8 *sn_tb[] = { +static const u8 *sn_tb[] = { sn_hv7131, sn_mi0360, sn_mo4000, @@ -348,88 +345,88 @@ static const __u8 reg84[] = { 0x00, 0x00, 0x00 /* YUV offsets */ }; static const __u8 hv7131r_sensor_init[][8] = { - {0xC1, 0x11, 0x01, 0x08, 0x01, 0x00, 0x00, 0x10}, - {0xB1, 0x11, 0x34, 0x17, 0x7F, 0x00, 0x00, 0x10}, - {0xD1, 0x11, 0x40, 0xFF, 0x7F, 0x7F, 0x7F, 0x10}, - {0x91, 0x11, 0x44, 0x00, 0x00, 0x00, 0x00, 0x10}, - {0xD1, 0x11, 0x10, 0x00, 0x00, 0x00, 0x00, 0x10}, - {0xD1, 0x11, 0x14, 0x01, 0xE2, 0x02, 0x82, 0x10}, - {0x91, 0x11, 0x18, 0x00, 0x00, 0x00, 0x00, 0x10}, - - {0xA1, 0x11, 0x01, 0x08, 0x00, 0x00, 0x00, 0x10}, - {0xA1, 0x11, 0x01, 0x08, 0x00, 0x00, 0x00, 0x10}, - {0xC1, 0x11, 0x25, 0x00, 0x61, 0xA8, 0x00, 0x10}, - {0xA1, 0x11, 0x30, 0x22, 0x00, 0x00, 0x00, 0x10}, - {0xC1, 0x11, 0x31, 0x20, 0x2E, 0x20, 0x00, 0x10}, - {0xC1, 0x11, 0x25, 0x00, 0xC3, 0x50, 0x00, 0x10}, - {0xA1, 0x11, 0x30, 0x07, 0x00, 0x00, 0x00, 0x10}, /* gain14 */ - {0xC1, 0x11, 0x31, 0x10, 0x10, 0x10, 0x00, 0x10}, /* r g b 101a10 */ - - {0xA1, 0x11, 0x01, 0x08, 0x00, 0x00, 0x00, 0x10}, - {0xA1, 0x11, 0x20, 0x00, 0x00, 0x00, 0x00, 0x10}, - {0xA1, 0x11, 0x21, 0xD0, 0x00, 0x00, 0x00, 0x10}, - {0xA1, 0x11, 0x22, 0x00, 0x00, 0x00, 0x00, 0x10}, - {0xA1, 0x11, 0x23, 0x09, 0x00, 0x00, 0x00, 0x10}, - - {0xA1, 0x11, 0x01, 0x08, 0x00, 0x00, 0x00, 0x10}, - {0xA1, 0x11, 0x20, 0x00, 0x00, 0x00, 0x00, 0x10}, - {0xA1, 0x11, 0x21, 0xD0, 0x00, 0x00, 0x00, 0x10}, - {0xA1, 0x11, 0x22, 0x00, 0x00, 0x00, 0x00, 0x10}, - {0xA1, 0x11, 0x23, 0x10, 0x00, 0x00, 0x00, 0x10}, + {0xc1, 0x11, 0x01, 0x08, 0x01, 0x00, 0x00, 0x10}, + {0xb1, 0x11, 0x34, 0x17, 0x7f, 0x00, 0x00, 0x10}, + {0xd1, 0x11, 0x40, 0xff, 0x7f, 0x7f, 0x7f, 0x10}, +/* {0x91, 0x11, 0x44, 0x00, 0x00, 0x00, 0x00, 0x10}, */ + {0xd1, 0x11, 0x10, 0x00, 0x00, 0x00, 0x00, 0x10}, + {0xd1, 0x11, 0x14, 0x01, 0xe2, 0x02, 0x82, 0x10}, +/* {0x91, 0x11, 0x18, 0x00, 0x00, 0x00, 0x00, 0x10}, */ + + {0xa1, 0x11, 0x01, 0x08, 0x00, 0x00, 0x00, 0x10}, + {0xa1, 0x11, 0x01, 0x08, 0x00, 0x00, 0x00, 0x10}, + {0xc1, 0x11, 0x25, 0x00, 0x61, 0xa8, 0x00, 0x10}, + {0xa1, 0x11, 0x30, 0x22, 0x00, 0x00, 0x00, 0x10}, + {0xc1, 0x11, 0x31, 0x20, 0x2e, 0x20, 0x00, 0x10}, + {0xc1, 0x11, 0x25, 0x00, 0xc3, 0x50, 0x00, 0x10}, + {0xa1, 0x11, 0x30, 0x07, 0x00, 0x00, 0x00, 0x10}, /* gain14 */ + {0xc1, 0x11, 0x31, 0x10, 0x10, 0x10, 0x00, 0x10}, /* r g b 101a10 */ + + {0xa1, 0x11, 0x01, 0x08, 0x00, 0x00, 0x00, 0x10}, + {0xa1, 0x11, 0x20, 0x00, 0x00, 0x00, 0x00, 0x10}, + {0xa1, 0x11, 0x21, 0xD0, 0x00, 0x00, 0x00, 0x10}, + {0xa1, 0x11, 0x22, 0x00, 0x00, 0x00, 0x00, 0x10}, + {0xa1, 0x11, 0x23, 0x09, 0x00, 0x00, 0x00, 0x10}, + + {0xa1, 0x11, 0x01, 0x08, 0x00, 0x00, 0x00, 0x10}, + {0xa1, 0x11, 0x20, 0x00, 0x00, 0x00, 0x00, 0x10}, + {0xa1, 0x11, 0x21, 0xd0, 0x00, 0x00, 0x00, 0x10}, + {0xa1, 0x11, 0x22, 0x00, 0x00, 0x00, 0x00, 0x10}, + {0xa1, 0x11, 0x23, 0x10, 0x00, 0x00, 0x00, 0x10}, {} }; static const __u8 mi0360_sensor_init[][8] = { - {0xB1, 0x5D, 0x07, 0x00, 0x02, 0x00, 0x00, 0x10}, - {0xB1, 0x5D, 0x0D, 0x00, 0x01, 0x00, 0x00, 0x10}, - {0xB1, 0x5D, 0x0D, 0x00, 0x00, 0x00, 0x00, 0x10}, - {0xD1, 0x5D, 0x01, 0x00, 0x08, 0x00, 0x16, 0x10}, - {0xD1, 0x5D, 0x03, 0x01, 0xE2, 0x02, 0x82, 0x10}, - {0xD1, 0x5D, 0x05, 0x00, 0x09, 0x00, 0x53, 0x10}, - {0xB1, 0x5D, 0x0D, 0x00, 0x02, 0x00, 0x00, 0x10}, - {0xD1, 0x5D, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x10}, - {0xD1, 0x5D, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x10}, - {0xD1, 0x5D, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x10}, - {0xD1, 0x5D, 0x10, 0x00, 0x00, 0x00, 0x00, 0x10}, - {0xD1, 0x5D, 0x12, 0x00, 0x00, 0x00, 0x00, 0x10}, - {0xD1, 0x5D, 0x14, 0x00, 0x00, 0x00, 0x00, 0x10}, - {0xD1, 0x5D, 0x16, 0x00, 0x00, 0x00, 0x00, 0x10}, - {0xD1, 0x5D, 0x18, 0x00, 0x00, 0x00, 0x00, 0x10}, - {0xD1, 0x5D, 0x1A, 0x00, 0x00, 0x00, 0x00, 0x10}, - {0xD1, 0x5D, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x10}, - {0xB1, 0x5D, 0x32, 0x00, 0x00, 0x00, 0x00, 0x10}, - {0xD1, 0x5D, 0x20, 0x91, 0x01, 0x00, 0x00, 0x10}, - {0xD1, 0x5D, 0x22, 0x00, 0x00, 0x00, 0x00, 0x10}, - {0xD1, 0x5D, 0x24, 0x00, 0x00, 0x00, 0x00, 0x10}, - {0xD1, 0x5D, 0x26, 0x00, 0x00, 0x00, 0x24, 0x10}, - {0xD1, 0x5D, 0x2F, 0xF7, 0xB0, 0x00, 0x04, 0x10}, - {0xD1, 0x5D, 0x31, 0x00, 0x00, 0x00, 0x00, 0x10}, - {0xD1, 0x5D, 0x33, 0x00, 0x00, 0x01, 0x00, 0x10}, - {0xB1, 0x5D, 0x3D, 0x06, 0x8F, 0x00, 0x00, 0x10}, - {0xD1, 0x5D, 0x40, 0x01, 0xE0, 0x00, 0xD1, 0x10}, - {0xB1, 0x5D, 0x44, 0x00, 0x82, 0x00, 0x00, 0x10}, - {0xD1, 0x5D, 0x58, 0x00, 0x78, 0x00, 0x43, 0x10}, - {0xD1, 0x5D, 0x5A, 0x00, 0x00, 0x00, 0x00, 0x10}, - {0xD1, 0x5D, 0x5C, 0x00, 0x00, 0x00, 0x00, 0x10}, - {0xD1, 0x5D, 0x5E, 0x00, 0x00, 0xA3, 0x1D, 0x10}, - {0xB1, 0x5D, 0x62, 0x04, 0x11, 0x00, 0x00, 0x10}, - - {0xB1, 0x5D, 0x20, 0x91, 0x01, 0x00, 0x00, 0x10}, - {0xB1, 0x5D, 0x20, 0x11, 0x01, 0x00, 0x00, 0x10}, - {0xB1, 0x5D, 0x09, 0x00, 0x64, 0x00, 0x00, 0x10}, - {0xD1, 0x5D, 0x2B, 0x00, 0xA0, 0x00, 0xB0, 0x10}, - {0xD1, 0x5D, 0x2D, 0x00, 0xA0, 0x00, 0xA0, 0x10}, - - {0xB1, 0x5D, 0x0A, 0x00, 0x02, 0x00, 0x00, 0x10}, /* sensor clck ?2 */ - {0xB1, 0x5D, 0x06, 0x00, 0x30, 0x00, 0x00, 0x10}, - {0xB1, 0x5D, 0x05, 0x00, 0x0A, 0x00, 0x00, 0x10}, - {0xB1, 0x5D, 0x09, 0x02, 0x35, 0x00, 0x00, 0x10}, /* exposure 2 */ - - {0xD1, 0x5D, 0x2B, 0x00, 0xB9, 0x00, 0xE3, 0x10}, - {0xD1, 0x5D, 0x2D, 0x00, 0x5f, 0x00, 0xB9, 0x10}, /* 42 */ -/* {0xB1, 0x5D, 0x35, 0x00, 0x67, 0x00, 0x00, 0x10}, * gain orig */ -/* {0xB1, 0x5D, 0x35, 0x00, 0x20, 0x00, 0x00, 0x10}, * gain */ - {0xB1, 0x5D, 0x07, 0x00, 0x03, 0x00, 0x00, 0x10}, /* update */ - {0xB1, 0x5D, 0x07, 0x00, 0x02, 0x00, 0x00, 0x10}, /* sensor on */ + {0xb1, 0x5d, 0x07, 0x00, 0x02, 0x00, 0x00, 0x10}, + {0xb1, 0x5d, 0x0D, 0x00, 0x01, 0x00, 0x00, 0x10}, + {0xb1, 0x5d, 0x0D, 0x00, 0x00, 0x00, 0x00, 0x10}, + {0xd1, 0x5d, 0x01, 0x00, 0x08, 0x00, 0x16, 0x10}, + {0xd1, 0x5d, 0x03, 0x01, 0xe2, 0x02, 0x82, 0x10}, + {0xd1, 0x5d, 0x05, 0x00, 0x09, 0x00, 0x53, 0x10}, + {0xb1, 0x5d, 0x0d, 0x00, 0x02, 0x00, 0x00, 0x10}, + {0xd1, 0x5d, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x10}, + {0xd1, 0x5d, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x10}, + {0xd1, 0x5d, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x10}, + {0xd1, 0x5d, 0x10, 0x00, 0x00, 0x00, 0x00, 0x10}, + {0xd1, 0x5d, 0x12, 0x00, 0x00, 0x00, 0x00, 0x10}, + {0xd1, 0x5d, 0x14, 0x00, 0x00, 0x00, 0x00, 0x10}, + {0xd1, 0x5d, 0x16, 0x00, 0x00, 0x00, 0x00, 0x10}, + {0xd1, 0x5d, 0x18, 0x00, 0x00, 0x00, 0x00, 0x10}, + {0xd1, 0x5d, 0x1a, 0x00, 0x00, 0x00, 0x00, 0x10}, + {0xd1, 0x5d, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x10}, + {0xb1, 0x5d, 0x32, 0x00, 0x00, 0x00, 0x00, 0x10}, + {0xd1, 0x5d, 0x20, 0x91, 0x01, 0x00, 0x00, 0x10}, + {0xd1, 0x5d, 0x22, 0x00, 0x00, 0x00, 0x00, 0x10}, + {0xd1, 0x5d, 0x24, 0x00, 0x00, 0x00, 0x00, 0x10}, + {0xd1, 0x5d, 0x26, 0x00, 0x00, 0x00, 0x24, 0x10}, + {0xd1, 0x5d, 0x2F, 0xF7, 0xB0, 0x00, 0x04, 0x10}, + {0xd1, 0x5d, 0x31, 0x00, 0x00, 0x00, 0x00, 0x10}, + {0xd1, 0x5d, 0x33, 0x00, 0x00, 0x01, 0x00, 0x10}, + {0xb1, 0x5d, 0x3d, 0x06, 0x8f, 0x00, 0x00, 0x10}, + {0xd1, 0x5d, 0x40, 0x01, 0xe0, 0x00, 0xd1, 0x10}, + {0xb1, 0x5d, 0x44, 0x00, 0x82, 0x00, 0x00, 0x10}, + {0xd1, 0x5d, 0x58, 0x00, 0x78, 0x00, 0x43, 0x10}, + {0xd1, 0x5d, 0x5a, 0x00, 0x00, 0x00, 0x00, 0x10}, + {0xd1, 0x5d, 0x5c, 0x00, 0x00, 0x00, 0x00, 0x10}, + {0xd1, 0x5d, 0x5e, 0x00, 0x00, 0xa3, 0x1d, 0x10}, + {0xb1, 0x5d, 0x62, 0x04, 0x11, 0x00, 0x00, 0x10}, + + {0xb1, 0x5d, 0x20, 0x91, 0x01, 0x00, 0x00, 0x10}, + {0xb1, 0x5d, 0x20, 0x11, 0x01, 0x00, 0x00, 0x10}, + {0xb1, 0x5d, 0x09, 0x00, 0x64, 0x00, 0x00, 0x10}, + {0xd1, 0x5d, 0x2b, 0x00, 0xa0, 0x00, 0xb0, 0x10}, + {0xd1, 0x5d, 0x2d, 0x00, 0xa0, 0x00, 0xa0, 0x10}, + + {0xb1, 0x5d, 0x0a, 0x00, 0x02, 0x00, 0x00, 0x10}, /* sensor clck ?2 */ + {0xb1, 0x5d, 0x06, 0x00, 0x30, 0x00, 0x00, 0x10}, + {0xb1, 0x5d, 0x05, 0x00, 0x0a, 0x00, 0x00, 0x10}, + {0xb1, 0x5d, 0x09, 0x02, 0x35, 0x00, 0x00, 0x10}, /* exposure 2 */ + + {0xd1, 0x5d, 0x2b, 0x00, 0xb9, 0x00, 0xe3, 0x10}, + {0xd1, 0x5d, 0x2d, 0x00, 0x5f, 0x00, 0xb9, 0x10}, /* 42 */ +/* {0xb1, 0x5d, 0x35, 0x00, 0x67, 0x00, 0x00, 0x10}, * gain orig */ +/* {0xb1, 0x5d, 0x35, 0x00, 0x20, 0x00, 0x00, 0x10}, * gain */ + {0xb1, 0x5d, 0x07, 0x00, 0x03, 0x00, 0x00, 0x10}, /* update */ + {0xb1, 0x5d, 0x07, 0x00, 0x02, 0x00, 0x00, 0x10}, /* sensor on */ {} }; static const __u8 mo4000_sensor_init[][8] = { @@ -680,15 +677,15 @@ static const __u8 ov7660_sensor_init[][8] = { static const __u8 qtable4[] = { 0x06, 0x04, 0x04, 0x06, 0x04, 0x04, 0x06, 0x06, 0x06, 0x06, 0x08, 0x06, - 0x06, 0x08, 0x0A, 0x11, - 0x0A, 0x0A, 0x08, 0x08, 0x0A, 0x15, 0x0F, 0x0F, 0x0C, 0x11, 0x19, 0x15, + 0x06, 0x08, 0x0a, 0x11, + 0x0a, 0x0a, 0x08, 0x08, 0x0a, 0x15, 0x0f, 0x0f, 0x0c, 0x11, 0x19, 0x15, 0x19, 0x19, 0x17, 0x15, - 0x17, 0x17, 0x1B, 0x1D, 0x25, 0x21, 0x1B, 0x1D, 0x23, 0x1D, 0x17, 0x17, - 0x21, 0x2E, 0x21, 0x23, - 0x27, 0x29, 0x2C, 0x2C, 0x2C, 0x19, 0x1F, 0x30, 0x32, 0x2E, 0x29, 0x32, - 0x25, 0x29, 0x2C, 0x29, - 0x06, 0x08, 0x08, 0x0A, 0x08, 0x0A, 0x13, 0x0A, 0x0A, 0x13, 0x29, 0x1B, - 0x17, 0x1B, 0x29, 0x29, + 0x17, 0x17, 0x1b, 0x1d, 0x25, 0x21, 0x1b, 0x1d, 0x23, 0x1d, 0x17, 0x17, + 0x21, 0x2e, 0x21, 0x23, + 0x27, 0x29, 0x2c, 0x2c, 0x2c, 0x19, 0x1f, 0x30, 0x32, 0x2e, 0x29, 0x32, + 0x25, 0x29, 0x2c, 0x29, + 0x06, 0x08, 0x08, 0x0a, 0x08, 0x0a, 0x13, 0x0a, 0x0a, 0x13, 0x29, 0x1b, + 0x17, 0x1b, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, -- cgit v1.2.3 From 8d584a53ac82edc0bc01add620d94b3a2d4e9cce Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Tue, 13 Jan 2009 06:07:59 -0300 Subject: V4L/DVB (10357): gspca - main: Cleanup code. Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/gspca.c | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/gspca/gspca.c b/drivers/media/video/gspca/gspca.c index e13833b8ed67..5dd2abc17ae6 100644 --- a/drivers/media/video/gspca/gspca.c +++ b/drivers/media/video/gspca/gspca.c @@ -46,8 +46,6 @@ MODULE_LICENSE("GPL"); #define DRIVER_VERSION_NUMBER KERNEL_VERSION(2, 5, 0) -static int video_nr = -1; - #ifdef GSPCA_DEBUG int gspca_debug = D_ERR | D_PROBE; EXPORT_SYMBOL(gspca_debug); @@ -126,7 +124,7 @@ static void fill_frame(struct gspca_dev *gspca_dev, struct urb *urb) { struct gspca_frame *frame; - __u8 *data; /* address of data in the iso message */ + u8 *data; /* address of data in the iso message */ int i, len, st; cam_pkt_op pkt_scan; @@ -166,7 +164,7 @@ static void fill_frame(struct gspca_dev *gspca_dev, /* let the packet be analyzed by the subdriver */ PDEBUG(D_PACK, "packet [%d] o:%d l:%d", i, urb->iso_frame_desc[i].offset, len); - data = (__u8 *) urb->transfer_buffer + data = (u8 *) urb->transfer_buffer + urb->iso_frame_desc[i].offset; pkt_scan(gspca_dev, frame, data, len); } @@ -182,8 +180,7 @@ static void fill_frame(struct gspca_dev *gspca_dev, * * Analyse each packet and call the subdriver for copy to the frame buffer. */ -static void isoc_irq(struct urb *urb -) +static void isoc_irq(struct urb *urb) { struct gspca_dev *gspca_dev = (struct gspca_dev *) urb->context; @@ -196,8 +193,7 @@ static void isoc_irq(struct urb *urb /* * bulk message interrupt from the USB device */ -static void bulk_irq(struct urb *urb -) +static void bulk_irq(struct urb *urb) { struct gspca_dev *gspca_dev = (struct gspca_dev *) urb->context; struct gspca_frame *frame; @@ -1916,7 +1912,7 @@ int gspca_dev_probe(struct usb_interface *intf, gspca_dev->present = 1; ret = video_register_device(&gspca_dev->vdev, VFL_TYPE_GRABBER, - video_nr); + -1); if (ret < 0) { err("video_register_device err %d", ret); goto out; -- cgit v1.2.3 From 625deb3d25a45102b155764beb2e8f232b8d5864 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Thu, 15 Jan 2009 06:11:49 -0300 Subject: V4L/DVB (10360): gspca - mars: Bad interface/altsetting since 0a10a0e906be. Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/mars.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/gspca/mars.c b/drivers/media/video/gspca/mars.c index 1eeac4041a61..7f605ce3a7e5 100644 --- a/drivers/media/video/gspca/mars.c +++ b/drivers/media/video/gspca/mars.c @@ -176,7 +176,7 @@ static int sd_config(struct gspca_dev *gspca_dev, sd->colors = COLOR_DEF; sd->gamma = GAMMA_DEF; sd->sharpness = SHARPNESS_DEF; - gspca_dev->iface = 9; /* use the altsetting 08 */ + gspca_dev->nbalt = 9; /* use the altsetting 08 */ return 0; } -- cgit v1.2.3 From 592f4eb9a2dc63afdbe78e2874d728f6e9e1e9f0 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Thu, 15 Jan 2009 08:01:32 -0300 Subject: V4L/DVB (10361): gspca - sonixj: Gamma control added. Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/sonixj.c | 57 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 55 insertions(+), 2 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/gspca/sonixj.c b/drivers/media/video/gspca/sonixj.c index d1c85ce39e56..db8db0c6bbb9 100644 --- a/drivers/media/video/gspca/sonixj.c +++ b/drivers/media/video/gspca/sonixj.c @@ -44,6 +44,7 @@ struct sd { __u8 autogain; __u8 blue; __u8 red; + u8 gamma; __u8 vflip; /* ov7630 only */ __u8 infrared; /* mi0360 only */ @@ -78,6 +79,8 @@ static int sd_setblue_balance(struct gspca_dev *gspca_dev, __s32 val); static int sd_getblue_balance(struct gspca_dev *gspca_dev, __s32 *val); static int sd_setred_balance(struct gspca_dev *gspca_dev, __s32 val); static int sd_getred_balance(struct gspca_dev *gspca_dev, __s32 *val); +static int sd_setgamma(struct gspca_dev *gspca_dev, __s32 val); +static int sd_getgamma(struct gspca_dev *gspca_dev, __s32 *val); static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val); static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val); static int sd_setvflip(struct gspca_dev *gspca_dev, __s32 val); @@ -158,6 +161,20 @@ static struct ctrl sd_ctrls[] = { .set = sd_setred_balance, .get = sd_getred_balance, }, + { + { + .id = V4L2_CID_GAMMA, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "Gamma", + .minimum = 0, + .maximum = 40, + .step = 1, +#define GAMMA_DEF 20 + .default_value = GAMMA_DEF, + }, + .set = sd_setgamma, + .get = sd_getgamma, + }, #define AUTOGAIN_IDX 5 { { @@ -332,11 +349,12 @@ static const u8 *sn_tb[] = { sn_ov7660 }; -static const __u8 gamma_def[] = { +static const __u8 gamma_def[17] = { 0x00, 0x2d, 0x46, 0x5a, 0x6c, 0x7c, 0x8b, 0x99, 0xa6, 0xb2, 0xbf, 0xca, 0xd5, 0xe0, 0xeb, 0xf5, 0xff }; + /* color matrix and offsets */ static const __u8 reg84[] = { 0x14, 0x00, 0x27, 0x00, 0x07, 0x00, /* YR YG YB gains */ @@ -1027,6 +1045,7 @@ static int sd_config(struct gspca_dev *gspca_dev, sd->colors = COLOR_DEF; sd->blue = BLUE_BALANCE_DEF; sd->red = RED_BALANCE_DEF; + sd->gamma = GAMMA_DEF; sd->autogain = AUTOGAIN_DEF; sd->ag_cnt = -1; sd->vflip = VFLIP_DEF; @@ -1231,6 +1250,22 @@ static void setredblue(struct gspca_dev *gspca_dev) reg_w1(gspca_dev, 0x06, sd->blue); } +static void setgamma(struct gspca_dev *gspca_dev) +{ + struct sd *sd = (struct sd *) gspca_dev; + int i; + u8 gamma[17]; + static const u8 delta[17] = { + 0x00, 0x14, 0x1c, 0x1c, 0x1c, 0x1c, 0x1b, 0x1a, + 0x18, 0x13, 0x10, 0x0e, 0x08, 0x07, 0x04, 0x02, 0x00 + }; + + for (i = 0; i < sizeof gamma; i++) + gamma[i] = gamma_def[i] + + delta[i] * (sd->gamma - GAMMA_DEF) / 32; + reg_w(gspca_dev, 0x20, gamma, sizeof gamma); +} + static void setautogain(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; @@ -1310,7 +1345,7 @@ static int sd_start(struct gspca_dev *gspca_dev) reg_w1(gspca_dev, 0x07, sn9c1xx[7]); /* green */ reg_w1(gspca_dev, 0x06, sn9c1xx[6]); /* blue */ reg_w1(gspca_dev, 0x14, sn9c1xx[0x14]); - reg_w(gspca_dev, 0x20, gamma_def, sizeof gamma_def); + setgamma(gspca_dev); for (i = 0; i < 8; i++) reg_w(gspca_dev, 0x84, reg84, sizeof reg84); switch (sd->sensor) { @@ -1640,6 +1675,24 @@ static int sd_getred_balance(struct gspca_dev *gspca_dev, __s32 *val) return 0; } +static int sd_setgamma(struct gspca_dev *gspca_dev, __s32 val) +{ + struct sd *sd = (struct sd *) gspca_dev; + + sd->gamma = val; + if (gspca_dev->streaming) + setgamma(gspca_dev); + return 0; +} + +static int sd_getgamma(struct gspca_dev *gspca_dev, __s32 *val) +{ + struct sd *sd = (struct sd *) gspca_dev; + + *val = sd->gamma; + return 0; +} + static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val) { struct sd *sd = (struct sd *) gspca_dev; -- cgit v1.2.3 From 48d7a8912751d46f5401cbd86eb6408b48050da2 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Thu, 15 Jan 2009 09:34:55 -0300 Subject: V4L/DVB (10363): gspca - spca500: Abnormal error message when starting ClickSmart310. Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/spca500.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/gspca/spca500.c b/drivers/media/video/gspca/spca500.c index 62c12fa10570..f44613095d2e 100644 --- a/drivers/media/video/gspca/spca500.c +++ b/drivers/media/video/gspca/spca500.c @@ -711,7 +711,8 @@ static int sd_start(struct gspca_dev *gspca_dev) write_vector(gspca_dev, spca500_visual_defaults); spca500_setmode(gspca_dev, xmult, ymult); /* enable drop packet */ - reg_w(gspca_dev, 0x00, 0x850a, 0x0001); + err = reg_w(gspca_dev, 0x00, 0x850a, 0x0001); + if (err < 0) PDEBUG(D_ERR, "failed to enable drop packet"); reg_w(gspca_dev, 0x00, 0x8880, 3); err = spca50x_setup_qtable(gspca_dev, -- cgit v1.2.3 From d661e62205498ce6518b9859bc30444e59737d8b Mon Sep 17 00:00:00 2001 From: Kyle Guinn Date: Fri, 16 Jan 2009 05:36:14 -0300 Subject: V4L/DVB (10366): gspca - mr97310a: New subdriver. This patch adds support for USB webcams based on the MR97310A chip. It was tested with an Aiptek PenCam VGA+ webcam. Signed-off-by: Kyle Guinn Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab --- Documentation/video4linux/gspca.txt | 1 + drivers/media/video/gspca/Kconfig | 9 + drivers/media/video/gspca/Makefile | 98 ++++----- drivers/media/video/gspca/gspca.c | 1 + drivers/media/video/gspca/mr97310a.c | 378 +++++++++++++++++++++++++++++++++++ 5 files changed, 439 insertions(+), 48 deletions(-) create mode 100644 drivers/media/video/gspca/mr97310a.c (limited to 'drivers/media/video') diff --git a/Documentation/video4linux/gspca.txt b/Documentation/video4linux/gspca.txt index 1c58a7630146..af80c3344567 100644 --- a/Documentation/video4linux/gspca.txt +++ b/Documentation/video4linux/gspca.txt @@ -193,6 +193,7 @@ spca500 084d:0003 D-Link DSC-350 spca500 08ca:0103 Aiptek PocketDV sunplus 08ca:0104 Aiptek PocketDVII 1.3 sunplus 08ca:0106 Aiptek Pocket DV3100+ +mr97310a 08ca:0111 Aiptek PenCam VGA+ sunplus 08ca:2008 Aiptek Mini PenCam 2 M sunplus 08ca:2010 Aiptek PocketCam 3M sunplus 08ca:2016 Aiptek PocketCam 2 Mega diff --git a/drivers/media/video/gspca/Kconfig b/drivers/media/video/gspca/Kconfig index ee6a691dff22..11c5d2fc20de 100644 --- a/drivers/media/video/gspca/Kconfig +++ b/drivers/media/video/gspca/Kconfig @@ -56,6 +56,15 @@ config USB_GSPCA_MARS To compile this driver as a module, choose M here: the module will be called gspca_mars. +config USB_GSPCA_MR97310A + tristate "Mars-Semi MR97310A USB Camera Driver" + depends on VIDEO_V4L2 && USB_GSPCA + help + Say Y here if you want support for cameras based on the MR97310A chip. + + To compile this driver as a module, choose M here: the + module will be called gspca_mr97310a. + config USB_GSPCA_OV519 tristate "OV519 USB Camera Driver" depends on VIDEO_V4L2 && USB_GSPCA diff --git a/drivers/media/video/gspca/Makefile b/drivers/media/video/gspca/Makefile index bd8d9ee40504..b3cbcc1764f4 100644 --- a/drivers/media/video/gspca/Makefile +++ b/drivers/media/video/gspca/Makefile @@ -1,50 +1,52 @@ -obj-$(CONFIG_USB_GSPCA) += gspca_main.o -obj-$(CONFIG_USB_GSPCA_CONEX) += gspca_conex.o -obj-$(CONFIG_USB_GSPCA_ETOMS) += gspca_etoms.o -obj-$(CONFIG_USB_GSPCA_FINEPIX) += gspca_finepix.o -obj-$(CONFIG_USB_GSPCA_MARS) += gspca_mars.o -obj-$(CONFIG_USB_GSPCA_OV519) += gspca_ov519.o -obj-$(CONFIG_USB_GSPCA_OV534) += gspca_ov534.o -obj-$(CONFIG_USB_GSPCA_PAC207) += gspca_pac207.o -obj-$(CONFIG_USB_GSPCA_PAC7311) += gspca_pac7311.o -obj-$(CONFIG_USB_GSPCA_SONIXB) += gspca_sonixb.o -obj-$(CONFIG_USB_GSPCA_SONIXJ) += gspca_sonixj.o -obj-$(CONFIG_USB_GSPCA_SPCA500) += gspca_spca500.o -obj-$(CONFIG_USB_GSPCA_SPCA501) += gspca_spca501.o -obj-$(CONFIG_USB_GSPCA_SPCA505) += gspca_spca505.o -obj-$(CONFIG_USB_GSPCA_SPCA506) += gspca_spca506.o -obj-$(CONFIG_USB_GSPCA_SPCA508) += gspca_spca508.o -obj-$(CONFIG_USB_GSPCA_SPCA561) += gspca_spca561.o -obj-$(CONFIG_USB_GSPCA_SUNPLUS) += gspca_sunplus.o -obj-$(CONFIG_USB_GSPCA_STK014) += gspca_stk014.o -obj-$(CONFIG_USB_GSPCA_T613) += gspca_t613.o -obj-$(CONFIG_USB_GSPCA_TV8532) += gspca_tv8532.o -obj-$(CONFIG_USB_GSPCA_VC032X) += gspca_vc032x.o -obj-$(CONFIG_USB_GSPCA_ZC3XX) += gspca_zc3xx.o +obj-$(CONFIG_USB_GSPCA) += gspca_main.o +obj-$(CONFIG_USB_GSPCA_CONEX) += gspca_conex.o +obj-$(CONFIG_USB_GSPCA_ETOMS) += gspca_etoms.o +obj-$(CONFIG_USB_GSPCA_FINEPIX) += gspca_finepix.o +obj-$(CONFIG_USB_GSPCA_MARS) += gspca_mars.o +obj-$(CONFIG_USB_GSPCA_MR97310A) += gspca_mr97310a.o +obj-$(CONFIG_USB_GSPCA_OV519) += gspca_ov519.o +obj-$(CONFIG_USB_GSPCA_OV534) += gspca_ov534.o +obj-$(CONFIG_USB_GSPCA_PAC207) += gspca_pac207.o +obj-$(CONFIG_USB_GSPCA_PAC7311) += gspca_pac7311.o +obj-$(CONFIG_USB_GSPCA_SONIXB) += gspca_sonixb.o +obj-$(CONFIG_USB_GSPCA_SONIXJ) += gspca_sonixj.o +obj-$(CONFIG_USB_GSPCA_SPCA500) += gspca_spca500.o +obj-$(CONFIG_USB_GSPCA_SPCA501) += gspca_spca501.o +obj-$(CONFIG_USB_GSPCA_SPCA505) += gspca_spca505.o +obj-$(CONFIG_USB_GSPCA_SPCA506) += gspca_spca506.o +obj-$(CONFIG_USB_GSPCA_SPCA508) += gspca_spca508.o +obj-$(CONFIG_USB_GSPCA_SPCA561) += gspca_spca561.o +obj-$(CONFIG_USB_GSPCA_SUNPLUS) += gspca_sunplus.o +obj-$(CONFIG_USB_GSPCA_STK014) += gspca_stk014.o +obj-$(CONFIG_USB_GSPCA_T613) += gspca_t613.o +obj-$(CONFIG_USB_GSPCA_TV8532) += gspca_tv8532.o +obj-$(CONFIG_USB_GSPCA_VC032X) += gspca_vc032x.o +obj-$(CONFIG_USB_GSPCA_ZC3XX) += gspca_zc3xx.o -gspca_main-objs := gspca.o -gspca_conex-objs := conex.o -gspca_etoms-objs := etoms.o -gspca_finepix-objs := finepix.o -gspca_mars-objs := mars.o -gspca_ov519-objs := ov519.o -gspca_ov534-objs := ov534.o -gspca_pac207-objs := pac207.o -gspca_pac7311-objs := pac7311.o -gspca_sonixb-objs := sonixb.o -gspca_sonixj-objs := sonixj.o -gspca_spca500-objs := spca500.o -gspca_spca501-objs := spca501.o -gspca_spca505-objs := spca505.o -gspca_spca506-objs := spca506.o -gspca_spca508-objs := spca508.o -gspca_spca561-objs := spca561.o -gspca_stk014-objs := stk014.o -gspca_sunplus-objs := sunplus.o -gspca_t613-objs := t613.o -gspca_tv8532-objs := tv8532.o -gspca_vc032x-objs := vc032x.o -gspca_zc3xx-objs := zc3xx.o +gspca_main-objs := gspca.o +gspca_conex-objs := conex.o +gspca_etoms-objs := etoms.o +gspca_finepix-objs := finepix.o +gspca_mars-objs := mars.o +gspca_mr97310a-objs := mr97310a.o +gspca_ov519-objs := ov519.o +gspca_ov534-objs := ov534.o +gspca_pac207-objs := pac207.o +gspca_pac7311-objs := pac7311.o +gspca_sonixb-objs := sonixb.o +gspca_sonixj-objs := sonixj.o +gspca_spca500-objs := spca500.o +gspca_spca501-objs := spca501.o +gspca_spca505-objs := spca505.o +gspca_spca506-objs := spca506.o +gspca_spca508-objs := spca508.o +gspca_spca561-objs := spca561.o +gspca_stk014-objs := stk014.o +gspca_sunplus-objs := sunplus.o +gspca_t613-objs := t613.o +gspca_tv8532-objs := tv8532.o +gspca_vc032x-objs := vc032x.o +gspca_zc3xx-objs := zc3xx.o -obj-$(CONFIG_USB_M5602) += m5602/ -obj-$(CONFIG_USB_STV06XX) += stv06xx/ +obj-$(CONFIG_USB_M5602) += m5602/ +obj-$(CONFIG_USB_STV06XX) += stv06xx/ diff --git a/drivers/media/video/gspca/gspca.c b/drivers/media/video/gspca/gspca.c index 5dd2abc17ae6..6c03d57ae506 100644 --- a/drivers/media/video/gspca/gspca.c +++ b/drivers/media/video/gspca/gspca.c @@ -318,6 +318,7 @@ static int gspca_is_compressed(__u32 format) case V4L2_PIX_FMT_JPEG: case V4L2_PIX_FMT_SPCA561: case V4L2_PIX_FMT_PAC207: + case V4L2_PIX_FMT_MR97310A: return 1; } return 0; diff --git a/drivers/media/video/gspca/mr97310a.c b/drivers/media/video/gspca/mr97310a.c new file mode 100644 index 000000000000..24180bf0cdab --- /dev/null +++ b/drivers/media/video/gspca/mr97310a.c @@ -0,0 +1,378 @@ +/* + * Mars MR97310A library + * + * Copyright (C) 2009 Kyle Guinn + * + * 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 + * 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 + */ + +#define MODULE_NAME "mr97310a" + +#include "gspca.h" + +MODULE_AUTHOR("Kyle Guinn "); +MODULE_DESCRIPTION("GSPCA/Mars-Semi MR97310A USB Camera Driver"); +MODULE_LICENSE("GPL"); + +/* specific webcam descriptor */ +struct sd { + struct gspca_dev gspca_dev; /* !! must be the first item */ + + u8 sof_read; + u8 header_read; +}; + +/* V4L2 controls supported by the driver */ +static struct ctrl sd_ctrls[] = { +}; + +static const struct v4l2_pix_format vga_mode[] = { + {160, 120, V4L2_PIX_FMT_MR97310A, V4L2_FIELD_NONE, + .bytesperline = 160, + .sizeimage = 160 * 120, + .colorspace = V4L2_COLORSPACE_SRGB, + .priv = 4}, + {176, 144, V4L2_PIX_FMT_MR97310A, V4L2_FIELD_NONE, + .bytesperline = 176, + .sizeimage = 176 * 144, + .colorspace = V4L2_COLORSPACE_SRGB, + .priv = 3}, + {320, 240, V4L2_PIX_FMT_MR97310A, V4L2_FIELD_NONE, + .bytesperline = 320, + .sizeimage = 320 * 240, + .colorspace = V4L2_COLORSPACE_SRGB, + .priv = 2}, + {352, 288, V4L2_PIX_FMT_MR97310A, V4L2_FIELD_NONE, + .bytesperline = 352, + .sizeimage = 352 * 288, + .colorspace = V4L2_COLORSPACE_SRGB, + .priv = 1}, + {640, 480, V4L2_PIX_FMT_MR97310A, V4L2_FIELD_NONE, + .bytesperline = 640, + .sizeimage = 640 * 480, + .colorspace = V4L2_COLORSPACE_SRGB, + .priv = 0}, +}; + +/* the bytes to write are in gspca_dev->usb_buf */ +static int reg_w(struct gspca_dev *gspca_dev, int len) +{ + int rc; + + rc = usb_bulk_msg(gspca_dev->dev, + usb_sndbulkpipe(gspca_dev->dev, 4), + gspca_dev->usb_buf, len, 0, 500); + if (rc < 0) + PDEBUG(D_ERR, "reg write [%02x] error %d", + gspca_dev->usb_buf[0], rc); + return rc; +} + +/* this function is called at probe time */ +static int sd_config(struct gspca_dev *gspca_dev, + const struct usb_device_id *id) +{ + struct cam *cam; + + cam = &gspca_dev->cam; + cam->cam_mode = vga_mode; + cam->nmodes = ARRAY_SIZE(vga_mode); + return 0; +} + +/* this function is called at probe and resume time */ +static int sd_init(struct gspca_dev *gspca_dev) +{ + return 0; +} + +static int sd_start(struct gspca_dev *gspca_dev) +{ + struct sd *sd = (struct sd *) gspca_dev; + __u8 *data = gspca_dev->usb_buf; + int err_code; + + sd->sof_read = 0; + + /* Note: register descriptions guessed from MR97113A driver */ + + data[0] = 0x01; + data[1] = 0x01; + err_code = reg_w(gspca_dev, 2); + if (err_code < 0) + return err_code; + + data[0] = 0x00; + data[1] = 0x0d; + data[2] = 0x01; + data[5] = 0x2b; + data[7] = 0x00; + data[9] = 0x50; /* reg 8, no scale down */ + data[10] = 0xc0; + + switch (gspca_dev->width) { + case 160: + data[9] |= 0x0c; /* reg 8, 4:1 scale down */ + /* fall thru */ + case 320: + data[9] |= 0x04; /* reg 8, 2:1 scale down */ + /* fall thru */ + case 640: + default: + data[3] = 0x50; /* reg 2, H size */ + data[4] = 0x78; /* reg 3, V size */ + data[6] = 0x04; /* reg 5, H start */ + data[8] = 0x03; /* reg 7, V start */ + break; + + case 176: + data[9] |= 0x04; /* reg 8, 2:1 scale down */ + /* fall thru */ + case 352: + data[3] = 0x2c; /* reg 2, H size */ + data[4] = 0x48; /* reg 3, V size */ + data[6] = 0x94; /* reg 5, H start */ + data[8] = 0x63; /* reg 7, V start */ + break; + } + + err_code = reg_w(gspca_dev, 11); + if (err_code < 0) + return err_code; + + data[0] = 0x0a; + data[1] = 0x80; + err_code = reg_w(gspca_dev, 2); + if (err_code < 0) + return err_code; + + data[0] = 0x14; + data[1] = 0x0a; + err_code = reg_w(gspca_dev, 2); + if (err_code < 0) + return err_code; + + data[0] = 0x1b; + data[1] = 0x00; + err_code = reg_w(gspca_dev, 2); + if (err_code < 0) + return err_code; + + data[0] = 0x15; + data[1] = 0x16; + err_code = reg_w(gspca_dev, 2); + if (err_code < 0) + return err_code; + + data[0] = 0x16; + data[1] = 0x10; + err_code = reg_w(gspca_dev, 2); + if (err_code < 0) + return err_code; + + data[0] = 0x17; + data[1] = 0x3a; + err_code = reg_w(gspca_dev, 2); + if (err_code < 0) + return err_code; + + data[0] = 0x18; + data[1] = 0x68; + err_code = reg_w(gspca_dev, 2); + if (err_code < 0) + return err_code; + + data[0] = 0x1f; + data[1] = 0x00; + data[2] = 0x02; + data[3] = 0x06; + data[4] = 0x59; + data[5] = 0x0c; + data[6] = 0x16; + data[7] = 0x00; + data[8] = 0x07; + data[9] = 0x00; + data[10] = 0x01; + err_code = reg_w(gspca_dev, 11); + if (err_code < 0) + return err_code; + + data[0] = 0x1f; + data[1] = 0x04; + data[2] = 0x11; + data[3] = 0x01; + err_code = reg_w(gspca_dev, 4); + if (err_code < 0) + return err_code; + + data[0] = 0x1f; + data[1] = 0x00; + data[2] = 0x0a; + data[3] = 0x00; + data[4] = 0x01; + data[5] = 0x00; + data[6] = 0x00; + data[7] = 0x01; + data[8] = 0x00; + data[9] = 0x0a; + err_code = reg_w(gspca_dev, 10); + if (err_code < 0) + return err_code; + + data[0] = 0x1f; + data[1] = 0x04; + data[2] = 0x11; + data[3] = 0x01; + err_code = reg_w(gspca_dev, 4); + if (err_code < 0) + return err_code; + + data[0] = 0x1f; + data[1] = 0x00; + data[2] = 0x12; + data[3] = 0x00; + data[4] = 0x63; + data[5] = 0x00; + data[6] = 0x70; + data[7] = 0x00; + data[8] = 0x01; + err_code = reg_w(gspca_dev, 10); + if (err_code < 0) + return err_code; + + data[0] = 0x1f; + data[1] = 0x04; + data[2] = 0x11; + data[3] = 0x01; + err_code = reg_w(gspca_dev, 4); + if (err_code < 0) + return err_code; + + data[0] = 0x00; + data[1] = 0x4d; /* ISOC transfering enable... */ + err_code = reg_w(gspca_dev, 2); + return err_code; +} + +static void sd_stopN(struct gspca_dev *gspca_dev) +{ + int result; + + gspca_dev->usb_buf[0] = 1; + gspca_dev->usb_buf[1] = 0; + result = reg_w(gspca_dev, 2); + if (result < 0) + PDEBUG(D_ERR, "Camera Stop failed"); +} + +/* Include pac common sof detection functions */ +#include "pac_common.h" + +static void sd_pkt_scan(struct gspca_dev *gspca_dev, + struct gspca_frame *frame, /* target */ + __u8 *data, /* isoc packet */ + int len) /* iso packet length */ +{ + struct sd *sd = (struct sd *) gspca_dev; + unsigned char *sof; + + sof = pac_find_sof(gspca_dev, data, len); + if (sof) { + int n; + + /* finish decoding current frame */ + n = sof - data; + if (n > sizeof pac_sof_marker) + n -= sizeof pac_sof_marker; + else + n = 0; + frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame, + data, n); + sd->header_read = 0; + gspca_frame_add(gspca_dev, FIRST_PACKET, frame, NULL, 0); + len -= sof - data; + data = sof; + } + if (sd->header_read < 7) { + int needed; + + /* skip the rest of the header */ + needed = 7 - sd->header_read; + if (len <= needed) { + sd->header_read += len; + return; + } + data += needed; + len -= needed; + sd->header_read = 7; + } + + gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len); +} + +/* sub-driver description */ +static const struct sd_desc sd_desc = { + .name = MODULE_NAME, + .ctrls = sd_ctrls, + .nctrls = ARRAY_SIZE(sd_ctrls), + .config = sd_config, + .init = sd_init, + .start = sd_start, + .stopN = sd_stopN, + .pkt_scan = sd_pkt_scan, +}; + +/* -- module initialisation -- */ +static const __devinitdata struct usb_device_id device_table[] = { + {USB_DEVICE(0x08ca, 0x0111)}, + {} +}; +MODULE_DEVICE_TABLE(usb, device_table); + +/* -- device connect -- */ +static int sd_probe(struct usb_interface *intf, + const struct usb_device_id *id) +{ + return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd), + THIS_MODULE); +} + +static struct usb_driver sd_driver = { + .name = MODULE_NAME, + .id_table = device_table, + .probe = sd_probe, + .disconnect = gspca_disconnect, +#ifdef CONFIG_PM + .suspend = gspca_suspend, + .resume = gspca_resume, +#endif +}; + +/* -- module insert / remove -- */ +static int __init sd_mod_init(void) +{ + if (usb_register(&sd_driver) < 0) + return -1; + PDEBUG(D_PROBE, "registered"); + return 0; +} +static void __exit sd_mod_exit(void) +{ + usb_deregister(&sd_driver); + PDEBUG(D_PROBE, "deregistered"); +} + +module_init(sd_mod_init); +module_exit(sd_mod_exit); -- cgit v1.2.3 From 576ed7b5696b9435e8e6a6ec0c57da1f19c7e469 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Fri, 16 Jan 2009 08:57:28 -0300 Subject: V4L/DVB (10367): gspca - spca561: Optimize the isoc scanning function. Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/spca561.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/gspca/spca561.c b/drivers/media/video/gspca/spca561.c index 173c0c43fd1f..386aaec3e6e1 100644 --- a/drivers/media/video/gspca/spca561.c +++ b/drivers/media/video/gspca/spca561.c @@ -141,7 +141,6 @@ static const struct v4l2_pix_format sif_072a_mode[] = { #define SPCA561_OFFSET_WIN1GBAVE 14 #define SPCA561_OFFSET_FREQ 15 #define SPCA561_OFFSET_VSYNC 16 -#define SPCA561_OFFSET_DATA 1 #define SPCA561_INDEX_I2C_BASE 0x8800 #define SPCA561_SNAPBIT 0x20 #define SPCA561_SNAPCTRL 0x40 @@ -866,12 +865,11 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, { struct sd *sd = (struct sd *) gspca_dev; - switch (data[0]) { /* sequence number */ + len--; + switch (*data++) { /* sequence number */ case 0: /* start of frame */ frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame, data, 0); - data += SPCA561_OFFSET_DATA; - len -= SPCA561_OFFSET_DATA; if (data[1] & 0x10) { /* compressed bayer */ gspca_frame_add(gspca_dev, FIRST_PACKET, @@ -892,8 +890,6 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, case 0xff: /* drop (empty mpackets) */ return; } - data++; - len--; gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len); } -- cgit v1.2.3 From 0dbc2c1674b346ff22f729af14efa4822f81325c Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Fri, 16 Jan 2009 16:24:28 -0300 Subject: V4L/DVB (10368): gspca - spca561: Fix bugs and rewrite the init/start of the rev72a. The bugs were in the first init sequence of the sensor. The rewrite is adapted from a ms-win trace. Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/spca561.c | 168 +++++++++--------------------------- 1 file changed, 42 insertions(+), 126 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/gspca/spca561.c b/drivers/media/video/gspca/spca561.c index 386aaec3e6e1..c99fe0f904fe 100644 --- a/drivers/media/video/gspca/spca561.c +++ b/drivers/media/video/gspca/spca561.c @@ -145,33 +145,34 @@ static const struct v4l2_pix_format sif_072a_mode[] = { #define SPCA561_SNAPBIT 0x20 #define SPCA561_SNAPCTRL 0x40 -static const __u16 rev72a_init_data1[][2] = { +static const u16 rev72a_reset[][2] = { {0x0000, 0x8114}, /* Software GPIO output data */ {0x0001, 0x8114}, /* Software GPIO output data */ {0x0000, 0x8112}, /* Some kind of reset */ + {} +}; +static const __u16 rev72a_init_data1[][2] = { {0x0003, 0x8701}, /* PCLK clock delay adjustment */ {0x0001, 0x8703}, /* HSYNC from cmos inverted */ {0x0011, 0x8118}, /* Enable and conf sensor */ {0x0001, 0x8118}, /* Conf sensor */ {0x0092, 0x8804}, /* I know nothing about these */ {0x0010, 0x8802}, /* 0x88xx registers, so I won't */ - {0x000d, 0x8805}, /* sensor default setting */ {} }; -static const __u16 rev72a_init_sensor1[][2] = { - /* ms-win values */ - {0x0001, 0x0018}, /* 0x01 <- 0x0d */ - {0x0002, 0x0065}, /* 0x02 <- 0x18 */ - {0x0004, 0x0121}, /* 0x04 <- 0x0165 */ - {0x0005, 0x00aa}, /* 0x05 <- 0x21 */ - {0x0007, 0x0004}, /* 0x07 <- 0xaa */ - {0x0020, 0x1502}, /* 0x20 <- 0x1504 */ - {0x0039, 0x0010}, /* 0x39 <- 0x02 */ - {0x0035, 0x0049}, /* 0x35 <- 0x10 */ - {0x0009, 0x100b}, /* 0x09 <- 0x1049 */ - {0x0028, 0x000f}, /* 0x28 <- 0x0b */ - {0x003b, 0x003c}, /* 0x3b <- 0x0f */ - {0x003c, 0x0000}, /* 0x3c <- 0x00 */ +static const u16 rev72a_init_sensor1[][2] = { + {0x0001, 0x000d}, + {0x0002, 0x0018}, + {0x0004, 0x0165}, + {0x0005, 0x0021}, + {0x0007, 0x00aa}, + {0x0020, 0x1504}, + {0x0039, 0x0002}, + {0x0035, 0x0010}, + {0x0009, 0x1049}, + {0x0028, 0x000b}, + {0x003b, 0x000f}, + {0x003c, 0x0000}, {} }; static const __u16 rev72a_init_data2[][2] = { @@ -189,15 +190,10 @@ static const __u16 rev72a_init_data2[][2] = { {0x0002, 0x8201}, /* Output address for r/w serial EEPROM */ {0x0008, 0x8200}, /* Clear valid bit for serial EEPROM */ {0x0001, 0x8200}, /* OprMode to be executed by hardware */ - {0x0007, 0x8201}, /* Output address for r/w serial EEPROM */ - {0x0008, 0x8200}, /* Clear valid bit for serial EEPROM */ - {0x0001, 0x8200}, /* OprMode to be executed by hardware */ - {0x0010, 0x8660}, /* Compensation memory stuff */ - {0x0018, 0x8660}, /* Compensation memory stuff */ - - {0x0004, 0x8611}, /* R offset for white balance */ - {0x0004, 0x8612}, /* Gr offset for white balance */ - {0x0007, 0x8613}, /* B offset for white balance */ +/* from ms-win */ + {0x0000, 0x8611}, /* R offset for white balance */ + {0x00fd, 0x8612}, /* Gr offset for white balance */ + {0x0003, 0x8613}, /* B offset for white balance */ {0x0000, 0x8614}, /* Gb offset for white balance */ /* from ms-win */ {0x0035, 0x8651}, /* R gain for white balance */ @@ -205,8 +201,8 @@ static const __u16 rev72a_init_data2[][2] = { {0x005f, 0x8653}, /* B gain for white balance */ {0x0040, 0x8654}, /* Gb gain for white balance */ {0x0002, 0x8502}, /* Maximum average bit rate stuff */ - {0x0011, 0x8802}, + {0x0087, 0x8700}, /* Set master clock (96Mhz????) */ {0x0081, 0x8702}, /* Master clock output enable */ @@ -217,104 +213,15 @@ static const __u16 rev72a_init_data2[][2] = { {0x0003, 0x865c}, /* Vertical offset for valid lines */ {} }; -static const __u16 rev72a_init_sensor2[][2] = { - /* ms-win values */ - {0x0003, 0x0121}, /* 0x03 <- 0x01 0x21 //289 */ - {0x0004, 0x0165}, /* 0x04 <- 0x01 0x65 //357 */ - {0x0005, 0x002f}, /* 0x05 <- 0x2f */ - {0x0006, 0x0000}, /* 0x06 <- 0 */ - {0x000a, 0x0002}, /* 0x0a <- 2 */ - {0x0009, 0x1061}, /* 0x09 <- 0x1061 */ - {0x0035, 0x0014}, /* 0x35 <- 0x14 */ - {} -}; -static const __u16 rev72a_init_data3[][2] = { - {0x0030, 0x8112}, /* ISO and drop packet enable */ -/*fixme: should stop here*/ - {0x0000, 0x8112}, /* Some kind of reset ???? */ - {0x0009, 0x8118}, /* Enable sensor and set standby */ - {0x0000, 0x8114}, /* Software GPIO output data */ - {0x0000, 0x8114}, /* Software GPIO output data */ - {0x0001, 0x8114}, /* Software GPIO output data */ - {0x0000, 0x8112}, /* Some kind of reset ??? */ - {0x0003, 0x8701}, - {0x0001, 0x8703}, - {0x0011, 0x8118}, - {0x0001, 0x8118}, - /***************/ - {0x0092, 0x8804}, - {0x0010, 0x8802}, - {0x000d, 0x8805}, - {0x0001, 0x8801}, - {0x0000, 0x8800}, - {0x0018, 0x8805}, - {0x0002, 0x8801}, - {0x0000, 0x8800}, - {0x0065, 0x8805}, - {0x0004, 0x8801}, - {0x0001, 0x8800}, - {0x0021, 0x8805}, - {0x0005, 0x8801}, - {0x0000, 0x8800}, - {0x00aa, 0x8805}, - {0x0007, 0x8801}, /* mode 0xaa */ - {0x0000, 0x8800}, - {0x0004, 0x8805}, - {0x0020, 0x8801}, - {0x0015, 0x8800}, /* mode 0x0415 */ - {0x0002, 0x8805}, - {0x0039, 0x8801}, - {0x0000, 0x8800}, - {0x0010, 0x8805}, - {0x0035, 0x8801}, - {0x0000, 0x8800}, - {0x0049, 0x8805}, - {0x0009, 0x8801}, - {0x0010, 0x8800}, - {0x000b, 0x8805}, - {0x0028, 0x8801}, - {0x0000, 0x8800}, - {0x000f, 0x8805}, - {0x003b, 0x8801}, - {0x0000, 0x8800}, - {0x0000, 0x8805}, - {0x003c, 0x8801}, - {0x0000, 0x8800}, - {0x0002, 0x8502}, - {0x0039, 0x8801}, - {0x0000, 0x8805}, - {0x0000, 0x8800}, - - {0x0087, 0x8700}, /* overwrite by start */ - {0x0081, 0x8702}, - {0x0000, 0x8500}, -/* {0x0010, 0x8500}, -- Previous line was this */ - {0x0002, 0x865b}, - {0x0003, 0x865c}, - /***************/ - {0x0003, 0x8801}, /* 0x121-> 289 */ - {0x0021, 0x8805}, - {0x0001, 0x8800}, - {0x0004, 0x8801}, /* 0x165 -> 357 */ - {0x0065, 0x8805}, - {0x0001, 0x8800}, - {0x0005, 0x8801}, /* 0x2f //blanking control colonne */ - {0x002f, 0x8805}, - {0x0000, 0x8800}, - {0x0006, 0x8801}, /* 0x00 //blanking mode row */ - {0x0000, 0x8805}, - {0x0000, 0x8800}, - {0x000a, 0x8801}, /* 0x01 //0x02 */ - {0x0001, 0x8805}, - {0x0000, 0x8800}, - {0x0009, 0x8801}, /* 0x1061 - setexposure times && pixel clock +static const u16 rev72a_init_sensor2[][2] = { + {0x0003, 0x0121}, + {0x0004, 0x0165}, + {0x0005, 0x002f}, /* blanking control column */ + {0x0006, 0x0000}, /* blanking mode row*/ + {0x000a, 0x0002}, + {0x0009, 0x1061}, /* setexposure times && pixel clock * 0001 0 | 000 0110 0001 */ - {0x0061, 0x8805}, /* 61 31 */ - {0x0008, 0x8800}, /* 08 */ - {0x0035, 0x8801}, /* 0x14 - set gain general */ - {0x001f, 0x8805}, /* 0x14 */ - {0x0000, 0x8800}, - {0x000e, 0x8112}, /* white balance - was 30 */ + {0x0035, 0x0014}, {} }; @@ -459,6 +366,7 @@ static void i2c_write(struct gspca_dev *gspca_dev, __u16 value, __u16 reg) reg_r(gspca_dev, 0x8803, 1); if (!gspca_dev->usb_buf[0]) return; + msleep(10); } while (--retry); } @@ -478,6 +386,7 @@ static int i2c_read(struct gspca_dev *gspca_dev, __u16 reg, __u8 mode) reg_r(gspca_dev, 0x8805, 1); return ((int) value << 8) | gspca_dev->usb_buf[0]; } + msleep(10); } while (--retry); return -1; } @@ -570,11 +479,13 @@ static int sd_init_12a(struct gspca_dev *gspca_dev) static int sd_init_72a(struct gspca_dev *gspca_dev) { PDEBUG(D_STREAM, "Chip revision: 072a"); + write_vector(gspca_dev, rev72a_reset); + msleep(200); write_vector(gspca_dev, rev72a_init_data1); write_sensor_72a(gspca_dev, rev72a_init_sensor1); write_vector(gspca_dev, rev72a_init_data2); write_sensor_72a(gspca_dev, rev72a_init_sensor2); - write_vector(gspca_dev, rev72a_init_data3); + reg_w_val(gspca_dev->dev, 0x8112, 0x30); return 0; } @@ -729,6 +640,11 @@ static int sd_start_72a(struct gspca_dev *gspca_dev) int Clck; int mode; + write_vector(gspca_dev, rev72a_reset); + msleep(200); + write_vector(gspca_dev, rev72a_init_data1); + write_sensor_72a(gspca_dev, rev72a_init_sensor1); + mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv; switch (mode) { default: @@ -745,11 +661,11 @@ static int sd_start_72a(struct gspca_dev *gspca_dev) } reg_w_val(dev, 0x8500, mode); /* mode */ reg_w_val(dev, 0x8700, Clck); /* 0x27 clock */ - reg_w_val(dev, 0x8112, 0x10 | 0x20); + write_sensor_72a(gspca_dev, rev72a_init_sensor2); setcontrast(gspca_dev); /* setbrightness(gspca_dev); * fixme: bad values */ - setwhite(gspca_dev); setautogain(gspca_dev); + reg_w_val(dev, 0x8112, 0x10 | 0x20); return 0; } -- cgit v1.2.3 From ceb35beaed9fc8e71755ac99a83a105730c64111 Mon Sep 17 00:00:00 2001 From: Kyle Guinn Date: Sat, 17 Jan 2009 04:32:32 -0300 Subject: V4L/DVB (10369): gspca - mr97310a: Fix camera initialization copy/paste bugs. Signed-off-by: Kyle Guinn Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/mr97310a.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/gspca/mr97310a.c b/drivers/media/video/gspca/mr97310a.c index 24180bf0cdab..3a5ddff8f7a6 100644 --- a/drivers/media/video/gspca/mr97310a.c +++ b/drivers/media/video/gspca/mr97310a.c @@ -247,8 +247,8 @@ static int sd_start(struct gspca_dev *gspca_dev) data[5] = 0x00; data[6] = 0x70; data[7] = 0x00; - data[8] = 0x01; - err_code = reg_w(gspca_dev, 10); + data[8] = 0x00; + err_code = reg_w(gspca_dev, 9); if (err_code < 0) return err_code; -- cgit v1.2.3 From 8fee8453969ccb0ecc2da128879e54641028ffd1 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Sat, 17 Jan 2009 04:46:38 -0300 Subject: V4L/DVB (10370): gspca - main: Have 3 URBs instead of 2 for ISOC transfers. Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/gspca.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/gspca/gspca.c b/drivers/media/video/gspca/gspca.c index 6c03d57ae506..db22e3c24764 100644 --- a/drivers/media/video/gspca/gspca.c +++ b/drivers/media/video/gspca/gspca.c @@ -38,7 +38,10 @@ #include "gspca.h" /* global values */ -#define DEF_NURBS 2 /* default number of URBs */ +#define DEF_NURBS 3 /* default number of URBs */ +#if DEF_NURBS > MAX_NURBS +#error "DEF_NURBS too big" +#endif MODULE_AUTHOR("Jean-Francois Moine "); MODULE_DESCRIPTION("GSPCA USB Camera Driver"); -- cgit v1.2.3 From a48196a2f74a2e19e67debe194e337dfc583702f Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Sun, 18 Jan 2009 14:24:52 -0300 Subject: V4L/DVB (10371): gspca - spca561: Fix image problem in the 352x288 mode of rev72a. With the wrong clock value, the image had two moving colored lines. Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/spca561.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/gspca/spca561.c b/drivers/media/video/gspca/spca561.c index c99fe0f904fe..c99c5e34e211 100644 --- a/drivers/media/video/gspca/spca561.c +++ b/drivers/media/video/gspca/spca561.c @@ -648,8 +648,10 @@ static int sd_start_72a(struct gspca_dev *gspca_dev) mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv; switch (mode) { default: -/* case 0: - case 1: */ + case 0: + Clck = 0x27; /* ms-win 0x87 */ + break; + case 1: Clck = 0x25; break; case 2: @@ -659,8 +661,9 @@ static int sd_start_72a(struct gspca_dev *gspca_dev) Clck = 0x21; break; } - reg_w_val(dev, 0x8500, mode); /* mode */ reg_w_val(dev, 0x8700, Clck); /* 0x27 clock */ + reg_w_val(dev, 0x8702, 0x81); + reg_w_val(dev, 0x8500, mode); /* mode */ write_sensor_72a(gspca_dev, rev72a_init_sensor2); setcontrast(gspca_dev); /* setbrightness(gspca_dev); * fixme: bad values */ -- cgit v1.2.3 From 9881918756be1cf0a33ae7454ca767682cbfadc3 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Mon, 19 Jan 2009 07:37:33 -0300 Subject: V4L/DVB (10372): gspca - sonixj: Cleanup code. Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/sonixj.c | 182 ++++++++++++++++++------------------- 1 file changed, 91 insertions(+), 91 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/gspca/sonixj.c b/drivers/media/video/gspca/sonixj.c index db8db0c6bbb9..59363e077bbf 100644 --- a/drivers/media/video/gspca/sonixj.c +++ b/drivers/media/video/gspca/sonixj.c @@ -36,28 +36,28 @@ struct sd { struct gspca_dev gspca_dev; /* !! must be the first item */ atomic_t avg_lum; - unsigned int exposure; - - __u16 brightness; - __u8 contrast; - __u8 colors; - __u8 autogain; - __u8 blue; - __u8 red; + u32 exposure; + + u16 brightness; + u8 contrast; + u8 colors; + u8 autogain; + u8 blue; + u8 red; u8 gamma; - __u8 vflip; /* ov7630 only */ - __u8 infrared; /* mi0360 only */ + u8 vflip; /* ov7630 only */ + u8 infrared; /* mi0360 only */ - __s8 ag_cnt; + s8 ag_cnt; #define AG_CNT_START 13 - __u8 bridge; + u8 bridge; #define BRIDGE_SN9C102P 0 #define BRIDGE_SN9C105 1 #define BRIDGE_SN9C110 2 #define BRIDGE_SN9C120 3 #define BRIDGE_SN9C325 4 - __u8 sensor; /* Type of image sensor chip */ + u8 sensor; /* Type of image sensor chip */ #define SENSOR_HV7131R 0 #define SENSOR_MI0360 1 #define SENSOR_MO4000 2 @@ -65,7 +65,7 @@ struct sd { #define SENSOR_OV7630 4 #define SENSOR_OV7648 5 #define SENSOR_OV7660 6 - __u8 i2c_base; + u8 i2c_base; }; /* V4L2 controls supported by the driver */ @@ -349,20 +349,20 @@ static const u8 *sn_tb[] = { sn_ov7660 }; -static const __u8 gamma_def[17] = { +static const u8 gamma_def[17] = { 0x00, 0x2d, 0x46, 0x5a, 0x6c, 0x7c, 0x8b, 0x99, 0xa6, 0xb2, 0xbf, 0xca, 0xd5, 0xe0, 0xeb, 0xf5, 0xff }; /* color matrix and offsets */ -static const __u8 reg84[] = { +static const u8 reg84[] = { 0x14, 0x00, 0x27, 0x00, 0x07, 0x00, /* YR YG YB gains */ 0xe8, 0x0f, 0xda, 0x0f, 0x40, 0x00, /* UR UG UB */ 0x3e, 0x00, 0xcd, 0x0f, 0xf7, 0x0f, /* VR VG VB */ 0x00, 0x00, 0x00 /* YUV offsets */ }; -static const __u8 hv7131r_sensor_init[][8] = { +static const u8 hv7131r_sensor_init[][8] = { {0xc1, 0x11, 0x01, 0x08, 0x01, 0x00, 0x00, 0x10}, {0xb1, 0x11, 0x34, 0x17, 0x7f, 0x00, 0x00, 0x10}, {0xd1, 0x11, 0x40, 0xff, 0x7f, 0x7f, 0x7f, 0x10}, @@ -393,9 +393,9 @@ static const __u8 hv7131r_sensor_init[][8] = { {0xa1, 0x11, 0x23, 0x10, 0x00, 0x00, 0x00, 0x10}, {} }; -static const __u8 mi0360_sensor_init[][8] = { +static const u8 mi0360_sensor_init[][8] = { {0xb1, 0x5d, 0x07, 0x00, 0x02, 0x00, 0x00, 0x10}, - {0xb1, 0x5d, 0x0D, 0x00, 0x01, 0x00, 0x00, 0x10}, + {0xb1, 0x5d, 0x0d, 0x00, 0x01, 0x00, 0x00, 0x10}, {0xb1, 0x5d, 0x0D, 0x00, 0x00, 0x00, 0x00, 0x10}, {0xd1, 0x5d, 0x01, 0x00, 0x08, 0x00, 0x16, 0x10}, {0xd1, 0x5d, 0x03, 0x01, 0xe2, 0x02, 0x82, 0x10}, @@ -416,7 +416,7 @@ static const __u8 mi0360_sensor_init[][8] = { {0xd1, 0x5d, 0x22, 0x00, 0x00, 0x00, 0x00, 0x10}, {0xd1, 0x5d, 0x24, 0x00, 0x00, 0x00, 0x00, 0x10}, {0xd1, 0x5d, 0x26, 0x00, 0x00, 0x00, 0x24, 0x10}, - {0xd1, 0x5d, 0x2F, 0xF7, 0xB0, 0x00, 0x04, 0x10}, + {0xd1, 0x5d, 0x2f, 0xf7, 0xB0, 0x00, 0x04, 0x10}, {0xd1, 0x5d, 0x31, 0x00, 0x00, 0x00, 0x00, 0x10}, {0xd1, 0x5d, 0x33, 0x00, 0x00, 0x01, 0x00, 0x10}, {0xb1, 0x5d, 0x3d, 0x06, 0x8f, 0x00, 0x00, 0x10}, @@ -447,7 +447,7 @@ static const __u8 mi0360_sensor_init[][8] = { {0xb1, 0x5d, 0x07, 0x00, 0x02, 0x00, 0x00, 0x10}, /* sensor on */ {} }; -static const __u8 mo4000_sensor_init[][8] = { +static const u8 mo4000_sensor_init[][8] = { {0xa1, 0x21, 0x01, 0x02, 0x00, 0x00, 0x00, 0x10}, {0xa1, 0x21, 0x02, 0x00, 0x00, 0x00, 0x00, 0x10}, {0xa1, 0x21, 0x03, 0x00, 0x00, 0x00, 0x00, 0x10}, @@ -470,7 +470,7 @@ static const __u8 mo4000_sensor_init[][8] = { {0xa1, 0x21, 0x11, 0x38, 0x00, 0x00, 0x00, 0x10}, {} }; -static __u8 om6802_sensor_init[][8] = { +static const u8 om6802_sensor_init[][8] = { {0xa0, 0x34, 0x90, 0x05, 0x00, 0x00, 0x00, 0x10}, {0xa0, 0x34, 0x49, 0x85, 0x00, 0x00, 0x00, 0x10}, {0xa0, 0x34, 0x5a, 0xc0, 0x00, 0x00, 0x00, 0x10}, @@ -504,7 +504,7 @@ static __u8 om6802_sensor_init[][8] = { /* {0xa0, 0x34, 0x69, 0x01, 0x00, 0x00, 0x00, 0x10}, */ {} }; -static const __u8 ov7630_sensor_init[][8] = { +static const u8 ov7630_sensor_init[][8] = { {0xa1, 0x21, 0x76, 0x01, 0x00, 0x00, 0x00, 0x10}, {0xa1, 0x21, 0x12, 0xc8, 0x00, 0x00, 0x00, 0x10}, /* win: delay 20ms */ @@ -558,7 +558,7 @@ static const __u8 ov7630_sensor_init[][8] = { {} }; -static const __u8 ov7648_sensor_init[][8] = { +static const u8 ov7648_sensor_init[][8] = { {0xa1, 0x21, 0x76, 0x00, 0x00, 0x00, 0x00, 0x10}, {0xa1, 0x21, 0x12, 0x80, 0x00, 0x00, 0x00, 0x10}, /* reset */ {0xa1, 0x21, 0x12, 0x00, 0x00, 0x00, 0x00, 0x10}, @@ -604,7 +604,7 @@ static const __u8 ov7648_sensor_init[][8] = { {} }; -static const __u8 ov7660_sensor_init[][8] = { +static const u8 ov7660_sensor_init[][8] = { {0xa1, 0x21, 0x12, 0x80, 0x00, 0x00, 0x00, 0x10}, /* reset SCCB */ /* (delay 20ms) */ {0xa1, 0x21, 0x12, 0x05, 0x00, 0x00, 0x00, 0x10}, @@ -693,28 +693,28 @@ static const __u8 ov7660_sensor_init[][8] = { {} }; -static const __u8 qtable4[] = { - 0x06, 0x04, 0x04, 0x06, 0x04, 0x04, 0x06, 0x06, 0x06, 0x06, 0x08, 0x06, - 0x06, 0x08, 0x0a, 0x11, - 0x0a, 0x0a, 0x08, 0x08, 0x0a, 0x15, 0x0f, 0x0f, 0x0c, 0x11, 0x19, 0x15, - 0x19, 0x19, 0x17, 0x15, - 0x17, 0x17, 0x1b, 0x1d, 0x25, 0x21, 0x1b, 0x1d, 0x23, 0x1d, 0x17, 0x17, - 0x21, 0x2e, 0x21, 0x23, - 0x27, 0x29, 0x2c, 0x2c, 0x2c, 0x19, 0x1f, 0x30, 0x32, 0x2e, 0x29, 0x32, - 0x25, 0x29, 0x2c, 0x29, - 0x06, 0x08, 0x08, 0x0a, 0x08, 0x0a, 0x13, 0x0a, 0x0a, 0x13, 0x29, 0x1b, - 0x17, 0x1b, 0x29, 0x29, - 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, - 0x29, 0x29, 0x29, 0x29, - 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, - 0x29, 0x29, 0x29, 0x29, - 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, - 0x29, 0x29, 0x29, 0x29 +static const u8 qtable4[] = { + 0x06, 0x04, 0x04, 0x06, 0x04, 0x04, 0x06, 0x06, + 0x06, 0x06, 0x08, 0x06, 0x06, 0x08, 0x0a, 0x11, + 0x0a, 0x0a, 0x08, 0x08, 0x0a, 0x15, 0x0f, 0x0f, + 0x0c, 0x11, 0x19, 0x15, 0x19, 0x19, 0x17, 0x15, + 0x17, 0x17, 0x1b, 0x1d, 0x25, 0x21, 0x1b, 0x1d, + 0x23, 0x1d, 0x17, 0x17, 0x21, 0x2e, 0x21, 0x23, + 0x27, 0x29, 0x2c, 0x2c, 0x2c, 0x19, 0x1f, 0x30, + 0x32, 0x2e, 0x29, 0x32, 0x25, 0x29, 0x2c, 0x29, + 0x06, 0x08, 0x08, 0x0a, 0x08, 0x0a, 0x13, 0x0a, + 0x0a, 0x13, 0x29, 0x1b, 0x17, 0x1b, 0x29, 0x29, + 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, + 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, + 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, + 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, + 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, + 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29 }; /* read bytes to gspca_dev->usb_buf */ static void reg_r(struct gspca_dev *gspca_dev, - __u16 value, int len) + u16 value, int len) { #ifdef GSPCA_DEBUG if (len > USB_BUF_SZ) { @@ -733,8 +733,8 @@ static void reg_r(struct gspca_dev *gspca_dev, } static void reg_w1(struct gspca_dev *gspca_dev, - __u16 value, - __u8 data) + u16 value, + u8 data) { PDEBUG(D_USBO, "reg_w1 [%02x] = %02x", value, data); gspca_dev->usb_buf[0] = data; @@ -748,8 +748,8 @@ static void reg_w1(struct gspca_dev *gspca_dev, 500); } static void reg_w(struct gspca_dev *gspca_dev, - __u16 value, - const __u8 *buffer, + u16 value, + const u8 *buffer, int len) { PDEBUG(D_USBO, "reg_w [%02x] = %02x %02x ..", @@ -771,7 +771,7 @@ static void reg_w(struct gspca_dev *gspca_dev, } /* I2C write 1 byte */ -static void i2c_w1(struct gspca_dev *gspca_dev, __u8 reg, __u8 val) +static void i2c_w1(struct gspca_dev *gspca_dev, u8 reg, u8 val) { struct sd *sd = (struct sd *) gspca_dev; @@ -796,7 +796,7 @@ static void i2c_w1(struct gspca_dev *gspca_dev, __u8 reg, __u8 val) /* I2C write 8 bytes */ static void i2c_w8(struct gspca_dev *gspca_dev, - const __u8 *buffer) + const u8 *buffer) { memcpy(gspca_dev->usb_buf, buffer, 8); usb_control_msg(gspca_dev->dev, @@ -810,10 +810,10 @@ static void i2c_w8(struct gspca_dev *gspca_dev, } /* read 5 bytes in gspca_dev->usb_buf */ -static void i2c_r5(struct gspca_dev *gspca_dev, __u8 reg) +static void i2c_r5(struct gspca_dev *gspca_dev, u8 reg) { struct sd *sd = (struct sd *) gspca_dev; - __u8 mode[8]; + u8 mode[8]; mode[0] = 0x81 | 0x10; mode[1] = sd->i2c_base; @@ -855,15 +855,15 @@ static int probesensor(struct gspca_dev *gspca_dev) } static int configure_gpio(struct gspca_dev *gspca_dev, - const __u8 *sn9c1xx) + const u8 *sn9c1xx) { struct sd *sd = (struct sd *) gspca_dev; - const __u8 *reg9a; - static const __u8 reg9a_def[] = + const u8 *reg9a; + static const u8 reg9a_def[] = {0x08, 0x40, 0x20, 0x10, 0x00, 0x04}; - static const __u8 reg9a_sn9c325[] = + static const u8 reg9a_sn9c325[] = {0x0a, 0x40, 0x38, 0x30, 0x00, 0x20}; - static const __u8 regd4[] = {0x60, 0x00, 0x00}; + static const u8 regd4[] = {0x60, 0x00, 0x00}; reg_w1(gspca_dev, 0xf1, 0x00); reg_w1(gspca_dev, 0x01, sn9c1xx[1]); @@ -931,7 +931,7 @@ static int configure_gpio(struct gspca_dev *gspca_dev, static void hv7131R_InitSensor(struct gspca_dev *gspca_dev) { int i = 0; - static const __u8 SetSensorClk[] = /* 0x08 Mclk */ + static const u8 SetSensorClk[] = /* 0x08 Mclk */ { 0xa1, 0x11, 0x01, 0x18, 0x00, 0x00, 0x00, 0x10 }; while (hv7131r_sensor_init[i][0]) { @@ -1059,8 +1059,8 @@ static int sd_config(struct gspca_dev *gspca_dev, static int sd_init(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; - __u8 regGpio[] = { 0x29, 0x74 }; - __u8 regF1; + u8 regGpio[] = { 0x29, 0x74 }; + u8 regF1; /* setup a selector by bridge */ reg_w1(gspca_dev, 0xf1, 0x01); @@ -1100,20 +1100,14 @@ static int sd_init(struct gspca_dev *gspca_dev) return 0; } -static unsigned int setexposure(struct gspca_dev *gspca_dev, - unsigned int expo) +static u32 setexposure(struct gspca_dev *gspca_dev, + u32 expo) { struct sd *sd = (struct sd *) gspca_dev; - static const __u8 doit[] = /* update sensor */ - { 0xb1, 0x5d, 0x07, 0x00, 0x03, 0x00, 0x00, 0x10 }; - static const __u8 sensorgo[] = /* sensor on */ - { 0xb1, 0x5d, 0x07, 0x00, 0x02, 0x00, 0x00, 0x10 }; - static const __u8 gainMo[] = - { 0xa1, 0x21, 0x00, 0x10, 0x00, 0x00, 0x00, 0x1d }; switch (sd->sensor) { case SENSOR_HV7131R: { - __u8 Expodoit[] = + u8 Expodoit[] = { 0xc1, 0x11, 0x25, 0x07, 0x27, 0xc0, 0x00, 0x16 }; Expodoit[3] = expo >> 16; @@ -1123,8 +1117,12 @@ static unsigned int setexposure(struct gspca_dev *gspca_dev, break; } case SENSOR_MI0360: { - __u8 expoMi[] = /* exposure 0x0635 -> 4 fp/s 0x10 */ + u8 expoMi[] = /* exposure 0x0635 -> 4 fp/s 0x10 */ { 0xb1, 0x5d, 0x09, 0x06, 0x35, 0x00, 0x00, 0x16 }; + static const u8 doit[] = /* update sensor */ + { 0xb1, 0x5d, 0x07, 0x00, 0x03, 0x00, 0x00, 0x10 }; + static const u8 sensorgo[] = /* sensor on */ + { 0xb1, 0x5d, 0x07, 0x00, 0x02, 0x00, 0x00, 0x10 }; if (expo > 0x0635) expo = 0x0635; @@ -1138,10 +1136,12 @@ static unsigned int setexposure(struct gspca_dev *gspca_dev, break; } case SENSOR_MO4000: { - __u8 expoMof[] = + u8 expoMof[] = { 0xa1, 0x21, 0x0f, 0x20, 0x00, 0x00, 0x00, 0x10 }; - __u8 expoMo10[] = + u8 expoMo10[] = { 0xa1, 0x21, 0x10, 0x20, 0x00, 0x00, 0x00, 0x10 }; + static const u8 gainMo[] = + { 0xa1, 0x21, 0x00, 0x10, 0x00, 0x00, 0x00, 0x1d }; if (expo > 0x1fff) expo = 0x1fff; @@ -1160,7 +1160,7 @@ static unsigned int setexposure(struct gspca_dev *gspca_dev, break; } case SENSOR_OM6802: { - __u8 gainOm[] = + u8 gainOm[] = { 0xa0, 0x34, 0xe5, 0x00, 0x00, 0x00, 0x00, 0x10 }; if (expo > 0x03ff) @@ -1181,7 +1181,7 @@ static void setbrightness(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; unsigned int expo; - __u8 k2; + u8 k2; k2 = ((int) sd->brightness - 0x8000) >> 10; switch (sd->sensor) { @@ -1211,8 +1211,8 @@ static void setbrightness(struct gspca_dev *gspca_dev) static void setcontrast(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; - __u8 k2; - __u8 contrast[6]; + u8 k2; + u8 contrast[6]; k2 = sd->contrast * 0x30 / (CONTRAST_MAX + 1) + 0x10; /* 10..40 */ contrast[0] = (k2 + 1) / 2; /* red */ @@ -1228,8 +1228,8 @@ static void setcolors(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; int i, v; - __u8 reg8a[12]; /* U & V gains */ - static __s16 uv[6] = { /* same as reg84 in signed decimal */ + u8 reg8a[12]; /* U & V gains */ + static s16 uv[6] = { /* same as reg84 in signed decimal */ -24, -38, 64, /* UR UG UB */ 62, -51, -9 /* VR VG VB */ }; @@ -1297,13 +1297,13 @@ static int sd_start(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; int i; - __u8 reg1, reg17, reg18; - const __u8 *sn9c1xx; + u8 reg1, reg17, reg18; + const u8 *sn9c1xx; int mode; - static const __u8 C0[] = { 0x2d, 0x2d, 0x3a, 0x05, 0x04, 0x3f }; - static const __u8 CA[] = { 0x28, 0xd8, 0x14, 0xec }; - static const __u8 CE[] = { 0x32, 0xdd, 0x2d, 0xdd }; /* MI0360 */ - static const __u8 CE_ov76xx[] = + static const u8 C0[] = { 0x2d, 0x2d, 0x3a, 0x05, 0x04, 0x3f }; + static const u8 CA[] = { 0x28, 0xd8, 0x14, 0xec }; + static const u8 CE[] = { 0x32, 0xdd, 0x2d, 0xdd }; /* MI0360 */ + static const u8 CE_ov76xx[] = { 0x32, 0xdd, 0x32, 0xdd }; sn9c1xx = sn_tb[(int) sd->sensor]; @@ -1460,14 +1460,14 @@ static int sd_start(struct gspca_dev *gspca_dev) static void sd_stopN(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; - static const __u8 stophv7131[] = + static const u8 stophv7131[] = { 0xa1, 0x11, 0x02, 0x09, 0x00, 0x00, 0x00, 0x10 }; - static const __u8 stopmi0360[] = + static const u8 stopmi0360[] = { 0xb1, 0x5d, 0x07, 0x00, 0x00, 0x00, 0x00, 0x10 }; - static const __u8 stopov7648[] = + static const u8 stopov7648[] = { 0xa1, 0x21, 0x76, 0x20, 0x00, 0x00, 0x00, 0x10 }; - __u8 data; - const __u8 *sn9c1xx; + u8 data; + const u8 *sn9c1xx; data = 0x0b; switch (sd->sensor) { @@ -1503,8 +1503,8 @@ static void do_autogain(struct gspca_dev *gspca_dev) struct sd *sd = (struct sd *) gspca_dev; int delta; int expotimes; - __u8 luma_mean = 130; - __u8 luma_delta = 20; + u8 luma_mean = 130; + u8 luma_delta = 20; /* Thanks S., without your advice, autobright should not work :) */ if (sd->ag_cnt < 0) @@ -1546,7 +1546,7 @@ static void do_autogain(struct gspca_dev *gspca_dev) /* This function is run at interrupt level. */ static void sd_pkt_scan(struct gspca_dev *gspca_dev, struct gspca_frame *frame, /* target */ - __u8 *data, /* isoc packet */ + u8 *data, /* isoc packet */ int len) /* iso packet length */ { struct sd *sd = (struct sd *) gspca_dev; -- cgit v1.2.3 From 3d22118360cdf603ebce1a3b927139e23aa3b9b1 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Mon, 19 Jan 2009 15:18:44 -0300 Subject: V4L/DVB (10373): gspca - zc3xx: Sensor adcm2700 added. Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/zc3xx.c | 454 ++++++++++++++++++++++++++++++-------- 1 file changed, 362 insertions(+), 92 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/gspca/zc3xx.c b/drivers/media/video/gspca/zc3xx.c index 74eabce7b4ae..b986362bdd17 100644 --- a/drivers/media/video/gspca/zc3xx.c +++ b/drivers/media/video/gspca/zc3xx.c @@ -48,25 +48,26 @@ struct sd { signed char sensor; /* Type of image sensor chip */ /* !! values used in different tables */ -#define SENSOR_CS2102 0 -#define SENSOR_CS2102K 1 -#define SENSOR_GC0305 2 -#define SENSOR_HDCS2020b 3 -#define SENSOR_HV7131B 4 -#define SENSOR_HV7131C 5 -#define SENSOR_ICM105A 6 -#define SENSOR_MC501CB 7 -#define SENSOR_OV7620 8 -/*#define SENSOR_OV7648 8 - same values */ -#define SENSOR_OV7630C 9 -#define SENSOR_PAS106 10 -#define SENSOR_PAS202B 11 -#define SENSOR_PB0330 12 -#define SENSOR_PO2030 13 -#define SENSOR_TAS5130CK 14 -#define SENSOR_TAS5130CXX 15 -#define SENSOR_TAS5130C_VF0250 16 -#define SENSOR_MAX 17 +#define SENSOR_ADCM2700 0 +#define SENSOR_CS2102 1 +#define SENSOR_CS2102K 2 +#define SENSOR_GC0305 3 +#define SENSOR_HDCS2020b 4 +#define SENSOR_HV7131B 5 +#define SENSOR_HV7131C 6 +#define SENSOR_ICM105A 7 +#define SENSOR_MC501CB 8 +#define SENSOR_OV7620 9 +/*#define SENSOR_OV7648 9 - same values */ +#define SENSOR_OV7630C 10 +#define SENSOR_PAS106 11 +#define SENSOR_PAS202B 12 +#define SENSOR_PB0330 13 +#define SENSOR_PO2030 14 +#define SENSOR_TAS5130CK 15 +#define SENSOR_TAS5130CXX 16 +#define SENSOR_TAS5130C_VF0250 17 +#define SENSOR_MAX 18 unsigned short chip_revision; }; @@ -206,6 +207,241 @@ struct usb_action { __u16 idx; }; +static const struct usb_action adcm2700_Initial[] = { + {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, /* 00,00,01,cc */ + {0xa0, 0x04, ZC3XX_R002_CLOCKSELECT}, /* 00,02,04,cc */ + {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, /* 00,08,03,cc */ + {0xa0, 0x0a, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,0a,cc */ + {0xa0, 0xd3, ZC3XX_R08B_I2CDEVICEADDR}, /* 00,8b,d3,cc */ + {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH}, /* 00,03,02,cc */ + {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW}, /* 00,04,80,cc */ + {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH}, /* 00,05,01,cc */ + {0xa0, 0xd8, ZC3XX_R006_FRAMEHEIGHTLOW}, /* 00,06,d8,cc */ + {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING}, /* 00,01,01,cc */ + {0xa0, 0x03, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,03,cc */ + {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,01,cc */ + {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,05,cc */ + {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW}, /* 00,98,00,cc */ + {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW}, /* 00,9a,00,cc */ + {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW}, /* 01,1a,00,cc */ + {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW}, /* 01,1c,00,cc */ + {0xa0, 0xde, ZC3XX_R09C_WINHEIGHTLOW}, /* 00,9c,de,cc */ + {0xa0, 0x86, ZC3XX_R09E_WINWIDTHLOW}, /* 00,9e,86,cc */ + {0xbb, 0x00, 0x0400}, /* 04,00,00,bb */ + {0xdd, 0x00, 0x0010}, /* 00,00,10,dd */ + {0xbb, 0x0f, 0x140f}, /* 14,0f,0f,bb */ + {0xa0, 0x37, ZC3XX_R101_SENSORCORRECTION}, /* 01,01,37,cc */ + {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE}, /* 01,00,0d,cc */ + {0xa0, 0x06, ZC3XX_R189_AWBSTATUS}, /* 01,89,06,cc */ + {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE}, /* 01,c5,03,cc */ + {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05}, /* 01,cb,13,cc */ + {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE}, /* 02,50,08,cc */ + {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS}, /* 03,01,08,cc */ + {0xa0, 0x58, ZC3XX_R116_RGAIN}, /* 01,16,58,cc */ + {0xa0, 0x5a, ZC3XX_R118_BGAIN}, /* 01,18,5a,cc */ + {0xa0, 0x02, ZC3XX_R180_AUTOCORRECTENABLE}, /* 01,80,02,cc */ + {0xa0, 0xd3, ZC3XX_R08B_I2CDEVICEADDR}, /* 00,8b,d3,cc */ + {0xbb, 0x00, 0x0408}, /* 04,00,08,bb */ + {0xdd, 0x00, 0x0200}, /* 00,02,00,dd */ + {0xbb, 0x00, 0x0400}, /* 04,00,00,bb */ + {0xdd, 0x00, 0x0010}, /* 00,00,10,dd */ + {0xbb, 0x0f, 0x140f}, /* 14,0f,0f,bb */ + {0xbb, 0xe0, 0x0c2e}, /* 0c,e0,2e,bb */ + {0xbb, 0x01, 0x2000}, /* 20,01,00,bb */ + {0xbb, 0x96, 0x2400}, /* 24,96,00,bb */ + {0xbb, 0x06, 0x1006}, /* 10,06,06,bb */ + {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,01,cc */ + {0xdd, 0x00, 0x0010}, /* 00,00,10,dd */ + {0xaa, 0xfe, 0x0002}, /* 00,fe,02,aa */ + {0xa0, 0x0a, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,0a,cc */ + {0xdd, 0x00, 0x0010}, /* 00,00,10,dd */ + {0xbb, 0x5f, 0x2090}, /* 20,5f,90,bb */ + {0xbb, 0x01, 0x8000}, /* 80,01,00,bb */ + {0xbb, 0x09, 0x8400}, /* 84,09,00,bb */ + {0xbb, 0x86, 0x0002}, /* 00,86,02,bb */ + {0xbb, 0xe6, 0x0401}, /* 04,e6,01,bb */ + {0xbb, 0x86, 0x0802}, /* 08,86,02,bb */ + {0xbb, 0xe6, 0x0c01}, /* 0c,e6,01,bb */ + {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,01,cc */ + {0xdd, 0x00, 0x0010}, /* 00,00,10,dd */ + {0xaa, 0xfe, 0x0000}, /* 00,fe,00,aa */ + {0xa0, 0x0a, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,0a,cc */ + {0xdd, 0x00, 0x0010}, /* 00,00,10,dd */ + {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,01,cc */ + {0xaa, 0xfe, 0x0020}, /* 00,fe,20,aa */ + {0xa0, 0x0a, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,0a,cc */ + {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,01,cc */ + {0xdd, 0x00, 0x0010}, /* 00,00,10,dd */ + {0xaa, 0xfe, 0x0000}, /* 00,fe,00,aa */ + {0xa0, 0x0a, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,0a,cc */ + {0xdd, 0x00, 0x0010}, /* 00,00,10,dd */ + {0xbb, 0x04, 0x0400}, /* 04,04,00,bb */ + {0xdd, 0x00, 0x0100}, /* 00,01,00,dd */ + {0xbb, 0x01, 0x0400}, /* 04,01,00,bb */ + {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,01,cc */ + {0xaa, 0xfe, 0x0002}, /* 00,fe,02,aa */ + {0xa0, 0x0a, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,0a,cc */ + {0xbb, 0x41, 0x2803}, /* 28,41,03,bb */ + {0xbb, 0x40, 0x2c03}, /* 2c,40,03,bb */ + {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,01,cc */ + {0xaa, 0xfe, 0x0010}, /* 00,fe,10,aa */ + {} +}; +static const struct usb_action adcm2700_InitialScale[] = { + {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, /* 00,00,01,cc */ + {0xa0, 0x10, ZC3XX_R002_CLOCKSELECT}, /* 00,02,10,cc */ + {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, /* 00,08,03,cc */ + {0xa0, 0x0a, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,0a,cc */ + {0xa0, 0xd3, ZC3XX_R08B_I2CDEVICEADDR}, /* 00,8b,d3,cc */ + {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH}, /* 00,03,02,cc */ + {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW}, /* 00,04,80,cc */ + {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH}, /* 00,05,01,cc */ + {0xa0, 0xd0, ZC3XX_R006_FRAMEHEIGHTLOW}, /* 00,06,d0,cc */ + {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING}, /* 00,01,01,cc */ + {0xa0, 0x03, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,03,cc */ + {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,01,cc */ + {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,05,cc */ + {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW}, /* 00,98,00,cc */ + {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW}, /* 00,9a,00,cc */ + {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW}, /* 01,1a,00,cc */ + {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW}, /* 01,1c,00,cc */ + {0xa0, 0xd8, ZC3XX_R09C_WINHEIGHTLOW}, /* 00,9c,d8,cc */ + {0xa0, 0x88, ZC3XX_R09E_WINWIDTHLOW}, /* 00,9e,88,cc */ + {0xbb, 0x00, 0x0400}, /* 04,00,00,bb */ + {0xdd, 0x00, 0x0010}, /* 00,00,10,dd */ + {0xbb, 0x0f, 0x140f}, /* 14,0f,0f,bb */ + {0xa0, 0x37, ZC3XX_R101_SENSORCORRECTION}, /* 01,01,37,cc */ + {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE}, /* 01,00,0d,cc */ + {0xa0, 0x06, ZC3XX_R189_AWBSTATUS}, /* 01,89,06,cc */ + {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE}, /* 01,c5,03,cc */ + {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05}, /* 01,cb,13,cc */ + {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE}, /* 02,50,08,cc */ + {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS}, /* 03,01,08,cc */ + {0xa0, 0x58, ZC3XX_R116_RGAIN}, /* 01,16,58,cc */ + {0xa0, 0x5a, ZC3XX_R118_BGAIN}, /* 01,18,5a,cc */ + {0xa0, 0x02, ZC3XX_R180_AUTOCORRECTENABLE}, /* 01,80,02,cc */ + {0xa0, 0xd3, ZC3XX_R08B_I2CDEVICEADDR}, /* 00,8b,d3,cc */ + {0xbb, 0x00, 0x0408}, /* 04,00,08,bb */ + {0xdd, 0x00, 0x0200}, /* 00,02,00,dd */ + {0xbb, 0x00, 0x0400}, /* 04,00,00,bb */ + {0xdd, 0x00, 0x0050}, /* 00,00,50,dd */ + {0xbb, 0x0f, 0x140f}, /* 14,0f,0f,bb */ + {0xbb, 0xe0, 0x0c2e}, /* 0c,e0,2e,bb */ + {0xbb, 0x01, 0x2000}, /* 20,01,00,bb */ + {0xbb, 0x96, 0x2400}, /* 24,96,00,bb */ + {0xbb, 0x06, 0x1006}, /* 10,06,06,bb */ + {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,01,cc */ + {0xdd, 0x00, 0x0010}, /* 00,00,10,dd */ + {0xaa, 0xfe, 0x0002}, /* 00,fe,02,aa */ + {0xa0, 0x0a, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,0a,cc */ + {0xdd, 0x00, 0x0010}, /* 00,00,10,dd */ + {0xbb, 0x5f, 0x2090}, /* 20,5f,90,bb */ + {0xbb, 0x01, 0x8000}, /* 80,01,00,bb */ + {0xbb, 0x09, 0x8400}, /* 84,09,00,bb */ + {0xbb, 0x88, 0x0002}, /* 00,88,02,bb */ + {0xbb, 0xe6, 0x0401}, /* 04,e6,01,bb */ + {0xbb, 0x88, 0x0802}, /* 08,88,02,bb */ + {0xbb, 0xe6, 0x0c01}, /* 0c,e6,01,bb */ + {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,01,cc */ + {0xdd, 0x00, 0x0010}, /* 00,00,10,dd */ + {0xaa, 0xfe, 0x0000}, /* 00,fe,00,aa */ + {0xa0, 0x0a, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,0a,cc */ + {0xdd, 0x00, 0x0010}, /* 00,00,10,dd */ + {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,01,cc */ + {0xaa, 0xfe, 0x0020}, /* 00,fe,20,aa */ + /*******/ + {0xa0, 0x0a, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,0a,cc */ + {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,01,cc */ + {0xdd, 0x00, 0x0010}, /* 00,00,10,dd */ + {0xaa, 0xfe, 0x0000}, /* 00,fe,00,aa */ + {0xa0, 0x0a, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,0a,cc */ + {0xdd, 0x00, 0x0010}, /* 00,00,10,dd */ + {0xbb, 0x04, 0x0400}, /* 04,04,00,bb */ + {0xdd, 0x00, 0x0100}, /* 00,01,00,dd */ + {0xbb, 0x01, 0x0400}, /* 04,01,00,bb */ + {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,01,cc */ + {0xaa, 0xfe, 0x0002}, /* 00,fe,02,aa */ + {0xa0, 0x0a, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,0a,cc */ + {0xbb, 0x41, 0x2803}, /* 28,41,03,bb */ + {0xbb, 0x40, 0x2c03}, /* 2c,40,03,bb */ + {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,01,cc */ + {0xaa, 0xfe, 0x0010}, /* 00,fe,10,aa */ + {} +}; +static const struct usb_action adcm2700_50HZ[] = { + {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,01,cc */ + {0xaa, 0xfe, 0x0002}, /* 00,fe,02,aa */ + {0xa0, 0x0a, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,0a,cc */ + {0xbb, 0x05, 0x8400}, /* 84,05,00,bb */ + {0xbb, 0xd0, 0xb007}, /* b0,d0,07,bb */ + {0xbb, 0xa0, 0xb80f}, /* b8,a0,0f,bb */ + {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,01,cc */ + {0xaa, 0xfe, 0x0010}, /* 00,fe,10,aa */ + {0xaa, 0x26, 0x00d0}, /* 00,26,d0,aa */ + {0xaa, 0x28, 0x0002}, /* 00,28,02,aa */ + {} +}; +static const struct usb_action adcm2700_50HZScale[] = { + {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,01,cc */ + {0xaa, 0xfe, 0x0002}, /* 00,fe,02,aa */ + {0xa0, 0x0a, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,0a,cc */ + {0xbb, 0x05, 0x8400}, /* 84,05,00,bb */ + {0xbb, 0xd0, 0xb007}, /* b0,d0,07,bb */ + {0xbb, 0xa0, 0xb80f}, /* b8,a0,0f,bb */ + {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,01,cc */ + {0xaa, 0xfe, 0x0010}, /* 00,fe,10,aa */ + {0xaa, 0x26, 0x00d0}, /* 00,26,d0,aa */ + {0xaa, 0x28, 0x0002}, /* 00,28,02,aa */ + {} +}; +static const struct usb_action adcm2700_60HZ[] = { + {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,01,cc */ + {0xaa, 0xfe, 0x0002}, /* 00,fe,02,aa */ + {0xa0, 0x0a, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,0a,cc */ + {0xbb, 0x07, 0x8400}, /* 84,07,00,bb */ + {0xbb, 0x82, 0xb006}, /* b0,82,06,bb */ + {0xbb, 0x04, 0xb80d}, /* b8,04,0d,bb */ + {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,01,cc */ + {0xaa, 0xfe, 0x0010}, /* 00,fe,10,aa */ + {0xaa, 0x26, 0x0057}, /* 00,26,57,aa */ + {0xaa, 0x28, 0x0002}, /* 00,28,02,aa */ + {} +}; +static const struct usb_action adcm2700_60HZScale[] = { + {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,01,cc */ + {0xaa, 0xfe, 0x0002}, /* 00,fe,02,aa */ + {0xa0, 0x0a, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,0a,cc */ + {0xbb, 0x07, 0x8400}, /* 84,07,00,bb */ + {0xbb, 0x82, 0xb006}, /* b0,82,06,bb */ + {0xbb, 0x04, 0xb80d}, /* b8,04,0d,bb */ + {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,01,cc */ + {0xaa, 0xfe, 0x0010}, /* 00,fe,10,aa */ + {0xaa, 0x26, 0x0057}, /* 00,26,57,aa */ + {0xaa, 0x28, 0x0002}, /* 00,28,02,aa */ + {} +}; +static const struct usb_action adcm2700_NoFliker[] = { + {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,01,cc */ + {0xaa, 0xfe, 0x0002}, /* 00,fe,02,aa */ + {0xa0, 0x0a, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,0a,cc */ + {0xbb, 0x07, 0x8400}, /* 84,07,00,bb */ + {0xbb, 0x05, 0xb000}, /* b0,05,00,bb */ + {0xbb, 0xa0, 0xb801}, /* b8,a0,01,bb */ + {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,01,cc */ + {0xaa, 0xfe, 0x0010}, /* 00,fe,10,aa */ + {} +}; +static const struct usb_action adcm2700_NoFlikerScale[] = { + {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,01,cc */ + {0xaa, 0xfe, 0x0002}, /* 00,fe,02,aa */ + {0xa0, 0x0a, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,0a,cc */ + {0xbb, 0x07, 0x8400}, /* 84,07,00,bb */ + {0xbb, 0x05, 0xb000}, /* b0,05,00,bb */ + {0xbb, 0xa0, 0xb801}, /* b8,a0,01,bb */ + {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,01,cc */ + {0xaa, 0xfe, 0x0010}, /* 00,fe,10,aa */ + {} +}; static const struct usb_action cs2102_Initial[] = { {0xa1, 0x01, 0x0008}, {0xa1, 0x01, 0x0008}, @@ -6286,8 +6522,8 @@ static __u16 i2c_read(struct gspca_dev *gspca_dev, __u8 retbyte; __u16 retval; - reg_w_i(gspca_dev->dev, reg, 0x92); - reg_w_i(gspca_dev->dev, 0x02, 0x90); /* <- read command */ + reg_w_i(gspca_dev->dev, reg, 0x0092); + reg_w_i(gspca_dev->dev, 0x02, 0x0090); /* <- read command */ msleep(25); retbyte = reg_r_i(gspca_dev, 0x0091); /* read status */ retval = reg_r_i(gspca_dev, 0x0095); /* read Lowbyte */ @@ -6332,6 +6568,12 @@ static void usb_exchange(struct gspca_dev *gspca_dev, action->idx & 0xff, /* valL */ action->idx >> 8); /* valH */ break; + case 0xbb: + i2c_write(gspca_dev, + action->idx >> 8, /* reg */ + action->idx & 0xff, /* valL */ + action->val); /* valH */ + break; default: /* case 0xdd: * delay */ msleep(action->val / 64 + 10); @@ -6347,6 +6589,8 @@ static void setmatrix(struct gspca_dev *gspca_dev) struct sd *sd = (struct sd *) gspca_dev; int i; const __u8 *matrix; + static const u8 adcm2700_matrix[9] = + {0x66, 0xed, 0xed, 0xed, 0x66, 0xed, 0xed, 0xed, 0x66}; static const __u8 gc0305_matrix[9] = {0x50, 0xf8, 0xf8, 0xf8, 0x50, 0xf8, 0xf8, 0xf8, 0x50}; static const __u8 ov7620_matrix[9] = @@ -6358,23 +6602,24 @@ static void setmatrix(struct gspca_dev *gspca_dev) static const __u8 vf0250_matrix[9] = {0x7b, 0xea, 0xea, 0xea, 0x7b, 0xea, 0xea, 0xea, 0x7b}; static const __u8 *matrix_tb[SENSOR_MAX] = { - NULL, /* SENSOR_CS2102 0 */ - NULL, /* SENSOR_CS2102K 1 */ - gc0305_matrix, /* SENSOR_GC0305 2 */ - NULL, /* SENSOR_HDCS2020b 3 */ - NULL, /* SENSOR_HV7131B 4 */ - NULL, /* SENSOR_HV7131C 5 */ - NULL, /* SENSOR_ICM105A 6 */ - NULL, /* SENSOR_MC501CB 7 */ - ov7620_matrix, /* SENSOR_OV7620 8 */ - NULL, /* SENSOR_OV7630C 9 */ - NULL, /* SENSOR_PAS106 10 */ - pas202b_matrix, /* SENSOR_PAS202B 11 */ - NULL, /* SENSOR_PB0330 12 */ - po2030_matrix, /* SENSOR_PO2030 13 */ - NULL, /* SENSOR_TAS5130CK 14 */ - NULL, /* SENSOR_TAS5130CXX 15 */ - vf0250_matrix, /* SENSOR_TAS5130C_VF0250 16 */ + adcm2700_matrix, /* SENSOR_ADCM2700 0 */ + NULL, /* SENSOR_CS2102 1 */ + NULL, /* SENSOR_CS2102K 2 */ + gc0305_matrix, /* SENSOR_GC0305 3 */ + NULL, /* SENSOR_HDCS2020b 4 */ + NULL, /* SENSOR_HV7131B 5 */ + NULL, /* SENSOR_HV7131C 6 */ + NULL, /* SENSOR_ICM105A 7 */ + NULL, /* SENSOR_MC501CB 8 */ + ov7620_matrix, /* SENSOR_OV7620 9 */ + NULL, /* SENSOR_OV7630C 10 */ + NULL, /* SENSOR_PAS106 11 */ + pas202b_matrix, /* SENSOR_PAS202B 12 */ + NULL, /* SENSOR_PB0330 13 */ + po2030_matrix, /* SENSOR_PO2030 14 */ + NULL, /* SENSOR_TAS5130CK 15 */ + NULL, /* SENSOR_TAS5130CXX 16 */ + vf0250_matrix, /* SENSOR_TAS5130C_VF0250 17 */ }; matrix = matrix_tb[sd->sensor]; @@ -6390,6 +6635,7 @@ static void setbrightness(struct gspca_dev *gspca_dev) __u8 brightness; switch (sd->sensor) { + case SENSOR_ADCM2700: case SENSOR_GC0305: case SENSOR_OV7620: case SENSOR_PO2030: @@ -6574,71 +6820,75 @@ static int setlightfreq(struct gspca_dev *gspca_dev) int i, mode; const struct usb_action *zc3_freq; static const struct usb_action *freq_tb[SENSOR_MAX][6] = { -/* SENSOR_CS2102 0 */ +/* SENSOR_ADCM2700 0 */ + {adcm2700_NoFlikerScale, adcm2700_NoFliker, + adcm2700_50HZScale, adcm2700_50HZ, + adcm2700_60HZScale, adcm2700_60HZ}, +/* SENSOR_CS2102 1 */ {cs2102_NoFliker, cs2102_NoFlikerScale, cs2102_50HZ, cs2102_50HZScale, cs2102_60HZ, cs2102_60HZScale}, -/* SENSOR_CS2102K 1 */ +/* SENSOR_CS2102K 2 */ {cs2102_NoFliker, cs2102_NoFlikerScale, NULL, NULL, /* currently disabled */ NULL, NULL}, -/* SENSOR_GC0305 2 */ +/* SENSOR_GC0305 3 */ {gc0305_NoFliker, gc0305_NoFliker, gc0305_50HZ, gc0305_50HZ, gc0305_60HZ, gc0305_60HZ}, -/* SENSOR_HDCS2020b 3 */ +/* SENSOR_HDCS2020b 4 */ {hdcs2020b_NoFliker, hdcs2020b_NoFliker, hdcs2020b_50HZ, hdcs2020b_50HZ, hdcs2020b_60HZ, hdcs2020b_60HZ}, -/* SENSOR_HV7131B 4 */ +/* SENSOR_HV7131B 5 */ {hv7131b_NoFlikerScale, hv7131b_NoFliker, hv7131b_50HZScale, hv7131b_50HZ, hv7131b_60HZScale, hv7131b_60HZ}, -/* SENSOR_HV7131C 5 */ +/* SENSOR_HV7131C 6 */ {NULL, NULL, NULL, NULL, NULL, NULL}, -/* SENSOR_ICM105A 6 */ +/* SENSOR_ICM105A 7 */ {icm105a_NoFliker, icm105a_NoFlikerScale, icm105a_50HZ, icm105a_50HZScale, icm105a_60HZ, icm105a_60HZScale}, -/* SENSOR_MC501CB 7 */ +/* SENSOR_MC501CB 8 */ {MC501CB_NoFliker, MC501CB_NoFlikerScale, MC501CB_50HZ, MC501CB_50HZScale, MC501CB_60HZ, MC501CB_60HZScale}, -/* SENSOR_OV7620 8 */ +/* SENSOR_OV7620 9 */ {OV7620_NoFliker, OV7620_NoFliker, OV7620_50HZ, OV7620_50HZ, OV7620_60HZ, OV7620_60HZ}, -/* SENSOR_OV7630C 9 */ +/* SENSOR_OV7630C 10 */ {NULL, NULL, NULL, NULL, NULL, NULL}, -/* SENSOR_PAS106 10 */ +/* SENSOR_PAS106 11 */ {pas106b_NoFliker, pas106b_NoFliker, pas106b_50HZ, pas106b_50HZ, pas106b_60HZ, pas106b_60HZ}, -/* SENSOR_PAS202B 11 */ +/* SENSOR_PAS202B 12 */ {pas202b_NoFlikerScale, pas202b_NoFliker, pas202b_50HZScale, pas202b_50HZ, pas202b_60HZScale, pas202b_60HZ}, -/* SENSOR_PB0330 12 */ +/* SENSOR_PB0330 13 */ {pb0330_NoFliker, pb0330_NoFlikerScale, pb0330_50HZ, pb0330_50HZScale, pb0330_60HZ, pb0330_60HZScale}, -/* SENSOR_PO2030 13 */ +/* SENSOR_PO2030 14 */ {PO2030_NoFliker, PO2030_NoFliker, PO2030_50HZ, PO2030_50HZ, PO2030_60HZ, PO2030_60HZ}, -/* SENSOR_TAS5130CK 14 */ +/* SENSOR_TAS5130CK 15 */ {tas5130cxx_NoFliker, tas5130cxx_NoFlikerScale, tas5130cxx_50HZ, tas5130cxx_50HZScale, tas5130cxx_60HZ, tas5130cxx_60HZScale}, -/* SENSOR_TAS5130CXX 15 */ +/* SENSOR_TAS5130CXX 16 */ {tas5130cxx_NoFliker, tas5130cxx_NoFlikerScale, tas5130cxx_50HZ, tas5130cxx_50HZScale, tas5130cxx_60HZ, tas5130cxx_60HZScale}, -/* SENSOR_TAS5130C_VF0250 16 */ +/* SENSOR_TAS5130C_VF0250 17 */ {tas5130c_vf0250_NoFliker, tas5130c_vf0250_NoFlikerScale, tas5130c_vf0250_50HZ, tas5130c_vf0250_50HZScale, tas5130c_vf0250_60HZ, tas5130c_vf0250_60HZScale}, @@ -6692,6 +6942,7 @@ static void send_unknown(struct usb_device *dev, int sensor) reg_w(dev, 0x0c, 0x003b); reg_w(dev, 0x08, 0x0038); break; + case SENSOR_ADCM2700: case SENSOR_GC0305: case SENSOR_OV7620: case SENSOR_PB0330: @@ -6949,7 +7200,7 @@ static int vga_3wr_probe(struct gspca_dev *gspca_dev) retword = i2c_read(gspca_dev, 0x01); if (retword != 0) { PDEBUG(D_PROBE, "probe 3wr vga type 0a ? ret: %04x", retword); - return 0x0a; /* ?? */ + return retword; /* 0x6200/0x6100?? */ } return -1; } @@ -6993,23 +7244,24 @@ static int sd_config(struct gspca_dev *gspca_dev, int sensor; int vga = 1; /* 1: vga, 0: sif */ static const __u8 gamma[SENSOR_MAX] = { - 5, /* SENSOR_CS2102 0 */ - 5, /* SENSOR_CS2102K 1 */ - 4, /* SENSOR_GC0305 2 */ - 4, /* SENSOR_HDCS2020b 3 */ - 4, /* SENSOR_HV7131B 4 */ - 4, /* SENSOR_HV7131C 5 */ - 4, /* SENSOR_ICM105A 6 */ - 4, /* SENSOR_MC501CB 7 */ - 3, /* SENSOR_OV7620 8 */ - 4, /* SENSOR_OV7630C 9 */ - 4, /* SENSOR_PAS106 10 */ - 4, /* SENSOR_PAS202B 11 */ - 4, /* SENSOR_PB0330 12 */ - 4, /* SENSOR_PO2030 13 */ - 4, /* SENSOR_TAS5130CK 14 */ - 4, /* SENSOR_TAS5130CXX 15 */ - 3, /* SENSOR_TAS5130C_VF0250 16 */ + 4, /* SENSOR_ADCM2700 0 */ + 5, /* SENSOR_CS2102 1 */ + 5, /* SENSOR_CS2102K 2 */ + 4, /* SENSOR_GC0305 3 */ + 4, /* SENSOR_HDCS2020b 4 */ + 4, /* SENSOR_HV7131B 5 */ + 4, /* SENSOR_HV7131C 6 */ + 4, /* SENSOR_ICM105A 7 */ + 4, /* SENSOR_MC501CB 8 */ + 3, /* SENSOR_OV7620 9 */ + 4, /* SENSOR_OV7630C 10 */ + 4, /* SENSOR_PAS106 11 */ + 4, /* SENSOR_PAS202B 12 */ + 4, /* SENSOR_PB0330 13 */ + 4, /* SENSOR_PO2030 14 */ + 4, /* SENSOR_TAS5130CK 15 */ + 4, /* SENSOR_TAS5130CXX 16 */ + 3, /* SENSOR_TAS5130C_VF0250 17 */ }; /* define some sensors from the vendor/product */ @@ -7017,7 +7269,7 @@ static int sd_config(struct gspca_dev *gspca_dev, sd->sensor = id->driver_info; sensor = zcxx_probeSensor(gspca_dev); if (sensor >= 0) - PDEBUG(D_PROBE, "probe sensor -> %02x", sensor); + PDEBUG(D_PROBE, "probe sensor -> %04x", sensor); if ((unsigned) force_sensor < SENSOR_MAX) { sd->sensor = force_sensor; PDEBUG(D_PROBE, "sensor forced to %d", force_sensor); @@ -7109,6 +7361,12 @@ static int sd_config(struct gspca_dev *gspca_dev, sd->sensor = SENSOR_PO2030; sd->sharpness = 0; /* from win traces */ break; + case 0x6100: + case 0x6200: + PDEBUG(D_PROBE, "Find Sensor ADCM2700"); + sd->sensor = SENSOR_ADCM2700; + send_unknown(gspca_dev->dev, sd->sensor); + break; case 0x7620: PDEBUG(D_PROBE, "Find Sensor OV7620"); sd->sensor = SENSOR_OV7620; @@ -7178,25 +7436,26 @@ static int sd_start(struct gspca_dev *gspca_dev) const struct usb_action *zc3_init; int mode; static const struct usb_action *init_tb[SENSOR_MAX][2] = { - {cs2102_InitialScale, cs2102_Initial}, /* 0 */ - {cs2102K_InitialScale, cs2102K_Initial}, /* 1 */ - {gc0305_Initial, gc0305_InitialScale}, /* 2 */ - {hdcs2020xb_InitialScale, hdcs2020xb_Initial}, /* 3 */ - {hv7131bxx_InitialScale, hv7131bxx_Initial}, /* 4 */ - {hv7131cxx_InitialScale, hv7131cxx_Initial}, /* 5 */ - {icm105axx_InitialScale, icm105axx_Initial}, /* 6 */ - {MC501CB_InitialScale, MC501CB_Initial}, /* 7 */ - {OV7620_mode0, OV7620_mode1}, /* 8 */ - {ov7630c_InitialScale, ov7630c_Initial}, /* 9 */ - {pas106b_InitialScale, pas106b_Initial}, /* 10 */ - {pas202b_Initial, pas202b_InitialScale}, /* 11 */ - {pb0330xx_InitialScale, pb0330xx_Initial}, /* 12 */ + {adcm2700_Initial, adcm2700_InitialScale}, /* 0 */ + {cs2102_InitialScale, cs2102_Initial}, /* 1 */ + {cs2102K_InitialScale, cs2102K_Initial}, /* 2 */ + {gc0305_Initial, gc0305_InitialScale}, /* 3 */ + {hdcs2020xb_InitialScale, hdcs2020xb_Initial}, /* 4 */ + {hv7131bxx_InitialScale, hv7131bxx_Initial}, /* 5 */ + {hv7131cxx_InitialScale, hv7131cxx_Initial}, /* 6 */ + {icm105axx_InitialScale, icm105axx_Initial}, /* 7 */ + {MC501CB_InitialScale, MC501CB_Initial}, /* 8 */ + {OV7620_mode0, OV7620_mode1}, /* 9 */ + {ov7630c_InitialScale, ov7630c_Initial}, /* 10 */ + {pas106b_InitialScale, pas106b_Initial}, /* 11 */ + {pas202b_Initial, pas202b_InitialScale}, /* 12 */ + {pb0330xx_InitialScale, pb0330xx_Initial}, /* 13 */ /* or {pb03303x_InitialScale, pb03303x_Initial}, */ - {PO2030_mode0, PO2030_mode1}, /* 13 */ - {tas5130CK_InitialScale, tas5130CK_Initial}, /* 14 */ - {tas5130cxx_InitialScale, tas5130cxx_Initial}, /* 15 */ + {PO2030_mode0, PO2030_mode1}, /* 14 */ + {tas5130CK_InitialScale, tas5130CK_Initial}, /* 15 */ + {tas5130cxx_InitialScale, tas5130cxx_Initial}, /* 16 */ {tas5130c_vf0250_InitialScale, tas5130c_vf0250_Initial}, - /* 16 */ + /* 17 */ }; mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv; @@ -7225,11 +7484,12 @@ static int sd_start(struct gspca_dev *gspca_dev) usb_exchange(gspca_dev, zc3_init); switch (sd->sensor) { + case SENSOR_ADCM2700: case SENSOR_GC0305: case SENSOR_OV7620: case SENSOR_PO2030: case SENSOR_TAS5130C_VF0250: - msleep(100); /* ?? */ +/* msleep(100); * ?? */ reg_r(gspca_dev, 0x0002); /* --> 0x40 */ reg_w(dev, 0x09, 0x01ad); /* (from win traces) */ reg_w(dev, 0x15, 0x01ae); @@ -7242,6 +7502,7 @@ static int sd_start(struct gspca_dev *gspca_dev) setmatrix(gspca_dev); setbrightness(gspca_dev); switch (sd->sensor) { + case SENSOR_ADCM2700: case SENSOR_OV7620: reg_r(gspca_dev, 0x0008); reg_w(dev, 0x00, 0x0008); @@ -7271,6 +7532,8 @@ static int sd_start(struct gspca_dev *gspca_dev) } setmatrix(gspca_dev); /* one more time? */ switch (sd->sensor) { + case SENSOR_ADCM2700: + break; case SENSOR_OV7620: case SENSOR_PAS202B: reg_r(gspca_dev, 0x0180); /* from win */ @@ -7283,6 +7546,13 @@ static int sd_start(struct gspca_dev *gspca_dev) setlightfreq(gspca_dev); switch (sd->sensor) { + case SENSOR_ADCM2700: + reg_w(dev, 0x09, 0x01ad); /* (from win traces) */ + reg_w(dev, 0x15, 0x01ae); + reg_w(dev, 0x02, 0x0180); + /* ms-win + */ + reg_w(dev, 0x40, 0x0117); + break; case SENSOR_GC0305: reg_w(dev, 0x09, 0x01ad); /* (from win traces) */ reg_w(dev, 0x15, 0x01ae); -- cgit v1.2.3 From 5be2b095b04b309267644ed6ecd1e092669fc4ad Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Tue, 20 Jan 2009 05:12:34 -0300 Subject: V4L/DVB (10374): gspca - zc3xx: Bad probe of the sensor adcm2700. Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/zc3xx.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/gspca/zc3xx.c b/drivers/media/video/gspca/zc3xx.c index b986362bdd17..a2f25e35b844 100644 --- a/drivers/media/video/gspca/zc3xx.c +++ b/drivers/media/video/gspca/zc3xx.c @@ -7084,6 +7084,7 @@ static const struct sensor_by_chipset_revision chipset_revision_sensor[] = { {0x8001, 0x13}, {0x8000, 0x14}, /* CS2102K */ {0x8400, 0x15}, /* TAS5130K */ + {0x4001, 0x16}, /* ADCM2700 */ }; static int vga_3wr_probe(struct gspca_dev *gspca_dev) @@ -7200,7 +7201,7 @@ static int vga_3wr_probe(struct gspca_dev *gspca_dev) retword = i2c_read(gspca_dev, 0x01); if (retword != 0) { PDEBUG(D_PROBE, "probe 3wr vga type 0a ? ret: %04x", retword); - return retword; /* 0x6200/0x6100?? */ + return retword; } return -1; } @@ -7348,6 +7349,10 @@ static int sd_config(struct gspca_dev *gspca_dev, sd->chip_revision); sd->sensor = SENSOR_TAS5130CK; break; + case 0x16: + PDEBUG(D_PROBE, "Find Sensor ADCM2700"); + sd->sensor = SENSOR_ADCM2700; + break; case 0x29: PDEBUG(D_PROBE, "Find Sensor GC0305"); sd->sensor = SENSOR_GC0305; @@ -7361,12 +7366,6 @@ static int sd_config(struct gspca_dev *gspca_dev, sd->sensor = SENSOR_PO2030; sd->sharpness = 0; /* from win traces */ break; - case 0x6100: - case 0x6200: - PDEBUG(D_PROBE, "Find Sensor ADCM2700"); - sd->sensor = SENSOR_ADCM2700; - send_unknown(gspca_dev->dev, sd->sensor); - break; case 0x7620: PDEBUG(D_PROBE, "Find Sensor OV7620"); sd->sensor = SENSOR_OV7620; @@ -7376,7 +7375,7 @@ static int sd_config(struct gspca_dev *gspca_dev, sd->sensor = SENSOR_OV7620; /* same sensor (?) */ break; default: - PDEBUG(D_ERR|D_PROBE, "Unknown sensor %02x", sensor); + PDEBUG(D_ERR|D_PROBE, "Unknown sensor %04x", sensor); return -EINVAL; } } -- cgit v1.2.3 From f1ee8e88e93cec2aabbd6669a0a94c8b8ad6d8fc Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Tue, 20 Jan 2009 08:14:17 -0300 Subject: V4L/DVB (10375): gspca - zc3xx: Remove duplicated sequence of sensor cs2102k. Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/zc3xx.c | 205 +------------------------------------- 1 file changed, 3 insertions(+), 202 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/gspca/zc3xx.c b/drivers/media/video/gspca/zc3xx.c index a2f25e35b844..57917652d209 100644 --- a/drivers/media/video/gspca/zc3xx.c +++ b/drivers/media/video/gspca/zc3xx.c @@ -1113,7 +1113,7 @@ static const struct usb_action cs2102K_Initial[] = { }; static const struct usb_action cs2102K_InitialScale[] = { - {0xa0, 0x11, ZC3XX_R002_CLOCKSELECT}, + {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, {0xa0, 0x00, ZC3XX_R002_CLOCKSELECT}, {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, {0xa0, 0x08, ZC3XX_R010_CMOSSENSORSELECT}, @@ -1130,6 +1130,7 @@ static const struct usb_action cs2102K_InitialScale[] = { {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW}, {0xa0, 0xe8, ZC3XX_R09C_WINHEIGHTLOW}, {0xa0, 0x88, ZC3XX_R09E_WINWIDTHLOW}, +/*fixme: next sequence = i2c exchanges*/ {0xa0, 0x55, ZC3XX_R08B_I2CDEVICEADDR}, {0xa0, 0x18, ZC3XX_R092_I2CADDRESSSELECT}, {0xa0, 0x00, ZC3XX_R093_I2CSETVALUE}, @@ -1313,207 +1314,6 @@ static const struct usb_action cs2102K_InitialScale[] = { {0xa0, 0x60, ZC3XX_R116_RGAIN}, {0xa0, 0x40, ZC3XX_R117_GGAIN}, {0xa0, 0x4c, ZC3XX_R118_BGAIN}, - {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, - {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, - {0xa0, 0x00, ZC3XX_R002_CLOCKSELECT}, - {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, - {0xa0, 0x08, ZC3XX_R010_CMOSSENSORSELECT}, - {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH}, - {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW}, - {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH}, - {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW}, - {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING}, - {0xa0, 0x03, ZC3XX_R012_VIDEOCONTROLFUNC}, - {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC}, - {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW}, - {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW}, - {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW}, - {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW}, - {0xa0, 0xe8, ZC3XX_R09C_WINHEIGHTLOW}, - {0xa0, 0x88, ZC3XX_R09E_WINWIDTHLOW}, - {0xa0, 0x55, ZC3XX_R08B_I2CDEVICEADDR}, - {0xa0, 0x18, ZC3XX_R092_I2CADDRESSSELECT}, - {0xa0, 0x00, ZC3XX_R093_I2CSETVALUE}, - {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK}, - {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND}, - {0xa0, 0x0A, ZC3XX_R092_I2CADDRESSSELECT}, - {0xa0, 0x02, ZC3XX_R093_I2CSETVALUE}, - {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK}, - {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND}, - {0xa0, 0x0B, ZC3XX_R092_I2CADDRESSSELECT}, - {0xa0, 0x02, ZC3XX_R093_I2CSETVALUE}, - {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK}, - {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND}, - {0xa0, 0x0C, ZC3XX_R092_I2CADDRESSSELECT}, - {0xa0, 0x7b, ZC3XX_R093_I2CSETVALUE}, - {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK}, - {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND}, - {0xa0, 0x0D, ZC3XX_R092_I2CADDRESSSELECT}, - {0xa0, 0xA3, ZC3XX_R093_I2CSETVALUE}, - {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK}, - {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND}, - {0xa0, 0x03, ZC3XX_R092_I2CADDRESSSELECT}, - {0xa0, 0xfb, ZC3XX_R093_I2CSETVALUE}, - {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK}, - {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND}, - {0xa0, 0x05, ZC3XX_R092_I2CADDRESSSELECT}, - {0xa0, 0x00, ZC3XX_R093_I2CSETVALUE}, - {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK}, - {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND}, - {0xa0, 0x06, ZC3XX_R092_I2CADDRESSSELECT}, - {0xa0, 0x03, ZC3XX_R093_I2CSETVALUE}, - {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK}, - {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND}, - {0xa0, 0x09, ZC3XX_R092_I2CADDRESSSELECT}, - {0xa0, 0x08, ZC3XX_R093_I2CSETVALUE}, - {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK}, - {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND}, - {0xa0, 0x0E, ZC3XX_R092_I2CADDRESSSELECT}, - {0xa0, 0x04, ZC3XX_R093_I2CSETVALUE}, - {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK}, - {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND}, - {0xa0, 0x0f, ZC3XX_R092_I2CADDRESSSELECT}, - {0xa0, 0x18, ZC3XX_R093_I2CSETVALUE}, - {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK}, - {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND}, - {0xa0, 0x10, ZC3XX_R092_I2CADDRESSSELECT}, - {0xa0, 0x18, ZC3XX_R093_I2CSETVALUE}, - {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK}, - {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND}, - {0xa0, 0x11, ZC3XX_R092_I2CADDRESSSELECT}, - {0xa0, 0x18, ZC3XX_R093_I2CSETVALUE}, - {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK}, - {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND}, - {0xa0, 0x12, ZC3XX_R092_I2CADDRESSSELECT}, - {0xa0, 0x18, ZC3XX_R093_I2CSETVALUE}, - {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK}, - {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND}, - {0xa0, 0x15, ZC3XX_R092_I2CADDRESSSELECT}, - {0xa0, 0x00, ZC3XX_R093_I2CSETVALUE}, - {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK}, - {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND}, - {0xa0, 0x16, ZC3XX_R092_I2CADDRESSSELECT}, - {0xa0, 0x0c, ZC3XX_R093_I2CSETVALUE}, - {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK}, - {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND}, - {0xa0, 0x17, ZC3XX_R092_I2CADDRESSSELECT}, - {0xa0, 0x0C, ZC3XX_R093_I2CSETVALUE}, - {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK}, - {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND}, - {0xa0, 0x18, ZC3XX_R092_I2CADDRESSSELECT}, - {0xa0, 0x04, ZC3XX_R093_I2CSETVALUE}, - {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK}, - {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND}, - {0xa0, 0xf7, ZC3XX_R101_SENSORCORRECTION}, - {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC}, - {0xa0, 0x78, ZC3XX_R18D_YTARGET}, - {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE}, - {0xa0, 0x06, ZC3XX_R189_AWBSTATUS}, - {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE}, - {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05}, - {0xa0, 0x20, ZC3XX_R087_EXPTIMEMID}, - {0xa0, 0x21, ZC3XX_R088_EXPTIMELOW}, - {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE}, - {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS}, - {0xa0, 0x00, 0x01ad}, - {0xa0, 0x01, 0x01b1}, - {0xa0, 0x02, ZC3XX_R180_AUTOCORRECTENABLE}, - {0xa0, 0x60, ZC3XX_R116_RGAIN}, - {0xa0, 0x40, ZC3XX_R117_GGAIN}, - {0xa0, 0x4c, ZC3XX_R118_BGAIN}, - {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, /* clock ? */ - {0xa0, 0x08, ZC3XX_R1C6_SHARPNESS00}, /* sharpness+ */ - {0xa0, 0x0f, ZC3XX_R1CB_SHARPNESS05}, /* sharpness- */ - {0xa0, 0x13, ZC3XX_R120_GAMMA00}, /* gamma 4 */ - {0xa0, 0x38, ZC3XX_R121_GAMMA01}, - {0xa0, 0x59, ZC3XX_R122_GAMMA02}, - {0xa0, 0x79, ZC3XX_R123_GAMMA03}, - {0xa0, 0x92, ZC3XX_R124_GAMMA04}, - {0xa0, 0xa7, ZC3XX_R125_GAMMA05}, - {0xa0, 0xb9, ZC3XX_R126_GAMMA06}, - {0xa0, 0xc8, ZC3XX_R127_GAMMA07}, - {0xa0, 0xd4, ZC3XX_R128_GAMMA08}, - {0xa0, 0xdf, ZC3XX_R129_GAMMA09}, - {0xa0, 0xe7, ZC3XX_R12A_GAMMA0A}, - {0xa0, 0xee, ZC3XX_R12B_GAMMA0B}, - {0xa0, 0xf4, ZC3XX_R12C_GAMMA0C}, - {0xa0, 0xf9, ZC3XX_R12D_GAMMA0D}, - {0xa0, 0xfc, ZC3XX_R12E_GAMMA0E}, - {0xa0, 0xff, ZC3XX_R12F_GAMMA0F}, - {0xa0, 0x26, ZC3XX_R130_GAMMA10}, - {0xa0, 0x22, ZC3XX_R131_GAMMA11}, - {0xa0, 0x20, ZC3XX_R132_GAMMA12}, - {0xa0, 0x1c, ZC3XX_R133_GAMMA13}, - {0xa0, 0x16, ZC3XX_R134_GAMMA14}, - {0xa0, 0x13, ZC3XX_R135_GAMMA15}, - {0xa0, 0x10, ZC3XX_R136_GAMMA16}, - {0xa0, 0x0d, ZC3XX_R137_GAMMA17}, - {0xa0, 0x0b, ZC3XX_R138_GAMMA18}, - {0xa0, 0x09, ZC3XX_R139_GAMMA19}, - {0xa0, 0x07, ZC3XX_R13A_GAMMA1A}, - {0xa0, 0x06, ZC3XX_R13B_GAMMA1B}, - {0xa0, 0x05, ZC3XX_R13C_GAMMA1C}, - {0xa0, 0x04, ZC3XX_R13D_GAMMA1D}, - {0xa0, 0x03, ZC3XX_R13E_GAMMA1E}, - {0xa0, 0x02, ZC3XX_R13F_GAMMA1F}, - {0xa0, 0x58, ZC3XX_R10A_RGB00}, /* matrix */ - {0xa0, 0xf4, ZC3XX_R10B_RGB01}, - {0xa0, 0xf4, ZC3XX_R10C_RGB02}, - {0xa0, 0xf4, ZC3XX_R10D_RGB10}, - {0xa0, 0x58, ZC3XX_R10E_RGB11}, - {0xa0, 0xf4, ZC3XX_R10F_RGB12}, - {0xa0, 0xf4, ZC3XX_R110_RGB20}, - {0xa0, 0xf4, ZC3XX_R111_RGB21}, - {0xa0, 0x58, ZC3XX_R112_RGB22}, - {0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE}, - {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, - {0xa0, 0x18, ZC3XX_R092_I2CADDRESSSELECT}, - {0xa0, 0x00, ZC3XX_R093_I2CSETVALUE}, - {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK}, - {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND}, - {0xa0, 0x13, ZC3XX_R092_I2CADDRESSSELECT}, - {0xa0, 0x22, ZC3XX_R093_I2CSETVALUE}, - {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK}, - {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND}, - {0xa0, 0x14, ZC3XX_R092_I2CADDRESSSELECT}, - {0xa0, 0x01, ZC3XX_R093_I2CSETVALUE}, - {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK}, - {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND}, - {0xa0, 0x20, ZC3XX_R092_I2CADDRESSSELECT}, - {0xa0, 0x01, ZC3XX_R093_I2CSETVALUE}, - {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK}, - {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND}, - {0xa0, 0x21, ZC3XX_R092_I2CADDRESSSELECT}, - {0xa0, 0x22, ZC3XX_R093_I2CSETVALUE}, - {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK}, - {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND}, - {0xa0, 0x18, ZC3XX_R092_I2CADDRESSSELECT}, - {0xa0, 0x04, ZC3XX_R093_I2CSETVALUE}, - {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK}, - {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND}, - {0xa0, 0x01, ZC3XX_R0A3_EXPOSURETIMEHIGH}, - {0xa0, 0x22, ZC3XX_R0A4_EXPOSURETIMELOW}, - {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, - {0xa0, 0x07, ZC3XX_R191_EXPOSURELIMITMID}, - {0xa0, 0xee, ZC3XX_R192_EXPOSURELIMITLOW}, - {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, - {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, - {0xa0, 0x3a, ZC3XX_R197_ANTIFLICKERLOW}, - {0xa0, 0x10, ZC3XX_R18C_AEFREEZE}, - {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE}, - {0xa0, 0x0c, ZC3XX_R1A9_DIGITALLIMITDIFF}, - {0xa0, 0x28, ZC3XX_R1AA_DIGITALGAINSTEP}, - {0xa0, 0x04, ZC3XX_R01D_HSYNC_0}, - {0xa0, 0x0f, ZC3XX_R01E_HSYNC_1}, - {0xa0, 0x19, ZC3XX_R01F_HSYNC_2}, - {0xa0, 0x1f, ZC3XX_R020_HSYNC_3}, - {0xa0, 0x60, ZC3XX_R11D_GLOBALGAIN}, - {0xa0, 0x60, ZC3XX_R11D_GLOBALGAIN}, - {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE}, - {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE}, - {0xa0, 0x60, ZC3XX_R116_RGAIN}, - {0xa0, 0x40, ZC3XX_R117_GGAIN}, - {0xa0, 0x4c, ZC3XX_R118_BGAIN}, {0xa0, 0x04, ZC3XX_R1A7_CALCGLOBALMEAN}, {0xa0, 0x20, ZC3XX_R092_I2CADDRESSSELECT}, {0xa0, 0x01, ZC3XX_R093_I2CSETVALUE}, @@ -1570,6 +1370,7 @@ static const struct usb_action cs2102K_InitialScale[] = { {0xa0, 0x00, ZC3XX_R1A7_CALCGLOBALMEAN}, {0xa0, 0x04, ZC3XX_R1A7_CALCGLOBALMEAN}, {0xa0, 0x00, ZC3XX_R1A7_CALCGLOBALMEAN}, +/*fixme:what does the next sequence?*/ {0xa0, 0x04, ZC3XX_R1A7_CALCGLOBALMEAN}, {0xa0, 0x00, ZC3XX_R1A7_CALCGLOBALMEAN}, {0xa0, 0x04, ZC3XX_R1A7_CALCGLOBALMEAN}, -- cgit v1.2.3 From c314b53bdd2059860ae49c0cd1256d9c60b185fd Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Tue, 20 Jan 2009 10:02:35 -0300 Subject: V4L/DVB (10376): gspca - zc3xx: Remove some useless tables of sensor adcm2700. Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/zc3xx.c | 43 +++------------------------------------ 1 file changed, 3 insertions(+), 40 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/gspca/zc3xx.c b/drivers/media/video/gspca/zc3xx.c index 57917652d209..fff95e69cd14 100644 --- a/drivers/media/video/gspca/zc3xx.c +++ b/drivers/media/video/gspca/zc3xx.c @@ -381,19 +381,6 @@ static const struct usb_action adcm2700_50HZ[] = { {0xaa, 0x28, 0x0002}, /* 00,28,02,aa */ {} }; -static const struct usb_action adcm2700_50HZScale[] = { - {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,01,cc */ - {0xaa, 0xfe, 0x0002}, /* 00,fe,02,aa */ - {0xa0, 0x0a, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,0a,cc */ - {0xbb, 0x05, 0x8400}, /* 84,05,00,bb */ - {0xbb, 0xd0, 0xb007}, /* b0,d0,07,bb */ - {0xbb, 0xa0, 0xb80f}, /* b8,a0,0f,bb */ - {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,01,cc */ - {0xaa, 0xfe, 0x0010}, /* 00,fe,10,aa */ - {0xaa, 0x26, 0x00d0}, /* 00,26,d0,aa */ - {0xaa, 0x28, 0x0002}, /* 00,28,02,aa */ - {} -}; static const struct usb_action adcm2700_60HZ[] = { {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,01,cc */ {0xaa, 0xfe, 0x0002}, /* 00,fe,02,aa */ @@ -407,19 +394,6 @@ static const struct usb_action adcm2700_60HZ[] = { {0xaa, 0x28, 0x0002}, /* 00,28,02,aa */ {} }; -static const struct usb_action adcm2700_60HZScale[] = { - {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,01,cc */ - {0xaa, 0xfe, 0x0002}, /* 00,fe,02,aa */ - {0xa0, 0x0a, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,0a,cc */ - {0xbb, 0x07, 0x8400}, /* 84,07,00,bb */ - {0xbb, 0x82, 0xb006}, /* b0,82,06,bb */ - {0xbb, 0x04, 0xb80d}, /* b8,04,0d,bb */ - {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,01,cc */ - {0xaa, 0xfe, 0x0010}, /* 00,fe,10,aa */ - {0xaa, 0x26, 0x0057}, /* 00,26,57,aa */ - {0xaa, 0x28, 0x0002}, /* 00,28,02,aa */ - {} -}; static const struct usb_action adcm2700_NoFliker[] = { {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,01,cc */ {0xaa, 0xfe, 0x0002}, /* 00,fe,02,aa */ @@ -431,17 +405,6 @@ static const struct usb_action adcm2700_NoFliker[] = { {0xaa, 0xfe, 0x0010}, /* 00,fe,10,aa */ {} }; -static const struct usb_action adcm2700_NoFlikerScale[] = { - {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,01,cc */ - {0xaa, 0xfe, 0x0002}, /* 00,fe,02,aa */ - {0xa0, 0x0a, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,0a,cc */ - {0xbb, 0x07, 0x8400}, /* 84,07,00,bb */ - {0xbb, 0x05, 0xb000}, /* b0,05,00,bb */ - {0xbb, 0xa0, 0xb801}, /* b8,a0,01,bb */ - {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,01,cc */ - {0xaa, 0xfe, 0x0010}, /* 00,fe,10,aa */ - {} -}; static const struct usb_action cs2102_Initial[] = { {0xa1, 0x01, 0x0008}, {0xa1, 0x01, 0x0008}, @@ -6622,9 +6585,9 @@ static int setlightfreq(struct gspca_dev *gspca_dev) const struct usb_action *zc3_freq; static const struct usb_action *freq_tb[SENSOR_MAX][6] = { /* SENSOR_ADCM2700 0 */ - {adcm2700_NoFlikerScale, adcm2700_NoFliker, - adcm2700_50HZScale, adcm2700_50HZ, - adcm2700_60HZScale, adcm2700_60HZ}, + {adcm2700_NoFliker, adcm2700_NoFliker, + adcm2700_50HZ, adcm2700_50HZ, + adcm2700_60HZ, adcm2700_60HZ}, /* SENSOR_CS2102 1 */ {cs2102_NoFliker, cs2102_NoFlikerScale, cs2102_50HZ, cs2102_50HZScale, -- cgit v1.2.3 From d08e2ce0ebb38f2b66d875a09ebab3ed548354ee Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Tue, 20 Jan 2009 16:21:44 -0300 Subject: V4L/DVB (10378): gspca - main: Avoid error on set interface on disconnection. Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/gspca.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/gspca/gspca.c b/drivers/media/video/gspca/gspca.c index db22e3c24764..068060231630 100644 --- a/drivers/media/video/gspca/gspca.c +++ b/drivers/media/video/gspca/gspca.c @@ -666,7 +666,8 @@ static void gspca_stream_off(struct gspca_dev *gspca_dev) && gspca_dev->sd_desc->stopN) gspca_dev->sd_desc->stopN(gspca_dev); destroy_urbs(gspca_dev); - gspca_set_alt0(gspca_dev); + if (gspca_dev->present) + gspca_set_alt0(gspca_dev); if (gspca_dev->sd_desc->stop0) gspca_dev->sd_desc->stop0(gspca_dev); PDEBUG(D_STREAM, "stream off OK"); -- cgit v1.2.3 From 5932028f749fe26292948d6d7d7ae1ee912350b3 Mon Sep 17 00:00:00 2001 From: Thierry MERLE Date: Wed, 21 Jan 2009 15:32:26 -0300 Subject: V4L/DVB (10379): gspca - main: Use usb_make_path() for VIDIOC_QUERYCAP. Signed-off-by: Thierry MERLE Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/gspca.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/gspca/gspca.c b/drivers/media/video/gspca/gspca.c index 068060231630..eac7aec44254 100644 --- a/drivers/media/video/gspca/gspca.c +++ b/drivers/media/video/gspca/gspca.c @@ -961,8 +961,7 @@ static int vidioc_querycap(struct file *file, void *priv, le16_to_cpu(gspca_dev->dev->descriptor.idVendor), le16_to_cpu(gspca_dev->dev->descriptor.idProduct)); } - strncpy(cap->bus_info, gspca_dev->dev->bus->bus_name, - sizeof cap->bus_info); + usb_make_path(gspca_dev->dev, cap->bus_info, sizeof(cap->bus_info)); cap->version = DRIVER_VERSION_NUMBER; cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING -- cgit v1.2.3 From 82e2549102a11c6ffc09f960e2325fd092c002a3 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Thu, 22 Jan 2009 07:18:48 -0300 Subject: V4L/DVB (10380): gspca - t613: Cleanup and optimize code. Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/t613.c | 379 +++++++++++++++++++-------------------- 1 file changed, 182 insertions(+), 197 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/gspca/t613.c b/drivers/media/video/gspca/t613.c index 76ba2c9588d7..8e89024b9135 100644 --- a/drivers/media/video/gspca/t613.c +++ b/drivers/media/video/gspca/t613.c @@ -37,18 +37,18 @@ MODULE_LICENSE("GPL"); struct sd { struct gspca_dev gspca_dev; /* !! must be the first item */ - unsigned char brightness; - unsigned char contrast; - unsigned char colors; - unsigned char autogain; - unsigned char gamma; - unsigned char sharpness; - unsigned char freq; - unsigned char whitebalance; - unsigned char mirror; - unsigned char effect; - - __u8 sensor; + u8 brightness; + u8 contrast; + u8 colors; + u8 autogain; + u8 gamma; + u8 sharpness; + u8 freq; + u8 whitebalance; + u8 mirror; + u8 effect; + + u8 sensor; #define SENSOR_TAS5130A 0 #define SENSOR_OM6802 1 }; @@ -78,7 +78,6 @@ static int sd_querymenu(struct gspca_dev *gspca_dev, struct v4l2_querymenu *menu); static struct ctrl sd_ctrls[] = { -#define SD_BRIGHTNESS 0 { { .id = V4L2_CID_BRIGHTNESS, @@ -87,12 +86,12 @@ static struct ctrl sd_ctrls[] = { .minimum = 0, .maximum = 14, .step = 1, - .default_value = 8, +#define BRIGHTNESS_DEF 8 + .default_value = BRIGHTNESS_DEF, }, .set = sd_setbrightness, .get = sd_getbrightness, }, -#define SD_CONTRAST 1 { { .id = V4L2_CID_CONTRAST, @@ -101,12 +100,12 @@ static struct ctrl sd_ctrls[] = { .minimum = 0, .maximum = 0x0d, .step = 1, - .default_value = 0x07, +#define CONTRAST_DEF 0x07 + .default_value = CONTRAST_DEF, }, .set = sd_setcontrast, .get = sd_getcontrast, }, -#define SD_COLOR 2 { { .id = V4L2_CID_SATURATION, @@ -115,7 +114,8 @@ static struct ctrl sd_ctrls[] = { .minimum = 0, .maximum = 0x0f, .step = 1, - .default_value = 0x05, +#define COLORS_DEF 0x05 + .default_value = COLORS_DEF, }, .set = sd_setcolors, .get = sd_getcolors, @@ -135,7 +135,6 @@ static struct ctrl sd_ctrls[] = { .set = sd_setgamma, .get = sd_getgamma, }, -#define SD_AUTOGAIN 4 { { .id = V4L2_CID_GAIN, /* here, i activate only the lowlight, @@ -146,12 +145,12 @@ static struct ctrl sd_ctrls[] = { .minimum = 0, .maximum = 1, .step = 1, - .default_value = 0x01, +#define AUTOGAIN_DEF 0x01 + .default_value = AUTOGAIN_DEF, }, .set = sd_setlowlight, .get = sd_getlowlight, }, -#define SD_MIRROR 5 { { .id = V4L2_CID_HFLIP, @@ -160,12 +159,12 @@ static struct ctrl sd_ctrls[] = { .minimum = 0, .maximum = 1, .step = 1, - .default_value = 0, +#define MIRROR_DEF 0 + .default_value = MIRROR_DEF, }, .set = sd_setflip, .get = sd_getflip }, -#define SD_LIGHTFREQ 6 { { .id = V4L2_CID_POWER_LINE_FREQUENCY, @@ -174,12 +173,12 @@ static struct ctrl sd_ctrls[] = { .minimum = 1, /* 1 -> 0x50, 2->0x60 */ .maximum = 2, .step = 1, - .default_value = 1, +#define FREQ_DEF 1 + .default_value = FREQ_DEF, }, .set = sd_setfreq, .get = sd_getfreq}, -#define SD_WHITE_BALANCE 7 { { .id = V4L2_CID_WHITE_BALANCE_TEMPERATURE, @@ -188,12 +187,12 @@ static struct ctrl sd_ctrls[] = { .minimum = 0, .maximum = 1, .step = 1, - .default_value = 0, +#define WHITE_BALANCE_DEF 0 + .default_value = WHITE_BALANCE_DEF, }, .set = sd_setwhitebalance, .get = sd_getwhitebalance }, -#define SD_SHARPNESS 8 /* (aka definition on win) */ { { .id = V4L2_CID_SHARPNESS, @@ -202,12 +201,12 @@ static struct ctrl sd_ctrls[] = { .minimum = 0, .maximum = 15, .step = 1, - .default_value = 0x06, +#define SHARPNESS_DEF 0x06 + .default_value = SHARPNESS_DEF, }, .set = sd_setsharpness, .get = sd_getsharpness, }, -#define SD_EFFECTS 9 { { .id = V4L2_CID_EFFECTS, @@ -216,7 +215,8 @@ static struct ctrl sd_ctrls[] = { .minimum = 0, .maximum = 4, .step = 1, - .default_value = 0, +#define EFFECTS_DEF 0 + .default_value = EFFECTS_DEF, }, .set = sd_seteffect, .get = sd_geteffect @@ -263,28 +263,22 @@ static const struct v4l2_pix_format vga_mode_t16[] = { /* sensor specific data */ struct additional_sensor_data { - const __u8 data1[20]; - const __u8 data2[18]; - const __u8 data3[18]; - const __u8 data4[4]; - const __u8 data5[6]; - const __u8 stream[4]; + const u8 data1[10]; + const u8 data2[9]; + const u8 data3[9]; + const u8 data4[4]; + const u8 data5[6]; + const u8 stream[4]; }; const static struct additional_sensor_data sensor_data[] = { { /* TAS5130A */ .data1 = - {0xd0, 0xbb, 0xd1, 0x28, 0xd2, 0x10, 0xd3, 0x10, - 0xd4, 0xbb, 0xd5, 0x28, 0xd6, 0x1e, 0xd7, 0x27, - 0xd8, 0xc8, 0xd9, 0xfc}, + {0xbb, 0x28, 0x10, 0x10, 0xbb, 0x28, 0x1e, 0x27, + 0xc8, 0xfc}, .data2 = - {0xe0, 0x60, 0xe1, 0xa8, 0xe2, 0xe0, 0xe3, 0x60, - 0xe4, 0xa8, 0xe5, 0xe0, 0xe6, 0x60, 0xe7, 0xa8, - 0xe8, 0xe0}, - .data3 = - {0xc7, 0x60, 0xc8, 0xa8, 0xc9, 0xe0, 0xca, 0x60, - 0xcb, 0xa8, 0xcc, 0xe0, 0xcd, 0x60, 0xce, 0xa8, - 0xcf, 0xe0}, + {0x60, 0xa8, 0xe0, 0x60, 0xa8, 0xe0, 0x60, 0xa8, + 0xe0}, .data4 = /* Freq (50/60Hz). Splitted for test purpose */ {0x66, 0x00, 0xa8, 0xe8}, .data5 = @@ -294,17 +288,11 @@ const static struct additional_sensor_data sensor_data[] = { }, { /* OM6802 */ .data1 = - {0xd0, 0xc2, 0xd1, 0x28, 0xd2, 0x0f, 0xd3, 0x22, - 0xd4, 0xcd, 0xd5, 0x27, 0xd6, 0x2c, 0xd7, 0x06, - 0xd8, 0xb3, 0xd9, 0xfc}, + {0xc2, 0x28, 0x0f, 0x22, 0xcd, 0x27, 0x2c, 0x06, + 0xb3, 0xfc}, .data2 = - {0xe0, 0x80, 0xe1, 0xff, 0xe2, 0xff, 0xe3, 0x80, - 0xe4, 0xff, 0xe5, 0xff, 0xe6, 0x80, 0xe7, 0xff, - 0xe8, 0xff}, - .data3 = - {0xc7, 0x80, 0xc8, 0xff, 0xc9, 0xff, 0xca, 0x80, - 0xcb, 0xff, 0xcc, 0xff, 0xcd, 0x80, 0xce, 0xff, - 0xcf, 0xff}, + {0x80, 0xff, 0xff, 0x80, 0xff, 0xff, 0x80, 0xff, + 0xff}, .data4 = /*Freq (50/60Hz). Splitted for test purpose */ {0x66, 0xca, 0xa8, 0xf0 }, .data5 = /* this could be removed later */ @@ -317,7 +305,7 @@ const static struct additional_sensor_data sensor_data[] = { #define MAX_EFFECTS 7 /* easily done by soft, this table could be removed, * i keep it here just in case */ -static const __u8 effects_table[MAX_EFFECTS][6] = { +static const u8 effects_table[MAX_EFFECTS][6] = { {0xa8, 0xe8, 0xc6, 0xd2, 0xc0, 0x00}, /* Normal */ {0xa8, 0xc8, 0xc6, 0x52, 0xc0, 0x04}, /* Repujar */ {0xa8, 0xe8, 0xc6, 0xd2, 0xc0, 0x20}, /* Monochrome */ @@ -327,90 +315,58 @@ static const __u8 effects_table[MAX_EFFECTS][6] = { {0xa8, 0xc8, 0xc6, 0xd2, 0xc0, 0x40}, /* Negative */ }; -static const __u8 gamma_table[GAMMA_MAX][34] = { - {0x90, 0x00, 0x91, 0x3e, 0x92, 0x69, 0x93, 0x85, /* 0 */ - 0x94, 0x95, 0x95, 0xa1, 0x96, 0xae, 0x97, 0xb9, - 0x98, 0xc2, 0x99, 0xcb, 0x9a, 0xd4, 0x9b, 0xdb, - 0x9c, 0xe3, 0x9d, 0xea, 0x9e, 0xf1, 0x9f, 0xf8, - 0xa0, 0xff}, - {0x90, 0x00, 0x91, 0x33, 0x92, 0x5a, 0x93, 0x75, /* 1 */ - 0x94, 0x85, 0x95, 0x93, 0x96, 0xa1, 0x97, 0xad, - 0x98, 0xb7, 0x99, 0xc2, 0x9a, 0xcb, 0x9b, 0xd4, - 0x9c, 0xde, 0x9D, 0xe7, 0x9e, 0xf0, 0x9f, 0xf7, - 0xa0, 0xff}, - {0x90, 0x00, 0x91, 0x2f, 0x92, 0x51, 0x93, 0x6b, /* 2 */ - 0x94, 0x7c, 0x95, 0x8a, 0x96, 0x99, 0x97, 0xa6, - 0x98, 0xb1, 0x99, 0xbc, 0x9a, 0xc6, 0x9b, 0xd0, - 0x9c, 0xdb, 0x9d, 0xe4, 0x9e, 0xed, 0x9f, 0xf6, - 0xa0, 0xff}, - {0x90, 0x00, 0x91, 0x29, 0x92, 0x48, 0x93, 0x60, /* 3 */ - 0x94, 0x72, 0x95, 0x81, 0x96, 0x90, 0x97, 0x9e, - 0x98, 0xaa, 0x99, 0xb5, 0x9a, 0xbf, 0x9b, 0xcb, - 0x9c, 0xd6, 0x9d, 0xe1, 0x9e, 0xeb, 0x9f, 0xf5, - 0xa0, 0xff}, - {0x90, 0x00, 0x91, 0x23, 0x92, 0x3f, 0x93, 0x55, /* 4 */ - 0x94, 0x68, 0x95, 0x77, 0x96, 0x86, 0x97, 0x95, - 0x98, 0xa2, 0x99, 0xad, 0x9a, 0xb9, 0x9b, 0xc6, - 0x9c, 0xd2, 0x9d, 0xde, 0x9e, 0xe9, 0x9f, 0xf4, - 0xa0, 0xff}, - {0x90, 0x00, 0x91, 0x1b, 0x92, 0x33, 0x93, 0x48, /* 5 */ - 0x94, 0x59, 0x95, 0x69, 0x96, 0x79, 0x97, 0x87, - 0x98, 0x96, 0x99, 0xa3, 0x9a, 0xb1, 0x9b, 0xbe, - 0x9c, 0xcc, 0x9d, 0xda, 0x9e, 0xe7, 0x9f, 0xf3, - 0xa0, 0xff}, - {0x90, 0x00, 0x91, 0x02, 0x92, 0x10, 0x93, 0x20, /* 6 */ - 0x94, 0x32, 0x95, 0x40, 0x96, 0x57, 0x97, 0x67, - 0x98, 0x77, 0x99, 0x88, 0x9a, 0x99, 0x9b, 0xaa, - 0x9c, 0xbb, 0x9d, 0xcc, 0x9e, 0xdd, 0x9f, 0xee, - 0xa0, 0xff}, - {0x90, 0x00, 0x91, 0x02, 0x92, 0x14, 0x93, 0x26, /* 7 */ - 0x94, 0x38, 0x95, 0x4a, 0x96, 0x60, 0x97, 0x70, - 0x98, 0x80, 0x99, 0x90, 0x9a, 0xa0, 0x9b, 0xb0, - 0x9c, 0xc0, 0x9D, 0xd0, 0x9e, 0xe0, 0x9f, 0xf0, - 0xa0, 0xff}, - {0x90, 0x00, 0x91, 0x10, 0x92, 0x22, 0x93, 0x35, /* 8 */ - 0x94, 0x47, 0x95, 0x5a, 0x96, 0x69, 0x97, 0x79, - 0x98, 0x88, 0x99, 0x97, 0x9a, 0xa7, 0x9b, 0xb6, - 0x9c, 0xc4, 0x9d, 0xd3, 0x9e, 0xe0, 0x9f, 0xf0, - 0xa0, 0xff}, - {0x90, 0x00, 0x91, 0x10, 0x92, 0x26, 0x93, 0x40, /* 9 */ - 0x94, 0x54, 0x95, 0x65, 0x96, 0x75, 0x97, 0x84, - 0x98, 0x93, 0x99, 0xa1, 0x9a, 0xb0, 0x9b, 0xbd, - 0x9c, 0xca, 0x9d, 0xd6, 0x9e, 0xe0, 0x9f, 0xf0, - 0xa0, 0xff}, - {0x90, 0x00, 0x91, 0x18, 0x92, 0x2b, 0x93, 0x44, /* 10 */ - 0x94, 0x60, 0x95, 0x70, 0x96, 0x80, 0x97, 0x8e, - 0x98, 0x9c, 0x99, 0xaa, 0x9a, 0xb7, 0x9b, 0xc4, - 0x9c, 0xd0, 0x9d, 0xd8, 0x9e, 0xe2, 0x9f, 0xf0, - 0xa0, 0xff}, - {0x90, 0x00, 0x91, 0x1a, 0x92, 0x34, 0x93, 0x52, /* 11 */ - 0x94, 0x66, 0x95, 0x7e, 0x96, 0x8D, 0x97, 0x9B, - 0x98, 0xa8, 0x99, 0xb4, 0x9a, 0xc0, 0x9b, 0xcb, - 0x9c, 0xd6, 0x9d, 0xe1, 0x9e, 0xeb, 0x9f, 0xf5, - 0xa0, 0xff}, - {0x90, 0x00, 0x91, 0x3f, 0x92, 0x5a, 0x93, 0x6e, /* 12 */ - 0x94, 0x7f, 0x95, 0x8e, 0x96, 0x9c, 0x97, 0xa8, - 0x98, 0xb4, 0x99, 0xbf, 0x9a, 0xc9, 0x9b, 0xd3, - 0x9c, 0xdc, 0x9d, 0xe5, 0x9e, 0xee, 0x9f, 0xf6, - 0xa0, 0xff}, - {0x90, 0x00, 0x91, 0x54, 0x92, 0x6f, 0x93, 0x83, /* 13 */ - 0x94, 0x93, 0x95, 0xa0, 0x96, 0xad, 0x97, 0xb7, - 0x98, 0xc2, 0x99, 0xcb, 0x9a, 0xd4, 0x9b, 0xdc, - 0x9c, 0xe4, 0x9d, 0xeb, 0x9e, 0xf2, 0x9f, 0xf9, - 0xa0, 0xff}, - {0x90, 0x00, 0x91, 0x6e, 0x92, 0x88, 0x93, 0x9a, /* 14 */ - 0x94, 0xa8, 0x95, 0xb3, 0x96, 0xbd, 0x97, 0xc6, - 0x98, 0xcf, 0x99, 0xd6, 0x9a, 0xdd, 0x9b, 0xe3, - 0x9c, 0xe9, 0x9d, 0xef, 0x9e, 0xf4, 0x9f, 0xfa, - 0xa0, 0xff}, - {0x90, 0x00, 0x91, 0x93, 0x92, 0xa8, 0x93, 0xb7, /* 15 */ - 0x94, 0xc1, 0x95, 0xca, 0x96, 0xd2, 0x97, 0xd8, - 0x98, 0xde, 0x99, 0xe3, 0x9a, 0xe8, 0x9b, 0xed, - 0x9c, 0xf1, 0x9d, 0xf5, 0x9e, 0xf8, 0x9f, 0xfc, - 0xa0, 0xff} +static const u8 gamma_table[GAMMA_MAX][17] = { + {0x00, 0x3e, 0x69, 0x85, 0x95, 0xa1, 0xae, 0xb9, /* 0 */ + 0xc2, 0xcb, 0xd4, 0xdb, 0xe3, 0xea, 0xf1, 0xf8, + 0xff}, + {0x00, 0x33, 0x5a, 0x75, 0x85, 0x93, 0xa1, 0xad, /* 1 */ + 0xb7, 0xc2, 0xcb, 0xd4, 0xde, 0xe7, 0xf0, 0xf7, + 0xff}, + {0x00, 0x2f, 0x51, 0x6b, 0x7c, 0x8a, 0x99, 0xa6, /* 2 */ + 0xb1, 0xbc, 0xc6, 0xd0, 0xdb, 0xe4, 0xed, 0xf6, + 0xff}, + {0x00, 0x29, 0x48, 0x60, 0x72, 0x81, 0x90, 0x9e, /* 3 */ + 0xaa, 0xb5, 0xbf, 0xcb, 0xd6, 0xe1, 0xeb, 0xf5, + 0xff}, + {0x00, 0x23, 0x3f, 0x55, 0x68, 0x77, 0x86, 0x95, /* 4 */ + 0xa2, 0xad, 0xb9, 0xc6, 0xd2, 0xde, 0xe9, 0xf4, + 0xff}, + {0x00, 0x1b, 0x33, 0x48, 0x59, 0x69, 0x79, 0x87, /* 5 */ + 0x96, 0xa3, 0xb1, 0xbe, 0xcc, 0xda, 0xe7, 0xf3, + 0xff}, + {0x00, 0x02, 0x10, 0x20, 0x32, 0x40, 0x57, 0x67, /* 6 */ + 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, + 0xff}, + {0x00, 0x02, 0x14, 0x26, 0x38, 0x4a, 0x60, 0x70, /* 7 */ + 0x80, 0x90, 0xa0, 0xb0, 0xc0, 0xd0, 0xe0, 0xf0, + 0xff}, + {0x00, 0x10, 0x22, 0x35, 0x47, 0x5a, 0x69, 0x79, /* 8 */ + 0x88, 0x97, 0xa7, 0xb6, 0xc4, 0xd3, 0xe0, 0xf0, + 0xff}, + {0x00, 0x10, 0x26, 0x40, 0x54, 0x65, 0x75, 0x84, /* 9 */ + 0x93, 0xa1, 0xb0, 0xbd, 0xca, 0xd6, 0xe0, 0xf0, + 0xff}, + {0x00, 0x18, 0x2b, 0x44, 0x60, 0x70, 0x80, 0x8e, /* 10 */ + 0x9c, 0xaa, 0xb7, 0xc4, 0xd0, 0xd8, 0xe2, 0xf0, + 0xff}, + {0x00, 0x1a, 0x34, 0x52, 0x66, 0x7e, 0x8D, 0x9B, /* 11 */ + 0xa8, 0xb4, 0xc0, 0xcb, 0xd6, 0xe1, 0xeb, 0xf5, + 0xff}, + {0x00, 0x3f, 0x5a, 0x6e, 0x7f, 0x8e, 0x9c, 0xa8, /* 12 */ + 0xb4, 0xbf, 0xc9, 0xd3, 0xdc, 0xe5, 0xee, 0xf6, + 0xff}, + {0x00, 0x54, 0x6f, 0x83, 0x93, 0xa0, 0xad, 0xb7, /* 13 */ + 0xc2, 0xcb, 0xd4, 0xdc, 0xe4, 0xeb, 0xf2, 0xf9, + 0xff}, + {0x00, 0x6e, 0x88, 0x9a, 0xa8, 0xb3, 0xbd, 0xc6, /* 14 */ + 0xcf, 0xd6, 0xdd, 0xe3, 0xe9, 0xef, 0xf4, 0xfa, + 0xff}, + {0x00, 0x93, 0xa8, 0xb7, 0xc1, 0xca, 0xd2, 0xd8, /* 15 */ + 0xde, 0xe3, 0xe8, 0xed, 0xf1, 0xf5, 0xf8, 0xfc, + 0xff} }; -static const __u8 tas5130a_sensor_init[][8] = { +static const u8 tas5130a_sensor_init[][8] = { {0x62, 0x08, 0x63, 0x70, 0x64, 0x1d, 0x60, 0x09}, {0x62, 0x20, 0x63, 0x01, 0x64, 0x02, 0x60, 0x09}, {0x62, 0x07, 0x63, 0x03, 0x64, 0x00, 0x60, 0x09}, @@ -418,11 +374,11 @@ static const __u8 tas5130a_sensor_init[][8] = { {}, }; -static __u8 sensor_reset[] = {0x61, 0x68, 0x62, 0xff, 0x60, 0x07}; +static u8 sensor_reset[] = {0x61, 0x68, 0x62, 0xff, 0x60, 0x07}; /* read 1 byte */ -static int reg_r(struct gspca_dev *gspca_dev, - __u16 index) +static u8 reg_r(struct gspca_dev *gspca_dev, + u16 index) { usb_control_msg(gspca_dev->dev, usb_rcvctrlpipe(gspca_dev->dev, 0), @@ -435,7 +391,7 @@ static int reg_r(struct gspca_dev *gspca_dev, } static void reg_w(struct gspca_dev *gspca_dev, - __u16 index) + u16 index) { usb_control_msg(gspca_dev->dev, usb_sndctrlpipe(gspca_dev->dev, 0), @@ -446,7 +402,7 @@ static void reg_w(struct gspca_dev *gspca_dev, } static void reg_w_buf(struct gspca_dev *gspca_dev, - const __u8 *buffer, __u16 len) + const u8 *buffer, u16 len) { if (len <= USB_BUF_SZ) { memcpy(gspca_dev->usb_buf, buffer, len); @@ -457,7 +413,7 @@ static void reg_w_buf(struct gspca_dev *gspca_dev, 0x01, 0, gspca_dev->usb_buf, len, 500); } else { - __u8 *tmpbuf; + u8 *tmpbuf; tmpbuf = kmalloc(len, GFP_KERNEL); memcpy(tmpbuf, buffer, len); @@ -471,14 +427,41 @@ static void reg_w_buf(struct gspca_dev *gspca_dev, } } +/* write values to consecutive registers */ +static void reg_w_ixbuf(struct gspca_dev *gspca_dev, + u8 reg, + const u8 *buffer, u16 len) +{ + int i; + u8 *p, *tmpbuf; + + if (len * 2 <= USB_BUF_SZ) + p = tmpbuf = gspca_dev->usb_buf; + else + p = tmpbuf = kmalloc(len * 2, GFP_KERNEL); + i = len; + while (--i >= 0) { + *p++ = reg++; + *p++ = *buffer++; + } + usb_control_msg(gspca_dev->dev, + usb_sndctrlpipe(gspca_dev->dev, 0), + 0, + USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, + 0x01, 0, + tmpbuf, len * 2, 500); + if (len * 2 > USB_BUF_SZ) + kfree(tmpbuf); +} + /* Reported as OM6802*/ static void om6802_sensor_init(struct gspca_dev *gspca_dev) { int i; - const __u8 *p; - __u8 byte; - __u8 val[6] = {0x62, 0, 0x64, 0, 0x60, 0x05}; - static const __u8 sensor_init[] = { + const u8 *p; + u8 byte; + u8 val[6] = {0x62, 0, 0x64, 0, 0x60, 0x05}; + static const u8 sensor_init[] = { 0xdf, 0x6d, 0xdd, 0x18, 0x5a, 0xe0, @@ -542,15 +525,16 @@ static int sd_config(struct gspca_dev *gspca_dev, cam->cam_mode = vga_mode_t16; cam->nmodes = ARRAY_SIZE(vga_mode_t16); - sd->brightness = sd_ctrls[SD_BRIGHTNESS].qctrl.default_value; - sd->contrast = sd_ctrls[SD_CONTRAST].qctrl.default_value; - sd->colors = sd_ctrls[SD_COLOR].qctrl.default_value; + sd->brightness = BRIGHTNESS_DEF; + sd->contrast = CONTRAST_DEF; + sd->colors = COLORS_DEF; sd->gamma = GAMMA_DEF; - sd->mirror = sd_ctrls[SD_MIRROR].qctrl.default_value; - sd->freq = sd_ctrls[SD_LIGHTFREQ].qctrl.default_value; - sd->whitebalance = sd_ctrls[SD_WHITE_BALANCE].qctrl.default_value; - sd->sharpness = sd_ctrls[SD_SHARPNESS].qctrl.default_value; - sd->effect = sd_ctrls[SD_EFFECTS].qctrl.default_value; + sd->autogain = AUTOGAIN_DEF; + sd->mirror = MIRROR_DEF; + sd->freq = FREQ_DEF; + sd->whitebalance = WHITE_BALANCE_DEF; + sd->sharpness = SHARPNESS_DEF; + sd->effect = EFFECTS_DEF; return 0; } @@ -558,7 +542,7 @@ static void setbrightness(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; unsigned int brightness; - __u8 set6[4] = { 0x8f, 0x24, 0xc3, 0x00 }; + u8 set6[4] = { 0x8f, 0x24, 0xc3, 0x00 }; brightness = sd->brightness; if (brightness < 7) { @@ -575,7 +559,7 @@ static void setcontrast(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; unsigned int contrast = sd->contrast; - __u16 reg_to_write; + u16 reg_to_write; if (contrast < 7) reg_to_write = 0x8ea9 - contrast * 0x200; @@ -588,7 +572,7 @@ static void setcontrast(struct gspca_dev *gspca_dev) static void setcolors(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; - __u16 reg_to_write; + u16 reg_to_write; reg_to_write = 0x80bb + sd->colors * 0x100; /* was 0xc0 */ reg_w(gspca_dev, reg_to_write); @@ -599,14 +583,15 @@ static void setgamma(struct gspca_dev *gspca_dev) struct sd *sd = (struct sd *) gspca_dev; PDEBUG(D_CONF, "Gamma: %d", sd->gamma); - reg_w_buf(gspca_dev, gamma_table[sd->gamma], sizeof gamma_table[0]); + reg_w_ixbuf(gspca_dev, 0x90, + gamma_table[sd->gamma], sizeof gamma_table[0]); } static void setwhitebalance(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; - __u8 white_balance[8] = + u8 white_balance[8] = {0x87, 0x20, 0x88, 0x20, 0x89, 0x20, 0x80, 0x38}; if (sd->whitebalance) @@ -618,7 +603,7 @@ static void setwhitebalance(struct gspca_dev *gspca_dev) static void setsharpness(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; - __u16 reg_to_write; + u16 reg_to_write; reg_to_write = 0x0aa6 + 0x1000 * sd->sharpness; @@ -634,18 +619,18 @@ static int sd_init(struct gspca_dev *gspca_dev) * to see the initial parameters.*/ struct sd *sd = (struct sd *) gspca_dev; int i; - __u8 byte, test_byte; + u8 byte, test_byte; - static const __u8 read_indexs[] = + static const u8 read_indexs[] = { 0x06, 0x07, 0x0a, 0x0b, 0x66, 0x80, 0x81, 0x8e, 0x8f, 0xa5, - 0xa6, 0xa8, 0xbb, 0xbc, 0xc6, 0x00, 0x00 }; - static const __u8 n1[] = + 0xa6, 0xa8, 0xbb, 0xbc, 0xc6, 0x00 }; + static const u8 n1[] = {0x08, 0x03, 0x09, 0x03, 0x12, 0x04}; - static const __u8 n2[] = + static const u8 n2[] = {0x08, 0x00}; - static const __u8 n3[] = + static const u8 n3[] = {0x61, 0x68, 0x65, 0x0a, 0x60, 0x04}; - static const __u8 n4[] = + static const u8 n4[] = {0x09, 0x01, 0x12, 0x04, 0x66, 0x8a, 0x80, 0x3c, 0x81, 0x22, 0x84, 0x50, 0x8a, 0x78, 0x8b, 0x68, 0x8c, 0x88, 0x8e, 0x33, 0x8f, 0x24, 0xaa, 0xb1, @@ -655,10 +640,10 @@ static int sd_init(struct gspca_dev *gspca_dev) 0x65, 0x0a, 0xbb, 0x86, 0xaf, 0x58, 0xb0, 0x68, 0x87, 0x40, 0x89, 0x2b, 0x8d, 0xff, 0x83, 0x40, 0xac, 0x84, 0xad, 0x86, 0xaf, 0x46}; - static const __u8 nset9[4] = - { 0x0b, 0x04, 0x0a, 0x78 }; - static const __u8 nset8[6] = + static const u8 nset8[6] = { 0xa8, 0xf0, 0xc6, 0x88, 0xc0, 0x00 }; + static const u8 nset9[4] = + { 0x0b, 0x04, 0x0a, 0x78 }; byte = reg_r(gspca_dev, 0x06); test_byte = reg_r(gspca_dev, 0x07); @@ -703,11 +688,11 @@ static int sd_init(struct gspca_dev *gspca_dev) reg_r(gspca_dev, 0x0080); reg_w(gspca_dev, 0x2c80); - reg_w_buf(gspca_dev, sensor_data[sd->sensor].data1, + reg_w_ixbuf(gspca_dev, 0xd0, sensor_data[sd->sensor].data1, sizeof sensor_data[sd->sensor].data1); - reg_w_buf(gspca_dev, sensor_data[sd->sensor].data3, - sizeof sensor_data[sd->sensor].data3); - reg_w_buf(gspca_dev, sensor_data[sd->sensor].data2, + reg_w_ixbuf(gspca_dev, 0xc7, sensor_data[sd->sensor].data2, + sizeof sensor_data[sd->sensor].data2); + reg_w_ixbuf(gspca_dev, 0xe0, sensor_data[sd->sensor].data2, sizeof sensor_data[sd->sensor].data2); reg_w(gspca_dev, 0x3880); @@ -734,11 +719,11 @@ static int sd_init(struct gspca_dev *gspca_dev) reg_w(gspca_dev, 0x2880); - reg_w_buf(gspca_dev, sensor_data[sd->sensor].data1, + reg_w_ixbuf(gspca_dev, 0xd0, sensor_data[sd->sensor].data1, sizeof sensor_data[sd->sensor].data1); - reg_w_buf(gspca_dev, sensor_data[sd->sensor].data3, - sizeof sensor_data[sd->sensor].data3); - reg_w_buf(gspca_dev, sensor_data[sd->sensor].data2, + reg_w_ixbuf(gspca_dev, 0xc7, sensor_data[sd->sensor].data2, + sizeof sensor_data[sd->sensor].data2); + reg_w_ixbuf(gspca_dev, 0xe0, sensor_data[sd->sensor].data2, sizeof sensor_data[sd->sensor].data2); return 0; @@ -747,7 +732,7 @@ static int sd_init(struct gspca_dev *gspca_dev) static void setflip(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; - __u8 flipcmd[8] = + u8 flipcmd[8] = {0x62, 0x07, 0x63, 0x03, 0x64, 0x00, 0x60, 0x09}; if (sd->mirror) @@ -777,7 +762,7 @@ static void seteffect(struct gspca_dev *gspca_dev) static void setlightfreq(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; - __u8 freq[4] = { 0x66, 0x40, 0xa8, 0xe8 }; + u8 freq[4] = { 0x66, 0x40, 0xa8, 0xe8 }; if (sd->freq == 2) /* 60hz */ freq[1] = 0x00; @@ -790,17 +775,17 @@ static void setlightfreq(struct gspca_dev *gspca_dev) static void poll_sensor(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; - static const __u8 poll1[] = + static const u8 poll1[] = {0x67, 0x05, 0x68, 0x81, 0x69, 0x80, 0x6a, 0x82, 0x6b, 0x68, 0x6c, 0x69, 0x72, 0xd9, 0x73, 0x34, 0x74, 0x32, 0x75, 0x92, 0x76, 0x00, 0x09, 0x01, 0x60, 0x14}; - static const __u8 poll2[] = + static const u8 poll2[] = {0x67, 0x02, 0x68, 0x71, 0x69, 0x72, 0x72, 0xa9, 0x73, 0x02, 0x73, 0x02, 0x60, 0x14}; - static const __u8 poll3[] = + static const u8 poll3[] = {0x87, 0x3f, 0x88, 0x20, 0x89, 0x2d}; - static const __u8 poll4[] = + static const u8 poll4[] = {0xa6, 0x0a, 0xea, 0xcf, 0xbe, 0x26, 0xb1, 0x5f, 0xa1, 0xb1, 0xda, 0x6b, 0xdb, 0x98, 0xdf, 0x0c, 0xc2, 0x80, 0xc3, 0x10}; @@ -818,13 +803,14 @@ static int sd_start(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; int i, mode; - __u8 t2[] = { 0x07, 0x00, 0x0d, 0x60, 0x0e, 0x80 }; - static const __u8 t3[] = - { 0xb3, 0x07, 0xb4, 0x00, 0xb5, 0x88, 0xb6, 0x02, 0xb7, 0x06, - 0xb8, 0x00, 0xb9, 0xe7, 0xba, 0x01 }; + u8 t2[] = { 0x07, 0x00, 0x0d, 0x60, 0x0e, 0x80 }; + static const u8 t3[] = + { 0x07, 0x00, 0x88, 0x02, 0x06, 0x00, 0xe7, 0x01 }; mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode]. priv; switch (mode) { + case 0: /* 640x480 (0x00) */ + break; case 1: /* 352x288 */ t2[1] = 0x40; break; @@ -834,11 +820,10 @@ static int sd_start(struct gspca_dev *gspca_dev) case 3: /* 176x144 */ t2[1] = 0x50; break; - case 4: /* 160x120 */ + default: +/* case 4: * 160x120 */ t2[1] = 0x20; break; - default: /* 640x480 (0x00) */ - break; } if (sd->sensor == SENSOR_TAS5130A) { @@ -860,7 +845,7 @@ static int sd_start(struct gspca_dev *gspca_dev) sizeof sensor_data[sd->sensor].data4); reg_r(gspca_dev, 0x0012); reg_w_buf(gspca_dev, t2, sizeof t2); - reg_w_buf(gspca_dev, t3, sizeof t3); + reg_w_ixbuf(gspca_dev, 0xb3, t3, sizeof t3); reg_w(gspca_dev, 0x0013); msleep(15); reg_w_buf(gspca_dev, sensor_data[sd->sensor].stream, @@ -890,10 +875,10 @@ static void sd_stopN(struct gspca_dev *gspca_dev) static void sd_pkt_scan(struct gspca_dev *gspca_dev, struct gspca_frame *frame, /* target */ - __u8 *data, /* isoc packet */ + u8 *data, /* isoc packet */ int len) /* iso packet length */ { - static __u8 ffd9[] = { 0xff, 0xd9 }; + static u8 ffd9[] = { 0xff, 0xd9 }; if (data[0] == 0x5a) { /* Control Packet, after this came the header again, -- cgit v1.2.3 From 2d56f3bbe795b72207ec127cb3dc3b08bb4b8775 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Thu, 22 Jan 2009 08:25:16 -0300 Subject: V4L/DVB (10381): gspca - t613: New unknown sensor added. Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/t613.c | 178 ++++++++++++++++++++++++++------------- 1 file changed, 120 insertions(+), 58 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/gspca/t613.c b/drivers/media/video/gspca/t613.c index 8e89024b9135..a97920eb03f9 100644 --- a/drivers/media/video/gspca/t613.c +++ b/drivers/media/video/gspca/t613.c @@ -49,8 +49,9 @@ struct sd { u8 effect; u8 sensor; -#define SENSOR_TAS5130A 0 -#define SENSOR_OM6802 1 +#define SENSOR_OM6802 0 +#define SENSOR_OTHER 1 +#define SENSOR_TAS5130A 2 }; /* V4L2 controls supported by the driver */ @@ -272,6 +273,34 @@ struct additional_sensor_data { }; const static struct additional_sensor_data sensor_data[] = { + { /* OM6802 */ + .data1 = + {0xc2, 0x28, 0x0f, 0x22, 0xcd, 0x27, 0x2c, 0x06, + 0xb3, 0xfc}, + .data2 = + {0x80, 0xff, 0xff, 0x80, 0xff, 0xff, 0x80, 0xff, + 0xff}, + .data4 = /*Freq (50/60Hz). Splitted for test purpose */ + {0x66, 0xca, 0xa8, 0xf0}, + .data5 = /* this could be removed later */ + {0x0c, 0x03, 0xab, 0x13, 0x81, 0x23}, + .stream = + {0x0b, 0x04, 0x0a, 0x78}, + }, + { /* OTHER */ + .data1 = + {0xc1, 0x48, 0x04, 0x1b, 0xca, 0x2e, 0x33, 0x3a, + 0xe8, 0xfc}, + .data2 = + {0x4e, 0x9c, 0xec, 0x40, 0x80, 0xc0, 0x48, 0x96, + 0xd9}, + .data4 = + {0x66, 0x00, 0xa8, 0xa8}, + .data5 = + {0x0c, 0x03, 0xab, 0x29, 0x81, 0x69}, + .stream = + {0x0b, 0x04, 0x0a, 0x00}, + }, { /* TAS5130A */ .data1 = {0xbb, 0x28, 0x10, 0x10, 0xbb, 0x28, 0x1e, 0x27, @@ -286,20 +315,6 @@ const static struct additional_sensor_data sensor_data[] = { .stream = {0x0b, 0x04, 0x0a, 0x40}, }, - { /* OM6802 */ - .data1 = - {0xc2, 0x28, 0x0f, 0x22, 0xcd, 0x27, 0x2c, 0x06, - 0xb3, 0xfc}, - .data2 = - {0x80, 0xff, 0xff, 0x80, 0xff, 0xff, 0x80, 0xff, - 0xff}, - .data4 = /*Freq (50/60Hz). Splitted for test purpose */ - {0x66, 0xca, 0xa8, 0xf0 }, - .data5 = /* this could be removed later */ - {0x0c, 0x03, 0xab, 0x13, 0x81, 0x23}, - .stream = - {0x0b, 0x04, 0x0a, 0x78}, - } }; #define MAX_EFFECTS 7 @@ -619,7 +634,9 @@ static int sd_init(struct gspca_dev *gspca_dev) * to see the initial parameters.*/ struct sd *sd = (struct sd *) gspca_dev; int i; - u8 byte, test_byte; + u16 sensor_id; + u8 test_byte; + u16 reg80, reg8e; static const u8 read_indexs[] = { 0x06, 0x07, 0x0a, 0x0b, 0x66, 0x80, 0x81, 0x8e, 0x8f, 0xa5, @@ -628,8 +645,10 @@ static int sd_init(struct gspca_dev *gspca_dev) {0x08, 0x03, 0x09, 0x03, 0x12, 0x04}; static const u8 n2[] = {0x08, 0x00}; - static const u8 n3[] = + static const u8 n3[6] = {0x61, 0x68, 0x65, 0x0a, 0x60, 0x04}; + static const u8 n3_other[6] = + {0x61, 0xc2, 0x65, 0x88, 0x60, 0x00}; static const u8 n4[] = {0x09, 0x01, 0x12, 0x04, 0x66, 0x8a, 0x80, 0x3c, 0x81, 0x22, 0x84, 0x50, 0x8a, 0x78, 0x8b, 0x68, @@ -640,40 +659,61 @@ static int sd_init(struct gspca_dev *gspca_dev) 0x65, 0x0a, 0xbb, 0x86, 0xaf, 0x58, 0xb0, 0x68, 0x87, 0x40, 0x89, 0x2b, 0x8d, 0xff, 0x83, 0x40, 0xac, 0x84, 0xad, 0x86, 0xaf, 0x46}; + static const u8 n4_other[] = + {0x66, 0x00, 0x7f, 0x00, 0x80, 0xac, 0x81, 0x69, + 0x84, 0x40, 0x85, 0x70, 0x86, 0x20, 0x8a, 0x68, + 0x8b, 0x58, 0x8c, 0x88, 0x8d, 0xff, 0x8e, 0xb8, + 0x8f, 0x28, 0xa2, 0x60, 0xa5, 0x40, 0xa8, 0xa8, + 0xac, 0x84, 0xad, 0x84, 0xae, 0x24, 0xaf, 0x56, + 0xb0, 0x68, 0xb1, 0x00, 0xb2, 0x88, 0xbb, 0xc5, + 0xbc, 0x4a, 0xbe, 0x36, 0xc2, 0x88, 0xc5, 0xc0, + 0xc6, 0xda, 0xe9, 0x26, 0xeb, 0x00}; static const u8 nset8[6] = { 0xa8, 0xf0, 0xc6, 0x88, 0xc0, 0x00 }; + static const u8 nset8_other[6] = + { 0xa8, 0xa8, 0xc6, 0xda, 0xc0, 0x00 }; static const u8 nset9[4] = { 0x0b, 0x04, 0x0a, 0x78 }; + static const u8 nset9_other[4] = + { 0x0b, 0x04, 0x0a, 0x00 }; - byte = reg_r(gspca_dev, 0x06); - test_byte = reg_r(gspca_dev, 0x07); - if (byte == 0x08 && test_byte == 0x07) { - PDEBUG(D_CONF, "sensor om6802"); - sd->sensor = SENSOR_OM6802; - } else if (byte == 0x08 && test_byte == 0x01) { + sensor_id = (reg_r(gspca_dev, 0x06) << 8) + | reg_r(gspca_dev, 0x07); + switch (sensor_id) { + case 0x0801: PDEBUG(D_CONF, "sensor tas5130a"); sd->sensor = SENSOR_TAS5130A; - } else { - PDEBUG(D_CONF, "unknown sensor %02x %02x", byte, test_byte); - sd->sensor = SENSOR_TAS5130A; + break; + case 0x0803: + PDEBUG(D_CONF, "sensor om6802"); + sd->sensor = SENSOR_OTHER; + break; + case 0x0807: + PDEBUG(D_CONF, "sensor om6802"); + sd->sensor = SENSOR_OM6802; + break; + default: + PDEBUG(D_CONF, "unknown sensor %04x", sensor_id); + return -1; } - reg_w_buf(gspca_dev, n1, sizeof n1); - test_byte = 0; - i = 5; - while (--i >= 0) { - reg_w_buf(gspca_dev, sensor_reset, sizeof sensor_reset); - test_byte = reg_r(gspca_dev, 0x0063); - msleep(100); - if (test_byte == 0x17) - break; /* OK */ - } - if (i < 0) { - err("Bad sensor reset %02x", test_byte); -/* return -EIO; */ + if (sd->sensor != SENSOR_OTHER) { + reg_w_buf(gspca_dev, n1, sizeof n1); + i = 5; + while (--i >= 0) { + reg_w_buf(gspca_dev, sensor_reset, sizeof sensor_reset); + test_byte = reg_r(gspca_dev, 0x0063); + msleep(100); + if (test_byte == 0x17) + break; /* OK */ + } + if (i < 0) { + err("Bad sensor reset %02x", test_byte); +/* return -EIO; */ /*fixme: test - continue */ + } + reg_w_buf(gspca_dev, n2, sizeof n2); } - reg_w_buf(gspca_dev, n2, sizeof n2); i = 0; while (read_indexs[i] != 0x00) { @@ -683,10 +723,20 @@ static int sd_init(struct gspca_dev *gspca_dev) i++; } - reg_w_buf(gspca_dev, n3, sizeof n3); - reg_w_buf(gspca_dev, n4, sizeof n4); - reg_r(gspca_dev, 0x0080); - reg_w(gspca_dev, 0x2c80); + if (sd->sensor != SENSOR_OTHER) { + reg_w_buf(gspca_dev, n3, sizeof n3); + reg_w_buf(gspca_dev, n4, sizeof n4); + reg_r(gspca_dev, 0x0080); + reg_w(gspca_dev, 0x2c80); + reg80 = 0x3880; + reg8e = 0x338e; + } else { + reg_w_buf(gspca_dev, n3_other, sizeof n3_other); + reg_w_buf(gspca_dev, n4_other, sizeof n4_other); + sd->gamma = 5; + reg80 = 0xac80; + reg8e = 0xb88e; + } reg_w_ixbuf(gspca_dev, 0xd0, sensor_data[sd->sensor].data1, sizeof sensor_data[sd->sensor].data1); @@ -695,9 +745,9 @@ static int sd_init(struct gspca_dev *gspca_dev) reg_w_ixbuf(gspca_dev, 0xe0, sensor_data[sd->sensor].data2, sizeof sensor_data[sd->sensor].data2); - reg_w(gspca_dev, 0x3880); - reg_w(gspca_dev, 0x3880); - reg_w(gspca_dev, 0x338e); + reg_w(gspca_dev, reg80); + reg_w(gspca_dev, reg80); + reg_w(gspca_dev, reg8e); setbrightness(gspca_dev); setcontrast(gspca_dev); @@ -714,10 +764,14 @@ static int sd_init(struct gspca_dev *gspca_dev) sizeof sensor_data[sd->sensor].data4); reg_w_buf(gspca_dev, sensor_data[sd->sensor].data5, sizeof sensor_data[sd->sensor].data5); - reg_w_buf(gspca_dev, nset8, sizeof nset8); - reg_w_buf(gspca_dev, nset9, sizeof nset9); - - reg_w(gspca_dev, 0x2880); + if (sd->sensor != SENSOR_OTHER) { + reg_w_buf(gspca_dev, nset8, sizeof nset8); + reg_w_buf(gspca_dev, nset9, sizeof nset9); + reg_w(gspca_dev, 0x2880); + } else { + reg_w_buf(gspca_dev, nset8_other, sizeof nset8_other); + reg_w_buf(gspca_dev, nset9_other, sizeof nset9_other); + } reg_w_ixbuf(gspca_dev, 0xd0, sensor_data[sd->sensor].data1, sizeof sensor_data[sd->sensor].data1); @@ -790,7 +844,7 @@ static void poll_sensor(struct gspca_dev *gspca_dev) 0xa1, 0xb1, 0xda, 0x6b, 0xdb, 0x98, 0xdf, 0x0c, 0xc2, 0x80, 0xc3, 0x10}; - if (sd->sensor != SENSOR_TAS5130A) { + if (sd->sensor == SENSOR_OM6802) { PDEBUG(D_STREAM, "[Sensor requires polling]"); reg_w_buf(gspca_dev, poll1, sizeof poll1); reg_w_buf(gspca_dev, poll2, sizeof poll2); @@ -826,7 +880,14 @@ static int sd_start(struct gspca_dev *gspca_dev) break; } - if (sd->sensor == SENSOR_TAS5130A) { + switch (sd->sensor) { + case SENSOR_OM6802: + om6802_sensor_init(gspca_dev); + break; + case SENSOR_OTHER: + break; + default: +/* case SENSOR_TAS5130A: */ i = 0; while (tas5130a_sensor_init[i][0] != 0) { reg_w_buf(gspca_dev, tas5130a_sensor_init[i], @@ -838,8 +899,7 @@ static int sd_start(struct gspca_dev *gspca_dev) reg_w_buf(gspca_dev, tas5130a_sensor_init[3], sizeof tas5130a_sensor_init[0]); reg_w(gspca_dev, 0x3c80); - } else { - om6802_sensor_init(gspca_dev); + break; } reg_w_buf(gspca_dev, sensor_data[sd->sensor].data4, sizeof sensor_data[sd->sensor].data4); @@ -869,8 +929,10 @@ static void sd_stopN(struct gspca_dev *gspca_dev) msleep(20); reg_w_buf(gspca_dev, sensor_data[sd->sensor].stream, sizeof sensor_data[sd->sensor].stream); - msleep(20); - reg_w(gspca_dev, 0x0309); + if (sd->sensor != SENSOR_OTHER) { + msleep(20); + reg_w(gspca_dev, 0x0309); + } } static void sd_pkt_scan(struct gspca_dev *gspca_dev, -- cgit v1.2.3 From 409b11dd74e653dd4dace01b0f3f8e987fe7fe81 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Thu, 22 Jan 2009 12:53:56 -0300 Subject: V4L/DVB (10382): gspca - t613: Bad returned value when no known sensor found. Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/t613.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/gspca/t613.c b/drivers/media/video/gspca/t613.c index a97920eb03f9..49db21e1376c 100644 --- a/drivers/media/video/gspca/t613.c +++ b/drivers/media/video/gspca/t613.c @@ -694,7 +694,7 @@ static int sd_init(struct gspca_dev *gspca_dev) break; default: PDEBUG(D_CONF, "unknown sensor %04x", sensor_id); - return -1; + return -EINVAL; } if (sd->sensor != SENSOR_OTHER) { -- cgit v1.2.3 From 16631aedb23bac40332549dcaed90c804271cc5b Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Thu, 22 Jan 2009 14:56:42 -0300 Subject: V4L/DVB (10383): gspca - spca505: Cleanup and optimize code. Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/spca505.c | 429 +++++++++++++++++------------------- 1 file changed, 208 insertions(+), 221 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/gspca/spca505.c b/drivers/media/video/gspca/spca505.c index 25e2bec9dc52..c99bf62614f3 100644 --- a/drivers/media/video/gspca/spca505.c +++ b/drivers/media/video/gspca/spca505.c @@ -31,9 +31,9 @@ MODULE_LICENSE("GPL"); struct sd { struct gspca_dev gspca_dev; /* !! must be the first item */ - unsigned char brightness; + u8 brightness; - char subtype; + u8 subtype; #define IntelPCCameraPro 0 #define Nxultra 1 }; @@ -43,7 +43,6 @@ static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val); static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val); static struct ctrl sd_ctrls[] = { -#define SD_BRIGHTNESS 0 { { .id = V4L2_CID_BRIGHTNESS, @@ -52,7 +51,8 @@ static struct ctrl sd_ctrls[] = { .minimum = 0, .maximum = 255, .step = 1, - .default_value = 127, +#define BRIGHTNESS_DEF 127 + .default_value = BRIGHTNESS_DEF, }, .set = sd_setbrightness, .get = sd_getbrightness, @@ -104,227 +104,224 @@ static const struct v4l2_pix_format vga_mode[] = { /* * Data to initialize a SPCA505. Common to the CCD and external modes */ -static const __u16 spca505_init_data[][3] = { - /* line bmRequest,value,index */ - /* 1819 */ +static const u8 spca505_init_data[][3] = { + /* bmRequest,value,index */ {SPCA50X_REG_GLOBAL, SPCA50X_GMISC3_SAA7113RST, SPCA50X_GLOBAL_MISC3}, /* Sensor reset */ - /* 1822 */ {SPCA50X_REG_GLOBAL, 0x00, SPCA50X_GLOBAL_MISC3}, - /* 1825 */ {SPCA50X_REG_GLOBAL, 0x00, SPCA50X_GLOBAL_MISC1}, + {SPCA50X_REG_GLOBAL, 0x00, SPCA50X_GLOBAL_MISC3}, + {SPCA50X_REG_GLOBAL, 0x00, SPCA50X_GLOBAL_MISC1}, /* Block USB reset */ - /* 1828 */ {SPCA50X_REG_GLOBAL, SPCA50X_GMISC0_IDSEL, - SPCA50X_GLOBAL_MISC0}, + {SPCA50X_REG_GLOBAL, SPCA50X_GMISC0_IDSEL, SPCA50X_GLOBAL_MISC0}, - /* 1831 */ {0x5, 0x01, 0x10}, + {0x05, 0x01, 0x10}, /* Maybe power down some stuff */ - /* 1834 */ {0x5, 0x0f, 0x11}, + {0x05, 0x0f, 0x11}, /* Setup internal CCD ? */ - /* 1837 */ {0x6, 0x10, 0x08}, - /* 1840 */ {0x6, 0x00, 0x09}, - /* 1843 */ {0x6, 0x00, 0x0a}, - /* 1846 */ {0x6, 0x00, 0x0b}, - /* 1849 */ {0x6, 0x10, 0x0c}, - /* 1852 */ {0x6, 0x00, 0x0d}, - /* 1855 */ {0x6, 0x00, 0x0e}, - /* 1858 */ {0x6, 0x00, 0x0f}, - /* 1861 */ {0x6, 0x10, 0x10}, - /* 1864 */ {0x6, 0x02, 0x11}, - /* 1867 */ {0x6, 0x00, 0x12}, - /* 1870 */ {0x6, 0x04, 0x13}, - /* 1873 */ {0x6, 0x02, 0x14}, - /* 1876 */ {0x6, 0x8a, 0x51}, - /* 1879 */ {0x6, 0x40, 0x52}, - /* 1882 */ {0x6, 0xb6, 0x53}, - /* 1885 */ {0x6, 0x3d, 0x54}, + {0x06, 0x10, 0x08}, + {0x06, 0x00, 0x09}, + {0x06, 0x00, 0x0a}, + {0x06, 0x00, 0x0b}, + {0x06, 0x10, 0x0c}, + {0x06, 0x00, 0x0d}, + {0x06, 0x00, 0x0e}, + {0x06, 0x00, 0x0f}, + {0x06, 0x10, 0x10}, + {0x06, 0x02, 0x11}, + {0x06, 0x00, 0x12}, + {0x06, 0x04, 0x13}, + {0x06, 0x02, 0x14}, + {0x06, 0x8a, 0x51}, + {0x06, 0x40, 0x52}, + {0x06, 0xb6, 0x53}, + {0x06, 0x3d, 0x54}, {} }; /* * Data to initialize the camera using the internal CCD */ -static const __u16 spca505_open_data_ccd[][3] = { - /* line bmRequest,value,index */ +static const u8 spca505_open_data_ccd[][3] = { + /* bmRequest,value,index */ /* Internal CCD data set */ - /* 1891 */ {0x3, 0x04, 0x01}, + {0x03, 0x04, 0x01}, /* This could be a reset */ - /* 1894 */ {0x3, 0x00, 0x01}, + {0x03, 0x00, 0x01}, /* Setup compression and image registers. 0x6 and 0x7 seem to be related to H&V hold, and are resolution mode specific */ - /* 1897 */ {0x4, 0x10, 0x01}, + {0x04, 0x10, 0x01}, /* DIFF(0x50), was (0x10) */ - /* 1900 */ {0x4, 0x00, 0x04}, - /* 1903 */ {0x4, 0x00, 0x05}, - /* 1906 */ {0x4, 0x20, 0x06}, - /* 1909 */ {0x4, 0x20, 0x07}, + {0x04, 0x00, 0x04}, + {0x04, 0x00, 0x05}, + {0x04, 0x20, 0x06}, + {0x04, 0x20, 0x07}, - /* 1912 */ {0x8, 0x0a, 0x00}, + {0x08, 0x0a, 0x00}, /* DIFF (0x4a), was (0xa) */ - /* 1915 */ {0x5, 0x00, 0x10}, - /* 1918 */ {0x5, 0x00, 0x11}, - /* 1921 */ {0x5, 0x00, 0x00}, + {0x05, 0x00, 0x10}, + {0x05, 0x00, 0x11}, + {0x05, 0x00, 0x00}, /* DIFF not written */ - /* 1924 */ {0x5, 0x00, 0x01}, + {0x05, 0x00, 0x01}, /* DIFF not written */ - /* 1927 */ {0x5, 0x00, 0x02}, + {0x05, 0x00, 0x02}, /* DIFF not written */ - /* 1930 */ {0x5, 0x00, 0x03}, + {0x05, 0x00, 0x03}, /* DIFF not written */ - /* 1933 */ {0x5, 0x00, 0x04}, + {0x05, 0x00, 0x04}, /* DIFF not written */ - /* 1936 */ {0x5, 0x80, 0x05}, + {0x05, 0x80, 0x05}, /* DIFF not written */ - /* 1939 */ {0x5, 0xe0, 0x06}, + {0x05, 0xe0, 0x06}, /* DIFF not written */ - /* 1942 */ {0x5, 0x20, 0x07}, + {0x05, 0x20, 0x07}, /* DIFF not written */ - /* 1945 */ {0x5, 0xa0, 0x08}, + {0x05, 0xa0, 0x08}, /* DIFF not written */ - /* 1948 */ {0x5, 0x0, 0x12}, + {0x05, 0x0, 0x12}, /* DIFF not written */ - /* 1951 */ {0x5, 0x02, 0x0f}, + {0x05, 0x02, 0x0f}, /* DIFF not written */ - /* 1954 */ {0x5, 0x10, 0x46}, + {0x05, 0x10, 0x46}, /* DIFF not written */ - /* 1957 */ {0x5, 0x8, 0x4a}, + {0x05, 0x8, 0x4a}, /* DIFF not written */ - /* 1960 */ {0x3, 0x08, 0x03}, + {0x03, 0x08, 0x03}, /* DIFF (0x3,0x28,0x3) */ - /* 1963 */ {0x3, 0x08, 0x01}, - /* 1966 */ {0x3, 0x0c, 0x03}, + {0x03, 0x08, 0x01}, + {0x03, 0x0c, 0x03}, /* DIFF not written */ - /* 1969 */ {0x3, 0x21, 0x00}, + {0x03, 0x21, 0x00}, /* DIFF (0x39) */ /* Extra block copied from init to hopefully ensure CCD is in a sane state */ - /* 1837 */ {0x6, 0x10, 0x08}, - /* 1840 */ {0x6, 0x00, 0x09}, - /* 1843 */ {0x6, 0x00, 0x0a}, - /* 1846 */ {0x6, 0x00, 0x0b}, - /* 1849 */ {0x6, 0x10, 0x0c}, - /* 1852 */ {0x6, 0x00, 0x0d}, - /* 1855 */ {0x6, 0x00, 0x0e}, - /* 1858 */ {0x6, 0x00, 0x0f}, - /* 1861 */ {0x6, 0x10, 0x10}, - /* 1864 */ {0x6, 0x02, 0x11}, - /* 1867 */ {0x6, 0x00, 0x12}, - /* 1870 */ {0x6, 0x04, 0x13}, - /* 1873 */ {0x6, 0x02, 0x14}, - /* 1876 */ {0x6, 0x8a, 0x51}, - /* 1879 */ {0x6, 0x40, 0x52}, - /* 1882 */ {0x6, 0xb6, 0x53}, - /* 1885 */ {0x6, 0x3d, 0x54}, + {0x06, 0x10, 0x08}, + {0x06, 0x00, 0x09}, + {0x06, 0x00, 0x0a}, + {0x06, 0x00, 0x0b}, + {0x06, 0x10, 0x0c}, + {0x06, 0x00, 0x0d}, + {0x06, 0x00, 0x0e}, + {0x06, 0x00, 0x0f}, + {0x06, 0x10, 0x10}, + {0x06, 0x02, 0x11}, + {0x06, 0x00, 0x12}, + {0x06, 0x04, 0x13}, + {0x06, 0x02, 0x14}, + {0x06, 0x8a, 0x51}, + {0x06, 0x40, 0x52}, + {0x06, 0xb6, 0x53}, + {0x06, 0x3d, 0x54}, /* End of extra block */ - /* 1972 */ {0x6, 0x3f, 0x1}, + {0x06, 0x3f, 0x1}, /* Block skipped */ - /* 1975 */ {0x6, 0x10, 0x02}, - /* 1978 */ {0x6, 0x64, 0x07}, - /* 1981 */ {0x6, 0x10, 0x08}, - /* 1984 */ {0x6, 0x00, 0x09}, - /* 1987 */ {0x6, 0x00, 0x0a}, - /* 1990 */ {0x6, 0x00, 0x0b}, - /* 1993 */ {0x6, 0x10, 0x0c}, - /* 1996 */ {0x6, 0x00, 0x0d}, - /* 1999 */ {0x6, 0x00, 0x0e}, - /* 2002 */ {0x6, 0x00, 0x0f}, - /* 2005 */ {0x6, 0x10, 0x10}, - /* 2008 */ {0x6, 0x02, 0x11}, - /* 2011 */ {0x6, 0x00, 0x12}, - /* 2014 */ {0x6, 0x04, 0x13}, - /* 2017 */ {0x6, 0x02, 0x14}, - /* 2020 */ {0x6, 0x8a, 0x51}, - /* 2023 */ {0x6, 0x40, 0x52}, - /* 2026 */ {0x6, 0xb6, 0x53}, - /* 2029 */ {0x6, 0x3d, 0x54}, - /* 2032 */ {0x6, 0x60, 0x57}, - /* 2035 */ {0x6, 0x20, 0x58}, - /* 2038 */ {0x6, 0x15, 0x59}, - /* 2041 */ {0x6, 0x05, 0x5a}, - - /* 2044 */ {0x5, 0x01, 0xc0}, - /* 2047 */ {0x5, 0x10, 0xcb}, - /* 2050 */ {0x5, 0x80, 0xc1}, + {0x06, 0x10, 0x02}, + {0x06, 0x64, 0x07}, + {0x06, 0x10, 0x08}, + {0x06, 0x00, 0x09}, + {0x06, 0x00, 0x0a}, + {0x06, 0x00, 0x0b}, + {0x06, 0x10, 0x0c}, + {0x06, 0x00, 0x0d}, + {0x06, 0x00, 0x0e}, + {0x06, 0x00, 0x0f}, + {0x06, 0x10, 0x10}, + {0x06, 0x02, 0x11}, + {0x06, 0x00, 0x12}, + {0x06, 0x04, 0x13}, + {0x06, 0x02, 0x14}, + {0x06, 0x8a, 0x51}, + {0x06, 0x40, 0x52}, + {0x06, 0xb6, 0x53}, + {0x06, 0x3d, 0x54}, + {0x06, 0x60, 0x57}, + {0x06, 0x20, 0x58}, + {0x06, 0x15, 0x59}, + {0x06, 0x05, 0x5a}, + + {0x05, 0x01, 0xc0}, + {0x05, 0x10, 0xcb}, + {0x05, 0x80, 0xc1}, /* */ - /* 2053 */ {0x5, 0x0, 0xc2}, + {0x05, 0x0, 0xc2}, /* 4 was 0 */ - /* 2056 */ {0x5, 0x00, 0xca}, - /* 2059 */ {0x5, 0x80, 0xc1}, + {0x05, 0x00, 0xca}, + {0x05, 0x80, 0xc1}, /* */ - /* 2062 */ {0x5, 0x04, 0xc2}, - /* 2065 */ {0x5, 0x00, 0xca}, - /* 2068 */ {0x5, 0x0, 0xc1}, + {0x05, 0x04, 0xc2}, + {0x05, 0x00, 0xca}, + {0x05, 0x0, 0xc1}, /* */ - /* 2071 */ {0x5, 0x00, 0xc2}, - /* 2074 */ {0x5, 0x00, 0xca}, - /* 2077 */ {0x5, 0x40, 0xc1}, + {0x05, 0x00, 0xc2}, + {0x05, 0x00, 0xca}, + {0x05, 0x40, 0xc1}, /* */ - /* 2080 */ {0x5, 0x17, 0xc2}, - /* 2083 */ {0x5, 0x00, 0xca}, - /* 2086 */ {0x5, 0x80, 0xc1}, + {0x05, 0x17, 0xc2}, + {0x05, 0x00, 0xca}, + {0x05, 0x80, 0xc1}, /* */ - /* 2089 */ {0x5, 0x06, 0xc2}, - /* 2092 */ {0x5, 0x00, 0xca}, - /* 2095 */ {0x5, 0x80, 0xc1}, + {0x05, 0x06, 0xc2}, + {0x05, 0x00, 0xca}, + {0x05, 0x80, 0xc1}, /* */ - /* 2098 */ {0x5, 0x04, 0xc2}, - /* 2101 */ {0x5, 0x00, 0xca}, + {0x05, 0x04, 0xc2}, + {0x05, 0x00, 0xca}, - /* 2104 */ {0x3, 0x4c, 0x3}, - /* 2107 */ {0x3, 0x18, 0x1}, + {0x03, 0x4c, 0x3}, + {0x03, 0x18, 0x1}, - /* 2110 */ {0x6, 0x70, 0x51}, - /* 2113 */ {0x6, 0xbe, 0x53}, - /* 2116 */ {0x6, 0x71, 0x57}, - /* 2119 */ {0x6, 0x20, 0x58}, - /* 2122 */ {0x6, 0x05, 0x59}, - /* 2125 */ {0x6, 0x15, 0x5a}, + {0x06, 0x70, 0x51}, + {0x06, 0xbe, 0x53}, + {0x06, 0x71, 0x57}, + {0x06, 0x20, 0x58}, + {0x06, 0x05, 0x59}, + {0x06, 0x15, 0x5a}, - /* 2128 */ {0x4, 0x00, 0x08}, + {0x04, 0x00, 0x08}, /* Compress = OFF (0x1 to turn on) */ - /* 2131 */ {0x4, 0x12, 0x09}, - /* 2134 */ {0x4, 0x21, 0x0a}, - /* 2137 */ {0x4, 0x10, 0x0b}, - /* 2140 */ {0x4, 0x21, 0x0c}, - /* 2143 */ {0x4, 0x05, 0x00}, + {0x04, 0x12, 0x09}, + {0x04, 0x21, 0x0a}, + {0x04, 0x10, 0x0b}, + {0x04, 0x21, 0x0c}, + {0x04, 0x05, 0x00}, /* was 5 (Image Type ? ) */ - /* 2146 */ {0x4, 0x00, 0x01}, - - /* 2149 */ {0x6, 0x3f, 0x01}, - - /* 2152 */ {0x4, 0x00, 0x04}, - /* 2155 */ {0x4, 0x00, 0x05}, - /* 2158 */ {0x4, 0x40, 0x06}, - /* 2161 */ {0x4, 0x40, 0x07}, - - /* 2164 */ {0x6, 0x1c, 0x17}, - /* 2167 */ {0x6, 0xe2, 0x19}, - /* 2170 */ {0x6, 0x1c, 0x1b}, - /* 2173 */ {0x6, 0xe2, 0x1d}, - /* 2176 */ {0x6, 0xaa, 0x1f}, - /* 2179 */ {0x6, 0x70, 0x20}, - - /* 2182 */ {0x5, 0x01, 0x10}, - /* 2185 */ {0x5, 0x00, 0x11}, - /* 2188 */ {0x5, 0x01, 0x00}, - /* 2191 */ {0x5, 0x05, 0x01}, - /* 2194 */ {0x5, 0x00, 0xc1}, + {0x04, 0x00, 0x01}, + + {0x06, 0x3f, 0x01}, + + {0x04, 0x00, 0x04}, + {0x04, 0x00, 0x05}, + {0x04, 0x40, 0x06}, + {0x04, 0x40, 0x07}, + + {0x06, 0x1c, 0x17}, + {0x06, 0xe2, 0x19}, + {0x06, 0x1c, 0x1b}, + {0x06, 0xe2, 0x1d}, + {0x06, 0xaa, 0x1f}, + {0x06, 0x70, 0x20}, + + {0x05, 0x01, 0x10}, + {0x05, 0x00, 0x11}, + {0x05, 0x01, 0x00}, + {0x05, 0x05, 0x01}, + {0x05, 0x00, 0xc1}, /* */ - /* 2197 */ {0x5, 0x00, 0xc2}, - /* 2200 */ {0x5, 0x00, 0xca}, + {0x05, 0x00, 0xc2}, + {0x05, 0x00, 0xca}, - /* 2203 */ {0x6, 0x70, 0x51}, - /* 2206 */ {0x6, 0xbe, 0x53}, + {0x06, 0x70, 0x51}, + {0x06, 0xbe, 0x53}, {} }; /* - Made by Tomasz Zablocki (skalamandra@poczta.onet.pl) + * Made by Tomasz Zablocki (skalamandra@poczta.onet.pl) * SPCA505b chip based cameras initialization data - * */ /* jfm */ #define initial_brightness 0x7f /* 0x0(white)-0xff(black) */ @@ -332,7 +329,7 @@ static const __u16 spca505_open_data_ccd[][3] = { /* * Data to initialize a SPCA505. Common to the CCD and external modes */ -static const __u16 spca505b_init_data[][3] = { +static const u8 spca505b_init_data[][3] = { /* start */ {0x02, 0x00, 0x00}, /* init */ {0x02, 0x00, 0x01}, @@ -396,7 +393,7 @@ static const __u16 spca505b_init_data[][3] = { /* * Data to initialize the camera using the internal CCD */ -static const __u16 spca505b_open_data_ccd[][3] = { +static const u8 spca505b_open_data_ccd[][3] = { /* {0x02,0x00,0x00}, */ {0x03, 0x04, 0x01}, /* rst */ @@ -425,8 +422,8 @@ static const __u16 spca505b_open_data_ccd[][3] = { {0x05, 0x00, 0x11}, {0x05, 0x00, 0x12}, {0x05, 0x6f, 0x00}, - {0x05, initial_brightness >> 6, 0x00}, - {0x05, initial_brightness << 2, 0x01}, + {0x05, (u8) (initial_brightness >> 6), 0x00}, + {0x05, (u8) (initial_brightness << 2), 0x01}, {0x05, 0x00, 0x02}, {0x05, 0x01, 0x03}, {0x05, 0x00, 0x04}, @@ -436,7 +433,7 @@ static const __u16 spca505b_open_data_ccd[][3] = { {0x05, 0xa0, 0x08}, {0x05, 0x00, 0x12}, {0x05, 0x02, 0x0f}, - {0x05, 128, 0x14}, /* max exposure off (0=on) */ + {0x05, 0x80, 0x14}, /* max exposure off (0=on) */ {0x05, 0x01, 0xb0}, {0x05, 0x01, 0xbf}, {0x03, 0x02, 0x06}, @@ -559,27 +556,27 @@ static const __u16 spca505b_open_data_ccd[][3] = { {0x06, 0x5f, 0x1f}, {0x06, 0x32, 0x20}, - {0x05, initial_brightness >> 6, 0x00}, - {0x05, initial_brightness << 2, 0x01}, + {0x05, (u8) (initial_brightness >> 6), 0x00}, + {0x05, (u8) (initial_brightness << 2), 0x01}, {0x05, 0x06, 0xc1}, {0x05, 0x58, 0xc2}, - {0x05, 0x0, 0xca}, - {0x05, 0x0, 0x11}, + {0x05, 0x00, 0xca}, + {0x05, 0x00, 0x11}, {} }; static int reg_write(struct usb_device *dev, - __u16 reg, __u16 index, __u16 value) + u16 req, u16 index, u16 value) { int ret; ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), - reg, + req, USB_TYPE_VENDOR | USB_RECIP_DEVICE, value, index, NULL, 0, 500); - PDEBUG(D_PACK, "reg write: 0x%02x,0x%02x:0x%02x, 0x%x", - reg, index, value, ret); + PDEBUG(D_USBO, "reg write: 0x%02x,0x%02x:0x%02x, %d", + req, index, value, ret); if (ret < 0) PDEBUG(D_ERR, "reg write: error %d", ret); return ret; @@ -587,42 +584,34 @@ static int reg_write(struct usb_device *dev, /* returns: negative is error, pos or zero is data */ static int reg_read(struct gspca_dev *gspca_dev, - __u16 reg, /* bRequest */ - __u16 index, /* wIndex */ - __u16 length) /* wLength (1 or 2 only) */ + u16 req, /* bRequest */ + u16 index) /* wIndex */ { int ret; - gspca_dev->usb_buf[1] = 0; ret = usb_control_msg(gspca_dev->dev, usb_rcvctrlpipe(gspca_dev->dev, 0), - reg, + req, USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - (__u16) 0, /* value */ - (__u16) index, - gspca_dev->usb_buf, length, + 0, /* value */ + index, + gspca_dev->usb_buf, 2, 500); /* timeout */ - if (ret < 0) { - PDEBUG(D_ERR, "reg_read err %d", ret); - return -1; - } + if (ret < 0) + return ret; return (gspca_dev->usb_buf[1] << 8) + gspca_dev->usb_buf[0]; } static int write_vector(struct gspca_dev *gspca_dev, - const __u16 data[][3]) + const u8 data[][3]) { struct usb_device *dev = gspca_dev->dev; int ret, i = 0; - while (data[i][0] != 0 || data[i][1] != 0 || data[i][2] != 0) { + while (data[i][0] != 0) { ret = reg_write(dev, data[i][0], data[i][2], data[i][1]); - if (ret < 0) { - PDEBUG(D_ERR, - "Register write failed for 0x%x,0x%x,0x%x", - data[i][0], data[i][1], data[i][2]); + if (ret < 0) return ret; - } i++; } return 0; @@ -639,10 +628,10 @@ static int sd_config(struct gspca_dev *gspca_dev, cam->cam_mode = vga_mode; sd->subtype = id->driver_info; if (sd->subtype != IntelPCCameraPro) - cam->nmodes = sizeof vga_mode / sizeof vga_mode[0]; + cam->nmodes = ARRAY_SIZE(vga_mode); else /* no 640x480 for IntelPCCameraPro */ - cam->nmodes = sizeof vga_mode / sizeof vga_mode[0] - 1; - sd->brightness = sd_ctrls[SD_BRIGHTNESS].qctrl.default_value; + cam->nmodes = ARRAY_SIZE(vga_mode) - 1; + sd->brightness = BRIGHTNESS_DEF; if (sd->subtype == Nxultra) { if (write_vector(gspca_dev, spca505b_init_data)) @@ -660,30 +649,28 @@ static int sd_init(struct gspca_dev *gspca_dev) struct sd *sd = (struct sd *) gspca_dev; int ret; - PDEBUG(D_STREAM, "Initializing SPCA505"); if (sd->subtype == Nxultra) write_vector(gspca_dev, spca505b_open_data_ccd); else write_vector(gspca_dev, spca505_open_data_ccd); - ret = reg_read(gspca_dev, 6, 0x16, 2); + ret = reg_read(gspca_dev, 0x06, 0x16); if (ret < 0) { - PDEBUG(D_ERR|D_STREAM, - "register read failed for after vector read err = %d", + PDEBUG(D_ERR|D_CONF, + "register read failed err: %d", ret); - return -EIO; + return ret; } - PDEBUG(D_STREAM, - "After vector read returns : 0x%x should be 0x0101", - ret & 0xffff); - - ret = reg_write(gspca_dev->dev, 6, 0x16, 0x0a); - if (ret < 0) { - PDEBUG(D_ERR, "register write failed for (6,0xa,0x16) err=%d", - ret); - return -EIO; + if (ret != 0x0101) { + PDEBUG(D_ERR|D_CONF, + "After vector read returns 0x%04x should be 0x0101", + ret); } - reg_write(gspca_dev->dev, 5, 0xc2, 18); + + ret = reg_write(gspca_dev->dev, 0x06, 0x16, 0x0a); + if (ret < 0) + return ret; + reg_write(gspca_dev->dev, 0x05, 0xc2, 18); return 0; } @@ -749,15 +736,15 @@ static void sd_stop0(struct gspca_dev *gspca_dev) /* This maybe reset or power control */ reg_write(gspca_dev->dev, 0x03, 0x03, 0x20); - reg_write(gspca_dev->dev, 0x03, 0x01, 0x0); - reg_write(gspca_dev->dev, 0x03, 0x00, 0x1); - reg_write(gspca_dev->dev, 0x05, 0x10, 0x1); - reg_write(gspca_dev->dev, 0x05, 0x11, 0xf); + reg_write(gspca_dev->dev, 0x03, 0x01, 0x00); + reg_write(gspca_dev->dev, 0x03, 0x00, 0x01); + reg_write(gspca_dev->dev, 0x05, 0x10, 0x01); + reg_write(gspca_dev->dev, 0x05, 0x11, 0x0f); } static void sd_pkt_scan(struct gspca_dev *gspca_dev, struct gspca_frame *frame, /* target */ - __u8 *data, /* isoc packet */ + u8 *data, /* isoc packet */ int len) /* iso packet length */ { switch (data[0]) { @@ -770,7 +757,6 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, data, len); break; case 0xff: /* drop */ -/* gspca_dev->last_packet_type = DISCARD_PACKET; */ break; default: data += 1; @@ -784,10 +770,10 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, static void setbrightness(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; + u8 brightness = sd->brightness; - __u8 brightness = sd->brightness; - reg_write(gspca_dev->dev, 5, 0x00, (255 - brightness) >> 6); - reg_write(gspca_dev->dev, 5, 0x01, (255 - brightness) << 2); + reg_write(gspca_dev->dev, 0x05, 0x00, (255 - brightness) >> 6); + reg_write(gspca_dev->dev, 0x05, 0x01, (255 - brightness) << 2); } @@ -854,6 +840,7 @@ static struct usb_driver sd_driver = { static int __init sd_mod_init(void) { int ret; + ret = usb_register(&sd_driver); if (ret < 0) return ret; -- cgit v1.2.3 From a5df5c14335988317da4ba9aec64b7eb971a6ffc Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Fri, 23 Jan 2009 14:42:03 -0300 Subject: V4L/DVB (10384): gspca - spca505: Simplify and add the brightness in start. Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/spca505.c | 81 ++++++++++++++++--------------------- 1 file changed, 34 insertions(+), 47 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/gspca/spca505.c b/drivers/media/video/gspca/spca505.c index c99bf62614f3..b9139b1edac9 100644 --- a/drivers/media/video/gspca/spca505.c +++ b/drivers/media/video/gspca/spca505.c @@ -64,12 +64,12 @@ static const struct v4l2_pix_format vga_mode[] = { .bytesperline = 160, .sizeimage = 160 * 120 * 3 / 2, .colorspace = V4L2_COLORSPACE_SRGB, - .priv = 5}, + .priv = 4}, {176, 144, V4L2_PIX_FMT_SPCA505, V4L2_FIELD_NONE, .bytesperline = 176, .sizeimage = 176 * 144 * 3 / 2, .colorspace = V4L2_COLORSPACE_SRGB, - .priv = 4}, + .priv = 3}, {320, 240, V4L2_PIX_FMT_SPCA505, V4L2_FIELD_NONE, .bytesperline = 320, .sizeimage = 320 * 240 * 3 / 2, @@ -93,6 +93,7 @@ static const struct v4l2_pix_format vga_mode[] = { #define SPCA50X_USB_CTRL 0x00 /* spca505 */ #define SPCA50X_CUSB_ENABLE 0x01 /* spca505 */ + #define SPCA50X_REG_GLOBAL 0x03 /* spca505 */ #define SPCA50X_GMISC0_IDSEL 0x01 /* Global control device ID select spca505 */ #define SPCA50X_GLOBAL_MISC0 0x00 /* Global control miscellaneous 0 spca505 */ @@ -101,6 +102,9 @@ static const struct v4l2_pix_format vga_mode[] = { #define SPCA50X_GLOBAL_MISC3 0x03 /* 505 */ #define SPCA50X_GMISC3_SAA7113RST 0x20 /* Not sure about this one spca505 */ +/* Image format and compression control */ +#define SPCA50X_REG_COMPRESS 0x04 + /* * Data to initialize a SPCA505. Common to the CCD and external modes */ @@ -670,55 +674,48 @@ static int sd_init(struct gspca_dev *gspca_dev) ret = reg_write(gspca_dev->dev, 0x06, 0x16, 0x0a); if (ret < 0) return ret; - reg_write(gspca_dev->dev, 0x05, 0xc2, 18); + reg_write(gspca_dev->dev, 0x05, 0xc2, 0x12); return 0; } +static void setbrightness(struct gspca_dev *gspca_dev) +{ + struct sd *sd = (struct sd *) gspca_dev; + u8 brightness = sd->brightness; + + reg_write(gspca_dev->dev, 0x05, 0x00, (255 - brightness) >> 6); + reg_write(gspca_dev->dev, 0x05, 0x01, (255 - brightness) << 2); +} + static int sd_start(struct gspca_dev *gspca_dev) { struct usb_device *dev = gspca_dev->dev; - int ret; + int ret, mode; + static u8 mode_tb[][3] = { + /* r00 r06 r07 */ + {0x00, 0x10, 0x10}, /* 640x480 */ + {0x01, 0x1a, 0x1a}, /* 352x288 */ + {0x02, 0x1c, 0x1d}, /* 320x240 */ + {0x04, 0x34, 0x34}, /* 176x144 */ + {0x05, 0x40, 0x40} /* 160x120 */ + }; /* necessary because without it we can see stream * only once after loading module */ /* stopping usb registers Tomasz change */ - reg_write(dev, 0x02, 0x0, 0x0); - switch (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv) { - case 0: - reg_write(dev, 0x04, 0x00, 0x00); - reg_write(dev, 0x04, 0x06, 0x10); - reg_write(dev, 0x04, 0x07, 0x10); - break; - case 1: - reg_write(dev, 0x04, 0x00, 0x01); - reg_write(dev, 0x04, 0x06, 0x1a); - reg_write(dev, 0x04, 0x07, 0x1a); - break; - case 2: - reg_write(dev, 0x04, 0x00, 0x02); - reg_write(dev, 0x04, 0x06, 0x1c); - reg_write(dev, 0x04, 0x07, 0x1d); - break; - case 4: - reg_write(dev, 0x04, 0x00, 0x04); - reg_write(dev, 0x04, 0x06, 0x34); - reg_write(dev, 0x04, 0x07, 0x34); - break; - default: -/* case 5: */ - reg_write(dev, 0x04, 0x00, 0x05); - reg_write(dev, 0x04, 0x06, 0x40); - reg_write(dev, 0x04, 0x07, 0x40); - break; - } -/* Enable ISO packet machine - should we do this here or in ISOC init ? */ + reg_write(dev, 0x02, 0x00, 0x00); + + mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv; + reg_write(dev, SPCA50X_REG_COMPRESS, 0x00, mode_tb[mode][0]); + reg_write(dev, SPCA50X_REG_COMPRESS, 0x06, mode_tb[mode][1]); + reg_write(dev, SPCA50X_REG_COMPRESS, 0x07, mode_tb[mode][2]); + ret = reg_write(dev, SPCA50X_REG_USB, SPCA50X_USB_CTRL, SPCA50X_CUSB_ENABLE); -/* reg_write(dev, 0x5, 0x0, 0x0); */ -/* reg_write(dev, 0x5, 0x0, 0x1); */ -/* reg_write(dev, 0x5, 0x11, 0x2); */ + setbrightness(gspca_dev); + return ret; } @@ -767,16 +764,6 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, } } -static void setbrightness(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - u8 brightness = sd->brightness; - - reg_write(gspca_dev->dev, 0x05, 0x00, (255 - brightness) >> 6); - reg_write(gspca_dev->dev, 0x05, 0x01, (255 - brightness) << 2); - -} - static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val) { struct sd *sd = (struct sd *) gspca_dev; -- cgit v1.2.3 From 1de1ddf35752485fd1b7774385b72f0f618058fd Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Sat, 24 Jan 2009 15:42:50 -0300 Subject: V4L/DVB (10387): gspca - spca505: Move some sequences from probe to streamon. The webcams worked only one time after connection. Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/spca505.c | 49 ++++++++++++++++++------------------- 1 file changed, 24 insertions(+), 25 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/gspca/spca505.c b/drivers/media/video/gspca/spca505.c index b9139b1edac9..4fc54d8b84aa 100644 --- a/drivers/media/video/gspca/spca505.c +++ b/drivers/media/video/gspca/spca505.c @@ -650,31 +650,6 @@ static int sd_config(struct gspca_dev *gspca_dev, /* this function is called at probe and resume time */ static int sd_init(struct gspca_dev *gspca_dev) { - struct sd *sd = (struct sd *) gspca_dev; - int ret; - - if (sd->subtype == Nxultra) - write_vector(gspca_dev, spca505b_open_data_ccd); - else - write_vector(gspca_dev, spca505_open_data_ccd); - ret = reg_read(gspca_dev, 0x06, 0x16); - - if (ret < 0) { - PDEBUG(D_ERR|D_CONF, - "register read failed err: %d", - ret); - return ret; - } - if (ret != 0x0101) { - PDEBUG(D_ERR|D_CONF, - "After vector read returns 0x%04x should be 0x0101", - ret); - } - - ret = reg_write(gspca_dev->dev, 0x06, 0x16, 0x0a); - if (ret < 0) - return ret; - reg_write(gspca_dev->dev, 0x05, 0xc2, 0x12); return 0; } @@ -689,6 +664,7 @@ static void setbrightness(struct gspca_dev *gspca_dev) static int sd_start(struct gspca_dev *gspca_dev) { + struct sd *sd = (struct sd *) gspca_dev; struct usb_device *dev = gspca_dev->dev; int ret, mode; static u8 mode_tb[][3] = { @@ -700,6 +676,29 @@ static int sd_start(struct gspca_dev *gspca_dev) {0x05, 0x40, 0x40} /* 160x120 */ }; + if (sd->subtype == Nxultra) + write_vector(gspca_dev, spca505b_open_data_ccd); + else + write_vector(gspca_dev, spca505_open_data_ccd); + ret = reg_read(gspca_dev, 0x06, 0x16); + + if (ret < 0) { + PDEBUG(D_ERR|D_CONF, + "register read failed err: %d", + ret); + return ret; + } + if (ret != 0x0101) { + PDEBUG(D_ERR|D_CONF, + "After vector read returns 0x%04x should be 0x0101", + ret); + } + + ret = reg_write(gspca_dev->dev, 0x06, 0x16, 0x0a); + if (ret < 0) + return ret; + reg_write(gspca_dev->dev, 0x05, 0xc2, 0x12); + /* necessary because without it we can see stream * only once after loading module */ /* stopping usb registers Tomasz change */ -- cgit v1.2.3 From db91235ee8350149213435c4cf178a7627c968b9 Mon Sep 17 00:00:00 2001 From: Lierdakil Date: Sun, 25 Jan 2009 14:37:26 -0300 Subject: V4L/DVB (10388): gspca - pac207: Webcam 093a:2474 added. Signed-off-by: Lierdakil Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab --- Documentation/video4linux/gspca.txt | 1 + drivers/media/video/gspca/pac207.c | 1 + 2 files changed, 2 insertions(+) (limited to 'drivers/media/video') diff --git a/Documentation/video4linux/gspca.txt b/Documentation/video4linux/gspca.txt index af80c3344567..3136c80280b1 100644 --- a/Documentation/video4linux/gspca.txt +++ b/Documentation/video4linux/gspca.txt @@ -216,6 +216,7 @@ pac207 093a:2468 PAC207 pac207 093a:2470 Genius GF112 pac207 093a:2471 Genius VideoCam ge111 pac207 093a:2472 Genius VideoCam ge110 +pac207 093a:2474 Genius iLook 111 pac207 093a:2476 Genius e-Messenger 112 pac7311 093a:2600 PAC7311 Typhoon pac7311 093a:2601 Philips SPC 610 NC diff --git a/drivers/media/video/gspca/pac207.c b/drivers/media/video/gspca/pac207.c index 93616cebf360..95a97ab684cd 100644 --- a/drivers/media/video/gspca/pac207.c +++ b/drivers/media/video/gspca/pac207.c @@ -535,6 +535,7 @@ static const __devinitdata struct usb_device_id device_table[] = { {USB_DEVICE(0x093a, 0x2470)}, {USB_DEVICE(0x093a, 0x2471)}, {USB_DEVICE(0x093a, 0x2472)}, + {USB_DEVICE(0x093a, 0x2474)}, {USB_DEVICE(0x093a, 0x2476)}, {USB_DEVICE(0x145f, 0x013a)}, {USB_DEVICE(0x2001, 0xf115)}, -- cgit v1.2.3 From c675e79c917c02a54f54fcac3776ccf0b428bd37 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Mon, 26 Jan 2009 05:29:06 -0300 Subject: V4L/DVB (10389): gspca - zc3xx: Do work the sensor adcm2700. The lack of the green color is fixed by sensor sequences closer to the ms-win traces. Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/zc3xx.c | 43 +++++++++++++++++++++++---------------- 1 file changed, 26 insertions(+), 17 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/gspca/zc3xx.c b/drivers/media/video/gspca/zc3xx.c index fff95e69cd14..e6a6cb946a21 100644 --- a/drivers/media/video/gspca/zc3xx.c +++ b/drivers/media/video/gspca/zc3xx.c @@ -210,7 +210,7 @@ struct usb_action { static const struct usb_action adcm2700_Initial[] = { {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, /* 00,00,01,cc */ {0xa0, 0x04, ZC3XX_R002_CLOCKSELECT}, /* 00,02,04,cc */ - {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, /* 00,08,03,cc */ + {0xa0, 0x00, ZC3XX_R008_CLOCKSETTING}, /* 00,08,03,cc */ {0xa0, 0x0a, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,0a,cc */ {0xa0, 0xd3, ZC3XX_R08B_I2CDEVICEADDR}, /* 00,8b,d3,cc */ {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH}, /* 00,03,02,cc */ @@ -230,7 +230,7 @@ static const struct usb_action adcm2700_Initial[] = { {0xbb, 0x00, 0x0400}, /* 04,00,00,bb */ {0xdd, 0x00, 0x0010}, /* 00,00,10,dd */ {0xbb, 0x0f, 0x140f}, /* 14,0f,0f,bb */ - {0xa0, 0x37, ZC3XX_R101_SENSORCORRECTION}, /* 01,01,37,cc */ + {0xa0, 0xb7, ZC3XX_R101_SENSORCORRECTION}, /* 01,01,37,cc */ {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE}, /* 01,00,0d,cc */ {0xa0, 0x06, ZC3XX_R189_AWBSTATUS}, /* 01,89,06,cc */ {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE}, /* 01,c5,03,cc */ @@ -269,6 +269,15 @@ static const struct usb_action adcm2700_Initial[] = { {0xdd, 0x00, 0x0010}, /* 00,00,10,dd */ {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,01,cc */ {0xaa, 0xfe, 0x0020}, /* 00,fe,20,aa */ +/*mswin+*/ + {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT}, + {0xaa, 0xfe, 0x0002}, + {0xa0, 0x0a, ZC3XX_R010_CMOSSENSORSELECT}, + {0xaa, 0xb4, 0xcd37}, + {0xaa, 0xa4, 0x0004}, + {0xaa, 0xa8, 0x0007}, + {0xaa, 0xac, 0x0004}, +/*mswin-*/ {0xa0, 0x0a, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,0a,cc */ {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,01,cc */ {0xdd, 0x00, 0x0010}, /* 00,00,10,dd */ @@ -290,7 +299,7 @@ static const struct usb_action adcm2700_Initial[] = { static const struct usb_action adcm2700_InitialScale[] = { {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, /* 00,00,01,cc */ {0xa0, 0x10, ZC3XX_R002_CLOCKSELECT}, /* 00,02,10,cc */ - {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, /* 00,08,03,cc */ + {0xa0, 0x00, ZC3XX_R008_CLOCKSETTING}, /* 00,08,03,cc */ {0xa0, 0x0a, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,0a,cc */ {0xa0, 0xd3, ZC3XX_R08B_I2CDEVICEADDR}, /* 00,8b,d3,cc */ {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH}, /* 00,03,02,cc */ @@ -310,7 +319,7 @@ static const struct usb_action adcm2700_InitialScale[] = { {0xbb, 0x00, 0x0400}, /* 04,00,00,bb */ {0xdd, 0x00, 0x0010}, /* 00,00,10,dd */ {0xbb, 0x0f, 0x140f}, /* 14,0f,0f,bb */ - {0xa0, 0x37, ZC3XX_R101_SENSORCORRECTION}, /* 01,01,37,cc */ + {0xa0, 0xb7, ZC3XX_R101_SENSORCORRECTION}, /* 01,01,37,cc */ {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE}, /* 01,00,0d,cc */ {0xa0, 0x06, ZC3XX_R189_AWBSTATUS}, /* 01,89,06,cc */ {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE}, /* 01,c5,03,cc */ @@ -338,9 +347,9 @@ static const struct usb_action adcm2700_InitialScale[] = { {0xbb, 0x5f, 0x2090}, /* 20,5f,90,bb */ {0xbb, 0x01, 0x8000}, /* 80,01,00,bb */ {0xbb, 0x09, 0x8400}, /* 84,09,00,bb */ - {0xbb, 0x88, 0x0002}, /* 00,88,02,bb */ + {0xbb, 0x86, 0x0002}, /* 00,88,02,bb */ {0xbb, 0xe6, 0x0401}, /* 04,e6,01,bb */ - {0xbb, 0x88, 0x0802}, /* 08,88,02,bb */ + {0xbb, 0x86, 0x0802}, /* 08,88,02,bb */ {0xbb, 0xe6, 0x0c01}, /* 0c,e6,01,bb */ {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,01,cc */ {0xdd, 0x00, 0x0010}, /* 00,00,10,dd */ @@ -6354,7 +6363,9 @@ static void setmatrix(struct gspca_dev *gspca_dev) int i; const __u8 *matrix; static const u8 adcm2700_matrix[9] = - {0x66, 0xed, 0xed, 0xed, 0x66, 0xed, 0xed, 0xed, 0x66}; +/* {0x66, 0xed, 0xed, 0xed, 0x66, 0xed, 0xed, 0xed, 0x66}; */ +/*ms-win*/ + {0x74, 0xed, 0xed, 0xed, 0x74, 0xed, 0xed, 0xed, 0x74}; static const __u8 gc0305_matrix[9] = {0x50, 0xf8, 0xf8, 0xf8, 0x50, 0xf8, 0xf8, 0xf8, 0x50}; static const __u8 ov7620_matrix[9] = @@ -6399,7 +6410,6 @@ static void setbrightness(struct gspca_dev *gspca_dev) __u8 brightness; switch (sd->sensor) { - case SENSOR_ADCM2700: case SENSOR_GC0305: case SENSOR_OV7620: case SENSOR_PO2030: @@ -6408,8 +6418,11 @@ static void setbrightness(struct gspca_dev *gspca_dev) /*fixme: is it really write to 011d and 018d for all other sensors? */ brightness = sd->brightness; reg_w(gspca_dev->dev, brightness, 0x011d); - if (sd->sensor == SENSOR_HV7131B) + switch (sd->sensor) { + case SENSOR_ADCM2700: + case SENSOR_HV7131B: return; + } if (brightness < 0x70) brightness += 0x10; else @@ -6549,6 +6562,7 @@ static void setquality(struct gspca_dev *gspca_dev) __u8 frxt; switch (sd->sensor) { + case SENSOR_ADCM2700: case SENSOR_GC0305: case SENSOR_HV7131B: case SENSOR_OV7620: @@ -7295,8 +7309,6 @@ static int sd_start(struct gspca_dev *gspca_dev) } setmatrix(gspca_dev); /* one more time? */ switch (sd->sensor) { - case SENSOR_ADCM2700: - break; case SENSOR_OV7620: case SENSOR_PAS202B: reg_r(gspca_dev, 0x0180); /* from win */ @@ -7338,19 +7350,16 @@ static int sd_start(struct gspca_dev *gspca_dev) setautogain(gspca_dev); switch (sd->sensor) { - case SENSOR_PAS202B: - reg_w(dev, 0x00, 0x0007); /* (from win traces) */ - break; case SENSOR_PO2030: msleep(500); reg_r(gspca_dev, 0x0008); reg_r(gspca_dev, 0x0007); + /*fall thru*/ + case SENSOR_PAS202B: reg_w(dev, 0x00, 0x0007); /* (from win traces) */ - reg_w(dev, 0x02, 0x0008); + reg_w(dev, 0x02, ZC3XX_R008_CLOCKSETTING); break; } - if (sd->sensor == SENSOR_PAS202B) - reg_w(dev, 0x02, ZC3XX_R008_CLOCKSETTING); return 0; } -- cgit v1.2.3 From aaf50d7d0e12ec797dc0677c4fc853839bdcf07d Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 19 Jan 2009 08:01:24 -0300 Subject: V4L/DVB (10394): KWorld ATSC 115 all static saa7134: Fix tuner access on Kworld ATSC110 -- To unsubscribe from this list: send the line "unsubscribe linux-media" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/saa7134/saa7134-cards.c | 46 +++++++++++++++++++---------- drivers/media/video/saa7134/saa7134.h | 23 ++++++++++++--- 2 files changed, 49 insertions(+), 20 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/saa7134/saa7134-cards.c b/drivers/media/video/saa7134/saa7134-cards.c index 0d50d7448fc5..42684d162040 100644 --- a/drivers/media/video/saa7134/saa7134-cards.c +++ b/drivers/media/video/saa7134/saa7134-cards.c @@ -5896,6 +5896,32 @@ static void hauppauge_eeprom(struct saa7134_dev *dev, u8 *eeprom_data) /* ----------------------------------------------------------- */ +static void nxt200x_gate_ctrl(struct saa7134_dev *dev, int open) +{ + /* enable tuner */ + int i; + static const u8 buffer [][2] = { + { 0x10, 0x12 }, + { 0x13, 0x04 }, + { 0x16, 0x00 }, + { 0x14, 0x04 }, + { 0x17, 0x00 }, + }; + + dev->i2c_client.addr = 0x0a; + + /* FIXME: don't know how to close the i2c gate on NXT200x */ + if (!open) + return; + + for (i = 0; i < ARRAY_SIZE(buffer); i++) + if (2 != i2c_master_send(&dev->i2c_client, + &buffer[i][0], ARRAY_SIZE(buffer[0]))) + printk(KERN_WARNING + "%s: Unable to enable tuner(%i).\n", + dev->name, i); +} + int saa7134_board_init1(struct saa7134_dev *dev) { /* Always print gpio, often manufacturers encode tuner type and other info. */ @@ -6089,6 +6115,10 @@ int saa7134_board_init1(struct saa7134_dev *dev) "are supported for now.\n", dev->name, card(dev).name, dev->name); break; + case SAA7134_BOARD_ADS_INSTANT_HDTV_PCI: + case SAA7134_BOARD_KWORLD_ATSC110: + dev->gate_ctrl = nxt200x_gate_ctrl; + break; } return 0; } @@ -6350,22 +6380,6 @@ int saa7134_board_init2(struct saa7134_dev *dev) i2c_transfer(&dev->i2c_adap, &msg, 1); break; } - case SAA7134_BOARD_ADS_INSTANT_HDTV_PCI: - case SAA7134_BOARD_KWORLD_ATSC110: - { - /* enable tuner */ - int i; - static const u8 buffer [] = { 0x10, 0x12, 0x13, 0x04, 0x16, - 0x00, 0x14, 0x04, 0x17, 0x00 }; - dev->i2c_client.addr = 0x0a; - for (i = 0; i < 5; i++) - if (2 != i2c_master_send(&dev->i2c_client, - &buffer[i*2], 2)) - printk(KERN_WARNING - "%s: Unable to enable tuner(%i).\n", - dev->name, i); - break; - } case SAA7134_BOARD_VIDEOMATE_DVBT_200: case SAA7134_BOARD_VIDEOMATE_DVBT_200A: /* The T200 and the T200A share the same pci id. Consequently, diff --git a/drivers/media/video/saa7134/saa7134.h b/drivers/media/video/saa7134/saa7134.h index bb6952118d01..6fbf5088c97a 100644 --- a/drivers/media/video/saa7134/saa7134.h +++ b/drivers/media/video/saa7134/saa7134.h @@ -589,6 +589,7 @@ struct saa7134_dev { 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 + void (*gate_ctrl)(struct saa7134_dev *dev, int open); }; /* ----------------------------------------------------------- */ @@ -618,10 +619,24 @@ struct saa7134_dev { V4L2_STD_PAL_60) #define GRP_EMPRESS (1) -#define saa_call_all(dev, o, f, args...) \ - v4l2_device_call_all(&(dev)->v4l2_dev, 0, o, f , ##args) -#define saa_call_empress(dev, o, f, args...) \ - v4l2_device_call_until_err(&(dev)->v4l2_dev, GRP_EMPRESS, o, f , ##args) +#define saa_call_all(dev, o, f, args...) do { \ + if (dev->gate_ctrl) \ + dev->gate_ctrl(dev, 1); \ + v4l2_device_call_all(&(dev)->v4l2_dev, 0, o, f , ##args); \ + if (dev->gate_ctrl) \ + dev->gate_ctrl(dev, 0); \ +} while (0) + +#define saa_call_empress(dev, o, f, args...) ({ \ + long _rc; \ + if (dev->gate_ctrl) \ + dev->gate_ctrl(dev, 1); \ + _rc = v4l2_device_call_until_err(&(dev)->v4l2_dev, \ + GRP_EMPRESS, o, f , ##args); \ + if (dev->gate_ctrl) \ + dev->gate_ctrl(dev, 0); \ + _rc; \ +}) /* ----------------------------------------------------------- */ /* saa7134-core.c */ -- cgit v1.2.3 From 74d200f13156f7057ed62ecca086be75cdf363d5 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sat, 31 Jan 2009 08:10:49 -0300 Subject: V4L/DVB (10404): saa7134-core: remove oss option, since saa7134-oss doesn't exist anymore Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/saa7134/saa7134-core.c | 6 ------ 1 file changed, 6 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/saa7134/saa7134-core.c b/drivers/media/video/saa7134/saa7134-core.c index 829006ebdf34..ea48bb5b4af0 100644 --- a/drivers/media/video/saa7134/saa7134-core.c +++ b/drivers/media/video/saa7134/saa7134-core.c @@ -58,10 +58,6 @@ static unsigned int alsa; module_param(alsa, int, 0644); MODULE_PARM_DESC(alsa,"enable ALSA DMA sound [dmasound]"); -static unsigned int oss; -module_param(oss, int, 0644); -MODULE_PARM_DESC(oss,"enable OSS DMA sound [dmasound]"); - static unsigned int latency = UNSET; module_param(latency, int, 0444); MODULE_PARM_DESC(latency,"pci latency timer"); @@ -158,8 +154,6 @@ static void request_module_async(struct work_struct *work){ request_module("saa7134-dvb"); if (alsa) request_module("saa7134-alsa"); - if (oss) - request_module("saa7134-oss"); } static void request_submodules(struct saa7134_dev *dev) -- cgit v1.2.3 From 23ce51d9751f716953c83fd2355c0b584bdc679a Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sat, 31 Jan 2009 08:14:24 -0300 Subject: V4L/DVB (10405): saa7134-core: loading saa7134-alsa is now the default Most boards nowadays supports saa7134-alsa. Even some of they doesn't have any option to wire an audio cable. So, lets load saa7134-alsa by default, if the board is not based on saa7130 and if saa7134-alsa is compiled. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/saa7134/saa7134-core.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/saa7134/saa7134-core.c b/drivers/media/video/saa7134/saa7134-core.c index ea48bb5b4af0..b0f886e27c60 100644 --- a/drivers/media/video/saa7134/saa7134-core.c +++ b/drivers/media/video/saa7134/saa7134-core.c @@ -54,9 +54,9 @@ static unsigned int gpio_tracking; module_param(gpio_tracking, int, 0644); MODULE_PARM_DESC(gpio_tracking,"enable debug messages [gpio]"); -static unsigned int alsa; +static unsigned int alsa = 1; module_param(alsa, int, 0644); -MODULE_PARM_DESC(alsa,"enable ALSA DMA sound [dmasound]"); +MODULE_PARM_DESC(alsa,"enable/disable ALSA DMA sound [dmasound]"); static unsigned int latency = UNSET; module_param(latency, int, 0444); @@ -152,8 +152,10 @@ static void request_module_async(struct work_struct *work){ request_module("saa7134-empress"); if (card_is_dvb(dev)) request_module("saa7134-dvb"); - if (alsa) - request_module("saa7134-alsa"); + if (alsa) { + if (dev->pci->device != PCI_DEVICE_ID_PHILIPS_SAA7130) + request_module("saa7134-alsa"); + } } static void request_submodules(struct saa7134_dev *dev) -- cgit v1.2.3 From d9ddd3b01043269a9a8803b6b8b8b472e054733c Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Thu, 29 Jan 2009 06:23:18 -0300 Subject: V4L/DVB (10406): gspca: fix compiler warning Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/t613.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/gspca/t613.c b/drivers/media/video/gspca/t613.c index 49db21e1376c..0a1f4efdc6ed 100644 --- a/drivers/media/video/gspca/t613.c +++ b/drivers/media/video/gspca/t613.c @@ -635,7 +635,7 @@ static int sd_init(struct gspca_dev *gspca_dev) struct sd *sd = (struct sd *) gspca_dev; int i; u16 sensor_id; - u8 test_byte; + u8 test_byte = 0; u16 reg80, reg8e; static const u8 read_indexs[] = -- cgit v1.2.3 From de6476f5f6ae9f792a8828782bdbc47372a021fb Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Thu, 29 Jan 2009 16:09:13 -0300 Subject: V4L/DVB (10408): v4l2: fix incorrect hue range check A hue of -128 was rejected due to an incorrect range check, which was faithfully copy-and-pasted into four drivers... Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx18/cx18-av-core.c | 2 +- drivers/media/video/cx25840/cx25840-core.c | 2 +- drivers/media/video/saa7115.c | 2 +- drivers/media/video/saa717x.c | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/cx18/cx18-av-core.c b/drivers/media/video/cx18/cx18-av-core.c index 0b1c84b4ddd6..780125002cbc 100644 --- a/drivers/media/video/cx18/cx18-av-core.c +++ b/drivers/media/video/cx18/cx18-av-core.c @@ -548,7 +548,7 @@ static int set_v4lctrl(struct cx18 *cx, struct v4l2_control *ctrl) break; case V4L2_CID_HUE: - if (ctrl->value < -127 || ctrl->value > 127) { + if (ctrl->value < -128 || ctrl->value > 127) { CX18_ERR("invalid hue setting %d\n", ctrl->value); return -ERANGE; } diff --git a/drivers/media/video/cx25840/cx25840-core.c b/drivers/media/video/cx25840/cx25840-core.c index be467b4b9545..d4059ecaa58e 100644 --- a/drivers/media/video/cx25840/cx25840-core.c +++ b/drivers/media/video/cx25840/cx25840-core.c @@ -763,7 +763,7 @@ static int cx25840_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) break; case V4L2_CID_HUE: - if (ctrl->value < -127 || ctrl->value > 127) { + if (ctrl->value < -128 || ctrl->value > 127) { v4l_err(client, "invalid hue setting %d\n", ctrl->value); return -ERANGE; } diff --git a/drivers/media/video/saa7115.c b/drivers/media/video/saa7115.c index 46c796c3fec8..dd1943987ce6 100644 --- a/drivers/media/video/saa7115.c +++ b/drivers/media/video/saa7115.c @@ -778,7 +778,7 @@ static int saa711x_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) break; case V4L2_CID_HUE: - if (ctrl->value < -127 || ctrl->value > 127) { + if (ctrl->value < -128 || ctrl->value > 127) { v4l2_err(sd, "invalid hue setting %d\n", ctrl->value); return -ERANGE; } diff --git a/drivers/media/video/saa717x.c b/drivers/media/video/saa717x.c index 88c5e942f751..490b9049b987 100644 --- a/drivers/media/video/saa717x.c +++ b/drivers/media/video/saa717x.c @@ -931,7 +931,7 @@ static int saa717x_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) break; case V4L2_CID_HUE: - if (ctrl->value < -127 || ctrl->value > 127) { + if (ctrl->value < -128 || ctrl->value > 127) { v4l2_err(sd, "invalid hue setting %d\n", ctrl->value); return -ERANGE; } -- cgit v1.2.3 From e230b22b59bc07d906f1558a8951206ccab33824 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Thu, 29 Jan 2009 16:21:12 -0300 Subject: V4L/DVB (10409): v4l: remove unused I2C_DRIVERIDs. I2C_DRIVERIDs are phased out. Remove those that are unused at the moment. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cs53l32a.c | 1 - drivers/media/video/m52790.c | 1 - drivers/media/video/saa5246a.c | 1 - drivers/media/video/saa5249.c | 1 - drivers/media/video/saa717x.c | 1 - drivers/media/video/tda7432.c | 1 - drivers/media/video/tda9840.c | 1 - drivers/media/video/tda9875.c | 1 - drivers/media/video/tea6415c.c | 1 - drivers/media/video/tea6420.c | 1 - drivers/media/video/tlv320aic23b.c | 1 - drivers/media/video/tvp5150.c | 1 - drivers/media/video/upd64031a.c | 1 - drivers/media/video/upd64083.c | 1 - drivers/media/video/vp27smpx.c | 1 - drivers/media/video/wm8739.c | 1 - 16 files changed, 16 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/cs53l32a.c b/drivers/media/video/cs53l32a.c index 7292a6316e63..2f33abd2e01c 100644 --- a/drivers/media/video/cs53l32a.c +++ b/drivers/media/video/cs53l32a.c @@ -218,7 +218,6 @@ MODULE_DEVICE_TABLE(i2c, cs53l32a_id); static struct v4l2_i2c_driver_data v4l2_i2c_data = { .name = "cs53l32a", - .driverid = I2C_DRIVERID_CS53L32A, .command = cs53l32a_command, .remove = cs53l32a_remove, .probe = cs53l32a_probe, diff --git a/drivers/media/video/m52790.c b/drivers/media/video/m52790.c index de397ef57b44..41988072b973 100644 --- a/drivers/media/video/m52790.c +++ b/drivers/media/video/m52790.c @@ -210,7 +210,6 @@ MODULE_DEVICE_TABLE(i2c, m52790_id); static struct v4l2_i2c_driver_data v4l2_i2c_data = { .name = "m52790", - .driverid = I2C_DRIVERID_M52790, .command = m52790_command, .probe = m52790_probe, .remove = m52790_remove, diff --git a/drivers/media/video/saa5246a.c b/drivers/media/video/saa5246a.c index e637e440b6d5..8f117bd50b86 100644 --- a/drivers/media/video/saa5246a.c +++ b/drivers/media/video/saa5246a.c @@ -1098,7 +1098,6 @@ MODULE_DEVICE_TABLE(i2c, saa5246a_id); static struct v4l2_i2c_driver_data v4l2_i2c_data = { .name = "saa5246a", - .driverid = I2C_DRIVERID_SAA5249, .probe = saa5246a_probe, .remove = saa5246a_remove, .id_table = saa5246a_id, diff --git a/drivers/media/video/saa5249.c b/drivers/media/video/saa5249.c index e29765192469..81e666df0db7 100644 --- a/drivers/media/video/saa5249.c +++ b/drivers/media/video/saa5249.c @@ -624,7 +624,6 @@ MODULE_DEVICE_TABLE(i2c, saa5249_id); static struct v4l2_i2c_driver_data v4l2_i2c_data = { .name = "saa5249", - .driverid = I2C_DRIVERID_SAA5249, .probe = saa5249_probe, .remove = saa5249_remove, .id_table = saa5249_id, diff --git a/drivers/media/video/saa717x.c b/drivers/media/video/saa717x.c index 490b9049b987..5ad7a77699de 100644 --- a/drivers/media/video/saa717x.c +++ b/drivers/media/video/saa717x.c @@ -1528,7 +1528,6 @@ MODULE_DEVICE_TABLE(i2c, saa717x_id); static struct v4l2_i2c_driver_data v4l2_i2c_data = { .name = "saa717x", - .driverid = I2C_DRIVERID_SAA717X, .command = saa717x_command, .probe = saa717x_probe, .remove = saa717x_remove, diff --git a/drivers/media/video/tda7432.c b/drivers/media/video/tda7432.c index 0c020585fffb..2090e170bd9c 100644 --- a/drivers/media/video/tda7432.c +++ b/drivers/media/video/tda7432.c @@ -498,7 +498,6 @@ MODULE_DEVICE_TABLE(i2c, tda7432_id); static struct v4l2_i2c_driver_data v4l2_i2c_data = { .name = "tda7432", - .driverid = I2C_DRIVERID_TDA7432, .command = tda7432_command, .probe = tda7432_probe, .remove = tda7432_remove, diff --git a/drivers/media/video/tda9840.c b/drivers/media/video/tda9840.c index 6afb7059502d..ae46a28dd052 100644 --- a/drivers/media/video/tda9840.c +++ b/drivers/media/video/tda9840.c @@ -262,7 +262,6 @@ MODULE_DEVICE_TABLE(i2c, tda9840_id); static struct v4l2_i2c_driver_data v4l2_i2c_data = { .name = "tda9840", - .driverid = I2C_DRIVERID_TDA9840, .command = tda9840_command, .probe = tda9840_probe, .remove = tda9840_remove, diff --git a/drivers/media/video/tda9875.c b/drivers/media/video/tda9875.c index 00c6cbe06ab0..19fbd18f4882 100644 --- a/drivers/media/video/tda9875.c +++ b/drivers/media/video/tda9875.c @@ -401,7 +401,6 @@ MODULE_DEVICE_TABLE(i2c, tda9875_id); static struct v4l2_i2c_driver_data v4l2_i2c_data = { .name = "tda9875", - .driverid = I2C_DRIVERID_TDA9875, .command = tda9875_command, .probe = tda9875_probe, .remove = tda9875_remove, diff --git a/drivers/media/video/tea6415c.c b/drivers/media/video/tea6415c.c index 7519fd1f57ef..bb9b7780c49f 100644 --- a/drivers/media/video/tea6415c.c +++ b/drivers/media/video/tea6415c.c @@ -191,7 +191,6 @@ MODULE_DEVICE_TABLE(i2c, tea6415c_id); static struct v4l2_i2c_driver_data v4l2_i2c_data = { .name = "tea6415c", - .driverid = I2C_DRIVERID_TEA6415C, .command = tea6415c_command, .probe = tea6415c_probe, .remove = tea6415c_remove, diff --git a/drivers/media/video/tea6420.c b/drivers/media/video/tea6420.c index 081e74fa3b2e..7546509c8282 100644 --- a/drivers/media/video/tea6420.c +++ b/drivers/media/video/tea6420.c @@ -171,7 +171,6 @@ MODULE_DEVICE_TABLE(i2c, tea6420_id); static struct v4l2_i2c_driver_data v4l2_i2c_data = { .name = "tea6420", - .driverid = I2C_DRIVERID_TEA6420, .command = tea6420_command, .probe = tea6420_probe, .remove = tea6420_remove, diff --git a/drivers/media/video/tlv320aic23b.c b/drivers/media/video/tlv320aic23b.c index 5c95ecd09dc2..b6e838ada66d 100644 --- a/drivers/media/video/tlv320aic23b.c +++ b/drivers/media/video/tlv320aic23b.c @@ -208,7 +208,6 @@ MODULE_DEVICE_TABLE(i2c, tlv320aic23b_id); static struct v4l2_i2c_driver_data v4l2_i2c_data = { .name = "tlv320aic23b", - .driverid = I2C_DRIVERID_TLV320AIC23B, .command = tlv320aic23b_command, .probe = tlv320aic23b_probe, .remove = tlv320aic23b_remove, diff --git a/drivers/media/video/tvp5150.c b/drivers/media/video/tvp5150.c index 2cd64ef27b95..6b600bed445f 100644 --- a/drivers/media/video/tvp5150.c +++ b/drivers/media/video/tvp5150.c @@ -1126,7 +1126,6 @@ MODULE_DEVICE_TABLE(i2c, tvp5150_id); static struct v4l2_i2c_driver_data v4l2_i2c_data = { .name = "tvp5150", - .driverid = I2C_DRIVERID_TVP5150, .command = tvp5150_command, .probe = tvp5150_probe, .remove = tvp5150_remove, diff --git a/drivers/media/video/upd64031a.c b/drivers/media/video/upd64031a.c index f4522bb08916..5b2c4399027c 100644 --- a/drivers/media/video/upd64031a.c +++ b/drivers/media/video/upd64031a.c @@ -267,7 +267,6 @@ MODULE_DEVICE_TABLE(i2c, upd64031a_id); static struct v4l2_i2c_driver_data v4l2_i2c_data = { .name = "upd64031a", - .driverid = I2C_DRIVERID_UPD64031A, .command = upd64031a_command, .probe = upd64031a_probe, .remove = upd64031a_remove, diff --git a/drivers/media/video/upd64083.c b/drivers/media/video/upd64083.c index a5fb74bf2407..acd66c172efe 100644 --- a/drivers/media/video/upd64083.c +++ b/drivers/media/video/upd64083.c @@ -239,7 +239,6 @@ MODULE_DEVICE_TABLE(i2c, upd64083_id); static struct v4l2_i2c_driver_data v4l2_i2c_data = { .name = "upd64083", - .driverid = I2C_DRIVERID_UPD64083, .command = upd64083_command, .probe = upd64083_probe, .remove = upd64083_remove, diff --git a/drivers/media/video/vp27smpx.c b/drivers/media/video/vp27smpx.c index 5d73f66d9f55..9a590a91d7de 100644 --- a/drivers/media/video/vp27smpx.c +++ b/drivers/media/video/vp27smpx.c @@ -206,7 +206,6 @@ MODULE_DEVICE_TABLE(i2c, vp27smpx_id); static struct v4l2_i2c_driver_data v4l2_i2c_data = { .name = "vp27smpx", - .driverid = I2C_DRIVERID_VP27SMPX, .command = vp27smpx_command, .probe = vp27smpx_probe, .remove = vp27smpx_remove, diff --git a/drivers/media/video/wm8739.c b/drivers/media/video/wm8739.c index f2864d5cd180..18535c4a0549 100644 --- a/drivers/media/video/wm8739.c +++ b/drivers/media/video/wm8739.c @@ -343,7 +343,6 @@ MODULE_DEVICE_TABLE(i2c, wm8739_id); static struct v4l2_i2c_driver_data v4l2_i2c_data = { .name = "wm8739", - .driverid = I2C_DRIVERID_WM8739, .command = wm8739_command, .probe = wm8739_probe, .remove = wm8739_remove, -- cgit v1.2.3 From f6070767f9b6157a405112bfc6d4ae3c923ee1b1 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Tue, 6 Jan 2009 14:10:59 -0300 Subject: V4L/DVB (10416): tveeprom: update to include Hauppauge tuners 151-155 Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/tveeprom.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers/media/video') diff --git a/drivers/media/video/tveeprom.c b/drivers/media/video/tveeprom.c index 78277abb733b..63705b8cd1ed 100644 --- a/drivers/media/video/tveeprom.c +++ b/drivers/media/video/tveeprom.c @@ -262,6 +262,11 @@ hauppauge_tuner[] = { TUNER_PHILIPS_TDA8290, "Philips 18271_8295"}, /* 150-159 */ { TUNER_ABSENT, "Xceive XC5000"}, + { TUNER_ABSENT, "Xceive XC3028L"}, + { TUNER_ABSENT, "NXP 18271C2_716x"}, + { TUNER_ABSENT, "Xceive XC4000"}, + { TUNER_ABSENT, "Dibcom 7070"}, + { TUNER_PHILIPS_TDA8290, "NXP 18271C2"}, }; /* Use V4L2_IDENT_AMBIGUOUS for those audio 'chips' that are -- cgit v1.2.3 From 3ef2c5be9c79ce668e3e58d323379be24e39e20c Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Thu, 29 Jan 2009 04:59:45 -0300 Subject: V4L/DVB (10419): gspca - sonixj: Sensor mt9v111 added. Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/sonixj.c | 206 ++++++++++++++++++++++++++++++++----- 1 file changed, 180 insertions(+), 26 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/gspca/sonixj.c b/drivers/media/video/gspca/sonixj.c index 59363e077bbf..74d2aca390b3 100644 --- a/drivers/media/video/gspca/sonixj.c +++ b/drivers/media/video/gspca/sonixj.c @@ -46,7 +46,7 @@ struct sd { u8 red; u8 gamma; u8 vflip; /* ov7630 only */ - u8 infrared; /* mi0360 only */ + u8 infrared; /* mt9v111 only */ s8 ag_cnt; #define AG_CNT_START 13 @@ -61,10 +61,11 @@ struct sd { #define SENSOR_HV7131R 0 #define SENSOR_MI0360 1 #define SENSOR_MO4000 2 -#define SENSOR_OM6802 3 -#define SENSOR_OV7630 4 -#define SENSOR_OV7648 5 -#define SENSOR_OV7660 6 +#define SENSOR_MT9V111 3 +#define SENSOR_OM6802 4 +#define SENSOR_OV7630 5 +#define SENSOR_OV7648 6 +#define SENSOR_OV7660 7 u8 i2c_base; }; @@ -206,7 +207,7 @@ static struct ctrl sd_ctrls[] = { .set = sd_setvflip, .get = sd_getvflip, }, -/* mi0360 only */ +/* mt9v111 only */ #define INFRARED_IDX 7 { { @@ -228,18 +229,20 @@ static struct ctrl sd_ctrls[] = { static __u32 ctrl_dis[] = { (1 << INFRARED_IDX) | (1 << VFLIP_IDX), /* SENSOR_HV7131R 0 */ - (1 << VFLIP_IDX), + (1 << INFRARED_IDX) | (1 << VFLIP_IDX), /* SENSOR_MI0360 1 */ (1 << INFRARED_IDX) | (1 << VFLIP_IDX), /* SENSOR_MO4000 2 */ + (1 << AUTOGAIN_IDX), + /* SENSOR_MT9V111 3 */ (1 << INFRARED_IDX) | (1 << VFLIP_IDX), - /* SENSOR_OM6802 3 */ + /* SENSOR_OM6802 4 */ (1 << AUTOGAIN_IDX) | (1 << INFRARED_IDX), - /* SENSOR_OV7630 4 */ + /* SENSOR_OV7630 5 */ (1 << AUTOGAIN_IDX) | (1 << INFRARED_IDX) | (1 << VFLIP_IDX), - /* SENSOR_OV7648 5 */ + /* SENSOR_OV7648 6 */ (1 << AUTOGAIN_IDX) | (1 << INFRARED_IDX) | (1 << VFLIP_IDX), - /* SENSOR_OV7660 6 */ + /* SENSOR_OV7660 7 */ }; static const struct v4l2_pix_format vga_mode[] = { @@ -294,6 +297,17 @@ static const u8 sn_mo4000[0x1c] = { 0x08, 0x00, 0x00, 0x00 }; +static const u8 sn_mt9v111[0x1c] = { +/* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */ + 0x00, 0x61, 0x40, 0x00, 0x1a, 0x20, 0x20, 0x20, +/* reg8 reg9 rega regb regc regd rege regf */ + 0x81, 0x5c, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, +/* reg10 reg11 reg12 reg13 reg14 reg15 reg16 reg17 */ + 0x03, 0x00, 0x00, 0x02, 0x1c, 0x28, 0x1e, 0x40, +/* reg18 reg19 reg1a reg1b */ + 0x06, 0x00, 0x00, 0x00 +}; + static const u8 sn_om6802[0x1c] = { /* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */ 0x00, 0x23, 0x72, 0x00, 0x1a, 0x34, 0x27, 0x20, @@ -343,6 +357,7 @@ static const u8 *sn_tb[] = { sn_hv7131, sn_mi0360, sn_mo4000, + sn_mt9v111, sn_om6802, sn_ov7630, sn_ov7648, @@ -396,7 +411,7 @@ static const u8 hv7131r_sensor_init[][8] = { static const u8 mi0360_sensor_init[][8] = { {0xb1, 0x5d, 0x07, 0x00, 0x02, 0x00, 0x00, 0x10}, {0xb1, 0x5d, 0x0d, 0x00, 0x01, 0x00, 0x00, 0x10}, - {0xb1, 0x5d, 0x0D, 0x00, 0x00, 0x00, 0x00, 0x10}, + {0xb1, 0x5d, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x10}, {0xd1, 0x5d, 0x01, 0x00, 0x08, 0x00, 0x16, 0x10}, {0xd1, 0x5d, 0x03, 0x01, 0xe2, 0x02, 0x82, 0x10}, {0xd1, 0x5d, 0x05, 0x00, 0x09, 0x00, 0x53, 0x10}, @@ -470,6 +485,38 @@ static const u8 mo4000_sensor_init[][8] = { {0xa1, 0x21, 0x11, 0x38, 0x00, 0x00, 0x00, 0x10}, {} }; +static const u8 mt9v111_sensor_init[][8] = { + {0xb1, 0x5c, 0x0d, 0x00, 0x01, 0x00, 0x00, 0x10}, /* reset? */ + /* delay 20 ms */ + {0xb1, 0x5c, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x10}, + {0xb1, 0x5c, 0x01, 0x00, 0x01, 0x00, 0x00, 0x10}, /* IFP select */ + {0xb1, 0x5c, 0x08, 0x04, 0x80, 0x00, 0x00, 0x10}, /* output fmt ctrl */ + {0xb1, 0x5c, 0x06, 0x00, 0x00, 0x00, 0x00, 0x10}, /* op mode ctrl */ + {0xb1, 0x5c, 0x01, 0x00, 0x04, 0x00, 0x00, 0x10}, /* sensor select */ + {0xb1, 0x5c, 0x08, 0x00, 0x08, 0x00, 0x00, 0x10}, /* row start */ + {0xb1, 0x5c, 0x02, 0x00, 0x16, 0x00, 0x00, 0x10}, /* col start */ + {0xb1, 0x5c, 0x03, 0x01, 0xe7, 0x00, 0x00, 0x10}, /* window height */ + {0xb1, 0x5c, 0x04, 0x02, 0x87, 0x00, 0x00, 0x10}, /* window width */ + {0xb1, 0x5c, 0x07, 0x30, 0x02, 0x00, 0x00, 0x10}, /* output ctrl */ + {0xb1, 0x5c, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x10}, /* shutter delay */ + {0xb1, 0x5c, 0x12, 0x00, 0xb0, 0x00, 0x00, 0x10}, /* zoom col start */ + {0xb1, 0x5c, 0x13, 0x00, 0x7c, 0x00, 0x00, 0x10}, /* zoom row start */ + {0xb1, 0x5c, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x10}, /* digital zoom */ + {0xb1, 0x5c, 0x20, 0x00, 0x00, 0x00, 0x00, 0x10}, /* read mode */ + {0xb1, 0x5c, 0x20, 0x00, 0x00, 0x00, 0x00, 0x10}, + /*******/ + {0xb1, 0x5c, 0x20, 0x00, 0x00, 0x00, 0x00, 0x10}, + {0xb1, 0x5c, 0x20, 0x00, 0x00, 0x00, 0x00, 0x10}, + {0xb1, 0x5c, 0x09, 0x00, 0x64, 0x00, 0x00, 0x10}, /* shutter width */ + {0xd1, 0x5c, 0x2b, 0x00, 0x33, 0x00, 0xa0, 0x10}, /* green1 gain */ + {0xd1, 0x5c, 0x2d, 0x00, 0xa0, 0x00, 0x33, 0x10}, /* red gain */ + /*******/ + {0xb1, 0x5c, 0x06, 0x00, 0x1e, 0x00, 0x00, 0x10}, /* vert blanking */ + {0xb1, 0x5c, 0x05, 0x00, 0x0a, 0x00, 0x00, 0x10}, /* horiz blanking */ + {0xd1, 0x5c, 0x2c, 0x00, 0xad, 0x00, 0xad, 0x10}, /* blue gain */ + {0xb1, 0x5c, 0x35, 0x01, 0xc0, 0x00, 0x00, 0x10}, /* global gain */ + {} +}; static const u8 om6802_sensor_init[][8] = { {0xa0, 0x34, 0x90, 0x05, 0x00, 0x00, 0x00, 0x10}, {0xa0, 0x34, 0x49, 0x85, 0x00, 0x00, 0x00, 0x10}, @@ -736,7 +783,7 @@ static void reg_w1(struct gspca_dev *gspca_dev, u16 value, u8 data) { - PDEBUG(D_USBO, "reg_w1 [%02x] = %02x", value, data); + PDEBUG(D_USBO, "reg_w1 [%04x] = %02x", value, data); gspca_dev->usb_buf[0] = data; usb_control_msg(gspca_dev->dev, usb_sndctrlpipe(gspca_dev->dev, 0), @@ -752,7 +799,7 @@ static void reg_w(struct gspca_dev *gspca_dev, const u8 *buffer, int len) { - PDEBUG(D_USBO, "reg_w [%02x] = %02x %02x ..", + PDEBUG(D_USBO, "reg_w [%04x] = %02x %02x ..", value, buffer[0], buffer[1]); #ifdef GSPCA_DEBUG if (len > USB_BUF_SZ) { @@ -832,7 +879,7 @@ static void i2c_r5(struct gspca_dev *gspca_dev, u8 reg) reg_r(gspca_dev, 0x0a, 5); } -static int probesensor(struct gspca_dev *gspca_dev) +static int hv7131r_probe(struct gspca_dev *gspca_dev) { i2c_w1(gspca_dev, 0x02, 0); /* sensor wakeup */ msleep(10); @@ -854,6 +901,52 @@ static int probesensor(struct gspca_dev *gspca_dev) return -ENODEV; } +static int mi0360_probe(struct gspca_dev *gspca_dev) +{ + int i, j; + u16 val; + static const u8 probe_tb[][4][8] = { + { + {0xb0, 0x5d, 0x07, 0x00, 0x02, 0x00, 0x00, 0x10}, + {0x90, 0x5d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10}, + {0xa2, 0x5d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10}, + {0xb0, 0x5d, 0x07, 0x00, 0x00, 0x00, 0x00, 0x10} + }, + { + {0xb0, 0x5c, 0x01, 0x00, 0x04, 0x00, 0x00, 0x10}, + {0x90, 0x5c, 0x36, 0x00, 0x00, 0x00, 0x00, 0x10}, + {0xa2, 0x5c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10}, + {} + }, + }; + + for (i = 0; i < ARRAY_SIZE(probe_tb); i++) { + reg_w1(gspca_dev, 0x17, 0x62); + reg_w1(gspca_dev, 0x01, 0x08); + for (j = 0; j < 3; j++) + i2c_w8(gspca_dev, probe_tb[i][j]); + msleep(2); + reg_r(gspca_dev, 0x0a, 5); + val = (gspca_dev->usb_buf[3] << 8) | gspca_dev->usb_buf[4]; + if (probe_tb[i][3][0] != 0) + i2c_w8(gspca_dev, probe_tb[i][3]); + reg_w1(gspca_dev, 0x01, 0x29); + reg_w1(gspca_dev, 0x17, 0x42); + if (val != 0xffff) + break; + } + switch (val) { + case 0x823a: + PDEBUG(D_PROBE, "Sensor mt9v111"); + return SENSOR_MT9V111; + case 0x8243: + PDEBUG(D_PROBE, "Sensor mi0360"); + return SENSOR_MI0360; + } + PDEBUG(D_PROBE, "Unknown sensor %04x - forced to mi0360", val); + return SENSOR_MI0360; +} + static int configure_gpio(struct gspca_dev *gspca_dev, const u8 *sn9c1xx) { @@ -887,6 +980,12 @@ static int configure_gpio(struct gspca_dev *gspca_dev, reg_w(gspca_dev, 0x03, &sn9c1xx[3], 0x0f); switch (sd->sensor) { + case SENSOR_MT9V111: + reg_w1(gspca_dev, 0x01, 0x61); + reg_w1(gspca_dev, 0x17, 0x61); + reg_w1(gspca_dev, 0x01, 0x60); + reg_w1(gspca_dev, 0x01, 0x40); + break; case SENSOR_OM6802: reg_w1(gspca_dev, 0x02, 0x71); reg_w1(gspca_dev, 0x01, 0x42); @@ -920,7 +1019,7 @@ static int configure_gpio(struct gspca_dev *gspca_dev, reg_w1(gspca_dev, 0x17, 0x61); reg_w1(gspca_dev, 0x01, 0x42); if (sd->sensor == SENSOR_HV7131R) { - if (probesensor(gspca_dev) < 0) + if (hv7131r_probe(gspca_dev) < 0) return -ENODEV; } break; @@ -961,6 +1060,19 @@ static void mo4000_InitSensor(struct gspca_dev *gspca_dev) } } +static void mt9v111_InitSensor(struct gspca_dev *gspca_dev) +{ + int i = 0; + + i2c_w8(gspca_dev, mt9v111_sensor_init[i]); + i++; + msleep(20); + while (mt9v111_sensor_init[i][0]) { + i2c_w8(gspca_dev, mt9v111_sensor_init[i]); + i++; + } +} + static void om6802_InitSensor(struct gspca_dev *gspca_dev) { int i = 0; @@ -1078,11 +1190,21 @@ static int sd_init(struct gspca_dev *gspca_dev) case BRIDGE_SN9C105: if (regF1 != 0x11) return -ENODEV; + if (sd->sensor == SENSOR_MI0360) { + sd->sensor = mi0360_probe(gspca_dev); + if (sd->sensor == SENSOR_MT9V111) + sd->i2c_base = 0x5c; + } reg_w(gspca_dev, 0x01, regGpio, 2); break; case BRIDGE_SN9C120: if (regF1 != 0x12) return -ENODEV; + if (sd->sensor == SENSOR_MI0360) { + sd->sensor = mi0360_probe(gspca_dev); + if (sd->sensor == SENSOR_MT9V111) + sd->i2c_base = 0x5c; + } regGpio[1] = 0x70; reg_w(gspca_dev, 0x01, regGpio, 2); break; @@ -1117,7 +1239,7 @@ static u32 setexposure(struct gspca_dev *gspca_dev, break; } case SENSOR_MI0360: { - u8 expoMi[] = /* exposure 0x0635 -> 4 fp/s 0x10 */ + u8 expoMi[] = /* exposure 0x0635 -> 4 fp/s 0x10 */ { 0xb1, 0x5d, 0x09, 0x06, 0x35, 0x00, 0x00, 0x16 }; static const u8 doit[] = /* update sensor */ { 0xb1, 0x5d, 0x07, 0x00, 0x03, 0x00, 0x00, 0x10 }; @@ -1153,12 +1275,25 @@ static u32 setexposure(struct gspca_dev *gspca_dev, | ((expo & 0x0003) << 4); i2c_w8(gspca_dev, expoMo10); i2c_w8(gspca_dev, gainMo); - PDEBUG(D_CONF, "set exposure %d", + PDEBUG(D_FRAM, "set exposure %d", ((expoMo10[3] & 0x07) << 10) | (expoMof[3] << 2) | ((expoMo10[3] & 0x30) >> 4)); break; } + case SENSOR_MT9V111: { + u8 expo_c1[] = + { 0xb1, 0x5c, 0x09, 0x00, 0x00, 0x00, 0x00, 0x10 }; + + if (expo > 0x0280) + expo = 0x0280; + else if (expo < 0x0040) + expo = 0x0040; + expo_c1[3] = expo >> 8; + expo_c1[4] = expo; + i2c_w8(gspca_dev, expo_c1); + break; + } case SENSOR_OM6802: { u8 gainOm[] = { 0xa0, 0x34, 0xe5, 0x00, 0x00, 0x00, 0x00, 0x10 }; @@ -1170,7 +1305,7 @@ static u32 setexposure(struct gspca_dev *gspca_dev, gainOm[3] = expo >> 2; i2c_w8(gspca_dev, gainOm); reg_w1(gspca_dev, 0x96, (expo >> 5) & 0x1f); - PDEBUG(D_CONF, "set exposure %d", gainOm[3]); + PDEBUG(D_FRAM, "set exposure %d", gainOm[3]); break; } } @@ -1198,6 +1333,10 @@ static void setbrightness(struct gspca_dev *gspca_dev) expo = sd->brightness >> 4; sd->exposure = setexposure(gspca_dev, expo); break; + case SENSOR_MT9V111: + expo = sd->brightness >> 8; + sd->exposure = setexposure(gspca_dev, expo); + break; case SENSOR_OM6802: expo = sd->brightness >> 6; sd->exposure = setexposure(gspca_dev, expo); @@ -1205,7 +1344,8 @@ static void setbrightness(struct gspca_dev *gspca_dev) break; } - reg_w1(gspca_dev, 0x96, k2); /* color matrix Y offset */ + if (sd->sensor != SENSOR_MT9V111) + reg_w1(gspca_dev, 0x96, k2); /* color matrix Y offset */ } static void setcontrast(struct gspca_dev *gspca_dev) @@ -1322,6 +1462,9 @@ static int sd_start(struct gspca_dev *gspca_dev) reg_w1(gspca_dev, 0xc9, 0x3c); reg_w1(gspca_dev, 0x18, sn9c1xx[0x18]); switch (sd->sensor) { + case SENSOR_MT9V111: + reg17 = 0xe0; + break; case SENSOR_OV7630: reg17 = 0xe2; break; @@ -1349,6 +1492,10 @@ static int sd_start(struct gspca_dev *gspca_dev) for (i = 0; i < 8; i++) reg_w(gspca_dev, 0x84, reg84, sizeof reg84); switch (sd->sensor) { + case SENSOR_MT9V111: + reg_w1(gspca_dev, 0x9a, 0x07); + reg_w1(gspca_dev, 0x99, 0x59); + break; case SENSOR_OV7648: reg_w1(gspca_dev, 0x9a, 0x0a); reg_w1(gspca_dev, 0x99, 0x60); @@ -1388,6 +1535,14 @@ static int sd_start(struct gspca_dev *gspca_dev) /* reg1 = 0x06; * 640 clk 24Mz (done) */ } break; + case SENSOR_MT9V111: + mt9v111_InitSensor(gspca_dev); + if (mode) { + reg1 = 0x04; /* 320 clk 48Mhz */ + } else { +/* reg1 = 0x06; * 640 clk 24Mz (done) */ + reg17 = 0xe2; + } case SENSOR_OM6802: om6802_InitSensor(gspca_dev); reg17 = 0x64; /* 640 MCKSIZE */ @@ -1436,17 +1591,14 @@ static int sd_start(struct gspca_dev *gspca_dev) reg18 = sn9c1xx[0x18] | (mode << 4); reg_w1(gspca_dev, 0x18, reg18 | 0x40); - reg_w(gspca_dev, 0x100, qtable4, 0x40); - reg_w(gspca_dev, 0x140, qtable4 + 0x40, 0x40); + reg_w(gspca_dev, 0x0100, qtable4, 0x40); + reg_w(gspca_dev, 0x0140, qtable4 + 0x40, 0x40); reg_w1(gspca_dev, 0x18, reg18); reg_w1(gspca_dev, 0x17, reg17); reg_w1(gspca_dev, 0x01, reg1); switch (sd->sensor) { - case SENSOR_MI0360: - setinfrared(sd); - break; case SENSOR_OV7630: setvflip(sd); break; @@ -1482,6 +1634,7 @@ static void sd_stopN(struct gspca_dev *gspca_dev) case SENSOR_OV7648: i2c_w8(gspca_dev, stopov7648); /* fall thru */ + case SENSOR_MT9V111: case SENSOR_OV7630: data = 0x29; break; @@ -1529,6 +1682,7 @@ static void do_autogain(struct gspca_dev *gspca_dev) default: /* case SENSOR_MO4000: */ /* case SENSOR_MI0360: */ +/* case SENSOR_MT9V111: */ /* case SENSOR_OM6802: */ expotimes = sd->exposure; expotimes += (luma_mean - delta) >> 6; @@ -1785,7 +1939,7 @@ static const __devinitdata struct usb_device_id device_table[] = { /* {USB_DEVICE(0x0c45, 0x607a), BSI(SN9C102P, OV7648, 0x??)}, */ {USB_DEVICE(0x0c45, 0x607c), BSI(SN9C102P, HV7131R, 0x11)}, /* {USB_DEVICE(0x0c45, 0x607e), BSI(SN9C102P, OV7630, 0x??)}, */ - {USB_DEVICE(0x0c45, 0x60c0), BSI(SN9C105, MI0360, 0x5d)}, + {USB_DEVICE(0x0c45, 0x60c0), BSI(SN9C105, MT9V111, 0x5c)}, /* {USB_DEVICE(0x0c45, 0x60c8), BSI(SN9C105, OM6801, 0x??)}, */ /* {USB_DEVICE(0x0c45, 0x60cc), BSI(SN9C105, HV7131GP, 0x??)}, */ {USB_DEVICE(0x0c45, 0x60ec), BSI(SN9C105, MO4000, 0x21)}, -- cgit v1.2.3 From a92e9064bb2fbbc09fc1e70fc5d2e4b6ab8be9e8 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Thu, 29 Jan 2009 05:32:23 -0300 Subject: V4L/DVB (10420): gspca - vc032x: Webcam 041e:405b added and mi1310_soc updated. The mi1310_soc sequences come from the ms-win driver C0130Dev.inf. Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/vc032x.c | 372 +++++++++++++++++++------------------ 1 file changed, 188 insertions(+), 184 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/gspca/vc032x.c b/drivers/media/video/gspca/vc032x.c index ab3108000756..1b34906ac1b9 100644 --- a/drivers/media/video/gspca/vc032x.c +++ b/drivers/media/video/gspca/vc032x.c @@ -400,92 +400,208 @@ static const __u8 mi0360_initQVGA_JPG[][4] = { static const __u8 mi1310_socinitVGA_JPG[][4] = { {0xb0, 0x03, 0x19, 0xcc}, {0xb0, 0x04, 0x02, 0xcc}, - {0xb3, 0x00, 0x64, 0xcc}, - {0xb3, 0x00, 0x65, 0xcc}, - {0xb3, 0x05, 0x00, 0xcc}, - {0xb3, 0x06, 0x00, 0xcc}, + {0xb3, 0x00, 0x24, 0xcc}, + {0xb3, 0x00, 0x25, 0xcc}, + {0xb3, 0x05, 0x01, 0xcc}, + {0xb3, 0x06, 0x03, 0xcc}, + {0xb3, 0x5c, 0x01, 0xcc}, {0xb3, 0x08, 0x01, 0xcc}, {0xb3, 0x09, 0x0c, 0xcc}, {0xb3, 0x34, 0x02, 0xcc}, {0xb3, 0x35, 0xdd, 0xcc}, - {0xb3, 0x02, 0x00, 0xcc}, {0xb3, 0x03, 0x0a, 0xcc}, - {0xb3, 0x04, 0x05, 0xcc}, + {0xb3, 0x04, 0x0d, 0xcc}, {0xb3, 0x20, 0x00, 0xcc}, {0xb3, 0x21, 0x00, 0xcc}, - {0xb3, 0x22, 0x03, 0xcc}, - {0xb3, 0x23, 0xc0, 0xcc}, + {0xb3, 0x22, 0x01, 0xcc}, + {0xb3, 0x23, 0xe0, 0xcc}, {0xb3, 0x14, 0x00, 0xcc}, {0xb3, 0x15, 0x00, 0xcc}, - {0xb3, 0x16, 0x04, 0xcc}, - {0xb3, 0x17, 0xff, 0xcc}, - {0xb3, 0x00, 0x65, 0xcc}, - {0xb8, 0x00, 0x00, 0xcc}, - {0xbc, 0x00, 0xd0, 0xcc}, - {0xbc, 0x01, 0x01, 0xcc}, - {0xf0, 0x00, 0x02, 0xbb}, - {0xc8, 0x9f, 0x0b, 0xbb}, - {0x5b, 0x00, 0x01, 0xbb}, - {0x2f, 0xde, 0x20, 0xbb}, + {0xb3, 0x16, 0x02, 0xcc}, + {0xb3, 0x17, 0x7f, 0xcc}, + {0xb8, 0x01, 0x7d, 0xcc}, + {0xb8, 0x81, 0x09, 0xcc}, + {0xb8, 0x27, 0x20, 0xcc}, + {0xb8, 0x26, 0x80, 0xcc}, + {0xb3, 0x00, 0x25, 0xcc}, + {0xb8, 0x00, 0x13, 0xcc}, + {0xbc, 0x00, 0x71, 0xcc}, + {0xb8, 0x81, 0x01, 0xcc}, + {0xb8, 0x2c, 0x5a, 0xcc}, + {0xb8, 0x2d, 0xff, 0xcc}, + {0xb8, 0x2e, 0xee, 0xcc}, + {0xb8, 0x2f, 0xfb, 0xcc}, + {0xb8, 0x30, 0x52, 0xcc}, + {0xb8, 0x31, 0xf8, 0xcc}, + {0xb8, 0x32, 0xf1, 0xcc}, + {0xb8, 0x33, 0xff, 0xcc}, + {0xb8, 0x34, 0x54, 0xcc}, + {0xb8, 0x35, 0x00, 0xcc}, + {0xb8, 0x36, 0x00, 0xcc}, + {0xb8, 0x37, 0x00, 0xcc}, {0xf0, 0x00, 0x00, 0xbb}, - {0x20, 0x03, 0x02, 0xbb}, + {0x00, 0x01, 0x00, 0xdd}, + {0x0d, 0x00, 0x09, 0xbb}, + {0x0d, 0x00, 0x08, 0xbb}, {0xf0, 0x00, 0x01, 0xbb}, - {0x05, 0x00, 0x07, 0xbb}, - {0x34, 0x00, 0x00, 0xbb}, - {0x35, 0xff, 0x00, 0xbb}, - {0xdc, 0x07, 0x02, 0xbb}, - {0xdd, 0x3c, 0x18, 0xbb}, - {0xde, 0x92, 0x6d, 0xbb}, - {0xdf, 0xcd, 0xb1, 0xbb}, - {0xe0, 0xff, 0xe7, 0xbb}, - {0x06, 0xf0, 0x0d, 0xbb}, - {0x06, 0x70, 0x0e, 0xbb}, - {0x4c, 0x00, 0x01, 0xbb}, - {0x4d, 0x00, 0x01, 0xbb}, - {0xf0, 0x00, 0x02, 0xbb}, - {0x2e, 0x0c, 0x55, 0xbb}, - {0x21, 0xb6, 0x6e, 0xbb}, - {0x36, 0x30, 0x10, 0xbb}, - {0x37, 0x00, 0xc1, 0xbb}, + {0x00, 0x01, 0x00, 0xdd}, + {0x06, 0x00, 0x14, 0xbb}, + {0x3a, 0x10, 0x00, 0xbb}, + {0x00, 0x00, 0x10, 0xdd}, + {0x9b, 0x10, 0x00, 0xbb}, + {0x00, 0x00, 0x10, 0xdd}, {0xf0, 0x00, 0x00, 0xbb}, - {0x07, 0x00, 0x84, 0xbb}, - {0x08, 0x02, 0x4a, 0xbb}, - {0x05, 0x01, 0x10, 0xbb}, - {0x06, 0x00, 0x39, 0xbb}, - {0xf0, 0x00, 0x02, 0xbb}, - {0x58, 0x02, 0x67, 0xbb}, - {0x57, 0x02, 0x00, 0xbb}, - {0x5a, 0x02, 0x67, 0xbb}, - {0x59, 0x02, 0x00, 0xbb}, - {0x5c, 0x12, 0x0d, 0xbb}, - {0x5d, 0x16, 0x11, 0xbb}, - {0x39, 0x06, 0x18, 0xbb}, - {0x3a, 0x06, 0x18, 0xbb}, - {0x3b, 0x06, 0x18, 0xbb}, - {0x3c, 0x06, 0x18, 0xbb}, - {0x64, 0x7b, 0x5b, 0xbb}, - {0xf0, 0x00, 0x02, 0xbb}, - {0x36, 0x30, 0x10, 0xbb}, - {0x37, 0x00, 0xc0, 0xbb}, - {0xbc, 0x0e, 0x00, 0xcc}, - {0xbc, 0x0f, 0x05, 0xcc}, - {0xbc, 0x10, 0xc0, 0xcc}, - {0xbc, 0x11, 0x03, 0xcc}, + {0x00, 0x01, 0x00, 0xdd}, + {0x2b, 0x00, 0x28, 0xbb}, + {0x2c, 0x00, 0x30, 0xbb}, + {0x2d, 0x00, 0x30, 0xbb}, + {0x2e, 0x00, 0x28, 0xbb}, + {0x41, 0x00, 0xd7, 0xbb}, + {0x09, 0x02, 0x3a, 0xbb}, + {0x0c, 0x00, 0x00, 0xbb}, + {0x20, 0x00, 0x00, 0xbb}, + {0x05, 0x00, 0x8c, 0xbb}, + {0x06, 0x00, 0x32, 0xbb}, + {0x07, 0x00, 0xc6, 0xbb}, + {0x08, 0x00, 0x19, 0xbb}, + {0x24, 0x80, 0x6f, 0xbb}, + {0xc8, 0x00, 0x0f, 0xbb}, + {0x20, 0x00, 0x0f, 0xbb}, {0xb6, 0x00, 0x00, 0xcc}, {0xb6, 0x03, 0x02, 0xcc}, {0xb6, 0x02, 0x80, 0xcc}, {0xb6, 0x05, 0x01, 0xcc}, {0xb6, 0x04, 0xe0, 0xcc}, - {0xb6, 0x12, 0xf8, 0xcc}, - {0xb6, 0x13, 0x25, 0xcc}, + {0xb6, 0x12, 0x78, 0xcc}, {0xb6, 0x18, 0x02, 0xcc}, {0xb6, 0x17, 0x58, 0xcc}, {0xb6, 0x16, 0x00, 0xcc}, {0xb6, 0x22, 0x12, 0xcc}, {0xb6, 0x23, 0x0b, 0xcc}, + {0xb3, 0x02, 0x02, 0xcc}, {0xbf, 0xc0, 0x39, 0xcc}, {0xbf, 0xc1, 0x04, 0xcc}, - {0xbf, 0xcc, 0x00, 0xcc}, + {0xbf, 0xcc, 0x10, 0xcc}, + {0xb9, 0x12, 0x00, 0xcc}, + {0xb9, 0x13, 0x0a, 0xcc}, + {0xb9, 0x14, 0x0a, 0xcc}, + {0xb9, 0x15, 0x0a, 0xcc}, + {0xb9, 0x16, 0x0a, 0xcc}, + {0xb9, 0x18, 0x00, 0xcc}, + {0xb9, 0x19, 0x0f, 0xcc}, + {0xb9, 0x1a, 0x0f, 0xcc}, + {0xb9, 0x1b, 0x0f, 0xcc}, + {0xb9, 0x1c, 0x0f, 0xcc}, + {0xb8, 0x8e, 0x00, 0xcc}, + {0xb8, 0x8f, 0xff, 0xcc}, + {0xb3, 0x01, 0x41, 0xcc}, + {0x03, 0x03, 0xc0, 0xbb}, + {0x06, 0x00, 0x10, 0xbb}, + {0xb6, 0x12, 0xf8, 0xcc}, + {0xb8, 0x0c, 0x20, 0xcc}, + {0xb8, 0x0d, 0x70, 0xcc}, + {0xb6, 0x13, 0x13, 0xcc}, + {0x2f, 0x00, 0xC0, 0xbb}, + {0xb8, 0xa0, 0x12, 0xcc}, + {}, +}; +static const __u8 mi1310_socinitQVGA_JPG[][4] = { + {0xb0, 0x03, 0x19, 0xcc}, + {0xb0, 0x04, 0x02, 0xcc}, + {0xb3, 0x00, 0x24, 0xcc}, + {0xb3, 0x00, 0x25, 0xcc}, + {0xb3, 0x05, 0x01, 0xcc}, + {0xb3, 0x06, 0x03, 0xcc}, + {0xb3, 0x5c, 0x01, 0xcc}, + {0xb3, 0x08, 0x01, 0xcc}, + {0xb3, 0x09, 0x0c, 0xcc}, + {0xb3, 0x34, 0x02, 0xcc}, + {0xb3, 0x35, 0xdd, 0xcc}, + {0xb3, 0x03, 0x0a, 0xcc}, + {0xb3, 0x04, 0x0d, 0xcc}, + {0xb3, 0x20, 0x00, 0xcc}, + {0xb3, 0x21, 0x00, 0xcc}, + {0xb3, 0x22, 0x01, 0xcc}, + {0xb3, 0x23, 0xe0, 0xcc}, + {0xb3, 0x14, 0x00, 0xcc}, + {0xb3, 0x15, 0x00, 0xcc}, + {0xb3, 0x16, 0x02, 0xcc}, + {0xb3, 0x17, 0x7f, 0xcc}, + {0xb8, 0x01, 0x7d, 0xcc}, + {0xb8, 0x81, 0x09, 0xcc}, + {0xb8, 0x27, 0x20, 0xcc}, + {0xb8, 0x26, 0x80, 0xcc}, + {0xb3, 0x00, 0x25, 0xcc}, + {0xb8, 0x00, 0x13, 0xcc}, + {0xbc, 0x00, 0xd1, 0xcc}, + {0xb8, 0x81, 0x01, 0xcc}, + {0xb8, 0x2c, 0x5a, 0xcc}, + {0xb8, 0x2d, 0xff, 0xcc}, + {0xb8, 0x2e, 0xee, 0xcc}, + {0xb8, 0x2f, 0xfb, 0xcc}, + {0xb8, 0x30, 0x52, 0xcc}, + {0xb8, 0x31, 0xf8, 0xcc}, + {0xb8, 0x32, 0xf1, 0xcc}, + {0xb8, 0x33, 0xff, 0xcc}, + {0xb8, 0x34, 0x54, 0xcc}, + {0xb8, 0x35, 0x00, 0xcc}, + {0xb8, 0x36, 0x00, 0xcc}, + {0xb8, 0x37, 0x00, 0xcc}, + {0xf0, 0x00, 0x00, 0xbb}, + {0x00, 0x01, 0x00, 0xdd}, + {0x0d, 0x00, 0x09, 0xbb}, + {0x0d, 0x00, 0x08, 0xbb}, + {0xf0, 0x00, 0x01, 0xbb}, + {0x00, 0x01, 0x00, 0xdd}, + {0x06, 0x00, 0x14, 0xbb}, + {0x3a, 0x10, 0x00, 0xbb}, + {0x00, 0x00, 0x10, 0xdd}, + {0x9b, 0x10, 0x00, 0xbb}, + {0x00, 0x00, 0x10, 0xdd}, + {0xf0, 0x00, 0x00, 0xbb}, + {0x00, 0x01, 0x00, 0xdd}, + {0x2b, 0x00, 0x28, 0xbb}, + {0x2c, 0x00, 0x30, 0xbb}, + {0x2d, 0x00, 0x30, 0xbb}, + {0x2e, 0x00, 0x28, 0xbb}, + {0x41, 0x00, 0xd7, 0xbb}, + {0x09, 0x02, 0x3a, 0xbb}, + {0x0c, 0x00, 0x00, 0xbb}, + {0x20, 0x00, 0x00, 0xbb}, + {0x05, 0x00, 0x8c, 0xbb}, + {0x06, 0x00, 0x32, 0xbb}, + {0x07, 0x00, 0xc6, 0xbb}, + {0x08, 0x00, 0x19, 0xbb}, + {0x24, 0x80, 0x6f, 0xbb}, + {0xc8, 0x00, 0x0f, 0xbb}, + {0x20, 0x00, 0x0f, 0xbb}, + {0xb6, 0x00, 0x00, 0xcc}, + {0xb6, 0x03, 0x01, 0xcc}, + {0xb6, 0x02, 0x40, 0xcc}, + {0xb6, 0x05, 0x00, 0xcc}, + {0xb6, 0x04, 0xf0, 0xcc}, + {0xb6, 0x12, 0x78, 0xcc}, + {0xb6, 0x18, 0x00, 0xcc}, + {0xb6, 0x17, 0x96, 0xcc}, + {0xb6, 0x16, 0x00, 0xcc}, + {0xb6, 0x22, 0x12, 0xcc}, + {0xb6, 0x23, 0x0b, 0xcc}, + {0xb3, 0x02, 0x02, 0xcc}, + {0xbf, 0xc0, 0x39, 0xcc}, + {0xbf, 0xc1, 0x04, 0xcc}, + {0xbf, 0xcc, 0x10, 0xcc}, + {0xb9, 0x12, 0x00, 0xcc}, + {0xb9, 0x13, 0x0a, 0xcc}, + {0xb9, 0x14, 0x0a, 0xcc}, + {0xb9, 0x15, 0x0a, 0xcc}, + {0xb9, 0x16, 0x0a, 0xcc}, + {0xb9, 0x18, 0x00, 0xcc}, + {0xb9, 0x19, 0x0f, 0xcc}, + {0xb9, 0x1a, 0x0f, 0xcc}, + {0xb9, 0x1b, 0x0f, 0xcc}, + {0xb9, 0x1c, 0x0f, 0xcc}, + {0xb8, 0x8e, 0x00, 0xcc}, + {0xb8, 0x8f, 0xff, 0xcc}, {0xbc, 0x02, 0x18, 0xcc}, {0xbc, 0x03, 0x50, 0xcc}, {0xbc, 0x04, 0x18, 0xcc}, @@ -496,130 +612,15 @@ static const __u8 mi1310_socinitVGA_JPG[][4] = { {0xbc, 0x0a, 0x10, 0xcc}, {0xbc, 0x0b, 0x00, 0xcc}, {0xbc, 0x0c, 0x00, 0xcc}, - {0xb3, 0x5c, 0x01, 0xcc}, - {0xf0, 0x00, 0x01, 0xbb}, - {0x80, 0x00, 0x03, 0xbb}, - {0x81, 0xc7, 0x14, 0xbb}, - {0x82, 0xeb, 0xe8, 0xbb}, - {0x83, 0xfe, 0xf4, 0xbb}, - {0x84, 0xcd, 0x10, 0xbb}, - {0x85, 0xf3, 0xee, 0xbb}, - {0x86, 0xff, 0xf1, 0xbb}, - {0x87, 0xcd, 0x10, 0xbb}, - {0x88, 0xf3, 0xee, 0xbb}, - {0x89, 0x01, 0xf1, 0xbb}, - {0x8a, 0xe5, 0x17, 0xbb}, - {0x8b, 0xe8, 0xe2, 0xbb}, - {0x8c, 0xf7, 0xed, 0xbb}, - {0x8d, 0x00, 0xff, 0xbb}, - {0x8e, 0xec, 0x10, 0xbb}, - {0x8f, 0xf0, 0xed, 0xbb}, - {0x90, 0xf9, 0xf2, 0xbb}, - {0x91, 0x00, 0x00, 0xbb}, - {0x92, 0xe9, 0x0d, 0xbb}, - {0x93, 0xf4, 0xf2, 0xbb}, - {0x94, 0xfb, 0xf5, 0xbb}, - {0x95, 0x00, 0xff, 0xbb}, - {0xb6, 0x0f, 0x08, 0xbb}, - {0xb7, 0x3d, 0x16, 0xbb}, - {0xb8, 0x0c, 0x04, 0xbb}, - {0xb9, 0x1c, 0x07, 0xbb}, - {0xba, 0x0a, 0x03, 0xbb}, - {0xbb, 0x1b, 0x09, 0xbb}, - {0xbc, 0x17, 0x0d, 0xbb}, - {0xbd, 0x23, 0x1d, 0xbb}, - {0xbe, 0x00, 0x28, 0xbb}, - {0xbf, 0x11, 0x09, 0xbb}, - {0xc0, 0x16, 0x15, 0xbb}, - {0xc1, 0x00, 0x1b, 0xbb}, - {0xc2, 0x0e, 0x07, 0xbb}, - {0xc3, 0x14, 0x10, 0xbb}, - {0xc4, 0x00, 0x17, 0xbb}, - {0x06, 0x74, 0x8e, 0xbb}, - {0xf0, 0x00, 0x01, 0xbb}, - {0x06, 0xf4, 0x8e, 0xbb}, - {0x00, 0x00, 0x50, 0xdd}, - {0x06, 0x74, 0x8e, 0xbb}, - {0xf0, 0x00, 0x02, 0xbb}, - {0x24, 0x50, 0x20, 0xbb}, - {0xf0, 0x00, 0x02, 0xbb}, - {0x34, 0x0c, 0x50, 0xbb}, {0xb3, 0x01, 0x41, 0xcc}, - {0xf0, 0x00, 0x00, 0xbb}, - {0x03, 0x03, 0xc0, 0xbb}, - {}, -}; -static const __u8 mi1310_socinitQVGA_JPG[][4] = { - {0xb0, 0x03, 0x19, 0xcc}, {0xb0, 0x04, 0x02, 0xcc}, - {0xb3, 0x00, 0x64, 0xcc}, {0xb3, 0x00, 0x65, 0xcc}, - {0xb3, 0x05, 0x00, 0xcc}, {0xb3, 0x06, 0x00, 0xcc}, - {0xb3, 0x08, 0x01, 0xcc}, {0xb3, 0x09, 0x0c, 0xcc}, - {0xb3, 0x34, 0x02, 0xcc}, {0xb3, 0x35, 0xdd, 0xcc}, - {0xb3, 0x02, 0x00, 0xcc}, {0xb3, 0x03, 0x0a, 0xcc}, - {0xb3, 0x04, 0x05, 0xcc}, {0xb3, 0x20, 0x00, 0xcc}, - {0xb3, 0x21, 0x00, 0xcc}, {0xb3, 0x22, 0x03, 0xcc}, - {0xb3, 0x23, 0xc0, 0xcc}, {0xb3, 0x14, 0x00, 0xcc}, - {0xb3, 0x15, 0x00, 0xcc}, {0xb3, 0x16, 0x04, 0xcc}, - {0xb3, 0x17, 0xff, 0xcc}, {0xb3, 0x00, 0x65, 0xcc}, - {0xb8, 0x00, 0x00, 0xcc}, {0xbc, 0x00, 0xf0, 0xcc}, - {0xbc, 0x01, 0x01, 0xcc}, {0xf0, 0x00, 0x02, 0xbb}, - {0xc8, 0x9f, 0x0b, 0xbb}, {0x5b, 0x00, 0x01, 0xbb}, - {0x2f, 0xde, 0x20, 0xbb}, {0xf0, 0x00, 0x00, 0xbb}, - {0x20, 0x03, 0x02, 0xbb}, {0xf0, 0x00, 0x01, 0xbb}, - {0x05, 0x00, 0x07, 0xbb}, {0x34, 0x00, 0x00, 0xbb}, - {0x35, 0xff, 0x00, 0xbb}, {0xdc, 0x07, 0x02, 0xbb}, - {0xdd, 0x3c, 0x18, 0xbb}, {0xde, 0x92, 0x6d, 0xbb}, - {0xdf, 0xcd, 0xb1, 0xbb}, {0xe0, 0xff, 0xe7, 0xbb}, - {0x06, 0xf0, 0x0d, 0xbb}, {0x06, 0x70, 0x0e, 0xbb}, - {0x4c, 0x00, 0x01, 0xbb}, {0x4d, 0x00, 0x01, 0xbb}, - {0xf0, 0x00, 0x02, 0xbb}, {0x2e, 0x0c, 0x55, 0xbb}, - {0x21, 0xb6, 0x6e, 0xbb}, {0x36, 0x30, 0x10, 0xbb}, - {0x37, 0x00, 0xc1, 0xbb}, {0xf0, 0x00, 0x00, 0xbb}, - {0x07, 0x00, 0x84, 0xbb}, {0x08, 0x02, 0x4a, 0xbb}, - {0x05, 0x01, 0x10, 0xbb}, {0x06, 0x00, 0x39, 0xbb}, - {0xf0, 0x00, 0x02, 0xbb}, {0x58, 0x02, 0x67, 0xbb}, - {0x57, 0x02, 0x00, 0xbb}, {0x5a, 0x02, 0x67, 0xbb}, - {0x59, 0x02, 0x00, 0xbb}, {0x5c, 0x12, 0x0d, 0xbb}, - {0x5d, 0x16, 0x11, 0xbb}, {0x39, 0x06, 0x18, 0xbb}, - {0x3a, 0x06, 0x18, 0xbb}, {0x3b, 0x06, 0x18, 0xbb}, - {0x3c, 0x06, 0x18, 0xbb}, {0x64, 0x7b, 0x5b, 0xbb}, - {0xf0, 0x00, 0x02, 0xbb}, {0x36, 0x30, 0x10, 0xbb}, - {0x37, 0x00, 0xc0, 0xbb}, {0xbc, 0x0e, 0x00, 0xcc}, - {0xbc, 0x0f, 0x05, 0xcc}, {0xbc, 0x10, 0xc0, 0xcc}, - {0xbc, 0x11, 0x03, 0xcc}, {0xb6, 0x00, 0x00, 0xcc}, - {0xb6, 0x03, 0x01, 0xcc}, {0xb6, 0x02, 0x40, 0xcc}, - {0xb6, 0x05, 0x00, 0xcc}, {0xb6, 0x04, 0xf0, 0xcc}, - {0xb6, 0x12, 0xf8, 0xcc}, {0xb6, 0x13, 0x25, 0xcc}, - {0xb6, 0x18, 0x00, 0xcc}, {0xb6, 0x17, 0x96, 0xcc}, - {0xb6, 0x16, 0x00, 0xcc}, {0xb6, 0x22, 0x12, 0xcc}, - {0xb6, 0x23, 0x0b, 0xcc}, {0xbf, 0xc0, 0x39, 0xcc}, - {0xbf, 0xc1, 0x04, 0xcc}, {0xbf, 0xcc, 0x00, 0xcc}, - {0xb3, 0x5c, 0x01, 0xcc}, {0xf0, 0x00, 0x01, 0xbb}, - {0x80, 0x00, 0x03, 0xbb}, {0x81, 0xc7, 0x14, 0xbb}, - {0x82, 0xeb, 0xe8, 0xbb}, {0x83, 0xfe, 0xf4, 0xbb}, - {0x84, 0xcd, 0x10, 0xbb}, {0x85, 0xf3, 0xee, 0xbb}, - {0x86, 0xff, 0xf1, 0xbb}, {0x87, 0xcd, 0x10, 0xbb}, - {0x88, 0xf3, 0xee, 0xbb}, {0x89, 0x01, 0xf1, 0xbb}, - {0x8a, 0xe5, 0x17, 0xbb}, {0x8b, 0xe8, 0xe2, 0xbb}, - {0x8c, 0xf7, 0xed, 0xbb}, {0x8d, 0x00, 0xff, 0xbb}, - {0x8e, 0xec, 0x10, 0xbb}, {0x8f, 0xf0, 0xed, 0xbb}, - {0x90, 0xf9, 0xf2, 0xbb}, {0x91, 0x00, 0x00, 0xbb}, - {0x92, 0xe9, 0x0d, 0xbb}, {0x93, 0xf4, 0xf2, 0xbb}, - {0x94, 0xfb, 0xf5, 0xbb}, {0x95, 0x00, 0xff, 0xbb}, - {0xb6, 0x0f, 0x08, 0xbb}, {0xb7, 0x3d, 0x16, 0xbb}, - {0xb8, 0x0c, 0x04, 0xbb}, {0xb9, 0x1c, 0x07, 0xbb}, - {0xba, 0x0a, 0x03, 0xbb}, {0xbb, 0x1b, 0x09, 0xbb}, - {0xbc, 0x17, 0x0d, 0xbb}, {0xbd, 0x23, 0x1d, 0xbb}, - {0xbe, 0x00, 0x28, 0xbb}, {0xbf, 0x11, 0x09, 0xbb}, - {0xc0, 0x16, 0x15, 0xbb}, {0xc1, 0x00, 0x1b, 0xbb}, - {0xc2, 0x0e, 0x07, 0xbb}, {0xc3, 0x14, 0x10, 0xbb}, - {0xc4, 0x00, 0x17, 0xbb}, {0x06, 0x74, 0x8e, 0xbb}, - {0xf0, 0x00, 0x01, 0xbb}, {0x06, 0xf4, 0x8e, 0xbb}, - {0x00, 0x00, 0x50, 0xdd}, {0x06, 0x74, 0x8e, 0xbb}, - {0xf0, 0x00, 0x02, 0xbb}, {0x24, 0x50, 0x20, 0xbb}, - {0xf0, 0x00, 0x02, 0xbb}, {0x34, 0x0c, 0x50, 0xbb}, - {0xb3, 0x01, 0x41, 0xcc}, {0xf0, 0x00, 0x00, 0xbb}, {0x03, 0x03, 0xc0, 0xbb}, + {0x06, 0x00, 0x10, 0xbb}, + {0xb6, 0x12, 0xf8, 0xcc}, + {0xb8, 0x0c, 0x20, 0xcc}, + {0xb8, 0x0d, 0x70, 0xcc}, + {0xb6, 0x13, 0x13, 0xcc}, + {0x2f, 0x00, 0xC0, 0xbb}, + {0xb8, 0xa0, 0x12, 0xcc}, {}, }; @@ -2182,6 +2183,8 @@ static int sd_start(struct gspca_dev *gspca_dev) } break; case SENSOR_MI1310_SOC: + GammaT = mi1320_gamma; + MatrixT = mi0360_matrix; if (mode) { /* 320x240 */ usb_exchange(gspca_dev, mi1310_socinitQVGA_JPG); @@ -2423,6 +2426,7 @@ static const struct sd_desc sd_desc = { /* -- module initialisation -- */ static const __devinitdata struct usb_device_id device_table[] = { + {USB_DEVICE(0x041e, 0x405b), .driver_info = BRIDGE_VC0321}, {USB_DEVICE(0x046d, 0x0892), .driver_info = BRIDGE_VC0321}, {USB_DEVICE(0x046d, 0x0896), .driver_info = BRIDGE_VC0321}, {USB_DEVICE(0x046d, 0x0897), .driver_info = BRIDGE_VC0321}, -- cgit v1.2.3 From 661ab25d6f44a98ecf3a23ab37721ec83b2986cc Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Thu, 29 Jan 2009 16:03:19 -0300 Subject: V4L/DVB (10423): gspca - sonixj: Bad sensor definition of the webcams 0c45:60c0. Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/sonixj.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/gspca/sonixj.c b/drivers/media/video/gspca/sonixj.c index 74d2aca390b3..325b71df96ff 100644 --- a/drivers/media/video/gspca/sonixj.c +++ b/drivers/media/video/gspca/sonixj.c @@ -1939,7 +1939,7 @@ static const __devinitdata struct usb_device_id device_table[] = { /* {USB_DEVICE(0x0c45, 0x607a), BSI(SN9C102P, OV7648, 0x??)}, */ {USB_DEVICE(0x0c45, 0x607c), BSI(SN9C102P, HV7131R, 0x11)}, /* {USB_DEVICE(0x0c45, 0x607e), BSI(SN9C102P, OV7630, 0x??)}, */ - {USB_DEVICE(0x0c45, 0x60c0), BSI(SN9C105, MT9V111, 0x5c)}, + {USB_DEVICE(0x0c45, 0x60c0), BSI(SN9C105, MI0360, 0x5d)}, /* {USB_DEVICE(0x0c45, 0x60c8), BSI(SN9C105, OM6801, 0x??)}, */ /* {USB_DEVICE(0x0c45, 0x60cc), BSI(SN9C105, HV7131GP, 0x??)}, */ {USB_DEVICE(0x0c45, 0x60ec), BSI(SN9C105, MO4000, 0x21)}, -- cgit v1.2.3 From 6af4e7a15086782c7702491774cbb349ec763fb8 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Thu, 29 Jan 2009 16:34:25 -0300 Subject: V4L/DVB (10424): gspca - vc032x: Add resolution 1280x1024 for sensor mi1310_soc. Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/vc032x.c | 213 +++++++++++++++++++++++++++---------- 1 file changed, 157 insertions(+), 56 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/gspca/vc032x.c b/drivers/media/video/gspca/vc032x.c index 1b34906ac1b9..4ffdc64e2016 100644 --- a/drivers/media/video/gspca/vc032x.c +++ b/drivers/media/video/gspca/vc032x.c @@ -149,6 +149,11 @@ static const struct v4l2_pix_format vc0323_mode[] = { .sizeimage = 640 * 480 * 3 / 8 + 590, .colorspace = V4L2_COLORSPACE_JPEG, .priv = 0}, + {1280, 1024, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, /* mi1310_soc only */ + .bytesperline = 1280, + .sizeimage = 1280 * 1024 * 1 / 4 + 590, + .colorspace = V4L2_COLORSPACE_JPEG, + .priv = 2}, }; static const struct v4l2_pix_format svga_mode[] = { @@ -623,6 +628,113 @@ static const __u8 mi1310_socinitQVGA_JPG[][4] = { {0xb8, 0xa0, 0x12, 0xcc}, {}, }; +static const u8 mi1310_soc_InitSXGA_JPG[][4] = { + {0xb0, 0x03, 0x19, 0xcc}, + {0xb0, 0x04, 0x02, 0xcc}, + {0xb3, 0x00, 0x24, 0xcc}, + {0xb3, 0x00, 0x25, 0xcc}, + {0xb3, 0x05, 0x00, 0xcc}, + {0xb3, 0x06, 0x01, 0xcc}, + {0xb3, 0x5c, 0x01, 0xcc}, + {0xb3, 0x08, 0x01, 0xcc}, + {0xb3, 0x09, 0x0c, 0xcc}, + {0xb3, 0x34, 0x02, 0xcc}, + {0xb3, 0x35, 0xdd, 0xcc}, + {0xb3, 0x03, 0x0a, 0xcc}, + {0xb3, 0x04, 0x0d, 0xcc}, + {0xb3, 0x20, 0x00, 0xcc}, + {0xb3, 0x21, 0x00, 0xcc}, + {0xb3, 0x22, 0x04, 0xcc}, + {0xb3, 0x23, 0x00, 0xcc}, + {0xb3, 0x14, 0x00, 0xcc}, + {0xb3, 0x15, 0x00, 0xcc}, + {0xb3, 0x16, 0x04, 0xcc}, + {0xb3, 0x17, 0xff, 0xcc}, + {0xb8, 0x01, 0x7d, 0xcc}, + {0xb8, 0x81, 0x09, 0xcc}, + {0xb8, 0x27, 0x20, 0xcc}, + {0xb8, 0x26, 0x80, 0xcc}, + {0xb8, 0x06, 0x00, 0xcc}, + {0xb8, 0x07, 0x05, 0xcc}, + {0xb8, 0x08, 0x00, 0xcc}, + {0xb8, 0x09, 0x04, 0xcc}, + {0xb3, 0x00, 0x25, 0xcc}, + {0xb8, 0x00, 0x11, 0xcc}, + {0xbc, 0x00, 0x71, 0xcc}, + {0xb8, 0x81, 0x01, 0xcc}, + {0xb8, 0x2c, 0x5a, 0xcc}, + {0xb8, 0x2d, 0xff, 0xcc}, + {0xb8, 0x2e, 0xee, 0xcc}, + {0xb8, 0x2f, 0xfb, 0xcc}, + {0xb8, 0x30, 0x52, 0xcc}, + {0xb8, 0x31, 0xf8, 0xcc}, + {0xb8, 0x32, 0xf1, 0xcc}, + {0xb8, 0x33, 0xff, 0xcc}, + {0xb8, 0x34, 0x54, 0xcc}, + {0xf0, 0x00, 0x00, 0xbb}, + {0x00, 0x01, 0x00, 0xdd}, + {0x0d, 0x00, 0x09, 0xbb}, + {0x0d, 0x00, 0x08, 0xbb}, + {0xf0, 0x00, 0x01, 0xbb}, + {0x00, 0x01, 0x00, 0xdd}, + {0x06, 0x00, 0x14, 0xbb}, + {0x3a, 0x10, 0x00, 0xbb}, + {0x00, 0x00, 0x10, 0xdd}, + {0x9b, 0x10, 0x00, 0xbb}, + {0x00, 0x00, 0x10, 0xdd}, + {0xf0, 0x00, 0x00, 0xbb}, + {0x00, 0x01, 0x00, 0xdd}, + {0x2b, 0x00, 0x28, 0xbb}, + {0x2c, 0x00, 0x30, 0xbb}, + {0x2d, 0x00, 0x30, 0xbb}, + {0x2e, 0x00, 0x28, 0xbb}, + {0x41, 0x00, 0xd7, 0xbb}, + {0x09, 0x02, 0x3a, 0xbb}, + {0x0c, 0x00, 0x00, 0xbb}, + {0x20, 0x00, 0x00, 0xbb}, + {0x05, 0x00, 0x8c, 0xbb}, + {0x06, 0x00, 0x32, 0xbb}, + {0x07, 0x00, 0xc6, 0xbb}, + {0x08, 0x00, 0x19, 0xbb}, + {0x24, 0x80, 0x6f, 0xbb}, + {0xc8, 0x00, 0x0f, 0xbb}, + {0x20, 0x00, 0x03, 0xbb}, + {0xb6, 0x00, 0x00, 0xcc}, + {0xb6, 0x03, 0x05, 0xcc}, + {0xb6, 0x02, 0x00, 0xcc}, + {0xb6, 0x05, 0x04, 0xcc}, + {0xb6, 0x04, 0x00, 0xcc}, + {0xb6, 0x12, 0xf8, 0xcc}, + {0xb6, 0x18, 0x0a, 0xcc}, + {0xb6, 0x17, 0x00, 0xcc}, + {0xb6, 0x16, 0x00, 0xcc}, + {0xb6, 0x22, 0x12, 0xcc}, + {0xb6, 0x23, 0x0b, 0xcc}, + {0xb3, 0x02, 0x02, 0xcc}, + {0xbf, 0xc0, 0x39, 0xcc}, + {0xbf, 0xc1, 0x04, 0xcc}, + {0xbf, 0xcc, 0x10, 0xcc}, + {0xb9, 0x12, 0x00, 0xcc}, + {0xb9, 0x13, 0x14, 0xcc}, + {0xb9, 0x14, 0x14, 0xcc}, + {0xb9, 0x15, 0x14, 0xcc}, + {0xb9, 0x16, 0x14, 0xcc}, + {0xb9, 0x18, 0x00, 0xcc}, + {0xb9, 0x19, 0x1e, 0xcc}, + {0xb9, 0x1a, 0x1e, 0xcc}, + {0xb9, 0x1b, 0x1e, 0xcc}, + {0xb9, 0x1c, 0x1e, 0xcc}, + {0xb3, 0x01, 0x41, 0xcc}, + {0xb8, 0x8e, 0x00, 0xcc}, + {0xb8, 0x8f, 0xff, 0xcc}, + {0xb6, 0x12, 0xf8, 0xcc}, + {0xb8, 0x0c, 0x20, 0xcc}, + {0xb8, 0x0d, 0x70, 0xcc}, + {0xb6, 0x13, 0x13, 0xcc}, + {0x2f, 0x00, 0xC0, 0xbb}, + {0xb8, 0xa0, 0x12, 0xcc}, + {} +}; static const __u8 mi1320_gamma[17] = { 0x00, 0x13, 0x38, 0x59, 0x79, 0x92, 0xa7, 0xb9, 0xc8, @@ -2022,7 +2134,10 @@ static int sd_config(struct gspca_dev *gspca_dev, } else { if (sensor != SENSOR_PO1200) { cam->cam_mode = vc0323_mode; - cam->nmodes = ARRAY_SIZE(vc0323_mode); + if (sd->sensor != SENSOR_MI1310_SOC) + cam->nmodes = ARRAY_SIZE(vc0323_mode); + else /* no SXGA */ + cam->nmodes = ARRAY_SIZE(vc0323_mode) - 1; } else { cam->cam_mode = svga_mode; cam->nmodes = ARRAY_SIZE(svga_mode); @@ -2124,6 +2239,7 @@ static void setsharpness(struct gspca_dev *gspca_dev) static int sd_start(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; + const __u8 (*init)[4]; const __u8 *GammaT = NULL; const __u8 *MatrixT = NULL; int mode; @@ -2141,96 +2257,81 @@ static int sd_start(struct gspca_dev *gspca_dev) case SENSOR_HV7131R: GammaT = hv7131r_gamma; MatrixT = hv7131r_matrix; - if (mode) { - /* 320x240 */ - usb_exchange(gspca_dev, hv7131r_initQVGA_data); - } else { - /* 640x480 */ - usb_exchange(gspca_dev, hv7131r_initVGA_data); - } + if (mode) + init = hv7131r_initQVGA_data; /* 320x240 */ + else + init = hv7131r_initVGA_data; /* 640x480 */ break; case SENSOR_OV7660: GammaT = ov7660_gamma; MatrixT = ov7660_matrix; - if (mode) { - /* 320x240 */ - usb_exchange(gspca_dev, ov7660_initQVGA_data); - } else { - /* 640x480 */ - usb_exchange(gspca_dev, ov7660_initVGA_data); - } + if (mode) + init = ov7660_initQVGA_data; /* 320x240 */ + else + init = ov7660_initVGA_data; /* 640x480 */ break; case SENSOR_OV7670: /*GammaT = ov7660_gamma; */ /*MatrixT = ov7660_matrix; */ - if (mode) { - /* 320x240 */ - usb_exchange(gspca_dev, ov7670_initQVGA_JPG); - } else { - /* 640x480 */ - usb_exchange(gspca_dev, ov7670_initVGA_JPG); - } + if (mode) + init = ov7670_initQVGA_JPG; /* 320x240 */ + else + init = ov7670_initVGA_JPG; /* 640x480 */ break; case SENSOR_MI0360: GammaT = mi1320_gamma; MatrixT = mi0360_matrix; - if (mode) { - /* 320x240 */ - usb_exchange(gspca_dev, mi0360_initQVGA_JPG); - } else { - /* 640x480 */ - usb_exchange(gspca_dev, mi0360_initVGA_JPG); - } + if (mode) + init = mi0360_initQVGA_JPG; /* 320x240 */ + else + init = mi0360_initVGA_JPG; /* 640x480 */ break; case SENSOR_MI1310_SOC: GammaT = mi1320_gamma; MatrixT = mi0360_matrix; - if (mode) { - /* 320x240 */ - usb_exchange(gspca_dev, mi1310_socinitQVGA_JPG); - } else { - /* 640x480 */ - usb_exchange(gspca_dev, mi1310_socinitVGA_JPG); + switch (mode) { + case 1: + init = mi1310_socinitQVGA_JPG; /* 320x240 */ + break; + case 0: + init = mi1310_socinitVGA_JPG; /* 640x480 */ + break; + default: + init = mi1310_soc_InitSXGA_JPG; /* 1280xq024 */ + break; } break; case SENSOR_MI1320: GammaT = mi1320_gamma; MatrixT = mi1320_matrix; - if (mode) { - /* 320x240 */ - usb_exchange(gspca_dev, mi1320_initQVGA_data); - } else { - /* 640x480 */ - usb_exchange(gspca_dev, mi1320_initVGA_data); - } + if (mode) + init = mi1320_initQVGA_data; /* 320x240 */ + else + init = mi1320_initVGA_data; /* 640x480 */ break; case SENSOR_PO3130NC: GammaT = po3130_gamma; MatrixT = po3130_matrix; - if (mode) { - /* 320x240 */ - usb_exchange(gspca_dev, po3130_initQVGA_data); - } else { - /* 640x480 */ - usb_exchange(gspca_dev, po3130_initVGA_data); - } - usb_exchange(gspca_dev, po3130_rundata); + if (mode) + init = po3130_initQVGA_data; /* 320x240 */ + else + init = po3130_initVGA_data; /* 640x480 */ + usb_exchange(gspca_dev, init); + init = po3130_rundata; break; - case SENSOR_PO1200: + default: +/* case SENSOR_PO1200: */ GammaT = po1200_gamma; MatrixT = po1200_matrix; - usb_exchange(gspca_dev, po1200_initVGA_data); + init = po1200_initVGA_data; break; - default: - PDEBUG(D_PROBE, "Damned !! no sensor found Bye"); - return -EMEDIUMTYPE; } + usb_exchange(gspca_dev, init); if (GammaT && MatrixT) { put_tab_to_reg(gspca_dev, GammaT, 17, 0xb84a); put_tab_to_reg(gspca_dev, GammaT, 17, 0xb85b); put_tab_to_reg(gspca_dev, GammaT, 17, 0xb86c); put_tab_to_reg(gspca_dev, MatrixT, 9, 0xb82c); - /* Seem SHARPNESS */ /* reg_w(gspca_dev->dev, 0xa0, 0x80, 0xb80a); -- cgit v1.2.3 From 0fbe057412a68d830698333eef24b47b5b0e8bef Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Fri, 30 Jan 2009 12:14:02 -0300 Subject: V4L/DVB (10425): gspca - sonixj: Bad initialization of sensor mt9v111. Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/sonixj.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/media/video') diff --git a/drivers/media/video/gspca/sonixj.c b/drivers/media/video/gspca/sonixj.c index 325b71df96ff..e4454b573598 100644 --- a/drivers/media/video/gspca/sonixj.c +++ b/drivers/media/video/gspca/sonixj.c @@ -1543,6 +1543,7 @@ static int sd_start(struct gspca_dev *gspca_dev) /* reg1 = 0x06; * 640 clk 24Mz (done) */ reg17 = 0xe2; } + break; case SENSOR_OM6802: om6802_InitSensor(gspca_dev); reg17 = 0x64; /* 640 MCKSIZE */ -- cgit v1.2.3 From 5e31dc8dda6e52934acfa4706854cc2a22542949 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Sun, 1 Feb 2009 13:59:42 -0300 Subject: V4L/DVB (10427): gspca - sonixj: Sensor sp80708 added for webcam 0c45:6143. Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/sonixj.c | 145 +++++++++++++++++++++++++++++++++++-- 1 file changed, 140 insertions(+), 5 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/gspca/sonixj.c b/drivers/media/video/gspca/sonixj.c index e4454b573598..d9a7d1157f92 100644 --- a/drivers/media/video/gspca/sonixj.c +++ b/drivers/media/video/gspca/sonixj.c @@ -66,6 +66,7 @@ struct sd { #define SENSOR_OV7630 5 #define SENSOR_OV7648 6 #define SENSOR_OV7660 7 +#define SENSOR_SP80708 8 u8 i2c_base; }; @@ -243,6 +244,8 @@ static __u32 ctrl_dis[] = { /* SENSOR_OV7648 6 */ (1 << AUTOGAIN_IDX) | (1 << INFRARED_IDX) | (1 << VFLIP_IDX), /* SENSOR_OV7660 7 */ + (1 << AUTOGAIN_IDX) | (1 << INFRARED_IDX) | (1 << VFLIP_IDX), + /* SENSOR_SP80708 8 */ }; static const struct v4l2_pix_format vga_mode[] = { @@ -352,6 +355,17 @@ static const u8 sn_ov7660[0x1c] = { 0x07, 0x00, 0x00, 0x00 }; +static const u8 sn_sp80708[0x1c] = { +/* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */ + 0x00, 0x63, 0x60, 0x00, 0x1a, 0x20, 0x20, 0x20, +/* reg8 reg9 rega regb regc regd rege regf */ + 0x81, 0x18, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, +/* reg10 reg11 reg12 reg13 reg14 reg15 reg16 reg17 */ + 0x03, 0x00, 0x00, 0x03, 0x04, 0x28, 0x1e, 0x00, +/* reg18 reg19 reg1a reg1b */ + 0x07, 0x00, 0x00, 0x00 +}; + /* sequence specific to the sensors - !! index = SENSOR_xxx */ static const u8 *sn_tb[] = { sn_hv7131, @@ -361,7 +375,8 @@ static const u8 *sn_tb[] = { sn_om6802, sn_ov7630, sn_ov7648, - sn_ov7660 + sn_ov7660, + sn_sp80708 }; static const u8 gamma_def[17] = { @@ -740,6 +755,89 @@ static const u8 ov7660_sensor_init[][8] = { {} }; +static const u8 sp80708_sensor_init[][8] = { + {0xa1, 0x18, 0x06, 0xf9, 0x00, 0x00, 0x00, 0x10}, + {0xa1, 0x18, 0x09, 0x1f, 0x00, 0x00, 0x00, 0x10}, + {0xa1, 0x18, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x10}, + {0xa1, 0x18, 0x0d, 0xc0, 0x00, 0x00, 0x00, 0x10}, + {0xa1, 0x18, 0x0c, 0x04, 0x00, 0x00, 0x00, 0x10}, + {0xa1, 0x18, 0x0f, 0x0f, 0x00, 0x00, 0x00, 0x10}, + {0xa1, 0x18, 0x10, 0x40, 0x00, 0x00, 0x00, 0x10}, + {0xa1, 0x18, 0x11, 0x4e, 0x00, 0x00, 0x00, 0x10}, + {0xa1, 0x18, 0x12, 0x53, 0x00, 0x00, 0x00, 0x10}, + {0xa1, 0x18, 0x15, 0x80, 0x00, 0x00, 0x00, 0x10}, + {0xa1, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x10}, + {0xa1, 0x18, 0x19, 0x18, 0x00, 0x00, 0x00, 0x10}, + {0xa1, 0x18, 0x1a, 0x10, 0x00, 0x00, 0x00, 0x10}, + {0xa1, 0x18, 0x1b, 0x10, 0x00, 0x00, 0x00, 0x10}, + {0xa1, 0x18, 0x1c, 0x28, 0x00, 0x00, 0x00, 0x10}, + {0xa1, 0x18, 0x1d, 0x02, 0x00, 0x00, 0x00, 0x10}, + {0xa1, 0x18, 0x1e, 0x10, 0x00, 0x00, 0x00, 0x10}, + {0xa1, 0x18, 0x26, 0x04, 0x00, 0x00, 0x00, 0x10}, + {0xa1, 0x18, 0x27, 0x1e, 0x00, 0x00, 0x00, 0x10}, + {0xa1, 0x18, 0x28, 0x5a, 0x00, 0x00, 0x00, 0x10}, + {0xa1, 0x18, 0x29, 0x28, 0x00, 0x00, 0x00, 0x10}, + {0xa1, 0x18, 0x2a, 0x78, 0x00, 0x00, 0x00, 0x10}, + {0xa1, 0x18, 0x2b, 0x01, 0x00, 0x00, 0x00, 0x10}, + {0xa1, 0x18, 0x2c, 0xf7, 0x00, 0x00, 0x00, 0x10}, + {0xa1, 0x18, 0x2d, 0x2d, 0x00, 0x00, 0x00, 0x10}, + {0xa1, 0x18, 0x2e, 0xd5, 0x00, 0x00, 0x00, 0x10}, + {0xa1, 0x18, 0x39, 0x42, 0x00, 0x00, 0x00, 0x10}, + {0xa1, 0x18, 0x3a, 0x67, 0x00, 0x00, 0x00, 0x10}, + {0xa1, 0x18, 0x3b, 0x87, 0x00, 0x00, 0x00, 0x10}, + {0xa1, 0x18, 0x3c, 0xa3, 0x00, 0x00, 0x00, 0x10}, + {0xa1, 0x18, 0x3d, 0xb0, 0x00, 0x00, 0x00, 0x10}, + {0xa1, 0x18, 0x3e, 0xbc, 0x00, 0x00, 0x00, 0x10}, + {0xa1, 0x18, 0x3f, 0xc8, 0x00, 0x00, 0x00, 0x10}, + {0xa1, 0x18, 0x40, 0xd4, 0x00, 0x00, 0x00, 0x10}, + {0xa1, 0x18, 0x41, 0xdf, 0x00, 0x00, 0x00, 0x10}, + {0xa1, 0x18, 0x42, 0xea, 0x00, 0x00, 0x00, 0x10}, + {0xa1, 0x18, 0x43, 0xf5, 0x00, 0x00, 0x00, 0x10}, + {0xa1, 0x18, 0x45, 0x80, 0x00, 0x00, 0x00, 0x10}, + {0xa1, 0x18, 0x46, 0x60, 0x00, 0x00, 0x00, 0x10}, + {0xa1, 0x18, 0x47, 0x50, 0x00, 0x00, 0x00, 0x10}, + {0xa1, 0x18, 0x48, 0x30, 0x00, 0x00, 0x00, 0x10}, + {0xa1, 0x18, 0x49, 0x01, 0x00, 0x00, 0x00, 0x10}, + {0xa1, 0x18, 0x4d, 0xae, 0x00, 0x00, 0x00, 0x10}, + {0xa1, 0x18, 0x4e, 0x03, 0x00, 0x00, 0x00, 0x10}, + {0xa1, 0x18, 0x4f, 0x66, 0x00, 0x00, 0x00, 0x10}, + {0xa1, 0x18, 0x50, 0x1c, 0x00, 0x00, 0x00, 0x10}, + {0xa1, 0x18, 0x44, 0x10, 0x00, 0x00, 0x00, 0x10}, + {0xa1, 0x18, 0x4a, 0x30, 0x00, 0x00, 0x00, 0x10}, + {0xa1, 0x18, 0x51, 0x80, 0x00, 0x00, 0x00, 0x10}, + {0xa1, 0x18, 0x52, 0x80, 0x00, 0x00, 0x00, 0x10}, + {0xa1, 0x18, 0x53, 0x80, 0x00, 0x00, 0x00, 0x10}, + {0xa1, 0x18, 0x54, 0x80, 0x00, 0x00, 0x00, 0x10}, + {0xa1, 0x18, 0x55, 0x80, 0x00, 0x00, 0x00, 0x10}, + {0xa1, 0x18, 0x56, 0x80, 0x00, 0x00, 0x00, 0x10}, + {0xa1, 0x18, 0x57, 0xe0, 0x00, 0x00, 0x00, 0x10}, + {0xa1, 0x18, 0x58, 0xc0, 0x00, 0x00, 0x00, 0x10}, + {0xa1, 0x18, 0x59, 0xab, 0x00, 0x00, 0x00, 0x10}, + {0xa1, 0x18, 0x5a, 0xa0, 0x00, 0x00, 0x00, 0x10}, + {0xa1, 0x18, 0x5b, 0x99, 0x00, 0x00, 0x00, 0x10}, + {0xa1, 0x18, 0x5c, 0x90, 0x00, 0x00, 0x00, 0x10}, + {0xa1, 0x18, 0x5e, 0x24, 0x00, 0x00, 0x00, 0x10}, + {0xa1, 0x18, 0x5f, 0x00, 0x00, 0x00, 0x00, 0x10}, + {0xa1, 0x18, 0x60, 0x00, 0x00, 0x00, 0x00, 0x10}, + {0xa1, 0x18, 0x61, 0x73, 0x00, 0x00, 0x00, 0x10}, + {0xa1, 0x18, 0x63, 0x42, 0x00, 0x00, 0x00, 0x10}, + {0xa1, 0x18, 0x64, 0x42, 0x00, 0x00, 0x00, 0x10}, + {0xa1, 0x18, 0x65, 0x42, 0x00, 0x00, 0x00, 0x10}, + {0xa1, 0x18, 0x66, 0x24, 0x00, 0x00, 0x00, 0x10}, + {0xa1, 0x18, 0x67, 0x24, 0x00, 0x00, 0x00, 0x10}, + {0xa1, 0x18, 0x68, 0x08, 0x00, 0x00, 0x00, 0x10}, + {0xa1, 0x18, 0x2f, 0xc9, 0x00, 0x00, 0x00, 0x10}, + /********/ + {0xa1, 0x18, 0x0c, 0x04, 0x00, 0x00, 0x00, 0x10}, + {0xa1, 0x18, 0x0c, 0x04, 0x00, 0x00, 0x00, 0x10}, + {0xa1, 0x18, 0x03, 0x01, 0x00, 0x00, 0x00, 0x10}, + {0xa1, 0x18, 0x04, 0xa4, 0x00, 0x00, 0x00, 0x10}, + {0xa1, 0x18, 0x14, 0x3f, 0x00, 0x00, 0x00, 0x10}, + {0xa1, 0x18, 0x5d, 0x80, 0x00, 0x00, 0x00, 0x10}, + {0xb1, 0x18, 0x11, 0x40, 0x40, 0x00, 0x00, 0x10}, + {} +}; + static const u8 qtable4[] = { 0x06, 0x04, 0x04, 0x06, 0x04, 0x04, 0x06, 0x06, 0x06, 0x06, 0x08, 0x06, 0x06, 0x08, 0x0a, 0x11, @@ -1014,6 +1112,14 @@ static int configure_gpio(struct gspca_dev *gspca_dev, break; } /* fall thru */ + case SENSOR_SP80708: + reg_w1(gspca_dev, 0x01, 0x63); + reg_w1(gspca_dev, 0x17, 0x20); + reg_w1(gspca_dev, 0x01, 0x62); + reg_w1(gspca_dev, 0x01, 0x42); + mdelay(100); + reg_w1(gspca_dev, 0x02, 0x62); + break; default: reg_w1(gspca_dev, 0x01, 0x43); reg_w1(gspca_dev, 0x17, 0x61); @@ -1137,6 +1243,19 @@ static void ov7660_InitSensor(struct gspca_dev *gspca_dev) } } +static void sp80708_InitSensor(struct gspca_dev *gspca_dev) +{ + int i = 0; + + i2c_w8(gspca_dev, sp80708_sensor_init[i]); /* reset SCCB */ + i++; + msleep(20); + while (sp80708_sensor_init[i][0]) { + i2c_w8(gspca_dev, sp80708_sensor_init[i]); + i++; + } +} + /* this function is called at probe time */ static int sd_config(struct gspca_dev *gspca_dev, const struct usb_device_id *id) @@ -1400,6 +1519,7 @@ static void setgamma(struct gspca_dev *gspca_dev) 0x18, 0x13, 0x10, 0x0e, 0x08, 0x07, 0x04, 0x02, 0x00 }; + for (i = 0; i < sizeof gamma; i++) gamma[i] = gamma_def[i] + delta[i] * (sd->gamma - GAMMA_DEF) / 32; @@ -1488,7 +1608,8 @@ static int sd_start(struct gspca_dev *gspca_dev) reg_w1(gspca_dev, 0x07, sn9c1xx[7]); /* green */ reg_w1(gspca_dev, 0x06, sn9c1xx[6]); /* blue */ reg_w1(gspca_dev, 0x14, sn9c1xx[0x14]); - setgamma(gspca_dev); + setgamma(gspca_dev); + for (i = 0; i < 8; i++) reg_w(gspca_dev, 0x84, reg84, sizeof reg84); switch (sd->sensor) { @@ -1500,6 +1621,10 @@ static int sd_start(struct gspca_dev *gspca_dev) reg_w1(gspca_dev, 0x9a, 0x0a); reg_w1(gspca_dev, 0x99, 0x60); break; + case SENSOR_SP80708: + reg_w1(gspca_dev, 0x9a, 0x05); + reg_w1(gspca_dev, 0x99, 0x59); + break; case SENSOR_OV7660: if (sd->bridge == BRIDGE_SN9C120) { reg_w1(gspca_dev, 0x9a, 0x05); @@ -1559,8 +1684,7 @@ static int sd_start(struct gspca_dev *gspca_dev) reg17 = 0x21; /* reg1 = 0x42; * 42 - 46? */ break; - default: -/* case SENSOR_OV7660: */ + case SENSOR_OV7660: ov7660_InitSensor(gspca_dev); if (sd->bridge == BRIDGE_SN9C120) { if (mode) { /* 320x240 - 160x120 */ @@ -1573,6 +1697,17 @@ static int sd_start(struct gspca_dev *gspca_dev) * inverse power down */ } break; + default: +/* case SENSOR_SP80708: */ + sp80708_InitSensor(gspca_dev); + if (mode) { +/*?? reg1 = 0x04; * 320 clk 48Mhz */ + ; + } else { + reg1 = 0x46; /* 640 clk 48Mz */ + reg17 = 0xa2; + } + break; } reg_w(gspca_dev, 0xc0, C0, 6); reg_w(gspca_dev, 0xca, CA, 4); @@ -1970,7 +2105,7 @@ static const __devinitdata struct usb_device_id device_table[] = { {USB_DEVICE(0x0c45, 0x613c), BSI(SN9C120, HV7131R, 0x11)}, /* {USB_DEVICE(0x0c45, 0x613e), BSI(SN9C120, OV7630, 0x??)}, */ #endif - {USB_DEVICE(0x0c45, 0x6143), BSI(SN9C120, MI0360, 0x5d)}, + {USB_DEVICE(0x0c45, 0x6143), BSI(SN9C120, SP80708, 0x18)}, {} }; MODULE_DEVICE_TABLE(usb, device_table); -- cgit v1.2.3 From b083b92f9386d82e8ff3c1cfe04eefae488cbf1f Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Sun, 1 Feb 2009 14:20:07 -0300 Subject: V4L/DVB (10428): gspca - sonixj: Specific gamma tables per sensor. Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/sonixj.c | 29 ++++++++++++++++++++++++++--- 1 file changed, 26 insertions(+), 3 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/gspca/sonixj.c b/drivers/media/video/gspca/sonixj.c index d9a7d1157f92..a5b58374333b 100644 --- a/drivers/media/video/gspca/sonixj.c +++ b/drivers/media/video/gspca/sonixj.c @@ -379,11 +379,21 @@ static const u8 *sn_tb[] = { sn_sp80708 }; +/* default gamma table */ static const u8 gamma_def[17] = { 0x00, 0x2d, 0x46, 0x5a, 0x6c, 0x7c, 0x8b, 0x99, 0xa6, 0xb2, 0xbf, 0xca, 0xd5, 0xe0, 0xeb, 0xf5, 0xff }; - +/* gamma for sensors HV7131R and MT9V111 */ +static const u8 gamma_spec_1[17] = { + 0x08, 0x3a, 0x52, 0x65, 0x75, 0x83, 0x91, 0x9d, + 0xa9, 0xb4, 0xbe, 0xc8, 0xd2, 0xdb, 0xe4, 0xed, 0xf5 +}; +/* gamma for sensor SP80708 */ +static const u8 gamma_spec_2[17] = { + 0x0a, 0x2d, 0x4e, 0x68, 0x7d, 0x8f, 0x9f, 0xab, + 0xb7, 0xc2, 0xcc, 0xd3, 0xd8, 0xde, 0xe2, 0xe5, 0xe6 +}; /* color matrix and offsets */ static const u8 reg84[] = { @@ -1514,14 +1524,27 @@ static void setgamma(struct gspca_dev *gspca_dev) struct sd *sd = (struct sd *) gspca_dev; int i; u8 gamma[17]; + const u8 *gamma_base; static const u8 delta[17] = { 0x00, 0x14, 0x1c, 0x1c, 0x1c, 0x1c, 0x1b, 0x1a, 0x18, 0x13, 0x10, 0x0e, 0x08, 0x07, 0x04, 0x02, 0x00 }; + switch (sd->sensor) { + case SENSOR_HV7131R: + case SENSOR_MT9V111: + gamma_base = gamma_spec_1; + break; + case SENSOR_SP80708: + gamma_base = gamma_spec_2; + break; + default: + gamma_base = gamma_def; + break; + } for (i = 0; i < sizeof gamma; i++) - gamma[i] = gamma_def[i] + gamma[i] = gamma_base[i] + delta[i] * (sd->gamma - GAMMA_DEF) / 32; reg_w(gspca_dev, 0x20, gamma, sizeof gamma); } @@ -1608,6 +1631,7 @@ static int sd_start(struct gspca_dev *gspca_dev) reg_w1(gspca_dev, 0x07, sn9c1xx[7]); /* green */ reg_w1(gspca_dev, 0x06, sn9c1xx[6]); /* blue */ reg_w1(gspca_dev, 0x14, sn9c1xx[0x14]); + setgamma(gspca_dev); for (i = 0; i < 8; i++) @@ -1702,7 +1726,6 @@ static int sd_start(struct gspca_dev *gspca_dev) sp80708_InitSensor(gspca_dev); if (mode) { /*?? reg1 = 0x04; * 320 clk 48Mhz */ - ; } else { reg1 = 0x46; /* 640 clk 48Mz */ reg17 = 0xa2; -- cgit v1.2.3 From 65c5259cc44c822215e670025c226d77f5a323bf Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Sun, 1 Feb 2009 14:26:51 -0300 Subject: V4L/DVB (10429): gspca - sonixj: Simplify the probe of the sensors mi0360/mt9v111. Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/sonixj.c | 32 +++++++++++++++----------------- 1 file changed, 15 insertions(+), 17 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/gspca/sonixj.c b/drivers/media/video/gspca/sonixj.c index a5b58374333b..4101a240e481 100644 --- a/drivers/media/video/gspca/sonixj.c +++ b/drivers/media/video/gspca/sonixj.c @@ -1009,18 +1009,19 @@ static int hv7131r_probe(struct gspca_dev *gspca_dev) return -ENODEV; } -static int mi0360_probe(struct gspca_dev *gspca_dev) +static void mi0360_probe(struct gspca_dev *gspca_dev) { + struct sd *sd = (struct sd *) gspca_dev; int i, j; u16 val; static const u8 probe_tb[][4][8] = { - { + { /* mi0360 */ {0xb0, 0x5d, 0x07, 0x00, 0x02, 0x00, 0x00, 0x10}, {0x90, 0x5d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10}, {0xa2, 0x5d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10}, {0xb0, 0x5d, 0x07, 0x00, 0x00, 0x00, 0x00, 0x10} }, - { + { /* mt9v111 */ {0xb0, 0x5c, 0x01, 0x00, 0x04, 0x00, 0x00, 0x10}, {0x90, 0x5c, 0x36, 0x00, 0x00, 0x00, 0x00, 0x10}, {0xa2, 0x5c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10}, @@ -1046,13 +1047,16 @@ static int mi0360_probe(struct gspca_dev *gspca_dev) switch (val) { case 0x823a: PDEBUG(D_PROBE, "Sensor mt9v111"); - return SENSOR_MT9V111; + sd->sensor = SENSOR_MT9V111; + sd->i2c_base = 0x5c; + break; case 0x8243: PDEBUG(D_PROBE, "Sensor mi0360"); - return SENSOR_MI0360; + break; + default: + PDEBUG(D_PROBE, "Unknown sensor %04x - forced to mi0360", val); + break; } - PDEBUG(D_PROBE, "Unknown sensor %04x - forced to mi0360", val); - return SENSOR_MI0360; } static int configure_gpio(struct gspca_dev *gspca_dev, @@ -1319,21 +1323,15 @@ static int sd_init(struct gspca_dev *gspca_dev) case BRIDGE_SN9C105: if (regF1 != 0x11) return -ENODEV; - if (sd->sensor == SENSOR_MI0360) { - sd->sensor = mi0360_probe(gspca_dev); - if (sd->sensor == SENSOR_MT9V111) - sd->i2c_base = 0x5c; - } + if (sd->sensor == SENSOR_MI0360) + mi0360_probe(gspca_dev); reg_w(gspca_dev, 0x01, regGpio, 2); break; case BRIDGE_SN9C120: if (regF1 != 0x12) return -ENODEV; - if (sd->sensor == SENSOR_MI0360) { - sd->sensor = mi0360_probe(gspca_dev); - if (sd->sensor == SENSOR_MT9V111) - sd->i2c_base = 0x5c; - } + if (sd->sensor == SENSOR_MI0360) + mi0360_probe(gspca_dev); regGpio[1] = 0x70; reg_w(gspca_dev, 0x01, regGpio, 2); break; -- cgit v1.2.3 From 2687a2fb1ce2b764298fb40c96765b04eaddac95 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Sun, 1 Feb 2009 14:48:55 -0300 Subject: V4L/DVB (10430): gspca - sonixj: Adjust some exchanges with the sensor mt9v111. This patch also enables the autogain for the mt9v111. Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/sonixj.c | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/gspca/sonixj.c b/drivers/media/video/gspca/sonixj.c index 4101a240e481..970c74f9fe8b 100644 --- a/drivers/media/video/gspca/sonixj.c +++ b/drivers/media/video/gspca/sonixj.c @@ -234,7 +234,7 @@ static __u32 ctrl_dis[] = { /* SENSOR_MI0360 1 */ (1 << INFRARED_IDX) | (1 << VFLIP_IDX), /* SENSOR_MO4000 2 */ - (1 << AUTOGAIN_IDX), + 0, /* SENSOR_MT9V111 3 */ (1 << INFRARED_IDX) | (1 << VFLIP_IDX), /* SENSOR_OM6802 4 */ @@ -517,8 +517,18 @@ static const u8 mt9v111_sensor_init[][8] = { {0xb1, 0x5c, 0x01, 0x00, 0x01, 0x00, 0x00, 0x10}, /* IFP select */ {0xb1, 0x5c, 0x08, 0x04, 0x80, 0x00, 0x00, 0x10}, /* output fmt ctrl */ {0xb1, 0x5c, 0x06, 0x00, 0x00, 0x00, 0x00, 0x10}, /* op mode ctrl */ + {0xb1, 0x5c, 0x02, 0x00, 0x16, 0x00, 0x00, 0x10}, + {0xb1, 0x5c, 0x03, 0x01, 0xe1, 0x00, 0x00, 0x10}, + {0xb1, 0x5c, 0x04, 0x02, 0x81, 0x00, 0x00, 0x10}, + {0xb1, 0x5c, 0x05, 0x00, 0x04, 0x00, 0x00, 0x10}, {0xb1, 0x5c, 0x01, 0x00, 0x04, 0x00, 0x00, 0x10}, /* sensor select */ + {0xb1, 0x5c, 0x02, 0x00, 0x16, 0x00, 0x00, 0x10}, + {0xb1, 0x5c, 0x03, 0x01, 0xe6, 0x00, 0x00, 0x10}, + {0xb1, 0x5c, 0x04, 0x02, 0x86, 0x00, 0x00, 0x10}, + {0xb1, 0x5c, 0x05, 0x00, 0x04, 0x00, 0x00, 0x10}, + {0xb1, 0x5c, 0x06, 0x00, 0x00, 0x00, 0x00, 0x10}, {0xb1, 0x5c, 0x08, 0x00, 0x08, 0x00, 0x00, 0x10}, /* row start */ + {0xb1, 0x5c, 0x0e, 0x00, 0x08, 0x00, 0x00, 0x10}, {0xb1, 0x5c, 0x02, 0x00, 0x16, 0x00, 0x00, 0x10}, /* col start */ {0xb1, 0x5c, 0x03, 0x01, 0xe7, 0x00, 0x00, 0x10}, /* window height */ {0xb1, 0x5c, 0x04, 0x02, 0x87, 0x00, 0x00, 0x10}, /* window width */ @@ -532,7 +542,7 @@ static const u8 mt9v111_sensor_init[][8] = { /*******/ {0xb1, 0x5c, 0x20, 0x00, 0x00, 0x00, 0x00, 0x10}, {0xb1, 0x5c, 0x20, 0x00, 0x00, 0x00, 0x00, 0x10}, - {0xb1, 0x5c, 0x09, 0x00, 0x64, 0x00, 0x00, 0x10}, /* shutter width */ + {0xb1, 0x5c, 0x09, 0x01, 0x2c, 0x00, 0x00, 0x10}, {0xd1, 0x5c, 0x2b, 0x00, 0x33, 0x00, 0xa0, 0x10}, /* green1 gain */ {0xd1, 0x5c, 0x2d, 0x00, 0xa0, 0x00, 0x33, 0x10}, /* red gain */ /*******/ @@ -1688,7 +1698,7 @@ static int sd_start(struct gspca_dev *gspca_dev) reg1 = 0x04; /* 320 clk 48Mhz */ } else { /* reg1 = 0x06; * 640 clk 24Mz (done) */ - reg17 = 0xe2; + reg17 = 0xc2; } break; case SENSOR_OM6802: -- cgit v1.2.3 From 8d538699e761be7b1ad431273919034806132806 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Sun, 1 Feb 2009 16:15:01 -0300 Subject: V4L/DVB (10431): gspca - vc032x: Bad revision for the webcam 041e:405b. Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/vc032x.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/gspca/vc032x.c b/drivers/media/video/gspca/vc032x.c index 4ffdc64e2016..be1507ac0262 100644 --- a/drivers/media/video/gspca/vc032x.c +++ b/drivers/media/video/gspca/vc032x.c @@ -2527,7 +2527,7 @@ static const struct sd_desc sd_desc = { /* -- module initialisation -- */ static const __devinitdata struct usb_device_id device_table[] = { - {USB_DEVICE(0x041e, 0x405b), .driver_info = BRIDGE_VC0321}, + {USB_DEVICE(0x041e, 0x405b), .driver_info = BRIDGE_VC0323}, {USB_DEVICE(0x046d, 0x0892), .driver_info = BRIDGE_VC0321}, {USB_DEVICE(0x046d, 0x0896), .driver_info = BRIDGE_VC0321}, {USB_DEVICE(0x046d, 0x0897), .driver_info = BRIDGE_VC0321}, -- cgit v1.2.3 From 49796e4059b40032f3dba0fa5ad559ef4b977e89 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Mon, 2 Feb 2009 06:33:31 -0300 Subject: V4L/DVB (10432): gspca - vc032x: Cleanup source, optimize and check i2c_write. Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/vc032x.c | 93 +++++++++++++++----------------------- 1 file changed, 37 insertions(+), 56 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/gspca/vc032x.c b/drivers/media/video/gspca/vc032x.c index be1507ac0262..f8d535ce9081 100644 --- a/drivers/media/video/gspca/vc032x.c +++ b/drivers/media/video/gspca/vc032x.c @@ -1927,44 +1927,40 @@ static void reg_w(struct usb_device *dev, 500); } -static void read_sensor_register(struct gspca_dev *gspca_dev, - __u16 address, __u16 *value) +static u16 read_sensor_register(struct gspca_dev *gspca_dev, + u16 address) { struct usb_device *dev = gspca_dev->dev; __u8 ldata, mdata, hdata; int retry = 50; - *value = 0; - reg_r(gspca_dev, 0xa1, 0xb33f, 1); - /*PDEBUG(D_PROBE, " I2c Bus Busy Wait 0x%02X ", tmpvalue); */ if (!(gspca_dev->usb_buf[0] & 0x02)) { - PDEBUG(D_ERR, "I2c Bus Busy Wait %d", - gspca_dev->usb_buf[0] & 0x02); - return; + PDEBUG(D_ERR, "I2c Bus Busy Wait %02x", + gspca_dev->usb_buf[0]); + return 0; } reg_w(dev, 0xa0, address, 0xb33a); reg_w(dev, 0xa0, 0x02, 0xb339); - reg_r(gspca_dev, 0xa1, 0xb33b, 1); - while (retry-- && gspca_dev->usb_buf[0]) { + do { + msleep(8); reg_r(gspca_dev, 0xa1, 0xb33b, 1); -/* PDEBUG(D_PROBE, "Read again 0xb33b %d", tmpvalue); */ - msleep(1); - } + } while (retry-- && gspca_dev->usb_buf[0]); + reg_r(gspca_dev, 0xa1, 0xb33e, 1); ldata = gspca_dev->usb_buf[0]; reg_r(gspca_dev, 0xa1, 0xb33d, 1); mdata = gspca_dev->usb_buf[0]; reg_r(gspca_dev, 0xa1, 0xb33c, 1); hdata = gspca_dev->usb_buf[0]; - PDEBUG(D_PROBE, "Read Sensor %02x%02x %02x", - hdata, mdata, ldata); + if (hdata != 0 && mdata != 0 && ldata != 0) + PDEBUG(D_PROBE, "Read Sensor %02x%02x %02x", + hdata, mdata, ldata); reg_r(gspca_dev, 0xa1, 0xb334, 1); if (gspca_dev->usb_buf[0] == 0x02) - *value = (hdata << 8) + mdata; - else - *value = hdata; + return (hdata << 8) + mdata; + return hdata; } static int vc032x_probe_sensor(struct gspca_dev *gspca_dev) @@ -1985,7 +1981,7 @@ static int vc032x_probe_sensor(struct gspca_dev *gspca_dev) reg_w(dev, 0xa0, 0x0c, 0xb309); reg_w(dev, 0xa0, ptsensor_info->I2cAdd, 0xb335); reg_w(dev, 0xa0, ptsensor_info->op, 0xb301); - read_sensor_register(gspca_dev, ptsensor_info->IdAdd, &value); + value = read_sensor_register(gspca_dev, ptsensor_info->IdAdd); if (value == ptsensor_info->VpId) return ptsensor_info->sensorId; @@ -1997,13 +1993,16 @@ static int vc032x_probe_sensor(struct gspca_dev *gspca_dev) return -1; } -static __u8 i2c_write(struct gspca_dev *gspca_dev, +static void i2c_write(struct gspca_dev *gspca_dev, __u8 reg, const __u8 *val, __u8 size) { struct usb_device *dev = gspca_dev->dev; + int retry; +#ifdef GSPCA_DEBUG if (size > 3 || size < 1) - return -EINVAL; + return; +#endif reg_r(gspca_dev, 0xa1, 0xb33f, 1); reg_w(dev, 0xa0, size, 0xb334); reg_w(dev, 0xa0, reg, 0xb33a); @@ -2015,18 +2014,23 @@ static __u8 i2c_write(struct gspca_dev *gspca_dev, reg_w(dev, 0xa0, val[0], 0xb336); reg_w(dev, 0xa0, val[1], 0xb337); break; - case 3: + default: +/* case 3: */ reg_w(dev, 0xa0, val[0], 0xb336); reg_w(dev, 0xa0, val[1], 0xb337); reg_w(dev, 0xa0, val[2], 0xb338); break; - default: - reg_w(dev, 0xa0, 0x01, 0xb334); - return -EINVAL; } reg_w(dev, 0xa0, 0x01, 0xb339); - reg_r(gspca_dev, 0xa1, 0xb33b, 1); - return gspca_dev->usb_buf[0] == 0; + retry = 4; + do { + reg_r(gspca_dev, 0xa1, 0xb33b, 1); + if (gspca_dev->usb_buf[0] == 0) + break; + msleep(20); + } while (--retry > 0); + if (retry <= 0) + PDEBUG(D_ERR, "i2c_write failed"); } static void put_tab_to_reg(struct gspca_dev *gspca_dev, @@ -2051,7 +2055,7 @@ static void usb_exchange(struct gspca_dev *gspca_dev, return; case 0xcc: /* normal write */ reg_w(dev, 0xa0, data[i][2], - ((data[i][0])<<8) | data[i][1]); + (data[i][0]) << 8 | data[i][1]); break; case 0xaa: /* i2c op */ i2c_write(gspca_dev, data[i][1], &data[i][2], 1); @@ -2068,11 +2072,6 @@ static void usb_exchange(struct gspca_dev *gspca_dev, /*not reached*/ } -/* - "GammaT"=hex:04,17,31,4f,6a,83,99,ad,bf,ce,da,e5,ee,f5,fb,ff,ff - "MatrixT"=hex:60,f9,e5,e7,50,05,f3,e6,66 - */ - static void vc0321_reset(struct gspca_dev *gspca_dev) { reg_w(gspca_dev->dev, 0xa0, 0x00, 0xb04d); @@ -2176,7 +2175,7 @@ static int sd_config(struct gspca_dev *gspca_dev, return 0; } -/* this function is called at probe and time */ +/* this function is called at probe and resume time */ static int sd_init(struct gspca_dev *gspca_dev) { return 0; @@ -2332,27 +2331,7 @@ static int sd_start(struct gspca_dev *gspca_dev) put_tab_to_reg(gspca_dev, GammaT, 17, 0xb85b); put_tab_to_reg(gspca_dev, GammaT, 17, 0xb86c); put_tab_to_reg(gspca_dev, MatrixT, 9, 0xb82c); - /* Seem SHARPNESS */ - /* - reg_w(gspca_dev->dev, 0xa0, 0x80, 0xb80a); - reg_w(gspca_dev->dev, 0xa0, 0xff, 0xb80b); - reg_w(gspca_dev->dev, 0xa0, 0xff, 0xb80e); - */ - /* all 0x40 ??? do nothing - reg_w(gspca_dev->dev, 0xa0, 0x40, 0xb822); - reg_w(gspca_dev->dev, 0xa0, 0x40, 0xb823); - reg_w(gspca_dev->dev, 0xa0, 0x40, 0xb824); - */ - /* Only works for HV7131R ?? - reg_r (gspca_dev, 0xa1, 0xb881, 1); - reg_w(gspca_dev->dev, 0xa0, 0xfe01, 0xb881); - reg_w(gspca_dev->dev, 0xa0, 0x79, 0xb801); - */ - /* only hv7131r et ov7660 - reg_w(gspca_dev->dev, 0xa0, 0x20, 0xb827); - reg_w(gspca_dev->dev, 0xa0, 0xff, 0xb826); * ISP_GAIN 80 - reg_w(gspca_dev->dev, 0xa0, 0x23, 0xb800); * ISP CTRL_BAS - */ + /* set the led on 0x0892 0x0896 */ if (sd->sensor != SENSOR_PO1200) { reg_w(gspca_dev->dev, 0x89, 0xffff, 0xfdff); @@ -2502,7 +2481,8 @@ static int sd_querymenu(struct gspca_dev *gspca_dev, case 1: /* V4L2_CID_POWER_LINE_FREQUENCY_50HZ */ strcpy((char *) menu->name, "50 Hz"); return 0; - case 2: /* V4L2_CID_POWER_LINE_FREQUENCY_60HZ */ + default: +/* case 2: * V4L2_CID_POWER_LINE_FREQUENCY_60HZ */ strcpy((char *) menu->name, "60 Hz"); return 0; } @@ -2565,6 +2545,7 @@ static struct usb_driver sd_driver = { static int __init sd_mod_init(void) { int ret; + ret = usb_register(&sd_driver); if (ret < 0) return ret; -- cgit v1.2.3 From e474200d3502d4cb3cc240930640c7d857bf777b Mon Sep 17 00:00:00 2001 From: Andy Walls Date: Fri, 30 Jan 2009 22:21:45 -0300 Subject: V4L/DVB (10433): cx18: Defer A/V core initialization until a valid cx18_av_cmd arrives Signed-off-by: Andy Walls Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx18/cx18-av-core.c | 40 +++++++++++++++++++++++++++------ 1 file changed, 33 insertions(+), 7 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/cx18/cx18-av-core.c b/drivers/media/video/cx18/cx18-av-core.c index 780125002cbc..db887a008626 100644 --- a/drivers/media/video/cx18/cx18-av-core.c +++ b/drivers/media/video/cx18/cx18-av-core.c @@ -680,19 +680,45 @@ static int set_v4lfmt(struct cx18 *cx, struct v4l2_format *fmt) /* ----------------------------------------------------------------------- */ +static int valid_av_cmd(unsigned int cmd) +{ + switch (cmd) { + /* All commands supported by cx18_av_cmd() */ + case VIDIOC_INT_DECODE_VBI_LINE: + case VIDIOC_INT_AUDIO_CLOCK_FREQ: + case VIDIOC_STREAMON: + case VIDIOC_STREAMOFF: + case VIDIOC_LOG_STATUS: + case VIDIOC_G_CTRL: + case VIDIOC_S_CTRL: + case VIDIOC_QUERYCTRL: + case VIDIOC_G_STD: + case VIDIOC_S_STD: + case AUDC_SET_RADIO: + case VIDIOC_INT_G_VIDEO_ROUTING: + case VIDIOC_INT_S_VIDEO_ROUTING: + case VIDIOC_INT_G_AUDIO_ROUTING: + case VIDIOC_INT_S_AUDIO_ROUTING: + case VIDIOC_S_FREQUENCY: + case VIDIOC_G_TUNER: + case VIDIOC_S_TUNER: + case VIDIOC_G_FMT: + case VIDIOC_S_FMT: + case VIDIOC_INT_RESET: + return 1; + default: + return 0; + } + return 0; +} + int cx18_av_cmd(struct cx18 *cx, unsigned int cmd, void *arg) { struct cx18_av_state *state = &cx->av_state; struct v4l2_tuner *vt = arg; struct v4l2_routing *route = arg; - /* ignore these commands */ - switch (cmd) { - case TUNER_SET_TYPE_ADDR: - return 0; - } - - if (!state->is_initialized) { + if (!state->is_initialized && valid_av_cmd(cmd)) { CX18_DEBUG_INFO("cmd %08x triggered fw load\n", cmd); /* initialize on first use */ state->is_initialized = 1; -- cgit v1.2.3 From 072e6183c26cb00de0368a06cbbda2a2d55e6844 Mon Sep 17 00:00:00 2001 From: Andy Walls Date: Fri, 30 Jan 2009 22:39:26 -0300 Subject: V4L/DVB (10434): cx18: Smarter verification of CX18_AUDIO_ENABLE register writes The CX18_AUDIO_ENABLE register usually never reads back what was just written under normal circumstances. Perform better checking that a write went to the register as expected with a specification of what bits to verify. Signed-off-by: Andy Walls Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx18/cx18-audio.c | 3 +-- drivers/media/video/cx18/cx18-av-firmware.c | 3 ++- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/cx18/cx18-audio.c b/drivers/media/video/cx18/cx18-audio.c index 57beddf0af4d..d19bd778c6ac 100644 --- a/drivers/media/video/cx18/cx18-audio.c +++ b/drivers/media/video/cx18/cx18-audio.c @@ -64,8 +64,7 @@ int cx18_audio_set_io(struct cx18 *cx) val = cx18_read_reg(cx, CX18_AUDIO_ENABLE) & ~0x30; val |= (audio_input > CX18_AV_AUDIO_SERIAL2) ? 0x20 : (audio_input << 4); - cx18_write_reg(cx, val | 0xb00, CX18_AUDIO_ENABLE); - cx18_vapi(cx, CX18_APU_RESETAI, 1, 0); + cx18_write_reg_expect(cx, val | 0xb00, CX18_AUDIO_ENABLE, val, 0x30); return 0; } diff --git a/drivers/media/video/cx18/cx18-av-firmware.c b/drivers/media/video/cx18/cx18-av-firmware.c index b374c74d3e7b..940ea9352115 100644 --- a/drivers/media/video/cx18/cx18-av-firmware.c +++ b/drivers/media/video/cx18/cx18-av-firmware.c @@ -131,7 +131,8 @@ int cx18_av_loadfw(struct cx18 *cx) v = cx18_read_reg(cx, CX18_AUDIO_ENABLE); /* If bit 11 is 1, clear bit 10 */ if (v & 0x800) - cx18_write_reg(cx, v & 0xFFFFFBFF, CX18_AUDIO_ENABLE); + cx18_write_reg_expect(cx, v & 0xFFFFFBFF, CX18_AUDIO_ENABLE, + 0, 0x400); /* Enable WW auto audio standard detection */ v = cx18_av_read4(cx, CXADEC_STD_DET_CTL); -- cgit v1.2.3 From d5c02f6b27b8e70c11b341eef709e5f64ca16e42 Mon Sep 17 00:00:00 2001 From: Andy Walls Date: Fri, 30 Jan 2009 22:48:40 -0300 Subject: V4L/DVB (10435): cx18: Normalize APU after second APU firmware load Signed-off-by: Andy Walls Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx18/cx18-driver.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'drivers/media/video') diff --git a/drivers/media/video/cx18/cx18-driver.c b/drivers/media/video/cx18/cx18-driver.c index 0f13fdd890a4..1518a58e17fc 100644 --- a/drivers/media/video/cx18/cx18-driver.c +++ b/drivers/media/video/cx18/cx18-driver.c @@ -1080,6 +1080,19 @@ int cx18_init_on_first_open(struct cx18 *cx) return -ENXIO; } + /* + * The second firmware load requires us to normalize the APU state, + * or the audio for the first analog capture will be badly incorrect. + * + * I can't seem to call APU_RESETAI and have it succeed without the + * APU capturing audio, so we start and stop it here to do the reset + */ + + /* MPEG Encoding, 224 kbps, MPEG Layer II, 48 ksps */ + cx18_vapi(cx, CX18_APU_START, 2, CX18_APU_ENCODING_METHOD_MPEG|0xb9, 0); + cx18_vapi(cx, CX18_APU_RESETAI, 0); + cx18_vapi(cx, CX18_APU_STOP, 1, CX18_APU_ENCODING_METHOD_MPEG); + vf.tuner = 0; vf.type = V4L2_TUNER_ANALOG_TV; vf.frequency = 6400; /* the tuner 'baseline' frequency */ -- cgit v1.2.3 From 0b089742c79b39d4a650614896fec7a6569f338e Mon Sep 17 00:00:00 2001 From: Andy Walls Date: Sun, 1 Feb 2009 16:53:20 -0300 Subject: V4L/DVB (10436): cx18: Fix coding style of a switch statement per checkpatch.pl Signed-off-by: Andy Walls Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx18/cx18-av-core.c | 50 ++++++++++++++++----------------- 1 file changed, 25 insertions(+), 25 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/cx18/cx18-av-core.c b/drivers/media/video/cx18/cx18-av-core.c index db887a008626..091f0cac0633 100644 --- a/drivers/media/video/cx18/cx18-av-core.c +++ b/drivers/media/video/cx18/cx18-av-core.c @@ -683,31 +683,31 @@ static int set_v4lfmt(struct cx18 *cx, struct v4l2_format *fmt) static int valid_av_cmd(unsigned int cmd) { switch (cmd) { - /* All commands supported by cx18_av_cmd() */ - case VIDIOC_INT_DECODE_VBI_LINE: - case VIDIOC_INT_AUDIO_CLOCK_FREQ: - case VIDIOC_STREAMON: - case VIDIOC_STREAMOFF: - case VIDIOC_LOG_STATUS: - case VIDIOC_G_CTRL: - case VIDIOC_S_CTRL: - case VIDIOC_QUERYCTRL: - case VIDIOC_G_STD: - case VIDIOC_S_STD: - case AUDC_SET_RADIO: - case VIDIOC_INT_G_VIDEO_ROUTING: - case VIDIOC_INT_S_VIDEO_ROUTING: - case VIDIOC_INT_G_AUDIO_ROUTING: - case VIDIOC_INT_S_AUDIO_ROUTING: - case VIDIOC_S_FREQUENCY: - case VIDIOC_G_TUNER: - case VIDIOC_S_TUNER: - case VIDIOC_G_FMT: - case VIDIOC_S_FMT: - case VIDIOC_INT_RESET: - return 1; - default: - return 0; + /* All commands supported by cx18_av_cmd() */ + case VIDIOC_INT_DECODE_VBI_LINE: + case VIDIOC_INT_AUDIO_CLOCK_FREQ: + case VIDIOC_STREAMON: + case VIDIOC_STREAMOFF: + case VIDIOC_LOG_STATUS: + case VIDIOC_G_CTRL: + case VIDIOC_S_CTRL: + case VIDIOC_QUERYCTRL: + case VIDIOC_G_STD: + case VIDIOC_S_STD: + case AUDC_SET_RADIO: + case VIDIOC_INT_G_VIDEO_ROUTING: + case VIDIOC_INT_S_VIDEO_ROUTING: + case VIDIOC_INT_G_AUDIO_ROUTING: + case VIDIOC_INT_S_AUDIO_ROUTING: + case VIDIOC_S_FREQUENCY: + case VIDIOC_G_TUNER: + case VIDIOC_S_TUNER: + case VIDIOC_G_FMT: + case VIDIOC_S_FMT: + case VIDIOC_INT_RESET: + return 1; + default: + return 0; } return 0; } -- cgit v1.2.3 From 4325dff220918c2ced82d16c3475d9a5afb1cab3 Mon Sep 17 00:00:00 2001 From: Andy Walls Date: Sun, 1 Feb 2009 23:44:00 -0300 Subject: V4L/DVB (10437): cx18: Remove an unused spinlock Signed-off-by: Andy Walls Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx18/cx18-driver.c | 2 -- drivers/media/video/cx18/cx18-driver.h | 1 - 2 files changed, 3 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/cx18/cx18-driver.c b/drivers/media/video/cx18/cx18-driver.c index 1518a58e17fc..062f1910e8dd 100644 --- a/drivers/media/video/cx18/cx18-driver.c +++ b/drivers/media/video/cx18/cx18-driver.c @@ -563,8 +563,6 @@ static int __devinit cx18_init_struct1(struct cx18 *cx) mutex_init(&cx->epu2apu_mb_lock); mutex_init(&cx->epu2cpu_mb_lock); - spin_lock_init(&cx->lock); - cx->work_queue = create_singlethread_workqueue(cx->name); if (cx->work_queue == NULL) { CX18_ERR("Unable to create work hander thread\n"); diff --git a/drivers/media/video/cx18/cx18-driver.h b/drivers/media/video/cx18/cx18-driver.h index 3a21013cd82b..d95c6ace2b96 100644 --- a/drivers/media/video/cx18/cx18-driver.h +++ b/drivers/media/video/cx18/cx18-driver.h @@ -429,7 +429,6 @@ struct cx18 { unsigned long i_flags; /* global cx18 flags */ atomic_t ana_capturing; /* count number of active analog capture streams */ atomic_t tot_capturing; /* total count number of active capture streams */ - spinlock_t lock; /* lock access to this struct */ int search_pack_header; int open_id; /* incremented each time an open occurs, used as -- cgit v1.2.3 From 302df9702192a68578916ef922c33370cbba350d Mon Sep 17 00:00:00 2001 From: Andy Walls Date: Sat, 31 Jan 2009 00:33:02 -0300 Subject: V4L/DVB (10439): cx18: Clean-up and enable sliced VBI handling Removed legacy ivtv state variables, added comments, and cleaned up sliced VBI related code. Enabled sliced VBI. Signed-off-by: Andy Walls Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx18/cx18-av-core.c | 11 ++- drivers/media/video/cx18/cx18-av-vbi.c | 92 +++++++++++++++----- drivers/media/video/cx18/cx18-cards.c | 8 +- drivers/media/video/cx18/cx18-cards.h | 3 +- drivers/media/video/cx18/cx18-controls.c | 4 +- drivers/media/video/cx18/cx18-driver.c | 49 +---------- drivers/media/video/cx18/cx18-driver.h | 142 ++++++++++++++++++++++--------- drivers/media/video/cx18/cx18-fileops.c | 54 +++++++++--- drivers/media/video/cx18/cx18-ioctl.c | 77 +++++++++++++++-- drivers/media/video/cx18/cx18-streams.c | 45 +++++++--- drivers/media/video/cx18/cx18-vbi.c | 58 +++++++++---- 11 files changed, 383 insertions(+), 160 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/cx18/cx18-av-core.c b/drivers/media/video/cx18/cx18-av-core.c index 091f0cac0633..1d197649446e 100644 --- a/drivers/media/video/cx18/cx18-av-core.c +++ b/drivers/media/video/cx18/cx18-av-core.c @@ -169,9 +169,14 @@ static void cx18_av_initialize(struct cx18 *cx) /* Set VGA_TRACK_RANGE to 0x20 */ cx18_av_and_or4(cx, CXADEC_DFE_CTRL2, 0xFFFF00FF, 0x00002000); - /* Enable VBI capture */ - cx18_av_write4(cx, CXADEC_OUT_CTRL1, 0x4010253F); - /* cx18_av_write4(cx, CXADEC_OUT_CTRL1, 0x4010253E); */ + /* + * Initial VBI setup + * VIP-1.1, 10 bit mode, enable Raw, disable sliced, + * don't clamp raw samples when codes are in use, 4 byte user D-words, + * programmed IDID, RP code V bit transition on VBLANK, data during + * blanking intervals + */ + cx18_av_write4(cx, CXADEC_OUT_CTRL1, 0x4010252e); /* Set the video input. The setting in MODE_CTRL gets lost when we do the above setup */ diff --git a/drivers/media/video/cx18/cx18-av-vbi.c b/drivers/media/video/cx18/cx18-av-vbi.c index 1527ea4f6b06..72325d774a60 100644 --- a/drivers/media/video/cx18/cx18-av-vbi.c +++ b/drivers/media/video/cx18/cx18-av-vbi.c @@ -24,6 +24,52 @@ #include "cx18-driver.h" +/* + * For sliced VBI output, we set up to use VIP-1.1, 10-bit mode, + * NN counts 4 bytes Dwords, an IDID of 0x00 0x80 or one with the VBI line #. + * Thus, according to the VIP-2 Spec, our VBI ancillary data lines + * (should!) look like: + * 4 byte EAV code: 0xff 0x00 0x00 0xRP + * unknown number of possible idle bytes + * 3 byte Anc data preamble: 0x00 0xff 0xff + * 1 byte data identifier: ne010iii (parity bits, 010, DID bits) + * 1 byte secondary data id: nessssss (parity bits, SDID bits) + * 1 byte data word count: necccccc (parity bits, NN Dword count) + * 2 byte Internal DID: 0x00 0x80 (programmed value) + * 4*NN data bytes + * 1 byte checksum + * Fill bytes needed to fil out to 4*NN bytes of payload + * + * The RP codes for EAVs when in VIP-1.1 mode, not in raw mode, & + * in the vertical blanking interval are: + * 0xb0 (Task 0 VerticalBlank HorizontalBlank 0 0 0 0) + * 0xf0 (Task EvenField VerticalBlank HorizontalBlank 0 0 0 0) + * + * Since the V bit is only allowed to toggle in the EAV RP code, just + * before the first active region line and for active lines, they are: + * 0x90 (Task 0 0 HorizontalBlank 0 0 0 0) + * 0xd0 (Task EvenField 0 HorizontalBlank 0 0 0 0) + * + * The user application DID bytes we care about are: + * 0x91 (1 0 010 0 !ActiveLine AncDataPresent) + * 0x55 (0 1 010 2ndField !ActiveLine AncDataPresent) + * + */ +static const u8 sliced_vbi_did[2] = { 0x91, 0x55 }; + +struct vbi_anc_data { + /* u8 eav[4]; */ + /* u8 idle[]; Variable number of idle bytes */ + u8 preamble[3]; + u8 did; + u8 sdid; + u8 data_count; + u8 idid[2]; + u8 payload[1]; /* 4*data_count of payload */ + /* u8 checksum; */ + /* u8 fill[]; Variable number of fill bytes */ +}; + static int odd_parity(u8 c) { c ^= (c >> 4); @@ -96,7 +142,7 @@ int cx18_av_vbi(struct cx18 *cx, unsigned int cmd, void *arg) 0, V4L2_SLICED_TELETEXT_B, 0, /* 1 */ 0, V4L2_SLICED_WSS_625, 0, /* 4 */ V4L2_SLICED_CAPTION_525, /* 6 */ - 0, 0, V4L2_SLICED_VPS, 0, 0, /* 9 */ + V4L2_SLICED_VPS, 0, 0, 0, 0, /* 7 - unlike cx25840 */ 0, 0, 0, 0 }; int is_pal = !(state->std & V4L2_STD_525_60); @@ -220,47 +266,53 @@ int cx18_av_vbi(struct cx18 *cx, unsigned int cmd, void *arg) case VIDIOC_INT_DECODE_VBI_LINE: { struct v4l2_decode_vbi_line *vbi = arg; - u8 *p = vbi->p; - int id1, id2, l, err = 0; - - if (p[0] || p[1] != 0xff || p[2] != 0xff || - (p[3] != 0x55 && p[3] != 0x91)) { + u8 *p; + struct vbi_anc_data *anc = (struct vbi_anc_data *) vbi->p; + int did, sdid, l, err = 0; + + /* + * Check for the ancillary data header for sliced VBI + */ + if (anc->preamble[0] || + anc->preamble[1] != 0xff || anc->preamble[2] != 0xff || + (anc->did != sliced_vbi_did[0] && + anc->did != sliced_vbi_did[1])) { vbi->line = vbi->type = 0; break; } - p += 4; - id1 = p[-1]; - id2 = p[0] & 0xf; - l = p[2] & 0x3f; + did = anc->did; + sdid = anc->sdid & 0xf; + l = anc->idid[0] & 0x3f; l += state->vbi_line_offset; - p += 4; + p = anc->payload; - switch (id2) { + /* Decode the SDID set by the slicer */ + switch (sdid) { case 1: - id2 = V4L2_SLICED_TELETEXT_B; + sdid = V4L2_SLICED_TELETEXT_B; break; case 4: - id2 = V4L2_SLICED_WSS_625; + sdid = V4L2_SLICED_WSS_625; break; case 6: - id2 = V4L2_SLICED_CAPTION_525; + sdid = V4L2_SLICED_CAPTION_525; err = !odd_parity(p[0]) || !odd_parity(p[1]); break; - case 9: - id2 = V4L2_SLICED_VPS; + case 7: /* Differs from cx25840 */ + sdid = V4L2_SLICED_VPS; if (decode_vps(p, p) != 0) err = 1; break; default: - id2 = 0; + sdid = 0; err = 1; break; } - vbi->type = err ? 0 : id2; + vbi->type = err ? 0 : sdid; vbi->line = err ? 0 : l; - vbi->is_second_field = err ? 0 : (id1 == 0x55); + vbi->is_second_field = err ? 0 : (did == sliced_vbi_did[1]); vbi->p = p; break; } diff --git a/drivers/media/video/cx18/cx18-cards.c b/drivers/media/video/cx18/cx18-cards.c index a0d4d2e49d1b..6e2105ac2bc4 100644 --- a/drivers/media/video/cx18/cx18-cards.c +++ b/drivers/media/video/cx18/cx18-cards.c @@ -51,7 +51,7 @@ static struct cx18_card_tuner_i2c cx18_i2c_std = { static const struct cx18_card cx18_card_hvr1600_esmt = { .type = CX18_CARD_HVR_1600_ESMT, .name = "Hauppauge HVR-1600", - .comment = "Raw VBI supported; Sliced VBI is not yet supported\n", + .comment = "Simultaneous Digital and Analog TV capture supported\n", .v4l2_capabilities = CX18_CAP_ENCODER, .hw_audio_ctrl = CX18_HW_CX23418, .hw_muxer = CX18_HW_CS5345, @@ -97,7 +97,7 @@ static const struct cx18_card cx18_card_hvr1600_esmt = { static const struct cx18_card cx18_card_hvr1600_samsung = { .type = CX18_CARD_HVR_1600_SAMSUNG, .name = "Hauppauge HVR-1600 (Preproduction)", - .comment = "Raw VBI supported; Sliced VBI is not yet supported\n", + .comment = "Simultaneous Digital and Analog TV capture supported\n", .v4l2_capabilities = CX18_CAP_ENCODER, .hw_audio_ctrl = CX18_HW_CX23418, .hw_muxer = CX18_HW_CS5345, @@ -152,7 +152,7 @@ static const struct cx18_card_pci_info cx18_pci_h900[] = { static const struct cx18_card cx18_card_h900 = { .type = CX18_CARD_COMPRO_H900, .name = "Compro VideoMate H900", - .comment = "Raw VBI supported; Sliced VBI is not yet supported\n", + .comment = "Analog TV capture supported\n", .v4l2_capabilities = CX18_CAP_ENCODER, .hw_audio_ctrl = CX18_HW_CX23418, .hw_all = CX18_HW_TUNER, @@ -249,7 +249,7 @@ static const struct cx18_card_pci_info cx18_pci_cnxt_raptor_pal[] = { static const struct cx18_card cx18_card_cnxt_raptor_pal = { .type = CX18_CARD_CNXT_RAPTOR_PAL, .name = "Conexant Raptor PAL/SECAM", - .comment = "Raw VBI supported; Sliced VBI is not yet supported\n", + .comment = "Analog TV capture supported\n", .v4l2_capabilities = CX18_CAP_ENCODER, .hw_audio_ctrl = CX18_HW_CX23418, .hw_muxer = CX18_HW_GPIO, diff --git a/drivers/media/video/cx18/cx18-cards.h b/drivers/media/video/cx18/cx18-cards.h index 6fa7bcb42dde..f8ee29f102d4 100644 --- a/drivers/media/video/cx18/cx18-cards.h +++ b/drivers/media/video/cx18/cx18-cards.h @@ -49,8 +49,7 @@ /* V4L2 capability aliases */ #define CX18_CAP_ENCODER (V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_TUNER | \ V4L2_CAP_AUDIO | V4L2_CAP_READWRITE | \ - V4L2_CAP_VBI_CAPTURE) -/* | V4L2_CAP_SLICED_VBI_CAPTURE) not yet */ + V4L2_CAP_VBI_CAPTURE | V4L2_CAP_SLICED_VBI_CAPTURE) struct cx18_card_video_input { u8 video_type; /* video input type */ diff --git a/drivers/media/video/cx18/cx18-controls.c b/drivers/media/video/cx18/cx18-controls.c index 17edf305d649..6af4d5c190e1 100644 --- a/drivers/media/video/cx18/cx18-controls.c +++ b/drivers/media/video/cx18/cx18-controls.c @@ -178,8 +178,8 @@ static int cx18_setup_vbi_fmt(struct cx18 *cx, enum v4l2_mpeg_stream_vbi_fmt fmt int i; for (i = 0; i < CX18_VBI_FRAMES; i++) { - /* Yuck, hardcoded. Needs to be a define */ - cx->vbi.sliced_mpeg_data[i] = kmalloc(2049, GFP_KERNEL); + cx->vbi.sliced_mpeg_data[i] = + kmalloc(CX18_SLICED_MPEG_DATA_BUFSZ, GFP_KERNEL); if (cx->vbi.sliced_mpeg_data[i] == NULL) { while (--i >= 0) { kfree(cx->vbi.sliced_mpeg_data[i]); diff --git a/drivers/media/video/cx18/cx18-driver.c b/drivers/media/video/cx18/cx18-driver.c index 062f1910e8dd..842ce636e45c 100644 --- a/drivers/media/video/cx18/cx18-driver.c +++ b/drivers/media/video/cx18/cx18-driver.c @@ -586,7 +586,8 @@ static int __devinit cx18_init_struct1(struct cx18 *cx) (cx->params.video_temporal_filter_mode << 1) | (cx->params.video_median_filter_type << 2); cx->params.port = CX2341X_PORT_MEMORY; - cx->params.capabilities = CX2341X_CAP_HAS_TS | CX2341X_CAP_HAS_AC3; + cx->params.capabilities = + CX2341X_CAP_HAS_TS | CX2341X_CAP_HAS_AC3 | CX2341X_CAP_HAS_SLICED_VBI; init_waitqueue_head(&cx->cap_w); init_waitqueue_head(&cx->mb_apu_waitq); init_waitqueue_head(&cx->mb_cpu_waitq); @@ -596,49 +597,6 @@ static int __devinit cx18_init_struct1(struct cx18 *cx) cx->vbi.in.type = V4L2_BUF_TYPE_VBI_CAPTURE; cx->vbi.sliced_in = &cx->vbi.in.fmt.sliced; - /* - * The VBI line sizes depend on the pixel clock and the horiz rate - * - * (1/Fh)*(2*Fp) = Samples/line - * = 4 bytes EAV + Anc data in hblank + 4 bytes SAV + active samples - * - * Sliced VBI is sent as ancillary data during horizontal blanking - * Raw VBI is sent as active video samples during vertcal blanking - * - * We use a BT.656 pxiel clock of 13.5 MHz and a BT.656 active line - * length of 720 pixels @ 4:2:2 sampling. Thus... - * - * For systems that use a 15.734 kHz horizontal rate, such as - * NTSC-M, PAL-M, PAL-60, and other 60 Hz/525 line systems, we have: - * - * (1/15.734 kHz) * 2 * 13.5 MHz = 1716 samples/line = - * 4 bytes SAV + 268 bytes anc data + 4 bytes SAV + 1440 active samples - * - * For systems that use a 15.625 kHz horizontal rate, such as - * PAL-B/G/H, PAL-I, SECAM-L and other 50 Hz/625 line systems, we have: - * - * (1/15.625 kHz) * 2 * 13.5 MHz = 1728 samples/line = - * 4 bytes SAV + 280 bytes anc data + 4 bytes SAV + 1440 active samples - * - */ - - /* FIXME: init these based on tuner std & modify when std changes */ - /* CX18-AV-Core number of VBI samples output per horizontal line */ - cx->vbi.raw_decoder_line_size = 1444; /* 4 byte SAV + 2 * 720 */ - cx->vbi.sliced_decoder_line_size = 272; /* 60 Hz: 268+4, 50 Hz: 280+4 */ - - /* CX18-AV-Core VBI samples/line possibly rounded up */ - cx->vbi.raw_size = 1444; /* Real max size is 1444 */ - cx->vbi.sliced_size = 284; /* Real max size is 284 */ - - /* - * CX18-AV-Core SAV/EAV RP codes in VIP 1.x mode - * Task Field VerticalBlank HorizontalBlank 0 0 0 0 - */ - cx->vbi.raw_decoder_sav_odd_field = 0x20; /* V */ - cx->vbi.raw_decoder_sav_even_field = 0x60; /* FV */ - cx->vbi.sliced_decoder_sav_odd_field = 0xB0; /* T VH - actually EAV */ - cx->vbi.sliced_decoder_sav_even_field = 0xF0; /* TFVH - actually EAV */ return 0; } @@ -671,7 +629,6 @@ static void __devinit cx18_init_struct2(struct cx18 *cx) cx->av_state.aud_input = CX18_AV_AUDIO8; cx->av_state.audclk_freq = 48000; cx->av_state.audmode = V4L2_TUNER_MODE_LANG1; - /* FIXME - 8 is NTSC value, investigate */ cx->av_state.vbi_line_offset = 8; } @@ -936,7 +893,7 @@ static int __devinit cx18_probe(struct pci_dev *pci_dev, * suboptimal, as the CVBS and SVideo inputs could use a different std * and the buffer could end up being too small in that case. */ - vbi_buf_size = cx->vbi.raw_size * (cx->is_60hz ? 24 : 36) / 2; + vbi_buf_size = vbi_active_samples * (cx->is_60hz ? 24 : 36) / 2; cx->stream_buf_size[CX18_ENC_STREAM_TYPE_VBI] = vbi_buf_size; if (cx->stream_buffers[CX18_ENC_STREAM_TYPE_VBI] < 0) diff --git a/drivers/media/video/cx18/cx18-driver.h b/drivers/media/video/cx18/cx18-driver.h index d95c6ace2b96..a41d9c4178f0 100644 --- a/drivers/media/video/cx18/cx18-driver.h +++ b/drivers/media/video/cx18/cx18-driver.h @@ -319,59 +319,121 @@ struct cx18_open_id { /* forward declaration of struct defined in cx18-cards.h */ struct cx18_card; +/* + * A note about "sliced" VBI data as implemented in this driver: + * + * Currently we collect the sliced VBI in the form of Ancillary Data + * packets, inserted by the AV core decoder/digitizer/slicer in the + * horizontal blanking region of the VBI lines, in "raw" mode as far as + * the Encoder is concerned. We don't ever tell the Encoder itself + * to provide sliced VBI. (AV Core: sliced mode - Encoder: raw mode) + * + * We then process the ancillary data ourselves to send the sliced data + * to the user application directly or build up MPEG-2 private stream 1 + * packets to splice into (only!) MPEG-2 PS streams for the user app. + * + * (That's how ivtv essentially does it.) + * + * The Encoder should be able to extract certain sliced VBI data for + * us and provide it in a separate stream or splice it into any type of + * MPEG PS or TS stream, but this isn't implemented yet. + */ + +/* + * Number of "raw" VBI samples per horizontal line we tell the Encoder to + * grab from the decoder/digitizer/slicer output for raw or sliced VBI. + * It depends on the pixel clock and the horiz rate: + * + * (1/Fh)*(2*Fp) = Samples/line + * = 4 bytes EAV + Anc data in hblank + 4 bytes SAV + active samples + * + * Sliced VBI data is sent as ancillary data during horizontal blanking + * Raw VBI is sent as active video samples during vertcal blanking + * + * We use a BT.656 pxiel clock of 13.5 MHz and a BT.656 active line + * length of 720 pixels @ 4:2:2 sampling. Thus... + * + * For systems that use a 15.734 kHz horizontal rate, such as + * NTSC-M, PAL-M, PAL-60, and other 60 Hz/525 line systems, we have: + * + * (1/15.734 kHz) * 2 * 13.5 MHz = 1716 samples/line = + * 4 bytes SAV + 268 bytes anc data + 4 bytes SAV + 1440 active samples + * + * For systems that use a 15.625 kHz horizontal rate, such as + * PAL-B/G/H, PAL-I, SECAM-L and other 50 Hz/625 line systems, we have: + * + * (1/15.625 kHz) * 2 * 13.5 MHz = 1728 samples/line = + * 4 bytes SAV + 280 bytes anc data + 4 bytes SAV + 1440 active samples + */ +static const u32 vbi_active_samples = 1444; /* 4 byte SAV + 720 Y + 720 U/V */ +static const u32 vbi_hblank_samples_60Hz = 272; /* 4 byte EAV + 268 anc/fill */ +static const u32 vbi_hblank_samples_50Hz = 284; /* 4 byte EAV + 280 anc/fill */ #define CX18_VBI_FRAMES 32 -/* VBI data */ struct vbi_info { - u32 enc_size; - u32 frame; - u8 cc_data_odd[256]; - u8 cc_data_even[256]; - int cc_pos; - u8 cc_no_update; - u8 vps[5]; - u8 vps_found; - int wss; - u8 wss_found; - u8 wss_no_update; - u32 raw_decoder_line_size; - u8 raw_decoder_sav_odd_field; - u8 raw_decoder_sav_even_field; - u32 sliced_decoder_line_size; - u8 sliced_decoder_sav_odd_field; - u8 sliced_decoder_sav_even_field; + /* Current state of v4l2 VBI settings for this device */ struct v4l2_format in; - /* convenience pointer to sliced struct in vbi_in union */ - struct v4l2_sliced_vbi_format *sliced_in; - u32 service_set_in; - int insert_mpeg; + struct v4l2_sliced_vbi_format *sliced_in; /* pointer to in.fmt.sliced */ + u32 count; /* Count of VBI data lines: 60 Hz: 12 or 50 Hz: 18 */ + u32 start[2]; /* First VBI data line per field: 10 & 273 or 6 & 318 */ - /* Buffer for the maximum of 2 * 18 * packet_size sliced VBI lines. - One for /dev/vbi0 and one for /dev/vbi8 */ - struct v4l2_sliced_vbi_data sliced_data[36]; + u32 frame; /* Count of VBI buffers/frames received from Encoder */ - /* Buffer for VBI data inserted into MPEG stream. - The first byte is a dummy byte that's never used. - The next 16 bytes contain the MPEG header for the VBI data, - the remainder is the actual VBI data. - The max size accepted by the MPEG VBI reinsertion turns out - to be 1552 bytes, which happens to be 4 + (1 + 42) * (2 * 18) bytes, - where 4 is a four byte header, 42 is the max sliced VBI payload, 1 is - a single line header byte and 2 * 18 is the number of VBI lines per frame. + /* + * Vars for creation and insertion of MPEG Private Stream 1 packets + * of sliced VBI data into an MPEG PS + */ - However, it seems that the data must be 1K aligned, so we have to - pad the data until the 1 or 2 K boundary. + /* Boolean: create and insert Private Stream 1 packets into the PS */ + int insert_mpeg; + + /* + * Buffer for the maximum of 2 * 18 * packet_size sliced VBI lines. + * Used in cx18-vbi.c only for collecting sliced data, and as a source + * during conversion of sliced VBI data into MPEG Priv Stream 1 packets. + * We don't need to save state here, but the array may have been a bit + * too big (2304 bytes) to alloc from the stack. + */ + struct v4l2_sliced_vbi_data sliced_data[36]; - This pointer array will allocate 2049 bytes to store each VBI frame. */ + /* + * A ring buffer of driver-generated MPEG-2 PS + * Program Pack/Private Stream 1 packets for sliced VBI data insertion + * into the MPEG PS stream. + * + * In each sliced_mpeg_data[] buffer is: + * 16 byte MPEG-2 PS Program Pack Header + * 16 byte MPEG-2 Private Stream 1 PES Header + * 4 byte magic number: "itv0" or "ITV0" + * 4 byte first field line mask, if "itv0" + * 4 byte second field line mask, if "itv0" + * 36 lines, if "ITV0"; or <36 lines, if "itv0"; of sliced VBI data + * + * Each line in the payload is + * 1 byte line header derived from the SDID (WSS, CC, VPS, etc.) + * 42 bytes of line data + * + * That's a maximum 1552 bytes of payload in the Private Stream 1 packet + * which is the payload size a PVR-350 (CX23415) MPEG decoder will + * accept for VBI data. So, including the headers, it's a maximum 1584 + * bytes total. + */ +#define CX18_SLICED_MPEG_DATA_MAXSZ 1584 + /* copy_vbi_buf() needs 8 temp bytes on the end for the worst case */ +#define CX18_SLICED_MPEG_DATA_BUFSZ (CX18_SLICED_MPEG_DATA_MAXSZ+8) u8 *sliced_mpeg_data[CX18_VBI_FRAMES]; u32 sliced_mpeg_size[CX18_VBI_FRAMES]; - struct cx18_buffer sliced_mpeg_buf; + + /* Count of Program Pack/Program Stream 1 packets inserted into PS */ u32 inserted_frame; - u32 start[2], count; - u32 raw_size; - u32 sliced_size; + /* + * A dummy driver stream transfer buffer with a copy of the next + * sliced_mpeg_data[] buffer for output to userland apps. + * Only used in cx18-fileops.c, but its state needs to persist at times. + */ + struct cx18_buffer sliced_mpeg_buf; }; /* Per cx23418, per I2C bus private algo callback data */ diff --git a/drivers/media/video/cx18/cx18-fileops.c b/drivers/media/video/cx18/cx18-fileops.c index 23006f7d9159..0b1dbc67e1ab 100644 --- a/drivers/media/video/cx18/cx18-fileops.c +++ b/drivers/media/video/cx18/cx18-fileops.c @@ -176,6 +176,8 @@ static struct cx18_buffer *cx18_get_buffer(struct cx18_stream *s, int non_block, *err = 0; while (1) { if (s->type == CX18_ENC_STREAM_TYPE_MPG) { + /* Process pending program info updates and pending + VBI data */ if (time_after(jiffies, cx->dualwatch_jiffies + msecs_to_jiffies(1000))) { cx->dualwatch_jiffies = jiffies; @@ -260,6 +262,20 @@ static size_t cx18_copy_buf_to_user(struct cx18_stream *s, len = ucount; if (cx->vbi.insert_mpeg && s->type == CX18_ENC_STREAM_TYPE_MPG && !cx18_raw_vbi(cx) && buf != &cx->vbi.sliced_mpeg_buf) { + /* + * Try to find a good splice point in the PS, just before + * an MPEG-2 Program Pack start code, and provide only + * up to that point to the user, so it's easy to insert VBI data + * the next time around. + */ + /* FIXME - This only works for an MPEG-2 PS, not a TS */ + /* + * An MPEG-2 Program Stream (PS) is a series of + * MPEG-2 Program Packs terminated by an + * MPEG Program End Code after the last Program Pack. + * A Program Pack may hold a PS System Header packet and any + * number of Program Elementary Stream (PES) Packets + */ const char *start = buf->buf + buf->readpos; const char *p = start + 1; const u8 *q; @@ -267,38 +283,54 @@ static size_t cx18_copy_buf_to_user(struct cx18_stream *s, int stuffing, i; while (start + len > p) { + /* Scan for a 0 to find a potential MPEG-2 start code */ q = memchr(p, 0, start + len - p); if (q == NULL) break; p = q + 1; + /* + * Keep looking if not a + * MPEG-2 Pack header start code: 0x00 0x00 0x01 0xba + * or MPEG-2 video PES start code: 0x00 0x00 0x01 0xe0 + */ if ((char *)q + 15 >= buf->buf + buf->bytesused || q[1] != 0 || q[2] != 1 || q[3] != ch) continue; + + /* If expecting the primary video PES */ if (!cx->search_pack_header) { + /* Continue if it couldn't be a PES packet */ if ((q[6] & 0xc0) != 0x80) continue; - if (((q[7] & 0xc0) == 0x80 && - (q[9] & 0xf0) == 0x20) || - ((q[7] & 0xc0) == 0xc0 && - (q[9] & 0xf0) == 0x30)) { - ch = 0xba; + /* Check if a PTS or PTS & DTS follow */ + if (((q[7] & 0xc0) == 0x80 && /* PTS only */ + (q[9] & 0xf0) == 0x20) || /* PTS only */ + ((q[7] & 0xc0) == 0xc0 && /* PTS & DTS */ + (q[9] & 0xf0) == 0x30)) { /* DTS follows */ + /* Assume we found the video PES hdr */ + ch = 0xba; /* next want a Program Pack*/ cx->search_pack_header = 1; - p = q + 9; + p = q + 9; /* Skip this video PES hdr */ } continue; } + + /* We may have found a Program Pack start code */ + + /* Get the count of stuffing bytes & verify them */ stuffing = q[13] & 7; /* all stuffing bytes must be 0xff */ for (i = 0; i < stuffing; i++) if (q[14 + i] != 0xff) break; - if (i == stuffing && - (q[4] & 0xc4) == 0x44 && - (q[12] & 3) == 3 && - q[14 + stuffing] == 0 && + if (i == stuffing && /* right number of stuffing bytes*/ + (q[4] & 0xc4) == 0x44 && /* marker check */ + (q[12] & 3) == 3 && /* marker check */ + q[14 + stuffing] == 0 && /* PES Pack or Sys Hdr */ q[15 + stuffing] == 0 && q[16 + stuffing] == 1) { - cx->search_pack_header = 0; + /* We declare we actually found a Program Pack*/ + cx->search_pack_header = 0; /* expect vid PES */ len = (char *)q - start; cx18_setup_sliced_vbi_buf(cx); break; diff --git a/drivers/media/video/cx18/cx18-ioctl.c b/drivers/media/video/cx18/cx18-ioctl.c index 20467fce5251..1adb97220920 100644 --- a/drivers/media/video/cx18/cx18-ioctl.c +++ b/drivers/media/video/cx18/cx18-ioctl.c @@ -102,6 +102,19 @@ void cx18_expand_service_set(struct v4l2_sliced_vbi_format *fmt, int is_pal) } } +static int check_service_set(struct v4l2_sliced_vbi_format *fmt, int is_pal) +{ + int f, l; + u16 set = 0; + + for (f = 0; f < 2; f++) { + for (l = 0; l < 24; l++) { + fmt->service_lines[f][l] = select_service_from_set(f, l, fmt->service_lines[f][l], is_pal); + set |= fmt->service_lines[f][l]; + } + } + return set != 0; +} u16 cx18_get_service_set(struct v4l2_sliced_vbi_format *fmt) { @@ -150,7 +163,7 @@ static int cx18_g_fmt_vbi_cap(struct file *file, void *fh, vbifmt->sampling_rate = 27000000; vbifmt->offset = 248; - vbifmt->samples_per_line = cx->vbi.raw_decoder_line_size - 4; + vbifmt->samples_per_line = vbi_active_samples - 4; vbifmt->sample_format = V4L2_PIX_FMT_GREY; vbifmt->start[0] = cx->vbi.start[0]; vbifmt->start[1] = cx->vbi.start[1]; @@ -164,7 +177,17 @@ static int cx18_g_fmt_vbi_cap(struct file *file, void *fh, static int cx18_g_fmt_sliced_vbi_cap(struct file *file, void *fh, struct v4l2_format *fmt) { - return -EINVAL; + struct cx18 *cx = ((struct cx18_open_id *)fh)->cx; + struct v4l2_sliced_vbi_format *vbifmt = &fmt->fmt.sliced; + + vbifmt->reserved[0] = 0; + vbifmt->reserved[1] = 0; + vbifmt->io_size = sizeof(struct v4l2_sliced_vbi_data) * 36; + memset(vbifmt->service_lines, 0, sizeof(vbifmt->service_lines)); + + cx18_av_cmd(cx, VIDIOC_G_FMT, fmt); + vbifmt->service_set = cx18_get_service_set(vbifmt); + return 0; } static int cx18_try_fmt_vid_cap(struct file *file, void *fh, @@ -194,7 +217,18 @@ static int cx18_try_fmt_vbi_cap(struct file *file, void *fh, static int cx18_try_fmt_sliced_vbi_cap(struct file *file, void *fh, struct v4l2_format *fmt) { - return -EINVAL; + struct cx18 *cx = ((struct cx18_open_id *)fh)->cx; + struct v4l2_sliced_vbi_format *vbifmt = &fmt->fmt.sliced; + + vbifmt->io_size = sizeof(struct v4l2_sliced_vbi_data) * 36; + vbifmt->reserved[0] = 0; + vbifmt->reserved[1] = 0; + + if (vbifmt->service_set) + cx18_expand_service_set(vbifmt, cx->is_50hz); + check_service_set(vbifmt, cx->is_50hz); + vbifmt->service_set = cx18_get_service_set(vbifmt); + return 0; } static int cx18_s_fmt_vid_cap(struct file *file, void *fh, @@ -250,7 +284,28 @@ static int cx18_s_fmt_vbi_cap(struct file *file, void *fh, static int cx18_s_fmt_sliced_vbi_cap(struct file *file, void *fh, struct v4l2_format *fmt) { - return -EINVAL; + struct cx18_open_id *id = fh; + struct cx18 *cx = id->cx; + int ret; + struct v4l2_sliced_vbi_format *vbifmt = &fmt->fmt.sliced; + + ret = v4l2_prio_check(&cx->prio, &id->prio); + if (ret) + return ret; + + ret = cx18_try_fmt_sliced_vbi_cap(file, fh, fmt); + if (ret) + return ret; + + if (check_service_set(vbifmt, cx->is_50hz) == 0) + return -EINVAL; + + if (cx18_raw_vbi(cx) && atomic_read(&cx->ana_capturing) > 0) + return -EBUSY; + cx->vbi.in.type = V4L2_BUF_TYPE_SLICED_VBI_CAPTURE; + cx18_av_cmd(cx, VIDIOC_S_FMT, fmt); + memcpy(cx->vbi.sliced_in, vbifmt, sizeof(*cx->vbi.sliced_in)); + return 0; } static int cx18_g_chip_ident(struct file *file, void *fh, @@ -548,7 +603,6 @@ int cx18_s_std(struct file *file, void *fh, v4l2_std_id *std) cx->vbi.count = cx->is_50hz ? 18 : 12; cx->vbi.start[0] = cx->is_50hz ? 6 : 10; cx->vbi.start[1] = cx->is_50hz ? 318 : 273; - cx->vbi.sliced_decoder_line_size = cx->is_60hz ? 272 : 284; CX18_DEBUG_INFO("Switching standard to %llx.\n", (unsigned long long) cx->std); @@ -599,6 +653,19 @@ static int cx18_g_tuner(struct file *file, void *fh, struct v4l2_tuner *vt) static int cx18_g_sliced_vbi_cap(struct file *file, void *fh, struct v4l2_sliced_vbi_cap *cap) { + struct cx18 *cx = ((struct cx18_open_id *)fh)->cx; + int set = cx->is_50hz ? V4L2_SLICED_VBI_625 : V4L2_SLICED_VBI_525; + int f, l; + + if (cap->type == V4L2_BUF_TYPE_SLICED_VBI_CAPTURE) { + for (f = 0; f < 2; f++) { + for (l = 0; l < 24; l++) { + if (valid_service_line(f, l, cx->is_50hz)) + cap->service_lines[f][l] = set; + } + } + return 0; + } return -EINVAL; } diff --git a/drivers/media/video/cx18/cx18-streams.c b/drivers/media/video/cx18/cx18-streams.c index abc3fe605f00..a89f7f840d95 100644 --- a/drivers/media/video/cx18/cx18-streams.c +++ b/drivers/media/video/cx18/cx18-streams.c @@ -349,10 +349,6 @@ static void cx18_vbi_setup(struct cx18_stream *s) /* setup VBI registers */ cx18_av_cmd(cx, VIDIOC_S_FMT, &cx->vbi.in); - /* determine number of lines and total number of VBI bytes. - A raw line takes 1444 bytes: 4 byte SAV code + 2 * 720 - A sliced line takes 51 bytes: 4 byte frame header, 4 byte internal - header, 42 data bytes + checksum (to be confirmed) */ if (raw) { lines = cx->vbi.count * 2; } else { @@ -361,24 +357,53 @@ static void cx18_vbi_setup(struct cx18_stream *s) lines += 2; } - cx->vbi.enc_size = lines * - (raw ? cx->vbi.raw_size : cx->vbi.sliced_size); - data[0] = s->handle; /* Lines per field */ data[1] = (lines / 2) | ((lines / 2) << 16); /* bytes per line */ - data[2] = (raw ? cx->vbi.raw_decoder_line_size - : cx->vbi.sliced_decoder_line_size); + data[2] = (raw ? vbi_active_samples + : (cx->is_60hz ? vbi_hblank_samples_60Hz + : vbi_hblank_samples_50Hz)); /* Every X number of frames a VBI interrupt arrives (frames as in 25 or 30 fps) */ data[3] = 1; - /* Setup VBI for the cx25840 digitizer */ + /* + * Set the SAV/EAV RP codes to look for as start/stop points + * when in VIP-1.1 mode + */ if (raw) { + /* + * Start codes for beginning of "active" line in vertical blank + * 0x20 ( VerticalBlank ) + * 0x60 ( EvenField VerticalBlank ) + */ data[4] = 0x20602060; + /* + * End codes for end of "active" raw lines and regular lines + * 0x30 ( VerticalBlank HorizontalBlank) + * 0x70 ( EvenField VerticalBlank HorizontalBlank) + * 0x90 (Task HorizontalBlank) + * 0xd0 (Task EvenField HorizontalBlank) + */ data[5] = 0x307090d0; } else { + /* + * End codes for active video, we want data in the hblank region + * 0xb0 (Task 0 VerticalBlank HorizontalBlank) + * 0xf0 (Task EvenField VerticalBlank HorizontalBlank) + * + * Since the V bit is only allowed to toggle in the EAV RP code, + * just before the first active region line, these two + * are problematic and we have to ignore them: + * 0x90 (Task HorizontalBlank) + * 0xd0 (Task EvenField HorizontalBlank) + */ data[4] = 0xB0F0B0F0; + /* + * Start codes for beginning of active line in vertical blank + * 0xa0 (Task VerticalBlank ) + * 0xe0 (Task EvenField VerticalBlank ) + */ data[5] = 0xA0E0A0E0; } diff --git a/drivers/media/video/cx18/cx18-vbi.c b/drivers/media/video/cx18/cx18-vbi.c index fb595bd548e8..38d26c42e4cb 100644 --- a/drivers/media/video/cx18/cx18-vbi.c +++ b/drivers/media/video/cx18/cx18-vbi.c @@ -27,6 +27,16 @@ #include "cx18-queue.h" #include "cx18-av-core.h" +/* + * Raster Reference/Protection (RP) bytes, used in Start/End Active + * Video codes emitted from the digitzer in VIP 1.x mode, that flag the start + * of VBI sample or VBI ancilliary data regions in the digitial ratser line. + * + * Task FieldEven VerticalBlank HorizontalBlank 0 0 0 0 + */ +static const u8 raw_vbi_sav_rp[2] = { 0x20, 0x60 }; /* __V_, _FV_ */ +static const u8 sliced_vbi_eav_rp[2] = { 0xb0, 0xf0 }; /* T_VH, TFVH */ + static void copy_vbi_data(struct cx18 *cx, int lines, u32 pts_stamp) { int line = 0; @@ -34,10 +44,17 @@ static void copy_vbi_data(struct cx18 *cx, int lines, u32 pts_stamp) u32 linemask[2] = { 0, 0 }; unsigned short size; static const u8 mpeg_hdr_data[] = { - 0x00, 0x00, 0x01, 0xba, 0x44, 0x00, 0x0c, 0x66, - 0x24, 0x01, 0x01, 0xd1, 0xd3, 0xfa, 0xff, 0xff, - 0x00, 0x00, 0x01, 0xbd, 0x00, 0x1a, 0x84, 0x80, - 0x07, 0x21, 0x00, 0x5d, 0x63, 0xa7, 0xff, 0xff + /* MPEG-2 Program Pack */ + 0x00, 0x00, 0x01, 0xba, /* Prog Pack start code */ + 0x44, 0x00, 0x0c, 0x66, 0x24, 0x01, /* SCR, SCR Ext, markers */ + 0x01, 0xd1, 0xd3, /* Mux Rate, markers */ + 0xfa, 0xff, 0xff, /* Res, Suff cnt, Stuff */ + /* MPEG-2 Private Stream 1 PES Packet */ + 0x00, 0x00, 0x01, 0xbd, /* Priv Stream 1 start */ + 0x00, 0x1a, /* length */ + 0x84, 0x80, 0x07, /* flags, hdr data len */ + 0x21, 0x00, 0x5d, 0x63, 0xa7, /* PTS, markers */ + 0xff, 0xff /* stuffing */ }; const int sd = sizeof(mpeg_hdr_data); /* start of vbi data */ int idx = cx->vbi.frame % CX18_VBI_FRAMES; @@ -71,7 +88,7 @@ static void copy_vbi_data(struct cx18 *cx, int lines, u32 pts_stamp) memcpy(dst + sd + 4, dst + sd + 12, line * 43); size = 4 + ((43 * line + 3) & ~3); } else { - memcpy(dst + sd, "cx0", 4); + memcpy(dst + sd, "itv0", 4); memcpy(dst + sd + 4, &linemask[0], 8); size = 12 + ((43 * line + 3) & ~3); } @@ -90,10 +107,10 @@ static void copy_vbi_data(struct cx18 *cx, int lines, u32 pts_stamp) Returns new compressed size. */ static u32 compress_raw_buf(struct cx18 *cx, u8 *buf, u32 size) { - u32 line_size = cx->vbi.raw_decoder_line_size; + u32 line_size = vbi_active_samples; u32 lines = cx->vbi.count; - u8 sav1 = cx->vbi.raw_decoder_sav_odd_field; - u8 sav2 = cx->vbi.raw_decoder_sav_even_field; + u8 sav1 = raw_vbi_sav_rp[0]; + u8 sav2 = raw_vbi_sav_rp[1]; u8 *q = buf; u8 *p; int i; @@ -115,15 +132,16 @@ static u32 compress_raw_buf(struct cx18 *cx, u8 *buf, u32 size) /* Compressed VBI format, all found sliced blocks put next to one another Returns new compressed size */ static u32 compress_sliced_buf(struct cx18 *cx, u32 line, u8 *buf, - u32 size, u8 sav) + u32 size, u8 eav) { - u32 line_size = cx->vbi.sliced_decoder_line_size; struct v4l2_decode_vbi_line vbi; int i; + u32 line_size = cx->is_60hz ? vbi_hblank_samples_60Hz + : vbi_hblank_samples_50Hz; /* find the first valid line */ for (i = 0; i < size; i++, buf++) { - if (buf[0] == 0xff && !buf[1] && !buf[2] && buf[3] == sav) + if (buf[0] == 0xff && !buf[1] && !buf[2] && buf[3] == eav) break; } @@ -133,8 +151,8 @@ static u32 compress_sliced_buf(struct cx18 *cx, u32 line, u8 *buf, for (i = 0; i < size / line_size; i++) { u8 *p = buf + i * line_size; - /* Look for SAV code */ - if (p[0] != 0xff || p[1] || p[2] || p[3] != sav) + /* Look for EAV code */ + if (p[0] != 0xff || p[1] || p[2] || p[3] != eav) continue; vbi.p = p + 4; cx18_av_cmd(cx, VIDIOC_INT_DECODE_VBI_LINE, &vbi); @@ -159,6 +177,12 @@ void cx18_process_vbi_data(struct cx18 *cx, struct cx18_buffer *buf, if (streamtype != CX18_ENC_STREAM_TYPE_VBI) return; + /* + * Note the CX23418 provides a 12 byte header, in it's raw VBI + * buffers to us, that we currently throw away: + * 0x3fffffff [4 bytes of something] [4 byte timestamp] + */ + /* Raw VBI data */ if (cx18_raw_vbi(cx)) { u8 type; @@ -173,7 +197,7 @@ void cx18_process_vbi_data(struct cx18 *cx, struct cx18_buffer *buf, size = buf->bytesused = compress_raw_buf(cx, p, size); /* second field of the frame? */ - if (type == cx->vbi.raw_decoder_sav_even_field) { + if (type == raw_vbi_sav_rp[1]) { /* Dirty hack needed for backwards compatibility of old VBI software. */ p += size - 4; @@ -187,14 +211,14 @@ void cx18_process_vbi_data(struct cx18 *cx, struct cx18_buffer *buf, cx18_buf_swap(buf); /* first field */ - lines = compress_sliced_buf(cx, 0, p, size / 2, - cx->vbi.sliced_decoder_sav_odd_field); + /* compress_sliced_buf() will skip the 12 bytes of header */ + lines = compress_sliced_buf(cx, 0, p, size / 2, sliced_vbi_eav_rp[0]); /* second field */ /* experimentation shows that the second half does not always begin at the exact address. So start a bit earlier (hence 32). */ lines = compress_sliced_buf(cx, lines, p + size / 2 - 32, - size / 2 + 32, cx->vbi.sliced_decoder_sav_even_field); + size / 2 + 32, sliced_vbi_eav_rp[1]); /* always return at least one empty line */ if (lines == 0) { cx->vbi.sliced_data[0].id = 0; -- cgit v1.2.3 From 776fa869883e60a065df13e73252344477c8e1aa Mon Sep 17 00:00:00 2001 From: Andy Walls Date: Sun, 1 Feb 2009 21:42:12 -0300 Subject: V4L/DVB (10440): cx18: Fix presentation timestamp (PTS) for VBI buffers The old code from ivtv used a CX23415/6 PTS, which was simply left at 0 in the cx18 driver. Since the CX23418 gives us what I think is a PTS (or some other 90 kHz clock count) with each VBI buffer, this change has the cx18 driver use that as a PTS. Signed-off-by: Andy Walls Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx18/cx18-driver.h | 1 - drivers/media/video/cx18/cx18-fileops.c | 4 +--- drivers/media/video/cx18/cx18-vbi.c | 18 ++++++++++-------- drivers/media/video/cx18/cx18-vbi.h | 2 +- 4 files changed, 12 insertions(+), 13 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/cx18/cx18-driver.h b/drivers/media/video/cx18/cx18-driver.h index a41d9c4178f0..c9b6df50ab27 100644 --- a/drivers/media/video/cx18/cx18-driver.h +++ b/drivers/media/video/cx18/cx18-driver.h @@ -293,7 +293,6 @@ struct cx18_stream { int dma; /* can be PCI_DMA_TODEVICE, PCI_DMA_FROMDEVICE or PCI_DMA_NONE */ - u64 dma_pts; wait_queue_head_t waitq; /* Buffer Stats */ diff --git a/drivers/media/video/cx18/cx18-fileops.c b/drivers/media/video/cx18/cx18-fileops.c index 0b1dbc67e1ab..68dd50ac4bfe 100644 --- a/drivers/media/video/cx18/cx18-fileops.c +++ b/drivers/media/video/cx18/cx18-fileops.c @@ -188,7 +188,6 @@ static struct cx18_buffer *cx18_get_buffer(struct cx18_stream *s, int non_block, while ((buf = cx18_dequeue(s_vbi, &s_vbi->q_full))) { /* byteswap and process VBI data */ cx18_process_vbi_data(cx, buf, - s_vbi->dma_pts, s_vbi->type); cx18_stream_put_buf_fw(s_vbi, buf); } @@ -209,8 +208,7 @@ static struct cx18_buffer *cx18_get_buffer(struct cx18_stream *s, int non_block, cx18_buf_swap(buf); else { /* byteswap and process VBI data */ - cx18_process_vbi_data(cx, buf, - s->dma_pts, s->type); + cx18_process_vbi_data(cx, buf, s->type); } return buf; } diff --git a/drivers/media/video/cx18/cx18-vbi.c b/drivers/media/video/cx18/cx18-vbi.c index 38d26c42e4cb..d6e15e119582 100644 --- a/drivers/media/video/cx18/cx18-vbi.c +++ b/drivers/media/video/cx18/cx18-vbi.c @@ -168,27 +168,28 @@ static u32 compress_sliced_buf(struct cx18 *cx, u32 line, u8 *buf, } void cx18_process_vbi_data(struct cx18 *cx, struct cx18_buffer *buf, - u64 pts_stamp, int streamtype) + int streamtype) { u8 *p = (u8 *) buf->buf; + u32 *q = (u32 *) buf->buf; u32 size = buf->bytesused; + u32 pts; int lines; if (streamtype != CX18_ENC_STREAM_TYPE_VBI) return; + cx18_buf_swap(buf); + /* - * Note the CX23418 provides a 12 byte header, in it's raw VBI - * buffers to us, that we currently throw away: - * 0x3fffffff [4 bytes of something] [4 byte timestamp] + * The CX23418 provides a 12 byte header in it's raw VBI buffers to us: + * 0x3fffffff [4 bytes of something] [4 byte presentation time stamp?] */ /* Raw VBI data */ if (cx18_raw_vbi(cx)) { u8 type; - cx18_buf_swap(buf); - /* Skip 12 bytes of header that gets stuffed in */ size -= 12; memcpy(p, &buf->buf[12], size); @@ -208,7 +209,8 @@ void cx18_process_vbi_data(struct cx18 *cx, struct cx18_buffer *buf, } /* Sliced VBI data with data insertion */ - cx18_buf_swap(buf); + + pts = (q[0] == 0x3fffffff) ? q[2] : 0; /* first field */ /* compress_sliced_buf() will skip the 12 bytes of header */ @@ -230,6 +232,6 @@ void cx18_process_vbi_data(struct cx18 *cx, struct cx18_buffer *buf, memcpy(p, &cx->vbi.sliced_data[0], size); if (cx->vbi.insert_mpeg) - copy_vbi_data(cx, lines, pts_stamp); + copy_vbi_data(cx, lines, pts); cx->vbi.frame++; } diff --git a/drivers/media/video/cx18/cx18-vbi.h b/drivers/media/video/cx18/cx18-vbi.h index c56ff7d28f20..e7e1ae427f34 100644 --- a/drivers/media/video/cx18/cx18-vbi.h +++ b/drivers/media/video/cx18/cx18-vbi.h @@ -22,5 +22,5 @@ */ void cx18_process_vbi_data(struct cx18 *cx, struct cx18_buffer *buf, - u64 pts_stamp, int streamtype); + int streamtype); int cx18_used_line(struct cx18 *cx, int line, int field); -- cgit v1.2.3 From c1994084d6ad7d1a411219727fc135a18c40f9c8 Mon Sep 17 00:00:00 2001 From: Andy Walls Date: Thu, 5 Feb 2009 22:37:49 -0300 Subject: V4L/DVB (10441): cx18: Fix VBI ioctl() handling and Raw/Sliced VBI state management More sliced VBI fixes to bring the cx18 driver closer to full V4L2 spec compliance for VBI and to get sliced VBI working better. Signed-off-by: Andy Walls Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx18/cx18-av-vbi.c | 14 +++-- drivers/media/video/cx18/cx18-ioctl.c | 109 ++++++++++++++++++++++++++------- 2 files changed, 94 insertions(+), 29 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/cx18/cx18-av-vbi.c b/drivers/media/video/cx18/cx18-av-vbi.c index 72325d774a60..b5763372a316 100644 --- a/drivers/media/video/cx18/cx18-av-vbi.c +++ b/drivers/media/video/cx18/cx18-av-vbi.c @@ -25,8 +25,8 @@ #include "cx18-driver.h" /* - * For sliced VBI output, we set up to use VIP-1.1, 10-bit mode, - * NN counts 4 bytes Dwords, an IDID of 0x00 0x80 or one with the VBI line #. + * For sliced VBI output, we set up to use VIP-1.1, 8-bit mode, + * NN counts 1 byte Dwords, an IDID with the VBI line # in it. * Thus, according to the VIP-2 Spec, our VBI ancillary data lines * (should!) look like: * 4 byte EAV code: 0xff 0x00 0x00 0xRP @@ -35,8 +35,8 @@ * 1 byte data identifier: ne010iii (parity bits, 010, DID bits) * 1 byte secondary data id: nessssss (parity bits, SDID bits) * 1 byte data word count: necccccc (parity bits, NN Dword count) - * 2 byte Internal DID: 0x00 0x80 (programmed value) - * 4*NN data bytes + * 2 byte Internal DID: VBI-line-# 0x80 + * NN data bytes * 1 byte checksum * Fill bytes needed to fil out to 4*NN bytes of payload * @@ -65,7 +65,7 @@ struct vbi_anc_data { u8 sdid; u8 data_count; u8 idid[2]; - u8 payload[1]; /* 4*data_count of payload */ + u8 payload[1]; /* data_count of payload */ /* u8 checksum; */ /* u8 fill[]; Variable number of fill bytes */ }; @@ -215,6 +215,7 @@ int cx18_av_vbi(struct cx18 *cx, unsigned int cmd, void *arg) cx18_av_write(cx, 0x406, 0x13); cx18_av_write(cx, 0x47f, vbi_offset); + /* Force impossible lines to 0 */ if (is_pal) { for (i = 0; i <= 6; i++) svbi->service_lines[0][i] = @@ -229,6 +230,7 @@ int cx18_av_vbi(struct cx18 *cx, unsigned int cmd, void *arg) svbi->service_lines[1][i] = 0; } + /* Build register values for requested service lines */ for (i = 7; i <= 23; i++) { for (x = 0; x <= 1; x++) { switch (svbi->service_lines[1-x][i]) { @@ -242,7 +244,7 @@ int cx18_av_vbi(struct cx18 *cx, unsigned int cmd, void *arg) lcr[i] |= 6 << (4 * x); break; case V4L2_SLICED_VPS: - lcr[i] |= 9 << (4 * x); + lcr[i] |= 7 << (4 * x); /*'840 differs*/ break; } } diff --git a/drivers/media/video/cx18/cx18-ioctl.c b/drivers/media/video/cx18/cx18-ioctl.c index 1adb97220920..a454ede568a5 100644 --- a/drivers/media/video/cx18/cx18-ioctl.c +++ b/drivers/media/video/cx18/cx18-ioctl.c @@ -42,6 +42,13 @@ #include #include +static int cx18_vbi_streaming(struct cx18 *cx) +{ + struct cx18_stream *s_vbi = &cx->streams[CX18_ENC_STREAM_TYPE_VBI]; + return (s_vbi->handle != CX18_INVALID_TASK_HANDLE) && + test_bit(CX18_F_S_STREAMING, &s_vbi->s_flags); +} + u16 cx18_service2vbi(int type) { switch (type) { @@ -58,12 +65,21 @@ u16 cx18_service2vbi(int type) } } +/* Check if VBI services are allowed on the (field, line) for the video std */ static int valid_service_line(int field, int line, int is_pal) { - return (is_pal && line >= 6 && (line != 23 || field == 0)) || + return (is_pal && line >= 6 && + ((field == 0 && line <= 23) || (field == 1 && line <= 22))) || (!is_pal && line >= 10 && line < 22); } +/* + * For a (field, line, std) and inbound potential set of services for that line, + * return the first valid service of those passed in the incoming set for that + * line in priority order: + * CC, VPS, or WSS over TELETEXT for well known lines + * TELETEXT, before VPS, before CC, before WSS, for other lines + */ static u16 select_service_from_set(int field, int line, u16 set, int is_pal) { u16 valid_set = (is_pal ? V4L2_SLICED_VBI_625 : V4L2_SLICED_VBI_525); @@ -90,6 +106,10 @@ static u16 select_service_from_set(int field, int line, u16 set, int is_pal) return 0; } +/* + * Expand the service_set of *fmt into valid service_lines for the std, + * and clear the passed in fmt->service_set + */ void cx18_expand_service_set(struct v4l2_sliced_vbi_format *fmt, int is_pal) { u16 set = fmt->service_set; @@ -102,6 +122,10 @@ void cx18_expand_service_set(struct v4l2_sliced_vbi_format *fmt, int is_pal) } } +/* + * Sanitize the service_lines in *fmt per the video std, and return 1 + * if any service_line is left as valid after santization + */ static int check_service_set(struct v4l2_sliced_vbi_format *fmt, int is_pal) { int f, l; @@ -116,6 +140,7 @@ static int check_service_set(struct v4l2_sliced_vbi_format *fmt, int is_pal) return set != 0; } +/* Compute the service_set from the assumed valid service_lines of *fmt */ u16 cx18_get_service_set(struct v4l2_sliced_vbi_format *fmt) { int f, l; @@ -162,7 +187,7 @@ static int cx18_g_fmt_vbi_cap(struct file *file, void *fh, struct v4l2_vbi_format *vbifmt = &fmt->fmt.vbi; vbifmt->sampling_rate = 27000000; - vbifmt->offset = 248; + vbifmt->offset = 248; /* FIXME - slightly wrong for both 50 & 60 Hz */ vbifmt->samples_per_line = vbi_active_samples - 4; vbifmt->sample_format = V4L2_PIX_FMT_GREY; vbifmt->start[0] = cx->vbi.start[0]; @@ -180,12 +205,25 @@ static int cx18_g_fmt_sliced_vbi_cap(struct file *file, void *fh, struct cx18 *cx = ((struct cx18_open_id *)fh)->cx; struct v4l2_sliced_vbi_format *vbifmt = &fmt->fmt.sliced; + /* sane, V4L2 spec compliant, defaults */ vbifmt->reserved[0] = 0; vbifmt->reserved[1] = 0; vbifmt->io_size = sizeof(struct v4l2_sliced_vbi_data) * 36; memset(vbifmt->service_lines, 0, sizeof(vbifmt->service_lines)); + vbifmt->service_set = 0; + + /* + * Fetch the configured service_lines and total service_set from the + * digitizer/slicer. Note, cx18_av_vbi() wipes the passed in + * fmt->fmt.sliced under valid calling conditions + */ + if (cx18_av_cmd(cx, VIDIOC_G_FMT, fmt)) + return -EINVAL; - cx18_av_cmd(cx, VIDIOC_G_FMT, fmt); + /* Ensure V4L2 spec compliant output */ + vbifmt->reserved[0] = 0; + vbifmt->reserved[1] = 0; + vbifmt->io_size = sizeof(struct v4l2_sliced_vbi_data) * 36; vbifmt->service_set = cx18_get_service_set(vbifmt); return 0; } @@ -224,10 +262,12 @@ static int cx18_try_fmt_sliced_vbi_cap(struct file *file, void *fh, vbifmt->reserved[0] = 0; vbifmt->reserved[1] = 0; + /* If given a service set, expand it validly & clear passed in set */ if (vbifmt->service_set) cx18_expand_service_set(vbifmt, cx->is_50hz); - check_service_set(vbifmt, cx->is_50hz); - vbifmt->service_set = cx18_get_service_set(vbifmt); + /* Sanitize the service_lines, and compute the new set if any valid */ + if (check_service_set(vbifmt, cx->is_50hz)) + vbifmt->service_set = cx18_get_service_set(vbifmt); return 0; } @@ -272,12 +312,22 @@ static int cx18_s_fmt_vbi_cap(struct file *file, void *fh, if (ret) return ret; - if (!cx18_raw_vbi(cx) && atomic_read(&cx->ana_capturing) > 0) + if (!cx18_raw_vbi(cx) && cx18_vbi_streaming(cx)) return -EBUSY; + /* + * Set the digitizer registers for raw active VBI. + * Note cx18_av_vbi_wipes out alot of the passed in fmt under valid + * calling conditions + */ + ret = cx18_av_cmd(cx, VIDIOC_S_FMT, fmt); + if (ret) + return ret; + + /* Store our new v4l2 (non-)sliced VBI state */ cx->vbi.sliced_in->service_set = 0; cx->vbi.in.type = V4L2_BUF_TYPE_VBI_CAPTURE; - cx18_av_cmd(cx, VIDIOC_S_FMT, fmt); + return cx18_g_fmt_vbi_cap(file, fh, fmt); } @@ -293,17 +343,20 @@ static int cx18_s_fmt_sliced_vbi_cap(struct file *file, void *fh, if (ret) return ret; - ret = cx18_try_fmt_sliced_vbi_cap(file, fh, fmt); - if (ret) - return ret; - - if (check_service_set(vbifmt, cx->is_50hz) == 0) - return -EINVAL; + cx18_try_fmt_sliced_vbi_cap(file, fh, fmt); - if (cx18_raw_vbi(cx) && atomic_read(&cx->ana_capturing) > 0) + if (cx18_raw_vbi(cx) && cx18_vbi_streaming(cx)) return -EBUSY; + /* + * Set the service_lines requested in the digitizer/slicer registers. + * Note, cx18_av_vbi() wipes some "impossible" service lines in the + * passed in fmt->fmt.sliced under valid calling conditions + */ + ret = cx18_av_cmd(cx, VIDIOC_S_FMT, fmt); + if (ret) + return ret; + /* Store our current v4l2 sliced VBI settings */ cx->vbi.in.type = V4L2_BUF_TYPE_SLICED_VBI_CAPTURE; - cx18_av_cmd(cx, VIDIOC_S_FMT, fmt); memcpy(cx->vbi.sliced_in, vbifmt, sizeof(*cx->vbi.sliced_in)); return 0; } @@ -657,16 +710,26 @@ static int cx18_g_sliced_vbi_cap(struct file *file, void *fh, int set = cx->is_50hz ? V4L2_SLICED_VBI_625 : V4L2_SLICED_VBI_525; int f, l; - if (cap->type == V4L2_BUF_TYPE_SLICED_VBI_CAPTURE) { - for (f = 0; f < 2; f++) { - for (l = 0; l < 24; l++) { - if (valid_service_line(f, l, cx->is_50hz)) - cap->service_lines[f][l] = set; - } + if (cap->type != V4L2_BUF_TYPE_SLICED_VBI_CAPTURE) + return -EINVAL; + + cap->service_set = 0; + for (f = 0; f < 2; f++) { + for (l = 0; l < 24; l++) { + if (valid_service_line(f, l, cx->is_50hz)) { + /* + * We can find all v4l2 supported vbi services + * for the standard, on a valid line for the std + */ + cap->service_lines[f][l] = set; + cap->service_set |= set; + } else + cap->service_lines[f][l] = 0; } - return 0; } - return -EINVAL; + for (f = 0; f < 3; f++) + cap->reserved[f] = 0; + return 0; } static int cx18_g_enc_index(struct file *file, void *fh, -- cgit v1.2.3 From dcc0ef88209a26719241bcb7741f05f1b9ecc30e Mon Sep 17 00:00:00 2001 From: Andy Walls Date: Fri, 6 Feb 2009 18:33:43 -0300 Subject: V4L/DVB (10442): cx18: Fixes for enforcing when Encoder Raw VBI params can be set The Encoder will only allow the Raw VBI parameters, along with a number of other API parameters, to take effect when no analog captures are in progress. These parameters must be set before the first analog capture starts, be it MPEG, VBI, YUV, etc., and cannot be changed until the last one stops. It is not obvious to me what capture channel API parameters are shared and which ones must be set per capture channel, so set them all for every analog capture channel start up. This fixes the driver so that VBI capture can be started up after the MPEG capture is going. Signed-off-by: Andy Walls Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx18/cx18-ioctl.c | 20 +++++---- drivers/media/video/cx18/cx18-streams.c | 79 +++++++++++++++++++++++++-------- 2 files changed, 71 insertions(+), 28 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/cx18/cx18-ioctl.c b/drivers/media/video/cx18/cx18-ioctl.c index a454ede568a5..0f0cd560226c 100644 --- a/drivers/media/video/cx18/cx18-ioctl.c +++ b/drivers/media/video/cx18/cx18-ioctl.c @@ -42,13 +42,6 @@ #include #include -static int cx18_vbi_streaming(struct cx18 *cx) -{ - struct cx18_stream *s_vbi = &cx->streams[CX18_ENC_STREAM_TYPE_VBI]; - return (s_vbi->handle != CX18_INVALID_TASK_HANDLE) && - test_bit(CX18_F_S_STREAMING, &s_vbi->s_flags); -} - u16 cx18_service2vbi(int type) { switch (type) { @@ -312,7 +305,11 @@ static int cx18_s_fmt_vbi_cap(struct file *file, void *fh, if (ret) return ret; - if (!cx18_raw_vbi(cx) && cx18_vbi_streaming(cx)) + /* + * Changing the Encoder's Raw VBI parameters won't have any effect + * if any analog capture is ongoing + */ + if (!cx18_raw_vbi(cx) && atomic_read(&cx->ana_capturing) > 0) return -EBUSY; /* @@ -345,8 +342,13 @@ static int cx18_s_fmt_sliced_vbi_cap(struct file *file, void *fh, cx18_try_fmt_sliced_vbi_cap(file, fh, fmt); - if (cx18_raw_vbi(cx) && cx18_vbi_streaming(cx)) + /* + * Changing the Encoder's Raw VBI parameters won't have any effect + * if any analog capture is ongoing + */ + if (cx18_raw_vbi(cx) && atomic_read(&cx->ana_capturing) > 0) return -EBUSY; + /* * Set the service_lines requested in the digitizer/slicer registers. * Note, cx18_av_vbi() wipes some "impossible" service lines in the diff --git a/drivers/media/video/cx18/cx18-streams.c b/drivers/media/video/cx18/cx18-streams.c index a89f7f840d95..f074fdb29b8e 100644 --- a/drivers/media/video/cx18/cx18-streams.c +++ b/drivers/media/video/cx18/cx18-streams.c @@ -349,6 +349,14 @@ static void cx18_vbi_setup(struct cx18_stream *s) /* setup VBI registers */ cx18_av_cmd(cx, VIDIOC_S_FMT, &cx->vbi.in); + /* + * Send the CX18_CPU_SET_RAW_VBI_PARAM API command to setup Encoder Raw + * VBI when the first analog capture channel starts, as once it starts + * (e.g. MPEG), we can't effect any change in the Encoder Raw VBI setup + * (i.e. for the VBI capture channels). We also send it for each + * analog capture channel anyway just to make sure we get the proper + * behavior + */ if (raw) { lines = cx->vbi.count * 2; } else { @@ -410,8 +418,7 @@ static void cx18_vbi_setup(struct cx18_stream *s) CX18_DEBUG_INFO("Setup VBI h: %d lines %x bpl %d fr %d %x %x\n", data[0], data[1], data[2], data[3], data[4], data[5]); - if (s->type == CX18_ENC_STREAM_TYPE_VBI) - cx18_api(cx, CX18_CPU_SET_RAW_VBI_PARAM, 6, data); + cx18_api(cx, CX18_CPU_SET_RAW_VBI_PARAM, 6, data); } struct cx18_queue *cx18_stream_put_buf_fw(struct cx18_stream *s, @@ -460,8 +467,8 @@ int cx18_start_v4l2_encode_stream(struct cx18_stream *s) u32 data[MAX_MB_ARGUMENTS]; struct cx18 *cx = s->cx; struct cx18_buffer *buf; - int ts = 0; int captype = 0; + struct cx18_api_func_private priv; if (s->video_dev == NULL && s->dvb.enabled == 0) return -EINVAL; @@ -479,7 +486,6 @@ int cx18_start_v4l2_encode_stream(struct cx18_stream *s) case CX18_ENC_STREAM_TYPE_TS: captype = CAPTURE_CHANNEL_TYPE_TS; - ts = 1; break; case CX18_ENC_STREAM_TYPE_YUV: captype = CAPTURE_CHANNEL_TYPE_YUV; @@ -488,8 +494,16 @@ int cx18_start_v4l2_encode_stream(struct cx18_stream *s) captype = CAPTURE_CHANNEL_TYPE_PCM; break; case CX18_ENC_STREAM_TYPE_VBI: +#ifdef CX18_ENCODER_PARSES_SLICED captype = cx18_raw_vbi(cx) ? CAPTURE_CHANNEL_TYPE_VBI : CAPTURE_CHANNEL_TYPE_SLICED_VBI; +#else + /* + * Currently we set things up so that Sliced VBI from the + * digitizer is handled as Raw VBI by the encoder + */ + captype = CAPTURE_CHANNEL_TYPE_VBI; +#endif cx->vbi.frame = 0; cx->vbi.inserted_frame = 0; memset(cx->vbi.sliced_mpeg_size, @@ -499,10 +513,6 @@ int cx18_start_v4l2_encode_stream(struct cx18_stream *s) return -EINVAL; } - /* mute/unmute video */ - cx18_vapi(cx, CX18_CPU_SET_VIDEO_MUTE, 2, - s->handle, !!test_bit(CX18_F_I_RADIO_USER, &cx->i_flags)); - /* Clear Streamoff flags in case left from last capture */ clear_bit(CX18_F_S_STREAMOFF, &s->s_flags); @@ -510,31 +520,62 @@ int cx18_start_v4l2_encode_stream(struct cx18_stream *s) s->handle = data[0]; cx18_vapi(cx, CX18_CPU_SET_CHANNEL_TYPE, 2, s->handle, captype); - if (atomic_read(&cx->ana_capturing) == 0 && !ts) { - struct cx18_api_func_private priv; - - /* Stuff from Windows, we don't know what it is */ + /* + * For everything but CAPTURE_CHANNEL_TYPE_TS, play it safe and + * set up all the parameters, as it is not obvious which parameters the + * firmware shares across capture channel types and which it does not. + * + * Some of the cx18_vapi() calls below apply to only certain capture + * channel types. We're hoping there's no harm in calling most of them + * anyway, as long as the values are all consistent. Setting some + * shared parameters will have no effect once an analog capture channel + * has started streaming. + */ + if (captype != CAPTURE_CHANNEL_TYPE_TS) { cx18_vapi(cx, CX18_CPU_SET_VER_CROP_LINE, 2, s->handle, 0); cx18_vapi(cx, CX18_CPU_SET_MISC_PARAMETERS, 3, s->handle, 3, 1); cx18_vapi(cx, CX18_CPU_SET_MISC_PARAMETERS, 3, s->handle, 8, 0); cx18_vapi(cx, CX18_CPU_SET_MISC_PARAMETERS, 3, s->handle, 4, 1); - cx18_vapi(cx, CX18_CPU_SET_MISC_PARAMETERS, 2, s->handle, 12); + /* + * Audio related reset according to + * Documentation/video4linux/cx2341x/fw-encoder-api.txt + */ + if (atomic_read(&cx->ana_capturing) == 0) + cx18_vapi(cx, CX18_CPU_SET_MISC_PARAMETERS, 2, + s->handle, 12); + + /* + * Number of lines for Field 1 & Field 2 according to + * Documentation/video4linux/cx2341x/fw-encoder-api.txt + * FIXME - currently we set this to 0 & 0 but things seem OK + */ cx18_vapi(cx, CX18_CPU_SET_CAPTURE_LINE_NO, 3, - s->handle, cx->digitizer, cx->digitizer); + s->handle, cx->digitizer, cx->digitizer); - /* Setup VBI */ if (cx->v4l2_cap & V4L2_CAP_VBI_CAPTURE) cx18_vbi_setup(s); - /* assign program index info. - Mask 7: select I/P/B, Num_req: 400 max */ + /* + * assign program index info. + * Mask 7: select I/P/B, Num_req: 400 max + * FIXME - currently we have this hardcoded as disabled + */ cx18_vapi_result(cx, data, CX18_CPU_SET_INDEXTABLE, 1, 0); - /* Setup API for Stream */ + /* Call out to the common CX2341x API setup for user controls */ priv.cx = cx; priv.s = s; cx2341x_update(&priv, cx18_api_func, NULL, &cx->params); + + /* + * When starting a capture and we're set for radio, + * ensure the video is muted, despite the user control. + */ + if (!cx->params.video_mute && + test_bit(CX18_F_I_RADIO_USER, &cx->i_flags)) + cx18_vapi(cx, CX18_CPU_SET_VIDEO_MUTE, 2, s->handle, + (cx->params.video_mute_yuv << 8) | 1); } if (atomic_read(&cx->tot_capturing) == 0) { @@ -578,7 +619,7 @@ int cx18_start_v4l2_encode_stream(struct cx18_stream *s) } /* you're live! sit back and await interrupts :) */ - if (!ts) + if (captype != CAPTURE_CHANNEL_TYPE_TS) atomic_inc(&cx->ana_capturing); atomic_inc(&cx->tot_capturing); return 0; -- cgit v1.2.3 From f37aa51190c4391005bb71c92cd976f811500105 Mon Sep 17 00:00:00 2001 From: Andy Walls Date: Sat, 7 Feb 2009 01:15:44 -0300 Subject: V4L/DVB (10443): cx18: Use correct line counts per field in firmware API call The driver was incorrectly setting 0 line counts in a firmware API call to set the maximum amount of lines per field. Signed-off-by: Andy Walls Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx18/cx18-driver.h | 3 --- drivers/media/video/cx18/cx18-streams.c | 5 +++-- 2 files changed, 3 insertions(+), 5 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/cx18/cx18-driver.h b/drivers/media/video/cx18/cx18-driver.h index c9b6df50ab27..7fc914c521f7 100644 --- a/drivers/media/video/cx18/cx18-driver.h +++ b/drivers/media/video/cx18/cx18-driver.h @@ -479,9 +479,6 @@ struct cx18 { unsigned long dualwatch_jiffies; u32 dualwatch_stereo_mode; - /* Digitizer type */ - int digitizer; /* 0x00EF = saa7114 0x00FO = saa7115 0x0106 = mic */ - struct mutex serialize_lock; /* mutex used to serialize open/close/start/stop/ioctl operations */ struct cx18_options options; /* User options */ int stream_buffers[CX18_MAX_STREAMS]; /* # of buffers for each stream */ diff --git a/drivers/media/video/cx18/cx18-streams.c b/drivers/media/video/cx18/cx18-streams.c index f074fdb29b8e..a8dcc0f171d1 100644 --- a/drivers/media/video/cx18/cx18-streams.c +++ b/drivers/media/video/cx18/cx18-streams.c @@ -548,10 +548,11 @@ int cx18_start_v4l2_encode_stream(struct cx18_stream *s) /* * Number of lines for Field 1 & Field 2 according to * Documentation/video4linux/cx2341x/fw-encoder-api.txt - * FIXME - currently we set this to 0 & 0 but things seem OK + * Field 1 is 312 for 625 line systems in BT.656 + * Field 2 is 313 for 625 line systems in BT.656 */ cx18_vapi(cx, CX18_CPU_SET_CAPTURE_LINE_NO, 3, - s->handle, cx->digitizer, cx->digitizer); + s->handle, 312, 313); if (cx->v4l2_cap & V4L2_CAP_VBI_CAPTURE) cx18_vbi_setup(s); -- cgit v1.2.3 From 01cbc214cfa6e0dbfaea617d32d6d66e7f6608ff Mon Sep 17 00:00:00 2001 From: Andy Walls Date: Sat, 7 Feb 2009 01:31:22 -0300 Subject: V4L/DVB (10444): cx18: Fix sliced VBI PTS and fix artifacts in last raw line of field Fixed an endianess problem with the collection of the PTS from the VBI buffer given to us by the encoder. Also extrapolated the last 12 bytes of the last line of each field, to remove artifacts created by removing the first 12 bytes of each field for raw VBI. Signed-off-by: Andy Walls Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx18/cx18-vbi.c | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/cx18/cx18-vbi.c b/drivers/media/video/cx18/cx18-vbi.c index d6e15e119582..d8e7d371c8e2 100644 --- a/drivers/media/video/cx18/cx18-vbi.c +++ b/drivers/media/video/cx18/cx18-vbi.c @@ -179,6 +179,10 @@ void cx18_process_vbi_data(struct cx18 *cx, struct cx18_buffer *buf, if (streamtype != CX18_ENC_STREAM_TYPE_VBI) return; + /* + * The CX23418 sends us data that is 32 bit LE swapped, but we want + * the raw VBI bytes in the order they were in the raster line + */ cx18_buf_swap(buf); /* @@ -190,17 +194,27 @@ void cx18_process_vbi_data(struct cx18 *cx, struct cx18_buffer *buf, if (cx18_raw_vbi(cx)) { u8 type; - /* Skip 12 bytes of header that gets stuffed in */ + /* + * We've set up to get a field's worth of VBI data at a time. + * Skip 12 bytes of header prefixing the first field or the + * last 12 bytes in the last VBI line from the first field that + * prefixes the second field. + */ size -= 12; memcpy(p, &buf->buf[12], size); type = p[3]; + /* Extrapolate the last 12 bytes of the field's last line */ + memset(&p[size], (int) p[size - 1], 12); + size = buf->bytesused = compress_raw_buf(cx, p, size); - /* second field of the frame? */ if (type == raw_vbi_sav_rp[1]) { - /* Dirty hack needed for backwards - compatibility of old VBI software. */ + /* + * Hack needed for compatibility with old VBI software. + * Write the frame # at the end of the last line of the + * second field + */ p += size - 4; memcpy(p, &cx->vbi.frame, 4); cx->vbi.frame++; @@ -210,7 +224,7 @@ void cx18_process_vbi_data(struct cx18 *cx, struct cx18_buffer *buf, /* Sliced VBI data with data insertion */ - pts = (q[0] == 0x3fffffff) ? q[2] : 0; + pts = (be32_to_cpu(q[0] == 0x3fffffff)) ? be32_to_cpu(q[2]) : 0; /* first field */ /* compress_sliced_buf() will skip the 12 bytes of header */ -- cgit v1.2.3 From 466df46484aced005fa41706f87e18eaa86918ad Mon Sep 17 00:00:00 2001 From: Andy Walls Date: Sat, 7 Feb 2009 15:47:28 -0300 Subject: V4L/DVB (10445): cx18: Process Raw VBI on a whole frame basis; fix VBI buffer size The cx23418 appears to send Raw VBI buffers with a PTS on a per frame basis, not per field, so process Raw VBI on a whole frame basis and reduce some complexity. Fix VBI buffer size computation to handle a whole frame of Raw VBI for a 625 line system, which is the worst case and will work for 525 lines systems as well. Signed-off-by: Andy Walls Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx18/cx18-driver.c | 54 +++++++++++++--------------------- drivers/media/video/cx18/cx18-vbi.c | 31 ++++++++----------- 2 files changed, 33 insertions(+), 52 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/cx18/cx18-driver.c b/drivers/media/video/cx18/cx18-driver.c index 842ce636e45c..3cf8ddb633b4 100644 --- a/drivers/media/video/cx18/cx18-driver.c +++ b/drivers/media/video/cx18/cx18-driver.c @@ -448,34 +448,38 @@ static void cx18_process_options(struct cx18 *cx) cx->stream_buf_size[CX18_ENC_STREAM_TYPE_MPG] = enc_mpg_bufsize; cx->stream_buf_size[CX18_ENC_STREAM_TYPE_IDX] = enc_idx_bufsize; cx->stream_buf_size[CX18_ENC_STREAM_TYPE_YUV] = enc_yuv_bufsize; - cx->stream_buf_size[CX18_ENC_STREAM_TYPE_VBI] = 0; /* computed later */ + cx->stream_buf_size[CX18_ENC_STREAM_TYPE_VBI] = vbi_active_samples * 36; cx->stream_buf_size[CX18_ENC_STREAM_TYPE_PCM] = enc_pcm_bufsize; cx->stream_buf_size[CX18_ENC_STREAM_TYPE_RAD] = 0; /* control no data */ - /* Except for VBI ensure stream_buffers & stream_buf_size are valid */ + /* Ensure stream_buffers & stream_buf_size are valid */ for (i = 0; i < CX18_MAX_STREAMS; i++) { - /* User said to use 0 buffers */ - if (cx->stream_buffers[i] == 0) { - cx->options.megabytes[i] = 0; - cx->stream_buf_size[i] = 0; - continue; - } - /* User said to use 0 MB total */ - if (cx->options.megabytes[i] <= 0) { + if (cx->stream_buffers[i] == 0 || /* User said 0 buffers */ + cx->options.megabytes[i] <= 0 || /* User said 0 MB total */ + cx->stream_buf_size[i] <= 0) { /* User said buf size 0 */ cx->options.megabytes[i] = 0; cx->stream_buffers[i] = 0; cx->stream_buf_size[i] = 0; continue; } - /* VBI is computed later or user said buffer has size 0 */ - if (cx->stream_buf_size[i] <= 0) { - if (i != CX18_ENC_STREAM_TYPE_VBI) { - cx->options.megabytes[i] = 0; - cx->stream_buffers[i] = 0; - cx->stream_buf_size[i] = 0; + /* + * VBI is a special case where the stream_buf_size is fixed + * and already in bytes + */ + if (i == CX18_ENC_STREAM_TYPE_VBI) { + if (cx->stream_buffers[i] < 0) { + cx->stream_buffers[i] = + cx->options.megabytes[i] * 1024 * 1024 + / cx->stream_buf_size[i]; + } else { + /* N.B. This might round down to 0 */ + cx->options.megabytes[i] = + cx->stream_buffers[i] + * cx->stream_buf_size[i]/(1024 * 1024); } continue; } + /* All other streams have stream_buf_size in kB at this point */ if (cx->stream_buffers[i] < 0) { cx->stream_buffers[i] = cx->options.megabytes[i] * 1024 / cx->stream_buf_size[i]; @@ -732,7 +736,6 @@ static int __devinit cx18_probe(struct pci_dev *pci_dev, { int retval = 0; int i; - int vbi_buf_size; u32 devtype; struct cx18 *cx; @@ -888,23 +891,6 @@ static int __devinit cx18_probe(struct pci_dev *pci_dev, } cx->params.video_gop_size = cx->is_60hz ? 15 : 12; - /* - * FIXME: setting the buffer size based on the tuner standard is - * suboptimal, as the CVBS and SVideo inputs could use a different std - * and the buffer could end up being too small in that case. - */ - vbi_buf_size = vbi_active_samples * (cx->is_60hz ? 24 : 36) / 2; - cx->stream_buf_size[CX18_ENC_STREAM_TYPE_VBI] = vbi_buf_size; - - if (cx->stream_buffers[CX18_ENC_STREAM_TYPE_VBI] < 0) - cx->stream_buffers[CX18_ENC_STREAM_TYPE_VBI] = - cx->options.megabytes[CX18_ENC_STREAM_TYPE_VBI] * 1024 * 1024 - / vbi_buf_size; - else - cx->options.megabytes[CX18_ENC_STREAM_TYPE_VBI] = - cx->stream_buffers[CX18_ENC_STREAM_TYPE_VBI] * vbi_buf_size - / (1024 * 1024); - if (cx->options.radio > 0) cx->v4l2_cap |= V4L2_CAP_RADIO; diff --git a/drivers/media/video/cx18/cx18-vbi.c b/drivers/media/video/cx18/cx18-vbi.c index d8e7d371c8e2..52082d4a179e 100644 --- a/drivers/media/video/cx18/cx18-vbi.c +++ b/drivers/media/video/cx18/cx18-vbi.c @@ -103,12 +103,11 @@ static void copy_vbi_data(struct cx18 *cx, int lines, u32 pts_stamp) } /* Compress raw VBI format, removes leading SAV codes and surplus space - after the field. - Returns new compressed size. */ + after the frame. Returns new compressed size. */ static u32 compress_raw_buf(struct cx18 *cx, u8 *buf, u32 size) { u32 line_size = vbi_active_samples; - u32 lines = cx->vbi.count; + u32 lines = cx->vbi.count * 2; u8 sav1 = raw_vbi_sav_rp[0]; u8 sav2 = raw_vbi_sav_rp[1]; u8 *q = buf; @@ -195,30 +194,26 @@ void cx18_process_vbi_data(struct cx18 *cx, struct cx18_buffer *buf, u8 type; /* - * We've set up to get a field's worth of VBI data at a time. - * Skip 12 bytes of header prefixing the first field or the - * last 12 bytes in the last VBI line from the first field that - * prefixes the second field. + * We've set up to get a frame's worth of VBI data at a time. + * Skip 12 bytes of header prefixing the first field. */ size -= 12; memcpy(p, &buf->buf[12], size); type = p[3]; - /* Extrapolate the last 12 bytes of the field's last line */ + /* Extrapolate the last 12 bytes of the frame's last line */ memset(&p[size], (int) p[size - 1], 12); + size += 12; size = buf->bytesused = compress_raw_buf(cx, p, size); - if (type == raw_vbi_sav_rp[1]) { - /* - * Hack needed for compatibility with old VBI software. - * Write the frame # at the end of the last line of the - * second field - */ - p += size - 4; - memcpy(p, &cx->vbi.frame, 4); - cx->vbi.frame++; - } + /* + * Hack needed for compatibility with old VBI software. + * Write the frame # at the last 4 bytes of the frame + */ + p += size - 4; + memcpy(p, &cx->vbi.frame, 4); + cx->vbi.frame++; return; } -- cgit v1.2.3 From 812b1f9d54a5f75066f8a5c92166a979c48c98c6 Mon Sep 17 00:00:00 2001 From: Andy Walls Date: Sun, 8 Feb 2009 22:40:04 -0300 Subject: V4L/DVB (10446): cx18: Finally get sliced VBI working - for 525 line 60 Hz systems at least Sliced VBI, in the manner that ivtv implements it as a separate data stream, now works for 525 line 60 Hz systems like NTSC-M. It may work for 625 line 50 Hz systems, but I have more engineering work to do, to verify it is operating properly. Sliced data insertion into the MPEG PS should be working, but is untested. Signed-off-by: Andy Walls Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx18/cx18-av-core.c | 44 ++++++++++++++++++++++++--------- drivers/media/video/cx18/cx18-av-core.h | 19 +++++++++++++- drivers/media/video/cx18/cx18-av-vbi.c | 10 ++++---- drivers/media/video/cx18/cx18-driver.c | 4 ++- drivers/media/video/cx18/cx18-streams.c | 19 +++++++++++--- drivers/media/video/cx18/cx18-vbi.c | 19 ++++++++++---- 6 files changed, 88 insertions(+), 27 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/cx18/cx18-av-core.c b/drivers/media/video/cx18/cx18-av-core.c index 1d197649446e..a3bd2c95f582 100644 --- a/drivers/media/video/cx18/cx18-av-core.c +++ b/drivers/media/video/cx18/cx18-av-core.c @@ -172,11 +172,11 @@ static void cx18_av_initialize(struct cx18 *cx) /* * Initial VBI setup * VIP-1.1, 10 bit mode, enable Raw, disable sliced, - * don't clamp raw samples when codes are in use, 4 byte user D-words, - * programmed IDID, RP code V bit transition on VBLANK, data during + * don't clamp raw samples when codes are in use, 1 byte user D-words, + * IDID0 has line #, RP code V bit transition on VBLANK, data during * blanking intervals */ - cx18_av_write4(cx, CXADEC_OUT_CTRL1, 0x4010252e); + cx18_av_write4(cx, CXADEC_OUT_CTRL1, 0x4013252e); /* Set the video input. The setting in MODE_CTRL gets lost when we do the above setup */ @@ -218,6 +218,7 @@ void cx18_av_std_setup(struct cx18 *cx) cx18_av_write(cx, 0x49f, 0x14); if (std & V4L2_STD_625_50) { + /* FIXME - revisit these for Sliced VBI */ hblank = 132; hactive = 720; burst = 93; @@ -241,13 +242,34 @@ void cx18_av_std_setup(struct cx18 *cx) sc = 672351; } } else { + /* + * The following relationships of half line counts should hold: + * 525 = vsync + vactive + vblank656 + * 12 = vblank656 - vblank + * + * vsync: always 6 half-lines of vsync pulses + * vactive: half lines of active video + * vblank656: half lines, after line 3, of blanked video + * vblank: half lines, after line 9, of blanked video + * + * vblank656 starts counting from the falling edge of the first + * vsync pulse (start of line 4) + * vblank starts counting from the after the 6 vsync pulses and + * 6 equalization pulses (start of line 10) + * + * For 525 line systems the driver will extract VBI information + * from lines 10 through 21. To avoid the EAV RP code from + * toggling at the start of hblank at line 22, where sliced VBI + * data from line 21 is stuffed, also treat line 22 as blanked. + */ + vblank656 = 38; /* lines 4 through 22 */ + vblank = 26; /* lines 10 through 22 */ + vactive = 481; /* lines 23 through 262.5 */ + hactive = 720; hblank = 122; - vactive = 487; luma_lpf = 1; uv_lpf = 1; - vblank = 26; - vblank656 = 26; src_decimation = 0x21f; if (std == V4L2_STD_PAL_60) { @@ -330,14 +352,14 @@ void cx18_av_std_setup(struct cx18 *cx) cx18_av_write(cx, 0x47d, 0xff & sc >> 8); cx18_av_write(cx, 0x47e, 0xff & sc >> 16); - /* Sets VBI parameters */ if (std & V4L2_STD_625_50) { - cx18_av_write(cx, 0x47f, 0x01); - state->vbi_line_offset = 5; + state->slicer_line_delay = 1; + state->slicer_line_offset = (6 + state->slicer_line_delay - 2); } else { - cx18_av_write(cx, 0x47f, 0x00); - state->vbi_line_offset = 8; + state->slicer_line_delay = 0; + state->slicer_line_offset = (10 + state->slicer_line_delay - 2); } + cx18_av_write(cx, 0x47f, state->slicer_line_delay); } /* ----------------------------------------------------------------------- */ diff --git a/drivers/media/video/cx18/cx18-av-core.h b/drivers/media/video/cx18/cx18-av-core.h index cf68a6039091..d83760cae540 100644 --- a/drivers/media/video/cx18/cx18-av-core.h +++ b/drivers/media/video/cx18/cx18-av-core.h @@ -79,11 +79,28 @@ struct cx18_av_state { enum cx18_av_audio_input aud_input; u32 audclk_freq; int audmode; - int vbi_line_offset; int default_volume; u32 id; u32 rev; int is_initialized; + + /* + * The VBI slicer starts operating and counting lines, begining at + * slicer line count of 1, at D lines after the deassertion of VRESET + * This staring field line, S, is 6 or 10 for 625 or 525 line systems. + * Sliced ancillary data captured on VBI slicer line M is sent at the + * beginning of the next VBI slicer line, VBI slicer line count N = M+1. + * Thus when the VBI slicer reports a VBI slicer line number with + * ancillary data, the IDID0 byte indicates VBI slicer line N. + * The actual field line that the captured data comes from is + * L = M+(S+D-1) = N-1+(S+D-1) = N + (S+D-2). + * + * D is the slicer_line_delay value programmed into register 0x47f. + * (S+D-2) is the slicer_line_offset used to convert slicer reported + * line counts to actual field lines. + */ + int slicer_line_delay; + int slicer_line_offset; }; diff --git a/drivers/media/video/cx18/cx18-av-vbi.c b/drivers/media/video/cx18/cx18-av-vbi.c index b5763372a316..43267d1afb92 100644 --- a/drivers/media/video/cx18/cx18-av-vbi.c +++ b/drivers/media/video/cx18/cx18-av-vbi.c @@ -182,7 +182,6 @@ int cx18_av_vbi(struct cx18 *cx, unsigned int cmd, void *arg) case VIDIOC_S_FMT: { int is_pal = !(state->std & V4L2_STD_525_60); - int vbi_offset = is_pal ? 1 : 0; int i, x; u8 lcr[24]; @@ -199,7 +198,7 @@ int cx18_av_vbi(struct cx18 *cx, unsigned int cmd, void *arg) cx18_av_std_setup(cx); /* VBI Offset */ - cx18_av_write(cx, 0x47f, vbi_offset); + cx18_av_write(cx, 0x47f, state->slicer_line_delay); cx18_av_write(cx, 0x404, 0x2e); break; } @@ -213,7 +212,7 @@ int cx18_av_vbi(struct cx18 *cx, unsigned int cmd, void *arg) /* Sliced VBI */ cx18_av_write(cx, 0x404, 0x32); /* Ancillary data */ cx18_av_write(cx, 0x406, 0x13); - cx18_av_write(cx, 0x47f, vbi_offset); + cx18_av_write(cx, 0x47f, state->slicer_line_delay); /* Force impossible lines to 0 */ if (is_pal) { @@ -261,7 +260,8 @@ int cx18_av_vbi(struct cx18 *cx, unsigned int cmd, void *arg) } cx18_av_write(cx, 0x43c, 0x16); - cx18_av_write(cx, 0x474, is_pal ? 0x2a : 0x22); + /* FIXME - should match vblank set in cx18_av_std_setup() */ + cx18_av_write(cx, 0x474, is_pal ? 0x2a : 26); break; } @@ -286,7 +286,7 @@ int cx18_av_vbi(struct cx18 *cx, unsigned int cmd, void *arg) did = anc->did; sdid = anc->sdid & 0xf; l = anc->idid[0] & 0x3f; - l += state->vbi_line_offset; + l += state->slicer_line_offset; p = anc->payload; /* Decode the SDID set by the slicer */ diff --git a/drivers/media/video/cx18/cx18-driver.c b/drivers/media/video/cx18/cx18-driver.c index 3cf8ddb633b4..2a45bbc757e8 100644 --- a/drivers/media/video/cx18/cx18-driver.c +++ b/drivers/media/video/cx18/cx18-driver.c @@ -633,7 +633,9 @@ static void __devinit cx18_init_struct2(struct cx18 *cx) cx->av_state.aud_input = CX18_AV_AUDIO8; cx->av_state.audclk_freq = 48000; cx->av_state.audmode = V4L2_TUNER_MODE_LANG1; - cx->av_state.vbi_line_offset = 8; + cx->av_state.slicer_line_delay = 0; + cx->av_state.slicer_line_offset = + (10 + cx->av_state.slicer_line_delay - 2); } static int cx18_setup_pci(struct cx18 *cx, struct pci_dev *pci_dev, diff --git a/drivers/media/video/cx18/cx18-streams.c b/drivers/media/video/cx18/cx18-streams.c index a8dcc0f171d1..778aa0c0f9b5 100644 --- a/drivers/media/video/cx18/cx18-streams.c +++ b/drivers/media/video/cx18/cx18-streams.c @@ -360,9 +360,16 @@ static void cx18_vbi_setup(struct cx18_stream *s) if (raw) { lines = cx->vbi.count * 2; } else { - lines = cx->is_60hz ? 24 : 38; - if (cx->is_60hz) - lines += 2; + /* + * For 525/60 systems, according to the VIP 2 & BT.656 std: + * The EAV RP code's Field bit toggles on line 4, a few lines + * after the Vertcal Blank bit has already toggled. + * Tell the encoder to capture 21-4+1=18 lines per field, + * since we want lines 10 through 21. + * + * FIXME - revisit for 625/50 systems + */ + lines = cx->is_60hz ? (21 - 4 + 1) * 2 : 38; } data[0] = s->handle; @@ -402,9 +409,13 @@ static void cx18_vbi_setup(struct cx18_stream *s) * * Since the V bit is only allowed to toggle in the EAV RP code, * just before the first active region line, these two - * are problematic and we have to ignore them: + * are problematic: * 0x90 (Task HorizontalBlank) * 0xd0 (Task EvenField HorizontalBlank) + * + * We have set the digitzer to consider the first active line + * as part of VerticalBlank as well so we don't have to look for + * these problem codes nor lose the last line of sliced data. */ data[4] = 0xB0F0B0F0; /* diff --git a/drivers/media/video/cx18/cx18-vbi.c b/drivers/media/video/cx18/cx18-vbi.c index 52082d4a179e..8e6f4d4aff9a 100644 --- a/drivers/media/video/cx18/cx18-vbi.c +++ b/drivers/media/video/cx18/cx18-vbi.c @@ -221,13 +221,22 @@ void cx18_process_vbi_data(struct cx18 *cx, struct cx18_buffer *buf, pts = (be32_to_cpu(q[0] == 0x3fffffff)) ? be32_to_cpu(q[2]) : 0; + /* + * For calls to compress_sliced_buf(), ensure there are an integral + * number of lines by shifting the real data up over the 12 bytes header + * that got stuffed in. + * FIXME - there's a smarter way to do this with pointers, but for some + * reason I can't get it to work correctly right now. + */ + memcpy(p, &buf->buf[12], size-12); + /* first field */ - /* compress_sliced_buf() will skip the 12 bytes of header */ lines = compress_sliced_buf(cx, 0, p, size / 2, sliced_vbi_eav_rp[0]); - /* second field */ - /* experimentation shows that the second half does not always - begin at the exact address. So start a bit earlier - (hence 32). */ + /* + * second field + * In case the second half does not always begin at the exact address, + * start a bit earlier (hence 32). + */ lines = compress_sliced_buf(cx, lines, p + size / 2 - 32, size / 2 + 32, sliced_vbi_eav_rp[1]); /* always return at least one empty line */ -- cgit v1.2.3 From a4a787187bcf94b1bf4deb74cbe30eb442519875 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 6 Feb 2009 15:31:59 -0300 Subject: V4L/DVB (10486): ivtv/cx18: fix g_fmt and try_fmt for raw video The raw video device didn't report the image size correctly. When setting a new image the image height has to be a multiple of 32 lines. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx18/cx18-ioctl.c | 17 +++++++++++------ drivers/media/video/ivtv/ivtv-ioctl.c | 14 +++++++++----- 2 files changed, 20 insertions(+), 11 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/cx18/cx18-ioctl.c b/drivers/media/video/cx18/cx18-ioctl.c index 0f0cd560226c..5c8e9cb244f9 100644 --- a/drivers/media/video/cx18/cx18-ioctl.c +++ b/drivers/media/video/cx18/cx18-ioctl.c @@ -160,10 +160,8 @@ static int cx18_g_fmt_vid_cap(struct file *file, void *fh, pixfmt->priv = 0; if (id->type == CX18_ENC_STREAM_TYPE_YUV) { pixfmt->pixelformat = V4L2_PIX_FMT_HM12; - /* YUV size is (Y=(h*w) + UV=(h*(w/2))) */ - pixfmt->sizeimage = - pixfmt->height * pixfmt->width + - pixfmt->height * (pixfmt->width / 2); + /* YUV size is (Y=(h*720) + UV=(h*(720/2))) */ + pixfmt->sizeimage = pixfmt->height * 720 * 3 / 2; pixfmt->bytesperline = 720; } else { pixfmt->pixelformat = V4L2_PIX_FMT_MPEG; @@ -228,11 +226,18 @@ static int cx18_try_fmt_vid_cap(struct file *file, void *fh, struct cx18 *cx = id->cx; int w = fmt->fmt.pix.width; int h = fmt->fmt.pix.height; + int min_h = 2; w = min(w, 720); - w = max(w, 1); + w = max(w, 2); + if (id->type == CX18_ENC_STREAM_TYPE_YUV) { + /* YUV height must be a multiple of 32 */ + h &= ~0x1f; + min_h = 32; + } h = min(h, cx->is_50hz ? 576 : 480); - h = max(h, 2); + h = max(h, min_h); + cx18_g_fmt_vid_cap(file, fh, fmt); fmt->fmt.pix.width = w; fmt->fmt.pix.height = h; diff --git a/drivers/media/video/ivtv/ivtv-ioctl.c b/drivers/media/video/ivtv/ivtv-ioctl.c index c13bd2aa0bea..e8621da26d80 100644 --- a/drivers/media/video/ivtv/ivtv-ioctl.c +++ b/drivers/media/video/ivtv/ivtv-ioctl.c @@ -345,10 +345,8 @@ static int ivtv_g_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *f pixfmt->priv = 0; if (id->type == IVTV_ENC_STREAM_TYPE_YUV) { pixfmt->pixelformat = V4L2_PIX_FMT_HM12; - /* YUV size is (Y=(h*w) + UV=(h*(w/2))) */ - pixfmt->sizeimage = - pixfmt->height * pixfmt->width + - pixfmt->height * (pixfmt->width / 2); + /* YUV size is (Y=(h*720) + UV=(h*(720/2))) */ + pixfmt->sizeimage = pixfmt->height * 720 * 3 / 2; pixfmt->bytesperline = 720; } else { pixfmt->pixelformat = V4L2_PIX_FMT_MPEG; @@ -469,11 +467,17 @@ static int ivtv_try_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format struct ivtv *itv = id->itv; int w = fmt->fmt.pix.width; int h = fmt->fmt.pix.height; + int min_h = 2; w = min(w, 720); w = max(w, 2); + if (id->type == IVTV_ENC_STREAM_TYPE_YUV) { + /* YUV height must be a multiple of 32 */ + h &= ~0x1f; + min_h = 32; + } h = min(h, itv->is_50hz ? 576 : 480); - h = max(h, 2); + h = max(h, min_h); ivtv_g_fmt_vid_cap(file, fh, fmt); fmt->fmt.pix.width = w; fmt->fmt.pix.height = h; -- cgit v1.2.3 From 8ac05ae3192ce8a71fc84e4a88772cce0c09173c Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sat, 7 Feb 2009 07:02:27 -0300 Subject: V4L/DVB (10488): ivtv: cleanup naming conventions Use consistent naming for pci_dev, v4l2_device and video_device. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/ivtv/ivtv-driver.c | 93 ++++++++++++++++---------------- drivers/media/video/ivtv/ivtv-driver.h | 24 ++++----- drivers/media/video/ivtv/ivtv-fileops.c | 2 +- drivers/media/video/ivtv/ivtv-firmware.c | 2 +- drivers/media/video/ivtv/ivtv-gpio.c | 4 +- drivers/media/video/ivtv/ivtv-i2c.c | 14 ++--- drivers/media/video/ivtv/ivtv-ioctl.c | 6 +-- drivers/media/video/ivtv/ivtv-irq.c | 4 +- drivers/media/video/ivtv/ivtv-queue.c | 8 +-- drivers/media/video/ivtv/ivtv-queue.h | 8 +-- drivers/media/video/ivtv/ivtv-streams.c | 68 +++++++++++------------ drivers/media/video/ivtv/ivtv-udma.c | 10 ++-- drivers/media/video/ivtv/ivtv-udma.h | 4 +- drivers/media/video/ivtv/ivtv-yuv.c | 6 +-- drivers/media/video/ivtv/ivtvfb.c | 6 +-- 15 files changed, 129 insertions(+), 130 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/ivtv/ivtv-driver.c b/drivers/media/video/ivtv/ivtv-driver.c index c46c990987f9..eca8bf92a225 100644 --- a/drivers/media/video/ivtv/ivtv-driver.c +++ b/drivers/media/video/ivtv/ivtv-driver.c @@ -357,7 +357,7 @@ void ivtv_read_eeprom(struct ivtv *itv, struct tveeprom *tv) static void ivtv_process_eeprom(struct ivtv *itv) { struct tveeprom tv; - int pci_slot = PCI_SLOT(itv->dev->devfn); + int pci_slot = PCI_SLOT(itv->pdev->devfn); ivtv_read_eeprom(itv, &tv); @@ -604,7 +604,7 @@ static void ivtv_process_options(struct ivtv *itv) itv->std = ivtv_parse_std(itv); if (itv->std == 0 && tunertype >= 0) itv->std = tunertype ? V4L2_STD_MN : (V4L2_STD_ALL & ~V4L2_STD_MN); - itv->has_cx23415 = (itv->dev->device == PCI_DEVICE_ID_IVTV15); + itv->has_cx23415 = (itv->pdev->device == PCI_DEVICE_ID_IVTV15); chipname = itv->has_cx23415 ? "cx23415" : "cx23416"; if (itv->options.cardtype == -1) { IVTV_INFO("Ignore card (detected %s based chip)\n", chipname); @@ -617,9 +617,9 @@ static void ivtv_process_options(struct ivtv *itv) IVTV_ERR("Unknown user specified type, trying to autodetect card\n"); } if (itv->card == NULL) { - if (itv->dev->subsystem_vendor == IVTV_PCI_ID_HAUPPAUGE || - itv->dev->subsystem_vendor == IVTV_PCI_ID_HAUPPAUGE_ALT1 || - itv->dev->subsystem_vendor == IVTV_PCI_ID_HAUPPAUGE_ALT2) { + if (itv->pdev->subsystem_vendor == IVTV_PCI_ID_HAUPPAUGE || + itv->pdev->subsystem_vendor == IVTV_PCI_ID_HAUPPAUGE_ALT1 || + itv->pdev->subsystem_vendor == IVTV_PCI_ID_HAUPPAUGE_ALT2) { itv->card = ivtv_get_card(itv->has_cx23415 ? IVTV_CARD_PVR_350 : IVTV_CARD_PVR_150); IVTV_INFO("Autodetected Hauppauge card (%s based)\n", chipname); @@ -630,13 +630,13 @@ static void ivtv_process_options(struct ivtv *itv) if (itv->card->pci_list == NULL) continue; for (j = 0; itv->card->pci_list[j].device; j++) { - if (itv->dev->device != + if (itv->pdev->device != itv->card->pci_list[j].device) continue; - if (itv->dev->subsystem_vendor != + if (itv->pdev->subsystem_vendor != itv->card->pci_list[j].subsystem_vendor) continue; - if (itv->dev->subsystem_device != + if (itv->pdev->subsystem_device != itv->card->pci_list[j].subsystem_device) continue; IVTV_INFO("Autodetected %s card (%s based)\n", @@ -650,9 +650,9 @@ done: if (itv->card == NULL) { itv->card = ivtv_get_card(IVTV_CARD_PVR_150); IVTV_ERR("Unknown card: vendor/device: [%04x:%04x]\n", - itv->dev->vendor, itv->dev->device); + itv->pdev->vendor, itv->pdev->device); IVTV_ERR(" subsystem vendor/device: [%04x:%04x]\n", - itv->dev->subsystem_vendor, itv->dev->subsystem_device); + itv->pdev->subsystem_vendor, itv->pdev->subsystem_device); IVTV_ERR(" %s based\n", chipname); IVTV_ERR("Defaulting to %s card\n", itv->card->name); IVTV_ERR("Please mail the vendor/device and subsystem vendor/device IDs and what kind of\n"); @@ -671,7 +671,7 @@ done: */ static int __devinit ivtv_init_struct1(struct ivtv *itv) { - itv->base_addr = pci_resource_start(itv->dev, 0); + itv->base_addr = pci_resource_start(itv->pdev, 0); itv->enc_mbox.max_mbox = 2; /* the encoder has 3 mailboxes (0-2) */ itv->dec_mbox.max_mbox = 1; /* the decoder has 2 mailboxes (0-1) */ @@ -682,7 +682,7 @@ static int __devinit ivtv_init_struct1(struct ivtv *itv) spin_lock_init(&itv->lock); spin_lock_init(&itv->dma_reg_lock); - itv->irq_work_queues = create_singlethread_workqueue(itv->device.name); + itv->irq_work_queues = create_singlethread_workqueue(itv->v4l2_dev.name); if (itv->irq_work_queues == NULL) { IVTV_ERR("Could not create ivtv workqueue\n"); return -1; @@ -766,7 +766,7 @@ static void __devinit ivtv_init_struct2(struct ivtv *itv) itv->audio_input = itv->card->video_inputs[i].audio_index; } -static int ivtv_setup_pci(struct ivtv *itv, struct pci_dev *dev, +static int ivtv_setup_pci(struct ivtv *itv, struct pci_dev *pdev, const struct pci_device_id *pci_id) { u16 cmd; @@ -775,11 +775,11 @@ static int ivtv_setup_pci(struct ivtv *itv, struct pci_dev *dev, IVTV_DEBUG_INFO("Enabling pci device\n"); - if (pci_enable_device(dev)) { + if (pci_enable_device(pdev)) { IVTV_ERR("Can't enable device!\n"); return -EIO; } - if (pci_set_dma_mask(dev, 0xffffffff)) { + if (pci_set_dma_mask(pdev, 0xffffffff)) { IVTV_ERR("No suitable DMA available.\n"); return -EIO; } @@ -805,11 +805,11 @@ static int ivtv_setup_pci(struct ivtv *itv, struct pci_dev *dev, } /* Check for bus mastering */ - pci_read_config_word(dev, PCI_COMMAND, &cmd); + pci_read_config_word(pdev, PCI_COMMAND, &cmd); if (!(cmd & PCI_COMMAND_MASTER)) { IVTV_DEBUG_INFO("Attempting to enable Bus Mastering\n"); - pci_set_master(dev); - pci_read_config_word(dev, PCI_COMMAND, &cmd); + pci_set_master(pdev); + pci_read_config_word(pdev, PCI_COMMAND, &cmd); if (!(cmd & PCI_COMMAND_MASTER)) { IVTV_ERR("Bus Mastering is not enabled\n"); return -ENXIO; @@ -817,26 +817,26 @@ static int ivtv_setup_pci(struct ivtv *itv, struct pci_dev *dev, } IVTV_DEBUG_INFO("Bus Mastering Enabled.\n"); - pci_read_config_byte(dev, PCI_CLASS_REVISION, &card_rev); - pci_read_config_byte(dev, PCI_LATENCY_TIMER, &pci_latency); + pci_read_config_byte(pdev, PCI_CLASS_REVISION, &card_rev); + pci_read_config_byte(pdev, PCI_LATENCY_TIMER, &pci_latency); if (pci_latency < 64 && ivtv_pci_latency) { IVTV_INFO("Unreasonably low latency timer, " "setting to 64 (was %d)\n", pci_latency); - pci_write_config_byte(dev, PCI_LATENCY_TIMER, 64); - pci_read_config_byte(dev, PCI_LATENCY_TIMER, &pci_latency); + pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 64); + pci_read_config_byte(pdev, PCI_LATENCY_TIMER, &pci_latency); } /* This config space value relates to DMA latencies. The default value 0x8080 is too low however and will lead to DMA errors. 0xffff is the max value which solves these problems. */ - pci_write_config_dword(dev, 0x40, 0xffff); + pci_write_config_dword(pdev, 0x40, 0xffff); IVTV_DEBUG_INFO("%d (rev %d) at %02x:%02x.%x, " "irq: %d, latency: %d, memory: 0x%lx\n", - itv->dev->device, card_rev, dev->bus->number, - PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn), - itv->dev->irq, pci_latency, (unsigned long)itv->base_addr); + pdev->device, card_rev, pdev->bus->number, + PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn), + pdev->irq, pci_latency, (unsigned long)itv->base_addr); return 0; } @@ -935,7 +935,7 @@ static void ivtv_load_and_init_modules(struct ivtv *itv) } } -static int __devinit ivtv_probe(struct pci_dev *dev, +static int __devinit ivtv_probe(struct pci_dev *pdev, const struct pci_device_id *pci_id) { int retval = 0; @@ -945,17 +945,17 @@ static int __devinit ivtv_probe(struct pci_dev *dev, itv = kzalloc(sizeof(struct ivtv), GFP_ATOMIC); if (itv == NULL) return -ENOMEM; - itv->dev = dev; + itv->pdev = pdev; itv->instance = atomic_inc_return(&ivtv_instance) - 1; - retval = v4l2_device_register(&dev->dev, &itv->device); + retval = v4l2_device_register(&pdev->dev, &itv->v4l2_dev); if (retval) { kfree(itv); return retval; } /* "ivtv + PCI ID" is a bit of a mouthful, so use "ivtv + instance" instead. */ - snprintf(itv->device.name, sizeof(itv->device.name), + snprintf(itv->v4l2_dev.name, sizeof(itv->v4l2_dev.name), "ivtv%d", itv->instance); IVTV_INFO("Initializing card %d\n", itv->instance); @@ -972,12 +972,11 @@ static int __devinit ivtv_probe(struct pci_dev *dev, IVTV_DEBUG_INFO("base addr: 0x%08x\n", itv->base_addr); /* PCI Device Setup */ - if ((retval = ivtv_setup_pci(itv, dev, pci_id)) != 0) { - if (retval == -EIO) - goto free_workqueue; - else if (retval == -ENXIO) - goto free_mem; - } + retval = ivtv_setup_pci(itv, pdev, pci_id); + if (retval == -EIO) + goto free_workqueue; + if (retval == -ENXIO) + goto free_mem; /* map io memory */ IVTV_DEBUG_INFO("attempting ioremap at 0x%08x len 0x%08x\n", @@ -1154,8 +1153,8 @@ static int __devinit ivtv_probe(struct pci_dev *dev, ivtv_set_irq_mask(itv, 0xffffffff); /* Register IRQ */ - retval = request_irq(itv->dev->irq, ivtv_irq_handler, - IRQF_SHARED | IRQF_DISABLED, itv->device.name, (void *)itv); + retval = request_irq(itv->pdev->irq, ivtv_irq_handler, + IRQF_SHARED | IRQF_DISABLED, itv->v4l2_dev.name, (void *)itv); if (retval) { IVTV_ERR("Failed to register irq %d\n", retval); goto free_i2c; @@ -1177,7 +1176,7 @@ static int __devinit ivtv_probe(struct pci_dev *dev, free_streams: ivtv_streams_cleanup(itv, 1); free_irq: - free_irq(itv->dev->irq, (void *)itv); + free_irq(itv->pdev->irq, (void *)itv); free_i2c: exit_ivtv_i2c(itv); free_io: @@ -1194,7 +1193,7 @@ err: retval = -ENODEV; IVTV_ERR("Error %d on initialization\n", retval); - v4l2_device_unregister(&itv->device); + v4l2_device_unregister(&itv->v4l2_dev); kfree(itv); return retval; } @@ -1292,10 +1291,10 @@ int ivtv_init_on_first_open(struct ivtv *itv) return 0; } -static void ivtv_remove(struct pci_dev *pci_dev) +static void ivtv_remove(struct pci_dev *pdev) { - struct v4l2_device *dev = dev_get_drvdata(&pci_dev->dev); - struct ivtv *itv = to_ivtv(dev); + struct v4l2_device *v4l2_dev = dev_get_drvdata(&pdev->dev); + struct ivtv *itv = to_ivtv(v4l2_dev); int i; IVTV_DEBUG_INFO("Removing card\n"); @@ -1336,11 +1335,9 @@ static void ivtv_remove(struct pci_dev *pci_dev) ivtv_streams_cleanup(itv, 1); ivtv_udma_free(itv); - v4l2_device_unregister(&itv->device); - exit_ivtv_i2c(itv); - free_irq(itv->dev->irq, (void *)itv); + free_irq(itv->pdev->irq, (void *)itv); ivtv_iounmap(itv); release_mem_region(itv->base_addr, IVTV_ENCODER_SIZE); @@ -1348,11 +1345,13 @@ static void ivtv_remove(struct pci_dev *pci_dev) if (itv->has_cx23415) release_mem_region(itv->base_addr + IVTV_DECODER_OFFSET, IVTV_DECODER_SIZE); - pci_disable_device(itv->dev); + pci_disable_device(itv->pdev); for (i = 0; i < IVTV_VBI_FRAMES; i++) kfree(itv->vbi.sliced_mpeg_data[i]); printk(KERN_INFO "ivtv: Removed %s\n", itv->card_name); + + v4l2_device_unregister(&itv->v4l2_dev); kfree(itv); } diff --git a/drivers/media/video/ivtv/ivtv-driver.h b/drivers/media/video/ivtv/ivtv-driver.h index 94f7f44d5989..440f7328a7ed 100644 --- a/drivers/media/video/ivtv/ivtv-driver.h +++ b/drivers/media/video/ivtv/ivtv-driver.h @@ -133,7 +133,7 @@ extern int ivtv_debug; #define IVTV_DEBUG(x, type, fmt, args...) \ do { \ if ((x) & ivtv_debug) \ - v4l2_info(&itv->device, " " type ": " fmt , ##args); \ + v4l2_info(&itv->v4l2_dev, " " type ": " fmt , ##args); \ } while (0) #define IVTV_DEBUG_WARN(fmt, args...) IVTV_DEBUG(IVTV_DBGFLG_WARN, "warn", fmt , ## args) #define IVTV_DEBUG_INFO(fmt, args...) IVTV_DEBUG(IVTV_DBGFLG_INFO, "info", fmt , ## args) @@ -149,7 +149,7 @@ extern int ivtv_debug; #define IVTV_DEBUG_HIGH_VOL(x, type, fmt, args...) \ do { \ if (((x) & ivtv_debug) && (ivtv_debug & IVTV_DBGFLG_HIGHVOL)) \ - v4l2_info(&itv->device, " " type ": " fmt , ##args); \ + v4l2_info(&itv->v4l2_dev, " " type ": " fmt , ##args); \ } while (0) #define IVTV_DEBUG_HI_WARN(fmt, args...) IVTV_DEBUG_HIGH_VOL(IVTV_DBGFLG_WARN, "warn", fmt , ## args) #define IVTV_DEBUG_HI_INFO(fmt, args...) IVTV_DEBUG_HIGH_VOL(IVTV_DBGFLG_INFO, "info", fmt , ## args) @@ -163,9 +163,9 @@ extern int ivtv_debug; #define IVTV_DEBUG_HI_YUV(fmt, args...) IVTV_DEBUG_HIGH_VOL(IVTV_DBGFLG_YUV, "yuv", fmt , ## args) /* Standard kernel messages */ -#define IVTV_ERR(fmt, args...) v4l2_err(&itv->device, fmt , ## args) -#define IVTV_WARN(fmt, args...) v4l2_warn(&itv->device, fmt , ## args) -#define IVTV_INFO(fmt, args...) v4l2_info(&itv->device, fmt , ## args) +#define IVTV_ERR(fmt, args...) v4l2_err(&itv->v4l2_dev, fmt , ## args) +#define IVTV_WARN(fmt, args...) v4l2_warn(&itv->v4l2_dev, fmt , ## args) +#define IVTV_INFO(fmt, args...) v4l2_info(&itv->v4l2_dev, fmt , ## args) /* output modes (cx23415 only) */ #define OUT_NONE 0 @@ -315,7 +315,7 @@ struct ivtv; /* forward reference */ struct ivtv_stream { /* These first four fields are always set, even if the stream is not actually created. */ - struct video_device *v4l2dev; /* NULL when stream not created */ + struct video_device *vdev; /* NULL when stream not created */ struct ivtv *itv; /* for ease of use */ const char *name; /* name of the stream */ int type; /* stream type */ @@ -592,7 +592,7 @@ struct ivtv_card; /* Struct to hold info about ivtv cards */ struct ivtv { /* General fixed card data */ - struct pci_dev *dev; /* PCI device */ + struct pci_dev *pdev; /* PCI device */ const struct ivtv_card *card; /* card information */ const char *card_name; /* full name of the card */ const struct ivtv_card_tuner_i2c *card_i2c; /* i2c addresses to probe for tuner */ @@ -612,7 +612,7 @@ struct ivtv { volatile void __iomem *reg_mem; /* pointer to mapped registers */ struct ivtv_options options; /* user options */ - struct v4l2_device device; + struct v4l2_device v4l2_dev; struct v4l2_subdev sd_gpio; /* GPIO sub-device */ u16 instance; @@ -719,9 +719,9 @@ struct ivtv { struct osd_info *osd_info; /* ivtvfb private OSD info */ }; -static inline struct ivtv *to_ivtv(struct v4l2_device *dev) +static inline struct ivtv *to_ivtv(struct v4l2_device *v4l2_dev) { - return container_of(dev, struct ivtv, device); + return container_of(v4l2_dev, struct ivtv, v4l2_dev); } /* Globals */ @@ -788,7 +788,7 @@ static inline int ivtv_raw_vbi(const struct ivtv *itv) /* Call the specified callback for all subdevs matching hw (if 0, then match them all). Ignore any errors. */ #define ivtv_call_hw(itv, hw, o, f, args...) \ - __v4l2_device_call_subdevs(&(itv)->device, !(hw) || (sd->grp_id & (hw)), o, f , ##args) + __v4l2_device_call_subdevs(&(itv)->v4l2_dev, !(hw) || (sd->grp_id & (hw)), o, f , ##args) #define ivtv_call_all(itv, o, f, args...) ivtv_call_hw(itv, 0, o, f , ##args) @@ -796,7 +796,7 @@ static inline int ivtv_raw_vbi(const struct ivtv *itv) match them all). If the callback returns an error other than 0 or -ENOIOCTLCMD, then return with that error code. */ #define ivtv_call_hw_err(itv, hw, o, f, args...) \ - __v4l2_device_call_subdevs_until_err(&(itv)->device, !(hw) || (sd->grp_id & (hw)), o, f , ##args) + __v4l2_device_call_subdevs_until_err(&(itv)->v4l2_dev, !(hw) || (sd->grp_id & (hw)), o, f , ##args) #define ivtv_call_all_err(itv, o, f, args...) ivtv_call_hw_err(itv, 0, o, f , ##args) diff --git a/drivers/media/video/ivtv/ivtv-fileops.c b/drivers/media/video/ivtv/ivtv-fileops.c index 617667d1ceba..cfaacf6096d0 100644 --- a/drivers/media/video/ivtv/ivtv-fileops.c +++ b/drivers/media/video/ivtv/ivtv-fileops.c @@ -991,7 +991,7 @@ int ivtv_v4l2_open(struct file *filp) mutex_lock(&itv->serialize_lock); if (ivtv_init_on_first_open(itv)) { IVTV_ERR("Failed to initialize on minor %d\n", - s->v4l2dev->minor); + vdev->minor); mutex_unlock(&itv->serialize_lock); return -ENXIO; } diff --git a/drivers/media/video/ivtv/ivtv-firmware.c b/drivers/media/video/ivtv/ivtv-firmware.c index 6dba55b7e25a..c1b7ec475c27 100644 --- a/drivers/media/video/ivtv/ivtv-firmware.c +++ b/drivers/media/video/ivtv/ivtv-firmware.c @@ -52,7 +52,7 @@ static int load_fw_direct(const char *fn, volatile u8 __iomem *mem, struct ivtv int retries = 3; retry: - if (retries && request_firmware(&fw, fn, &itv->dev->dev) == 0) { + if (retries && request_firmware(&fw, fn, &itv->pdev->dev) == 0) { int i; volatile u32 __iomem *dst = (volatile u32 __iomem *)mem; const u32 *src = (const u32 *)fw->data; diff --git a/drivers/media/video/ivtv/ivtv-gpio.c b/drivers/media/video/ivtv/ivtv-gpio.c index dc2850e87a7e..3321983d89e5 100644 --- a/drivers/media/video/ivtv/ivtv-gpio.c +++ b/drivers/media/video/ivtv/ivtv-gpio.c @@ -384,7 +384,7 @@ int ivtv_gpio_init(struct ivtv *itv) write_reg(itv->card->gpio_init.initial_value | pin, IVTV_REG_GPIO_OUT); write_reg(itv->card->gpio_init.direction | pin, IVTV_REG_GPIO_DIR); v4l2_subdev_init(&itv->sd_gpio, &subdev_ops); - snprintf(itv->sd_gpio.name, sizeof(itv->sd_gpio.name), "%s-gpio", itv->device.name); + snprintf(itv->sd_gpio.name, sizeof(itv->sd_gpio.name), "%s-gpio", itv->v4l2_dev.name); itv->sd_gpio.grp_id = IVTV_HW_GPIO; - return v4l2_device_register_subdev(&itv->device, &itv->sd_gpio); + return v4l2_device_register_subdev(&itv->v4l2_dev, &itv->sd_gpio); } diff --git a/drivers/media/video/ivtv/ivtv-i2c.c b/drivers/media/video/ivtv/ivtv-i2c.c index ca1d9557945e..e73a196ecc7a 100644 --- a/drivers/media/video/ivtv/ivtv-i2c.c +++ b/drivers/media/video/ivtv/ivtv-i2c.c @@ -194,14 +194,14 @@ struct v4l2_subdev *ivtv_find_hw(struct ivtv *itv, u32 hw) struct v4l2_subdev *result = NULL; struct v4l2_subdev *sd; - spin_lock(&itv->device.lock); - v4l2_device_for_each_subdev(sd, &itv->device) { + spin_lock(&itv->v4l2_dev.lock); + v4l2_device_for_each_subdev(sd, &itv->v4l2_dev) { if (sd->grp_id == hw) { result = sd; break; } } - spin_unlock(&itv->device.lock); + spin_unlock(&itv->v4l2_dev.lock); return result; } @@ -472,8 +472,8 @@ static int ivtv_read(struct ivtv *itv, unsigned char addr, unsigned char *data, intervening stop condition */ static int ivtv_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg *msgs, int num) { - struct v4l2_device *drv = i2c_get_adapdata(i2c_adap); - struct ivtv *itv = to_ivtv(drv); + struct v4l2_device *v4l2_dev = i2c_get_adapdata(i2c_adap); + struct ivtv *itv = to_ivtv(v4l2_dev); int retval; int i; @@ -604,12 +604,12 @@ int init_ivtv_i2c(struct ivtv *itv) sprintf(itv->i2c_adap.name + strlen(itv->i2c_adap.name), " #%d", itv->instance); - i2c_set_adapdata(&itv->i2c_adap, &itv->device); + i2c_set_adapdata(&itv->i2c_adap, &itv->v4l2_dev); memcpy(&itv->i2c_client, &ivtv_i2c_client_template, sizeof(struct i2c_client)); itv->i2c_client.adapter = &itv->i2c_adap; - itv->i2c_adap.dev.parent = &itv->dev->dev; + itv->i2c_adap.dev.parent = &itv->pdev->dev; IVTV_DEBUG_I2C("setting scl and sda to 1\n"); ivtv_setscl(itv, 1); diff --git a/drivers/media/video/ivtv/ivtv-ioctl.c b/drivers/media/video/ivtv/ivtv-ioctl.c index e8621da26d80..9a0424298af1 100644 --- a/drivers/media/video/ivtv/ivtv-ioctl.c +++ b/drivers/media/video/ivtv/ivtv-ioctl.c @@ -770,7 +770,7 @@ static int ivtv_querycap(struct file *file, void *fh, struct v4l2_capability *vc strlcpy(vcap->driver, IVTV_DRIVER_NAME, sizeof(vcap->driver)); strlcpy(vcap->card, itv->card_name, sizeof(vcap->card)); - snprintf(vcap->bus_info, sizeof(vcap->bus_info), "PCI:%s", pci_name(itv->dev)); + snprintf(vcap->bus_info, sizeof(vcap->bus_info), "PCI:%s", pci_name(itv->pdev)); vcap->version = IVTV_DRIVER_VERSION; /* version */ vcap->capabilities = itv->v4l2_cap; /* capabilities */ return 0; @@ -1517,12 +1517,12 @@ static int ivtv_log_status(struct file *file, void *fh) } IVTV_INFO("Tuner: %s\n", test_bit(IVTV_F_I_RADIO_USER, &itv->i_flags) ? "Radio" : "TV"); - cx2341x_log_status(&itv->params, itv->device.name); + cx2341x_log_status(&itv->params, itv->v4l2_dev.name); IVTV_INFO("Status flags: 0x%08lx\n", itv->i_flags); for (i = 0; i < IVTV_MAX_STREAMS; i++) { struct ivtv_stream *s = &itv->streams[i]; - if (s->v4l2dev == NULL || s->buffers == 0) + if (s->vdev == NULL || s->buffers == 0) continue; IVTV_INFO("Stream %s: status 0x%04lx, %d%% of %d KiB (%d buffers) in use\n", s->name, s->s_flags, (s->buffers - s->q_free.buffers) * 100 / s->buffers, diff --git a/drivers/media/video/ivtv/ivtv-irq.c b/drivers/media/video/ivtv/ivtv-irq.c index f5d00ec5da73..01c14d2b381a 100644 --- a/drivers/media/video/ivtv/ivtv-irq.c +++ b/drivers/media/video/ivtv/ivtv-irq.c @@ -46,7 +46,7 @@ static void ivtv_pio_work_handler(struct ivtv *itv) IVTV_DEBUG_HI_DMA("ivtv_pio_work_handler\n"); if (itv->cur_pio_stream < 0 || itv->cur_pio_stream >= IVTV_MAX_STREAMS || - s->v4l2dev == NULL || !ivtv_use_pio(s)) { + s->vdev == NULL || !ivtv_use_pio(s)) { itv->cur_pio_stream = -1; /* trigger PIO complete user interrupt */ write_reg(IVTV_IRQ_ENC_PIO_COMPLETE, 0x44); @@ -109,7 +109,7 @@ static int stream_enc_dma_append(struct ivtv_stream *s, u32 data[CX2341X_MBOX_MA int rc; /* sanity checks */ - if (s->v4l2dev == NULL) { + if (s->vdev == NULL) { IVTV_DEBUG_WARN("Stream %s not started\n", s->name); return -1; } diff --git a/drivers/media/video/ivtv/ivtv-queue.c b/drivers/media/video/ivtv/ivtv-queue.c index 71bd13e22e2e..ff7b7deded4f 100644 --- a/drivers/media/video/ivtv/ivtv-queue.c +++ b/drivers/media/video/ivtv/ivtv-queue.c @@ -230,7 +230,7 @@ int ivtv_stream_alloc(struct ivtv_stream *s) return -ENOMEM; } if (ivtv_might_use_dma(s)) { - s->sg_handle = pci_map_single(itv->dev, s->sg_dma, sizeof(struct ivtv_sg_element), s->dma); + s->sg_handle = pci_map_single(itv->pdev, s->sg_dma, sizeof(struct ivtv_sg_element), s->dma); ivtv_stream_sync_for_cpu(s); } @@ -248,7 +248,7 @@ int ivtv_stream_alloc(struct ivtv_stream *s) } INIT_LIST_HEAD(&buf->list); if (ivtv_might_use_dma(s)) { - buf->dma_handle = pci_map_single(s->itv->dev, + buf->dma_handle = pci_map_single(s->itv->pdev, buf->buf, s->buf_size + 256, s->dma); ivtv_buf_sync_for_cpu(s, buf); } @@ -271,7 +271,7 @@ void ivtv_stream_free(struct ivtv_stream *s) /* empty q_free */ while ((buf = ivtv_dequeue(s, &s->q_free))) { if (ivtv_might_use_dma(s)) - pci_unmap_single(s->itv->dev, buf->dma_handle, + pci_unmap_single(s->itv->pdev, buf->dma_handle, s->buf_size + 256, s->dma); kfree(buf->buf); kfree(buf); @@ -280,7 +280,7 @@ void ivtv_stream_free(struct ivtv_stream *s) /* Free SG Array/Lists */ if (s->sg_dma != NULL) { if (s->sg_handle != IVTV_DMA_UNMAPPED) { - pci_unmap_single(s->itv->dev, s->sg_handle, + pci_unmap_single(s->itv->pdev, s->sg_handle, sizeof(struct ivtv_sg_element), PCI_DMA_TODEVICE); s->sg_handle = IVTV_DMA_UNMAPPED; } diff --git a/drivers/media/video/ivtv/ivtv-queue.h b/drivers/media/video/ivtv/ivtv-queue.h index 476556afd39a..91233839a26c 100644 --- a/drivers/media/video/ivtv/ivtv-queue.h +++ b/drivers/media/video/ivtv/ivtv-queue.h @@ -53,14 +53,14 @@ static inline int ivtv_use_dma(struct ivtv_stream *s) static inline void ivtv_buf_sync_for_cpu(struct ivtv_stream *s, struct ivtv_buffer *buf) { if (ivtv_use_dma(s)) - pci_dma_sync_single_for_cpu(s->itv->dev, buf->dma_handle, + pci_dma_sync_single_for_cpu(s->itv->pdev, buf->dma_handle, s->buf_size + 256, s->dma); } static inline void ivtv_buf_sync_for_device(struct ivtv_stream *s, struct ivtv_buffer *buf) { if (ivtv_use_dma(s)) - pci_dma_sync_single_for_device(s->itv->dev, buf->dma_handle, + pci_dma_sync_single_for_device(s->itv->pdev, buf->dma_handle, s->buf_size + 256, s->dma); } @@ -82,14 +82,14 @@ void ivtv_stream_free(struct ivtv_stream *s); static inline void ivtv_stream_sync_for_cpu(struct ivtv_stream *s) { if (ivtv_use_dma(s)) - pci_dma_sync_single_for_cpu(s->itv->dev, s->sg_handle, + pci_dma_sync_single_for_cpu(s->itv->pdev, s->sg_handle, sizeof(struct ivtv_sg_element), PCI_DMA_TODEVICE); } static inline void ivtv_stream_sync_for_device(struct ivtv_stream *s) { if (ivtv_use_dma(s)) - pci_dma_sync_single_for_device(s->itv->dev, s->sg_handle, + pci_dma_sync_single_for_device(s->itv->pdev, s->sg_handle, sizeof(struct ivtv_sg_element), PCI_DMA_TODEVICE); } diff --git a/drivers/media/video/ivtv/ivtv-streams.c b/drivers/media/video/ivtv/ivtv-streams.c index 854a950af78c..15da01710efc 100644 --- a/drivers/media/video/ivtv/ivtv-streams.c +++ b/drivers/media/video/ivtv/ivtv-streams.c @@ -137,11 +137,11 @@ static struct { static void ivtv_stream_init(struct ivtv *itv, int type) { struct ivtv_stream *s = &itv->streams[type]; - struct video_device *dev = s->v4l2dev; + struct video_device *vdev = s->vdev; - /* we need to keep v4l2dev, so restore it afterwards */ + /* we need to keep vdev, so restore it afterwards */ memset(s, 0, sizeof(*s)); - s->v4l2dev = dev; + s->vdev = vdev; /* initialize ivtv_stream fields */ s->itv = itv; @@ -172,10 +172,10 @@ static int ivtv_prep_dev(struct ivtv *itv, int type) int num_offset = ivtv_stream_info[type].num_offset; int num = itv->instance + ivtv_first_minor + num_offset; - /* These four fields are always initialized. If v4l2dev == NULL, then + /* These four fields are always initialized. If vdev == NULL, then this stream is not in use. In that case no other fields but these four can be used. */ - s->v4l2dev = NULL; + s->vdev = NULL; s->itv = itv; s->type = type; s->name = ivtv_stream_info[type].name; @@ -197,21 +197,21 @@ static int ivtv_prep_dev(struct ivtv *itv, int type) ivtv_stream_init(itv, type); /* allocate and initialize the v4l2 video device structure */ - s->v4l2dev = video_device_alloc(); - if (s->v4l2dev == NULL) { + s->vdev = video_device_alloc(); + if (s->vdev == NULL) { IVTV_ERR("Couldn't allocate v4l2 video_device for %s\n", s->name); return -ENOMEM; } - snprintf(s->v4l2dev->name, sizeof(s->v4l2dev->name), "%s %s", - itv->device.name, s->name); + snprintf(s->vdev->name, sizeof(s->vdev->name), "%s %s", + itv->v4l2_dev.name, s->name); - s->v4l2dev->num = num; - s->v4l2dev->v4l2_dev = &itv->device; - s->v4l2dev->fops = ivtv_stream_info[type].fops; - s->v4l2dev->release = video_device_release; - s->v4l2dev->tvnorms = V4L2_STD_ALL; - ivtv_set_funcs(s->v4l2dev); + s->vdev->num = num; + s->vdev->v4l2_dev = &itv->v4l2_dev; + s->vdev->fops = ivtv_stream_info[type].fops; + s->vdev->release = video_device_release; + s->vdev->tvnorms = V4L2_STD_ALL; + ivtv_set_funcs(s->vdev); return 0; } @@ -226,7 +226,7 @@ int ivtv_streams_setup(struct ivtv *itv) if (ivtv_prep_dev(itv, type)) break; - if (itv->streams[type].v4l2dev == NULL) + if (itv->streams[type].vdev == NULL) continue; /* Allocate Stream */ @@ -247,28 +247,28 @@ static int ivtv_reg_dev(struct ivtv *itv, int type) int vfl_type = ivtv_stream_info[type].vfl_type; int num; - if (s->v4l2dev == NULL) + if (s->vdev == NULL) return 0; - num = s->v4l2dev->num; + num = s->vdev->num; /* card number + user defined offset + device offset */ if (type != IVTV_ENC_STREAM_TYPE_MPG) { struct ivtv_stream *s_mpg = &itv->streams[IVTV_ENC_STREAM_TYPE_MPG]; - if (s_mpg->v4l2dev) - num = s_mpg->v4l2dev->num + ivtv_stream_info[type].num_offset; + if (s_mpg->vdev) + num = s_mpg->vdev->num + ivtv_stream_info[type].num_offset; } - video_set_drvdata(s->v4l2dev, s); + video_set_drvdata(s->vdev, s); /* Register device. First try the desired minor, then any free one. */ - if (video_register_device(s->v4l2dev, vfl_type, num)) { + if (video_register_device(s->vdev, vfl_type, num)) { IVTV_ERR("Couldn't register v4l2 device for %s kernel number %d\n", s->name, num); - video_device_release(s->v4l2dev); - s->v4l2dev = NULL; + video_device_release(s->vdev); + s->vdev = NULL; return -ENOMEM; } - num = s->v4l2dev->num; + num = s->vdev->num; switch (vfl_type) { case VFL_TYPE_GRABBER: @@ -316,9 +316,9 @@ void ivtv_streams_cleanup(struct ivtv *itv, int unregister) /* Teardown all streams */ for (type = 0; type < IVTV_MAX_STREAMS; type++) { - struct video_device *vdev = itv->streams[type].v4l2dev; + struct video_device *vdev = itv->streams[type].vdev; - itv->streams[type].v4l2dev = NULL; + itv->streams[type].vdev = NULL; if (vdev == NULL) continue; @@ -449,7 +449,7 @@ int ivtv_start_v4l2_encode_stream(struct ivtv_stream *s) int captype = 0, subtype = 0; int enable_passthrough = 0; - if (s->v4l2dev == NULL) + if (s->vdev == NULL) return -EINVAL; IVTV_DEBUG_INFO("Start encoder stream %s\n", s->name); @@ -611,7 +611,7 @@ static int ivtv_setup_v4l2_decode_stream(struct ivtv_stream *s) struct cx2341x_mpeg_params *p = &itv->params; int datatype; - if (s->v4l2dev == NULL) + if (s->vdev == NULL) return -EINVAL; IVTV_DEBUG_INFO("Setting some initial decoder settings\n"); @@ -657,7 +657,7 @@ int ivtv_start_v4l2_decode_stream(struct ivtv_stream *s, int gop_offset) { struct ivtv *itv = s->itv; - if (s->v4l2dev == NULL) + if (s->vdev == NULL) return -EINVAL; if (test_and_set_bit(IVTV_F_S_STREAMING, &s->s_flags)) @@ -705,7 +705,7 @@ void ivtv_stop_all_captures(struct ivtv *itv) for (i = IVTV_MAX_STREAMS - 1; i >= 0; i--) { struct ivtv_stream *s = &itv->streams[i]; - if (s->v4l2dev == NULL) + if (s->vdev == NULL) continue; if (test_bit(IVTV_F_S_STREAMING, &s->s_flags)) { ivtv_stop_v4l2_encode_stream(s, 0); @@ -720,7 +720,7 @@ int ivtv_stop_v4l2_encode_stream(struct ivtv_stream *s, int gop_end) int cap_type; int stopmode; - if (s->v4l2dev == NULL) + if (s->vdev == NULL) return -EINVAL; /* This function assumes that you are allowed to stop the capture @@ -834,7 +834,7 @@ int ivtv_stop_v4l2_decode_stream(struct ivtv_stream *s, int flags, u64 pts) { struct ivtv *itv = s->itv; - if (s->v4l2dev == NULL) + if (s->vdev == NULL) return -EINVAL; if (s->type != IVTV_DEC_STREAM_TYPE_YUV && s->type != IVTV_DEC_STREAM_TYPE_MPG) @@ -895,7 +895,7 @@ int ivtv_passthrough_mode(struct ivtv *itv, int enable) struct ivtv_stream *yuv_stream = &itv->streams[IVTV_ENC_STREAM_TYPE_YUV]; struct ivtv_stream *dec_stream = &itv->streams[IVTV_DEC_STREAM_TYPE_YUV]; - if (yuv_stream->v4l2dev == NULL || dec_stream->v4l2dev == NULL) + if (yuv_stream->vdev == NULL || dec_stream->vdev == NULL) return -EINVAL; IVTV_DEBUG_INFO("ivtv ioctl: Select passthrough mode\n"); diff --git a/drivers/media/video/ivtv/ivtv-udma.c b/drivers/media/video/ivtv/ivtv-udma.c index 460db03b0ba0..d07ad6c39024 100644 --- a/drivers/media/video/ivtv/ivtv-udma.c +++ b/drivers/media/video/ivtv/ivtv-udma.c @@ -93,7 +93,7 @@ void ivtv_udma_alloc(struct ivtv *itv) { if (itv->udma.SG_handle == 0) { /* Map DMA Page Array Buffer */ - itv->udma.SG_handle = pci_map_single(itv->dev, itv->udma.SGarray, + itv->udma.SG_handle = pci_map_single(itv->pdev, itv->udma.SGarray, sizeof(itv->udma.SGarray), PCI_DMA_TODEVICE); ivtv_udma_sync_for_cpu(itv); } @@ -147,7 +147,7 @@ int ivtv_udma_setup(struct ivtv *itv, unsigned long ivtv_dest_addr, } /* Map SG List */ - dma->SG_length = pci_map_sg(itv->dev, dma->SGlist, dma->page_count, PCI_DMA_TODEVICE); + dma->SG_length = pci_map_sg(itv->pdev, dma->SGlist, dma->page_count, PCI_DMA_TODEVICE); /* Fill SG Array with new values */ ivtv_udma_fill_sg_array (dma, ivtv_dest_addr, 0, -1); @@ -172,7 +172,7 @@ void ivtv_udma_unmap(struct ivtv *itv) /* Unmap Scatterlist */ if (dma->SG_length) { - pci_unmap_sg(itv->dev, dma->SGlist, dma->page_count, PCI_DMA_TODEVICE); + pci_unmap_sg(itv->pdev, dma->SGlist, dma->page_count, PCI_DMA_TODEVICE); dma->SG_length = 0; } /* sync DMA */ @@ -191,13 +191,13 @@ void ivtv_udma_free(struct ivtv *itv) /* Unmap SG Array */ if (itv->udma.SG_handle) { - pci_unmap_single(itv->dev, itv->udma.SG_handle, + pci_unmap_single(itv->pdev, itv->udma.SG_handle, sizeof(itv->udma.SGarray), PCI_DMA_TODEVICE); } /* Unmap Scatterlist */ if (itv->udma.SG_length) { - pci_unmap_sg(itv->dev, itv->udma.SGlist, itv->udma.page_count, PCI_DMA_TODEVICE); + pci_unmap_sg(itv->pdev, itv->udma.SGlist, itv->udma.page_count, PCI_DMA_TODEVICE); } for (i = 0; i < IVTV_DMA_SG_OSD_ENT; i++) { diff --git a/drivers/media/video/ivtv/ivtv-udma.h b/drivers/media/video/ivtv/ivtv-udma.h index df727e23be0a..ee3c9efb5b72 100644 --- a/drivers/media/video/ivtv/ivtv-udma.h +++ b/drivers/media/video/ivtv/ivtv-udma.h @@ -35,13 +35,13 @@ void ivtv_udma_start(struct ivtv *itv); static inline void ivtv_udma_sync_for_device(struct ivtv *itv) { - pci_dma_sync_single_for_device((struct pci_dev *)itv->dev, itv->udma.SG_handle, + pci_dma_sync_single_for_device(itv->pdev, itv->udma.SG_handle, sizeof(itv->udma.SGarray), PCI_DMA_TODEVICE); } static inline void ivtv_udma_sync_for_cpu(struct ivtv *itv) { - pci_dma_sync_single_for_cpu((struct pci_dev *)itv->dev, itv->udma.SG_handle, + pci_dma_sync_single_for_cpu(itv->pdev, itv->udma.SG_handle, sizeof(itv->udma.SGarray), PCI_DMA_TODEVICE); } diff --git a/drivers/media/video/ivtv/ivtv-yuv.c b/drivers/media/video/ivtv/ivtv-yuv.c index ee91107376c7..7912ed6b72ee 100644 --- a/drivers/media/video/ivtv/ivtv-yuv.c +++ b/drivers/media/video/ivtv/ivtv-yuv.c @@ -103,7 +103,7 @@ static int ivtv_yuv_prep_user_dma(struct ivtv *itv, struct ivtv_user_dma *dma, dma->page_count = 0; return -ENOMEM; } - dma->SG_length = pci_map_sg(itv->dev, dma->SGlist, dma->page_count, PCI_DMA_TODEVICE); + dma->SG_length = pci_map_sg(itv->pdev, dma->SGlist, dma->page_count, PCI_DMA_TODEVICE); /* Fill SG Array with new values */ ivtv_udma_fill_sg_array(dma, y_buffer_offset, uv_buffer_offset, y_size); @@ -910,7 +910,7 @@ static void ivtv_yuv_init(struct ivtv *itv) /* We need a buffer for blanking when Y plane is offset - non-fatal if we can't get one */ yi->blanking_ptr = kzalloc(720 * 16, GFP_KERNEL|__GFP_NOWARN); if (yi->blanking_ptr) { - yi->blanking_dmaptr = pci_map_single(itv->dev, yi->blanking_ptr, 720*16, PCI_DMA_TODEVICE); + yi->blanking_dmaptr = pci_map_single(itv->pdev, yi->blanking_ptr, 720*16, PCI_DMA_TODEVICE); } else { yi->blanking_dmaptr = 0; IVTV_DEBUG_WARN("Failed to allocate yuv blanking buffer\n"); @@ -1237,7 +1237,7 @@ void ivtv_yuv_close(struct ivtv *itv) if (yi->blanking_ptr) { kfree(yi->blanking_ptr); yi->blanking_ptr = NULL; - pci_unmap_single(itv->dev, yi->blanking_dmaptr, 720*16, PCI_DMA_TODEVICE); + pci_unmap_single(itv->pdev, yi->blanking_dmaptr, 720*16, PCI_DMA_TODEVICE); } /* Invalidate the old dimension information */ diff --git a/drivers/media/video/ivtv/ivtvfb.c b/drivers/media/video/ivtv/ivtvfb.c index 36abd2aef6f1..66e6eb513076 100644 --- a/drivers/media/video/ivtv/ivtvfb.c +++ b/drivers/media/video/ivtv/ivtvfb.c @@ -1192,12 +1192,12 @@ static int ivtvfb_init_card(struct ivtv *itv) static int __init ivtvfb_callback_init(struct device *dev, void *p) { struct v4l2_device *v4l2_dev = dev_get_drvdata(dev); - struct ivtv *itv = container_of(v4l2_dev, struct ivtv, device); + struct ivtv *itv = container_of(v4l2_dev, struct ivtv, v4l2_dev); if (itv && (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) { if (ivtvfb_init_card(itv) == 0) { IVTVFB_INFO("Framebuffer registered on %s\n", - itv->device.name); + itv->v4l2_dev.name); (*(int *)p)++; } } @@ -1207,7 +1207,7 @@ static int __init ivtvfb_callback_init(struct device *dev, void *p) static int ivtvfb_callback_cleanup(struct device *dev, void *p) { struct v4l2_device *v4l2_dev = dev_get_drvdata(dev); - struct ivtv *itv = container_of(v4l2_dev, struct ivtv, device); + struct ivtv *itv = container_of(v4l2_dev, struct ivtv, v4l2_dev); if (itv && (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) { if (unregister_framebuffer(&itv->osd_info->ivtvfb_info)) { -- cgit v1.2.3 From 80b36e0fcfe7520ee92f648148d091ad880ae711 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sat, 7 Feb 2009 11:00:02 -0300 Subject: V4L/DVB (10490): v4l2: prefill ident and revision from v4l2_dbg_chip_ident. Drivers that implement this always have to set the ident and revision to V4L2_IDENT_NONE and 0. Do this in the v4l2 core so drivers don't have to do this. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/v4l2-ioctl.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers/media/video') diff --git a/drivers/media/video/v4l2-ioctl.c b/drivers/media/video/v4l2-ioctl.c index 52d687b165e0..20a571f21577 100644 --- a/drivers/media/video/v4l2-ioctl.c +++ b/drivers/media/video/v4l2-ioctl.c @@ -24,6 +24,7 @@ #endif #include #include +#include #include #define dbgarg(cmd, fmt, arg...) \ @@ -1745,6 +1746,8 @@ static long __video_do_ioctl(struct file *file, if (!ops->vidioc_g_chip_ident) break; + p->ident = V4L2_IDENT_NONE; + p->revision = 0; ret = ops->vidioc_g_chip_ident(file, fh, p); if (!ret) dbgarg(cmd, "chip_ident=%u, revision=0x%x\n", p->ident, p->revision); -- cgit v1.2.3 From 1b8dac150a01e2312d8e3fedd6462a0ec34c96d0 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sat, 7 Feb 2009 11:18:05 -0300 Subject: V4L/DVB (10499): saa7146: convert saa7146 and mxb in particular to v4l2_subdev. Modified mxb to load the i2c modules through v4l2_subdev. So no more probing. Modified tea6415c and tea6420 to use the standard routing ops to do the routing, rather than using private commands. Dropped the private commands from tda9840 (they were never used except during initialization of the module). Added saa7146 support for VIDIOC_DBG_G_CHIP_IDENT. Converted saa5246a and saa5249 to v4l2_subdev. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/common/saa7146_video.c | 25 +++- drivers/media/video/mxb.c | 274 ++++++++++++++--------------------- drivers/media/video/saa5246a.c | 69 ++++++--- drivers/media/video/saa5249.c | 70 +++++---- drivers/media/video/tda9840.c | 81 ++--------- drivers/media/video/tda9840.h | 14 -- drivers/media/video/tea6415c.c | 52 +++---- drivers/media/video/tea6415c.h | 12 -- drivers/media/video/tea6420.c | 68 ++++----- drivers/media/video/tea6420.h | 27 ++-- include/media/v4l2-chip-ident.h | 18 +++ 11 files changed, 315 insertions(+), 395 deletions(-) delete mode 100644 drivers/media/video/tda9840.h (limited to 'drivers/media/video') diff --git a/drivers/media/common/saa7146_video.c b/drivers/media/common/saa7146_video.c index 91b7a4def46c..a2a8847e6789 100644 --- a/drivers/media/common/saa7146_video.c +++ b/drivers/media/common/saa7146_video.c @@ -1,4 +1,5 @@ #include +#include static int max_memory = 32; @@ -209,6 +210,7 @@ static struct v4l2_queryctrl controls[] = { .step = 1, .default_value = 128, .type = V4L2_CTRL_TYPE_INTEGER, + .flags = V4L2_CTRL_FLAG_SLIDER, },{ .id = V4L2_CID_CONTRAST, .name = "Contrast", @@ -217,6 +219,7 @@ static struct v4l2_queryctrl controls[] = { .step = 1, .default_value = 64, .type = V4L2_CTRL_TYPE_INTEGER, + .flags = V4L2_CTRL_FLAG_SLIDER, },{ .id = V4L2_CID_SATURATION, .name = "Saturation", @@ -225,15 +228,16 @@ static struct v4l2_queryctrl controls[] = { .step = 1, .default_value = 64, .type = V4L2_CTRL_TYPE_INTEGER, + .flags = V4L2_CTRL_FLAG_SLIDER, },{ .id = V4L2_CID_VFLIP, - .name = "Vertical flip", + .name = "Vertical Flip", .minimum = 0, .maximum = 1, .type = V4L2_CTRL_TYPE_BOOLEAN, },{ .id = V4L2_CID_HFLIP, - .name = "Horizontal flip", + .name = "Horizontal Flip", .minimum = 0, .maximum = 1, .type = V4L2_CTRL_TYPE_BOOLEAN, @@ -1112,6 +1116,22 @@ static int vidioc_streamoff(struct file *file, void *__fh, enum v4l2_buf_type ty return err; } +static int vidioc_g_chip_ident(struct file *file, void *__fh, + struct v4l2_dbg_chip_ident *chip) +{ + struct saa7146_fh *fh = __fh; + struct saa7146_dev *dev = fh->dev; + + chip->ident = V4L2_IDENT_NONE; + chip->revision = 0; + if (v4l2_chip_match_host(&chip->match)) { + chip->ident = V4L2_IDENT_SAA7146; + return 0; + } + return v4l2_device_call_until_err(&dev->v4l2_dev, 0, + core, g_chip_ident, chip); +} + #ifdef CONFIG_VIDEO_V4L1_COMPAT static int vidiocgmbuf(struct file *file, void *__fh, struct video_mbuf *mbuf) { @@ -1152,6 +1172,7 @@ const struct v4l2_ioctl_ops saa7146_video_ioctl_ops = { .vidioc_try_fmt_vid_overlay = vidioc_try_fmt_vid_overlay, .vidioc_s_fmt_vid_overlay = vidioc_s_fmt_vid_overlay, .vidioc_g_fmt_vbi_cap = vidioc_g_fmt_vbi_cap, + .vidioc_g_chip_ident = vidioc_g_chip_ident, .vidioc_overlay = vidioc_overlay, .vidioc_g_fbuf = vidioc_g_fbuf, diff --git a/drivers/media/video/mxb.c b/drivers/media/video/mxb.c index 8ecda8dfbd04..996011f2aba5 100644 --- a/drivers/media/video/mxb.c +++ b/drivers/media/video/mxb.c @@ -32,9 +32,14 @@ #include "mxb.h" #include "tea6415c.h" #include "tea6420.h" -#include "tda9840.h" -#define I2C_SAA7111 0x24 +#define I2C_SAA5246A 0x11 +#define I2C_SAA7111A 0x24 +#define I2C_TDA9840 0x42 +#define I2C_TEA6415C 0x43 +#define I2C_TEA6420_1 0x4c +#define I2C_TEA6420_2 0x4d +#define I2C_TUNER 0x60 #define MXB_BOARD_CAN_DO_VBI(dev) (dev->revision != 0) @@ -79,31 +84,29 @@ static struct { static int video_audio_connect[MXB_INPUTS] = { 0, 1, 3, 3 }; -/* these are the necessary input-output-pins for bringing one audio source -(see above) to the CD-output */ -static struct tea6420_multiplex TEA6420_cd[MXB_AUDIOS+1][2] = - { - {{1,1,0},{1,1,0}}, /* Tuner */ - {{5,1,0},{6,1,0}}, /* AUX 1 */ - {{4,1,0},{6,1,0}}, /* AUX 2 */ - {{3,1,0},{6,1,0}}, /* AUX 3 */ - {{1,1,0},{3,1,0}}, /* Radio */ - {{1,1,0},{2,1,0}}, /* CD-Rom */ - {{6,1,0},{6,1,0}} /* Mute */ - }; - -/* these are the necessary input-output-pins for bringing one audio source -(see above) to the line-output */ -static struct tea6420_multiplex TEA6420_line[MXB_AUDIOS+1][2] = - { - {{2,3,0},{1,2,0}}, - {{5,3,0},{6,2,0}}, - {{4,3,0},{6,2,0}}, - {{3,3,0},{6,2,0}}, - {{2,3,0},{3,2,0}}, - {{2,3,0},{2,2,0}}, - {{6,3,0},{6,2,0}} /* Mute */ - }; +/* These are the necessary input-output-pins for bringing one audio source + (see above) to the CD-output. Note that gain is set to 0 in this table. */ +static struct v4l2_routing TEA6420_cd[MXB_AUDIOS + 1][2] = { + { { 1, 1 }, { 1, 1 } }, /* Tuner */ + { { 5, 1 }, { 6, 1 } }, /* AUX 1 */ + { { 4, 1 }, { 6, 1 } }, /* AUX 2 */ + { { 3, 1 }, { 6, 1 } }, /* AUX 3 */ + { { 1, 1 }, { 3, 1 } }, /* Radio */ + { { 1, 1 }, { 2, 1 } }, /* CD-Rom */ + { { 6, 1 }, { 6, 1 } } /* Mute */ +}; + +/* These are the necessary input-output-pins for bringing one audio source + (see above) to the line-output. Note that gain is set to 0 in this table. */ +static struct v4l2_routing TEA6420_line[MXB_AUDIOS + 1][2] = { + { { 2, 3 }, { 1, 2 } }, + { { 5, 3 }, { 6, 2 } }, + { { 4, 3 }, { 6, 2 } }, + { { 3, 3 }, { 6, 2 } }, + { { 2, 3 }, { 3, 2 } }, + { { 2, 3 }, { 2, 2 } }, + { { 6, 3 }, { 6, 2 } } /* Mute */ +}; #define MAXCONTROLS 1 static struct v4l2_queryctrl mxb_controls[] = { @@ -117,12 +120,12 @@ struct mxb struct i2c_adapter i2c_adapter; - struct i2c_client *saa7111a; - struct i2c_client *tda9840; - struct i2c_client *tea6415c; - struct i2c_client *tuner; - struct i2c_client *tea6420_1; - struct i2c_client *tea6420_2; + struct v4l2_subdev *saa7111a; + struct v4l2_subdev *tda9840; + struct v4l2_subdev *tea6415c; + struct v4l2_subdev *tuner; + struct v4l2_subdev *tea6420_1; + struct v4l2_subdev *tea6420_2; int cur_mode; /* current audio mode (mono, stereo, ...) */ int cur_input; /* current input */ @@ -130,84 +133,51 @@ struct mxb struct v4l2_frequency cur_freq; /* current frequency the tuner is tuned to */ }; -static struct saa7146_extension extension; - -static int mxb_check_clients(struct device *dev, void *data) -{ - struct mxb *mxb = data; - struct i2c_client *client = i2c_verify_client(dev); - - if (!client) - return 0; - - if (I2C_ADDR_TEA6420_1 == client->addr) - mxb->tea6420_1 = client; - if (I2C_ADDR_TEA6420_2 == client->addr) - mxb->tea6420_2 = client; - if (I2C_TEA6415C_2 == client->addr) - mxb->tea6415c = client; - if (I2C_ADDR_TDA9840 == client->addr) - mxb->tda9840 = client; - if (I2C_SAA7111 == client->addr) - mxb->saa7111a = client; - if (0x60 == client->addr) - mxb->tuner = client; +#define saa7111a_call(mxb, o, f, args...) \ + v4l2_subdev_call(mxb->saa7111a, o, f, ##args) +#define tea6420_1_call(mxb, o, f, args...) \ + v4l2_subdev_call(mxb->tea6420_1, o, f, ##args) +#define tea6420_2_call(mxb, o, f, args...) \ + v4l2_subdev_call(mxb->tea6420_2, o, f, ##args) +#define tda9840_call(mxb, o, f, args...) \ + v4l2_subdev_call(mxb->tda9840, o, f, ##args) +#define tea6415c_call(mxb, o, f, args...) \ + v4l2_subdev_call(mxb->tea6415c, o, f, ##args) +#define tuner_call(mxb, o, f, args...) \ + v4l2_subdev_call(mxb->tuner, o, f, ##args) +#define call_all(dev, o, f, args...) \ + v4l2_device_call_until_err(&dev->v4l2_dev, 0, o, f, ##args) - return 0; -} +static struct saa7146_extension extension; -static int mxb_probe(struct saa7146_dev* dev) +static int mxb_probe(struct saa7146_dev *dev) { - struct mxb* mxb = NULL; - int result; - - result = request_module("saa7115"); - if (result < 0) { - printk("mxb: saa7111 i2c module not available.\n"); - return -ENODEV; - } - result = request_module("tea6420"); - if (result < 0) { - printk("mxb: tea6420 i2c module not available.\n"); - return -ENODEV; - } - result = request_module("tea6415c"); - if (result < 0) { - printk("mxb: tea6415c i2c module not available.\n"); - return -ENODEV; - } - result = request_module("tda9840"); - if (result < 0) { - printk("mxb: tda9840 i2c module not available.\n"); - return -ENODEV; - } - result = request_module("tuner"); - if (result < 0) { - printk("mxb: tuner i2c module not available.\n"); - return -ENODEV; - } + struct mxb *mxb = NULL; mxb = kzalloc(sizeof(struct mxb), GFP_KERNEL); - if( NULL == mxb ) { + if (mxb == NULL) { DEB_D(("not enough kernel memory.\n")); return -ENOMEM; } - mxb->i2c_adapter = (struct i2c_adapter) { - .class = I2C_CLASS_TV_ANALOG, - }; - snprintf(mxb->i2c_adapter.name, sizeof(mxb->i2c_adapter.name), "mxb%d", mxb_num); saa7146_i2c_adapter_prepare(dev, &mxb->i2c_adapter, SAA7146_I2C_BUS_BIT_RATE_480); - if(i2c_add_adapter(&mxb->i2c_adapter) < 0) { + if (i2c_add_adapter(&mxb->i2c_adapter) < 0) { DEB_S(("cannot register i2c-device. skipping.\n")); kfree(mxb); return -EFAULT; } - /* loop through all i2c-devices on the bus and look who is there */ - device_for_each_child(&mxb->i2c_adapter.dev, mxb, mxb_check_clients); + mxb->saa7111a = v4l2_i2c_new_subdev(&mxb->i2c_adapter, "saa7115", "saa7111", I2C_SAA7111A); + mxb->tea6420_1 = v4l2_i2c_new_subdev(&mxb->i2c_adapter, "tea6420", "tea6420", I2C_TEA6420_1); + mxb->tea6420_2 = v4l2_i2c_new_subdev(&mxb->i2c_adapter, "tea6420", "tea6420", I2C_TEA6420_2); + mxb->tea6415c = v4l2_i2c_new_subdev(&mxb->i2c_adapter, "tea6415c", "tea6415c", I2C_TEA6415C); + mxb->tda9840 = v4l2_i2c_new_subdev(&mxb->i2c_adapter, "tda9840", "tda9840", I2C_TDA9840); + mxb->tuner = v4l2_i2c_new_subdev(&mxb->i2c_adapter, "tuner", "tuner", I2C_TUNER); + if (v4l2_i2c_new_subdev(&mxb->i2c_adapter, "saa5246a", "saa5246a", I2C_SAA5246A)) { + printk(KERN_INFO "mxb: found teletext decoder\n"); + } /* check if all devices are present */ if (!mxb->tea6420_1 || !mxb->tea6420_2 || !mxb->tea6415c || @@ -295,47 +265,45 @@ static int mxb_init_done(struct saa7146_dev* dev) struct v4l2_routing route; int i = 0, err = 0; - struct tea6415c_multiplex vm; /* select video mode in saa7111a */ - mxb->saa7111a->driver->command(mxb->saa7111a, VIDIOC_S_STD, &std); + saa7111a_call(mxb, tuner, s_std, std); /* select tuner-output on saa7111a */ i = 0; route.input = SAA7115_COMPOSITE0; route.output = SAA7111_FMT_CCIR | SAA7111_VBI_BYPASS; - mxb->saa7111a->driver->command(mxb->saa7111a, VIDIOC_INT_S_VIDEO_ROUTING, &route); + saa7111a_call(mxb, video, s_routing, &route); /* select a tuner type */ tun_setup.mode_mask = T_ANALOG_TV; tun_setup.addr = ADDR_UNSET; tun_setup.type = TUNER_PHILIPS_PAL; - mxb->tuner->driver->command(mxb->tuner, TUNER_SET_TYPE_ADDR, &tun_setup); + tuner_call(mxb, tuner, s_type_addr, &tun_setup); /* tune in some frequency on tuner */ mxb->cur_freq.tuner = 0; mxb->cur_freq.type = V4L2_TUNER_ANALOG_TV; mxb->cur_freq.frequency = freq; - mxb->tuner->driver->command(mxb->tuner, VIDIOC_S_FREQUENCY, - &mxb->cur_freq); + tuner_call(mxb, tuner, s_frequency, &mxb->cur_freq); /* set a default video standard */ - mxb->tuner->driver->command(mxb->tuner, VIDIOC_S_STD, &std); + tuner_call(mxb, tuner, s_std, std); /* mute audio on tea6420s */ - mxb->tea6420_1->driver->command(mxb->tea6420_1, TEA6420_SWITCH, &TEA6420_line[6][0]); - mxb->tea6420_2->driver->command(mxb->tea6420_2, TEA6420_SWITCH, &TEA6420_line[6][1]); - mxb->tea6420_1->driver->command(mxb->tea6420_1, TEA6420_SWITCH, &TEA6420_cd[6][0]); - mxb->tea6420_2->driver->command(mxb->tea6420_2, TEA6420_SWITCH, &TEA6420_cd[6][1]); + tea6420_1_call(mxb, audio, s_routing, &TEA6420_line[6][0]); + tea6420_2_call(mxb, audio, s_routing, &TEA6420_line[6][1]); + tea6420_1_call(mxb, audio, s_routing, &TEA6420_line[6][0]); + tea6420_2_call(mxb, audio, s_routing, &TEA6420_line[6][1]); - /* switch to tuner-channel on tea6415c*/ - vm.out = 17; - vm.in = 3; - mxb->tea6415c->driver->command(mxb->tea6415c, TEA6415C_SWITCH, &vm); + /* switch to tuner-channel on tea6415c */ + route.input = 3; + route.output = 17; + tea6415c_call(mxb, video, s_routing, &route); - /* select tuner-output on multicable on tea6415c*/ - vm.in = 3; - vm.out = 13; - mxb->tea6415c->driver->command(mxb->tea6415c, TEA6415C_SWITCH, &vm); + /* select tuner-output on multicable on tea6415c */ + route.input = 3; + route.output = 13; + tea6415c_call(mxb, video, s_routing, &route); /* the rest for mxb */ mxb->cur_input = 0; @@ -461,14 +429,14 @@ static int vidioc_s_ctrl(struct file *file, void *fh, struct v4l2_control *vc) mxb->cur_mute = vc->value; if (!vc->value) { /* switch the audio-source */ - mxb->tea6420_1->driver->command(mxb->tea6420_1, TEA6420_SWITCH, + tea6420_1_call(mxb, audio, s_routing, &TEA6420_line[video_audio_connect[mxb->cur_input]][0]); - mxb->tea6420_2->driver->command(mxb->tea6420_2, TEA6420_SWITCH, + tea6420_2_call(mxb, audio, s_routing, &TEA6420_line[video_audio_connect[mxb->cur_input]][1]); } else { - mxb->tea6420_1->driver->command(mxb->tea6420_1, TEA6420_SWITCH, + tea6420_1_call(mxb, audio, s_routing, &TEA6420_line[6][0]); - mxb->tea6420_2->driver->command(mxb->tea6420_2, TEA6420_SWITCH, + tea6420_2_call(mxb, audio, s_routing, &TEA6420_line[6][1]); } DEB_EE(("VIDIOC_S_CTRL, V4L2_CID_AUDIO_MUTE: %d.\n", vc->value)); @@ -499,7 +467,6 @@ static int vidioc_s_input(struct file *file, void *fh, unsigned int input) { struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev; struct mxb *mxb = (struct mxb *)dev->ext_priv; - struct tea6415c_multiplex vm; struct v4l2_routing route; int i = 0; @@ -518,16 +485,16 @@ static int vidioc_s_input(struct file *file, void *fh, unsigned int input) switch (input) { case TUNER: i = SAA7115_COMPOSITE0; - vm.in = 3; - vm.out = 17; + route.input = 3; + route.output = 17; - if (mxb->tea6415c->driver->command(mxb->tea6415c, TEA6415C_SWITCH, &vm)) { + if (tea6415c_call(mxb, video, s_routing, &route)) { printk(KERN_ERR "VIDIOC_S_INPUT: could not address tea6415c #1\n"); return -EFAULT; } /* connect tuner-output always to multicable */ - vm.in = 3; - vm.out = 13; + route.input = 3; + route.output = 13; break; case AUX3_YC: /* nothing to be done here. aux3_yc is @@ -541,8 +508,8 @@ static int vidioc_s_input(struct file *file, void *fh, unsigned int input) break; case AUX1: i = SAA7115_COMPOSITE0; - vm.in = 1; - vm.out = 17; + route.input = 1; + route.output = 17; break; } @@ -550,7 +517,7 @@ static int vidioc_s_input(struct file *file, void *fh, unsigned int input) switch (input) { case TUNER: case AUX1: - if (mxb->tea6415c->driver->command(mxb->tea6415c, TEA6415C_SWITCH, &vm)) { + if (tea6415c_call(mxb, video, s_routing, &route)) { printk(KERN_ERR "VIDIOC_S_INPUT: could not address tea6415c #3\n"); return -EFAULT; } @@ -562,14 +529,14 @@ static int vidioc_s_input(struct file *file, void *fh, unsigned int input) /* switch video in saa7111a */ route.input = i; route.output = 0; - if (mxb->saa7111a->driver->command(mxb->saa7111a, VIDIOC_INT_S_VIDEO_ROUTING, &route)) + if (saa7111a_call(mxb, video, s_routing, &route)) printk(KERN_ERR "VIDIOC_S_INPUT: could not address saa7111a #1.\n"); /* switch the audio-source only if necessary */ if (0 == mxb->cur_mute) { - mxb->tea6420_1->driver->command(mxb->tea6420_1, TEA6420_SWITCH, + tea6420_1_call(mxb, audio, s_routing, &TEA6420_line[video_audio_connect[input]][0]); - mxb->tea6420_2->driver->command(mxb->tea6420_2, TEA6420_SWITCH, + tea6420_2_call(mxb, audio, s_routing, &TEA6420_line[video_audio_connect[input]][1]); } @@ -589,14 +556,12 @@ static int vidioc_g_tuner(struct file *file, void *fh, struct v4l2_tuner *t) DEB_EE(("VIDIOC_G_TUNER: %d\n", t->index)); memset(t, 0, sizeof(*t)); - i2c_clients_command(&mxb->i2c_adapter, VIDIOC_G_TUNER, t); - strlcpy(t->name, "TV Tuner", sizeof(t->name)); t->type = V4L2_TUNER_ANALOG_TV; t->capability = V4L2_TUNER_CAP_NORM | V4L2_TUNER_CAP_STEREO | V4L2_TUNER_CAP_LANG1 | V4L2_TUNER_CAP_LANG2 | V4L2_TUNER_CAP_SAP; t->audmode = mxb->cur_mode; - return 0; + return call_all(dev, tuner, g_tuner, t); } static int vidioc_s_tuner(struct file *file, void *fh, struct v4l2_tuner *t) @@ -610,8 +575,7 @@ static int vidioc_s_tuner(struct file *file, void *fh, struct v4l2_tuner *t) } mxb->cur_mode = t->audmode; - i2c_clients_command(&mxb->i2c_adapter, VIDIOC_S_TUNER, t); - return 0; + return call_all(dev, tuner, s_tuner, t); } static int vidioc_g_frequency(struct file *file, void *fh, struct v4l2_frequency *f) @@ -652,7 +616,7 @@ static int vidioc_s_frequency(struct file *file, void *fh, struct v4l2_frequency DEB_EE(("VIDIOC_S_FREQUENCY: freq:0x%08x.\n", mxb->cur_freq.frequency)); /* tune in desired frequency */ - mxb->tuner->driver->command(mxb->tuner, VIDIOC_S_FREQUENCY, &mxb->cur_freq); + tuner_call(mxb, tuner, s_frequency, &mxb->cur_freq); /* hack: changing the frequency should invalidate the vbi-counter (=> alevt) */ spin_lock(&dev->slock); @@ -687,19 +651,15 @@ static int vidioc_s_audio(struct file *file, void *fh, struct v4l2_audio *a) static int vidioc_g_register(struct file *file, void *fh, struct v4l2_dbg_register *reg) { struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev; - struct mxb *mxb = (struct mxb *)dev->ext_priv; - i2c_clients_command(&mxb->i2c_adapter, VIDIOC_DBG_G_REGISTER, reg); - return 0; + return call_all(dev, core, g_register, reg); } static int vidioc_s_register(struct file *file, void *fh, struct v4l2_dbg_register *reg) { struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev; - struct mxb *mxb = (struct mxb *)dev->ext_priv; - i2c_clients_command(&mxb->i2c_adapter, VIDIOC_DBG_S_REGISTER, reg); - return 0; + return call_all(dev, core, s_register, reg); } #endif @@ -720,8 +680,8 @@ static long vidioc_default(struct file *file, void *fh, int cmd, void *arg) DEB_EE(("MXB_S_AUDIO_CD: i:%d.\n", i)); - mxb->tea6420_1->driver->command(mxb->tea6420_1, TEA6420_SWITCH, &TEA6420_cd[i][0]); - mxb->tea6420_2->driver->command(mxb->tea6420_2, TEA6420_SWITCH, &TEA6420_cd[i][1]); + tea6420_1_call(mxb, audio, s_routing, &TEA6420_cd[i][0]); + tea6420_2_call(mxb, audio, s_routing, &TEA6420_cd[i][1]); return 0; } @@ -735,8 +695,8 @@ static long vidioc_default(struct file *file, void *fh, int cmd, void *arg) } DEB_EE(("MXB_S_AUDIO_LINE: i:%d.\n", i)); - mxb->tea6420_1->driver->command(mxb->tea6420_1, TEA6420_SWITCH, &TEA6420_line[i][0]); - mxb->tea6420_2->driver->command(mxb->tea6420_2, TEA6420_SWITCH, &TEA6420_line[i][1]); + tea6420_1_call(mxb, audio, s_routing, &TEA6420_line[i][0]); + tea6420_2_call(mxb, audio, s_routing, &TEA6420_line[i][1]); return 0; } @@ -791,13 +751,6 @@ static int mxb_attach(struct saa7146_dev *dev, struct saa7146_pci_extension_data } } - i2c_use_client(mxb->tea6420_1); - i2c_use_client(mxb->tea6420_2); - i2c_use_client(mxb->tea6415c); - i2c_use_client(mxb->tda9840); - i2c_use_client(mxb->saa7111a); - i2c_use_client(mxb->tuner); - printk("mxb: found Multimedia eXtension Board #%d.\n", mxb_num); mxb_num++; @@ -811,13 +764,6 @@ static int mxb_detach(struct saa7146_dev *dev) DEB_EE(("dev:%p\n", dev)); - i2c_release_client(mxb->tea6420_1); - i2c_release_client(mxb->tea6420_2); - i2c_release_client(mxb->tea6415c); - i2c_release_client(mxb->tda9840); - i2c_release_client(mxb->saa7111a); - i2c_release_client(mxb->tuner); - saa7146_unregister_device(&mxb->video_dev,dev); if (MXB_BOARD_CAN_DO_VBI(dev)) saa7146_unregister_device(&mxb->vbi_dev, dev); @@ -834,8 +780,6 @@ static int mxb_detach(struct saa7146_dev *dev) static int std_callback(struct saa7146_dev *dev, struct saa7146_standard *standard) { struct mxb *mxb = (struct mxb *)dev->ext_priv; - int zero = 0; - int one = 1; if (V4L2_STD_PAL_I == standard->id) { v4l2_std_id std = V4L2_STD_PAL_I; @@ -844,8 +788,8 @@ static int std_callback(struct saa7146_dev *dev, struct saa7146_standard *standa /* set the 7146 gpio register -- I don't know what this does exactly */ saa7146_write(dev, GPIO_CTRL, 0x00404050); /* unset the 7111 gpio register -- I don't know what this does exactly */ - mxb->saa7111a->driver->command(mxb->saa7111a, VIDIOC_INT_S_GPIO, &zero); - mxb->tuner->driver->command(mxb->tuner, VIDIOC_S_STD, &std); + saa7111a_call(mxb, core, s_gpio, 0); + tuner_call(mxb, tuner, s_std, std); } else { v4l2_std_id std = V4L2_STD_PAL_BG; @@ -853,8 +797,8 @@ static int std_callback(struct saa7146_dev *dev, struct saa7146_standard *standa /* set the 7146 gpio register -- I don't know what this does exactly */ saa7146_write(dev, GPIO_CTRL, 0x00404050); /* set the 7111 gpio register -- I don't know what this does exactly */ - mxb->saa7111a->driver->command(mxb->saa7111a, VIDIOC_INT_S_GPIO, &one); - mxb->tuner->driver->command(mxb->tuner, VIDIOC_S_STD, &std); + saa7111a_call(mxb, core, s_gpio, 1); + tuner_call(mxb, tuner, s_std, std); } return 0; } diff --git a/drivers/media/video/saa5246a.c b/drivers/media/video/saa5246a.c index 8f117bd50b86..da47b2f05288 100644 --- a/drivers/media/video/saa5246a.c +++ b/drivers/media/video/saa5246a.c @@ -46,10 +46,11 @@ #include #include #include -#include -#include +#include +#include +#include #include -#include +#include MODULE_AUTHOR("Michael Geng "); MODULE_DESCRIPTION("Philips SAA5246A, SAA5281 Teletext decoder driver"); @@ -388,13 +389,19 @@ MODULE_LICENSE("GPL"); struct saa5246a_device { + struct v4l2_subdev sd; + struct video_device *vdev; u8 pgbuf[NUM_DAUS][VTX_VIRTUALSIZE]; int is_searching[NUM_DAUS]; - struct i2c_client *client; unsigned long in_use; struct mutex lock; }; +static inline struct saa5246a_device *to_dev(struct v4l2_subdev *sd) +{ + return container_of(sd, struct saa5246a_device, sd); +} + static struct video_device saa_template; /* Declared near bottom */ /* @@ -403,12 +410,13 @@ static struct video_device saa_template; /* Declared near bottom */ static int i2c_sendbuf(struct saa5246a_device *t, int reg, int count, u8 *data) { + struct i2c_client *client = v4l2_get_subdevdata(&t->sd); char buf[64]; buf[0] = reg; memcpy(buf+1, data, count); - if(i2c_master_send(t->client, buf, count+1)==count+1) + if (i2c_master_send(client, buf, count + 1) == count + 1) return 0; return -1; } @@ -436,7 +444,9 @@ static int i2c_senddata(struct saa5246a_device *t, ...) */ static int i2c_getdata(struct saa5246a_device *t, int count, u8 *buf) { - if(i2c_master_recv(t->client, buf, count)!=count) + struct i2c_client *client = v4l2_get_subdevdata(&t->sd); + + if (i2c_master_recv(client, buf, count) != count) return -1; return 0; } @@ -961,9 +971,6 @@ static int saa5246a_open(struct file *file) { struct saa5246a_device *t = video_drvdata(file); - if (t->client == NULL) - return -ENODEV; - if (test_and_set_bit(0, &t->in_use)) return -EBUSY; @@ -1033,18 +1040,29 @@ static struct video_device saa_template = .minor = -1, }; -/* Addresses to scan */ -static unsigned short normal_i2c[] = { 0x22 >> 1, I2C_CLIENT_END }; +static int saa5246a_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip) +{ + struct i2c_client *client = v4l2_get_subdevdata(sd); + + return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_SAA5246A, 0); +} + +static const struct v4l2_subdev_core_ops saa5246a_core_ops = { + .g_chip_ident = saa5246a_g_chip_ident, +}; + +static const struct v4l2_subdev_ops saa5246a_ops = { + .core = &saa5246a_core_ops, +}; -I2C_CLIENT_INSMOD; static int saa5246a_probe(struct i2c_client *client, const struct i2c_device_id *id) { int pgbuf; int err; - struct video_device *vd; struct saa5246a_device *t; + struct v4l2_subdev *sd; v4l_info(client, "chip found @ 0x%x (%s)\n", client->addr << 1, client->adapter->name); @@ -1053,40 +1071,43 @@ static int saa5246a_probe(struct i2c_client *client, t = kzalloc(sizeof(*t), GFP_KERNEL); if (t == NULL) return -ENOMEM; + sd = &t->sd; + v4l2_i2c_subdev_init(sd, client, &saa5246a_ops); mutex_init(&t->lock); /* Now create a video4linux device */ - vd = video_device_alloc(); - if (vd == NULL) { + t->vdev = video_device_alloc(); + if (t->vdev == NULL) { kfree(t); return -ENOMEM; } - i2c_set_clientdata(client, vd); - memcpy(vd, &saa_template, sizeof(*vd)); + memcpy(t->vdev, &saa_template, sizeof(*t->vdev)); for (pgbuf = 0; pgbuf < NUM_DAUS; pgbuf++) { memset(t->pgbuf[pgbuf], ' ', sizeof(t->pgbuf[0])); t->is_searching[pgbuf] = false; } - video_set_drvdata(vd, t); + video_set_drvdata(t->vdev, t); /* Register it */ - err = video_register_device(vd, VFL_TYPE_VTX, -1); + err = video_register_device(t->vdev, VFL_TYPE_VTX, -1); if (err < 0) { kfree(t); - video_device_release(vd); + video_device_release(t->vdev); + t->vdev = NULL; return err; } - t->client = client; return 0; } static int saa5246a_remove(struct i2c_client *client) { - struct video_device *vd = i2c_get_clientdata(client); + struct v4l2_subdev *sd = i2c_get_clientdata(client); + struct saa5246a_device *t = to_dev(sd); - video_unregister_device(vd); - kfree(video_get_drvdata(vd)); + video_unregister_device(t->vdev); + v4l2_device_unregister_subdev(sd); + kfree(t); return 0; } diff --git a/drivers/media/video/saa5249.c b/drivers/media/video/saa5249.c index 81e666df0db7..48b27fe48087 100644 --- a/drivers/media/video/saa5249.c +++ b/drivers/media/video/saa5249.c @@ -50,15 +50,17 @@ #include #include #include -#include -#include +#include +#include +#include #include -#include +#include MODULE_AUTHOR("Michael Geng "); MODULE_DESCRIPTION("Philips SAA5249 Teletext decoder driver"); MODULE_LICENSE("GPL"); + #define VTX_VER_MAJ 1 #define VTX_VER_MIN 8 @@ -95,17 +97,23 @@ typedef struct { struct saa5249_device { + struct v4l2_subdev sd; + struct video_device *vdev; vdau_t vdau[NUM_DAUS]; /* Data for virtual DAUs (the 5249 only has one */ /* real DAU, so we have to simulate some more) */ int vtx_use_count; int is_searching[NUM_DAUS]; int disp_mode; int virtual_mode; - struct i2c_client *client; unsigned long in_use; struct mutex lock; }; +static inline struct saa5249_device *to_dev(struct v4l2_subdev *sd) +{ + return container_of(sd, struct saa5249_device, sd); +} + #define CCTWR 34 /* IC write/read-address of vtx-chip */ #define CCTRD 35 @@ -147,12 +155,13 @@ static void jdelay(unsigned long delay) static int i2c_sendbuf(struct saa5249_device *t, int reg, int count, u8 *data) { + struct i2c_client *client = v4l2_get_subdevdata(&t->sd); char buf[64]; buf[0] = reg; memcpy(buf+1, data, count); - if (i2c_master_send(t->client, buf, count + 1) == count + 1) + if (i2c_master_send(client, buf, count + 1) == count + 1) return 0; return -1; } @@ -180,7 +189,9 @@ static int i2c_senddata(struct saa5249_device *t, ...) static int i2c_getdata(struct saa5249_device *t, int count, u8 *buf) { - if(i2c_master_recv(t->client, buf, count)!=count) + struct i2c_client *client = v4l2_get_subdevdata(&t->sd); + + if (i2c_master_recv(client, buf, count) != count) return -1; return 0; } @@ -497,9 +508,6 @@ static int saa5249_open(struct file *file) struct saa5249_device *t = video_drvdata(file); int pgbuf; - if (t->client == NULL) - return -ENODEV; - if (test_and_set_bit(0, &t->in_use)) return -EBUSY; @@ -553,18 +561,28 @@ static struct video_device saa_template = .release = video_device_release, }; -/* Addresses to scan */ -static unsigned short normal_i2c[] = { 0x22 >> 1, I2C_CLIENT_END }; +static int saa5249_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip) +{ + struct i2c_client *client = v4l2_get_subdevdata(sd); + + return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_SAA5249, 0); +} -I2C_CLIENT_INSMOD; +static const struct v4l2_subdev_core_ops saa5249_core_ops = { + .g_chip_ident = saa5249_g_chip_ident, +}; + +static const struct v4l2_subdev_ops saa5249_ops = { + .core = &saa5249_core_ops, +}; static int saa5249_probe(struct i2c_client *client, const struct i2c_device_id *id) { int pgbuf; int err; - struct video_device *vd; struct saa5249_device *t; + struct v4l2_subdev *sd; v4l_info(client, "chip found @ 0x%x (%s)\n", client->addr << 1, client->adapter->name); @@ -573,16 +591,17 @@ static int saa5249_probe(struct i2c_client *client, t = kzalloc(sizeof(*t), GFP_KERNEL); if (t == NULL) return -ENOMEM; + sd = &t->sd; + v4l2_i2c_subdev_init(sd, client, &saa5249_ops); mutex_init(&t->lock); /* Now create a video4linux device */ - vd = kmalloc(sizeof(struct video_device), GFP_KERNEL); - if (vd == NULL) { + t->vdev = video_device_alloc(); + if (t->vdev == NULL) { kfree(client); return -ENOMEM; } - i2c_set_clientdata(client, vd); - memcpy(vd, &saa_template, sizeof(*vd)); + memcpy(t->vdev, &saa_template, sizeof(*t->vdev)); for (pgbuf = 0; pgbuf < NUM_DAUS; pgbuf++) { memset(t->vdau[pgbuf].pgbuf, ' ', sizeof(t->vdau[0].pgbuf)); @@ -593,26 +612,27 @@ static int saa5249_probe(struct i2c_client *client, t->vdau[pgbuf].stopped = true; t->is_searching[pgbuf] = false; } - video_set_drvdata(vd, t); + video_set_drvdata(t->vdev, t); /* Register it */ - err = video_register_device(vd, VFL_TYPE_VTX, -1); + err = video_register_device(t->vdev, VFL_TYPE_VTX, -1); if (err < 0) { kfree(t); - kfree(vd); + video_device_release(t->vdev); + t->vdev = NULL; return err; } - t->client = client; return 0; } static int saa5249_remove(struct i2c_client *client) { - struct video_device *vd = i2c_get_clientdata(client); + struct v4l2_subdev *sd = i2c_get_clientdata(client); + struct saa5249_device *t = to_dev(sd); - video_unregister_device(vd); - kfree(video_get_drvdata(vd)); - kfree(vd); + video_unregister_device(t->vdev); + v4l2_device_unregister_subdev(sd); + kfree(t); return 0; } diff --git a/drivers/media/video/tda9840.c b/drivers/media/video/tda9840.c index ae46a28dd052..fe1158094c24 100644 --- a/drivers/media/video/tda9840.c +++ b/drivers/media/video/tda9840.c @@ -30,8 +30,8 @@ #include #include #include -#include -#include "tda9840.h" +#include +#include MODULE_AUTHOR("Michael Hunold "); MODULE_DESCRIPTION("tda9840 driver"); @@ -56,11 +56,6 @@ MODULE_PARM_DESC(debug, "Debug level (0-1)"); #define TDA9840_SET_BOTH_R 0x16 #define TDA9840_SET_EXTERNAL 0x7a -/* addresses to scan, found only at 0x42 (7-Bit) */ -static unsigned short normal_i2c[] = { I2C_ADDR_TDA9840, I2C_CLIENT_END }; - -/* magic definition of all other variables and things */ -I2C_CLIENT_INSMOD; static void tda9840_write(struct v4l2_subdev *sd, u8 reg, u8 val) { @@ -137,60 +132,17 @@ static int tda9840_g_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *t) return 0; } -static long tda9840_ioctl(struct v4l2_subdev *sd, unsigned cmd, void *arg) +static int tda9840_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip) { - int byte; - - switch (cmd) { - case TDA9840_LEVEL_ADJUST: - byte = *(int *)arg; - v4l2_dbg(1, debug, sd, "TDA9840_LEVEL_ADJUST: %d\n", byte); - - /* check for correct range */ - if (byte > 25 || byte < -20) - return -EINVAL; - - /* calculate actual value to set, see specs, page 18 */ - byte /= 5; - if (0 < byte) - byte += 0x8; - else - byte = -byte; - tda9840_write(sd, LEVEL_ADJUST, byte); - break; - - case TDA9840_STEREO_ADJUST: - byte = *(int *)arg; - v4l2_dbg(1, debug, sd, "TDA9840_STEREO_ADJUST: %d\n", byte); - - /* check for correct range */ - if (byte > 25 || byte < -24) - return -EINVAL; - - /* calculate actual value to set */ - byte /= 5; - if (0 < byte) - byte += 0x20; - else - byte = -byte; - - tda9840_write(sd, STEREO_ADJUST, byte); - break; - default: - return -ENOIOCTLCMD; - } - return 0; -} + struct i2c_client *client = v4l2_get_subdevdata(sd); -static int tda9840_command(struct i2c_client *client, unsigned cmd, void *arg) -{ - return v4l2_subdev_command(i2c_get_clientdata(client), cmd, arg); + return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_TDA9840, 0); } /* ----------------------------------------------------------------------- */ static const struct v4l2_subdev_core_ops tda9840_core_ops = { - .ioctl = tda9840_ioctl, + .g_chip_ident = tda9840_g_chip_ident, }; static const struct v4l2_subdev_tuner_ops tda9840_tuner_ops = { @@ -209,8 +161,6 @@ static int tda9840_probe(struct i2c_client *client, const struct i2c_device_id *id) { struct v4l2_subdev *sd; - int result; - int byte; /* let's see whether this adapter can support what we need */ if (!i2c_check_functionality(client->adapter, @@ -227,15 +177,9 @@ static int tda9840_probe(struct i2c_client *client, v4l2_i2c_subdev_init(sd, client, &tda9840_ops); /* set initial values for level & stereo - adjustment, mode */ - byte = 0; - result = tda9840_ioctl(sd, TDA9840_LEVEL_ADJUST, &byte); - result |= tda9840_ioctl(sd, TDA9840_STEREO_ADJUST, &byte); + tda9840_write(sd, LEVEL_ADJUST, 0); + tda9840_write(sd, STEREO_ADJUST, 0); tda9840_write(sd, SWITCH, TDA9840_SET_STEREO); - if (result) { - v4l2_dbg(1, debug, sd, "could not initialize tda9840\n"); - kfree(sd); - return -ENODEV; - } return 0; } @@ -248,12 +192,7 @@ static int tda9840_remove(struct i2c_client *client) return 0; } -static int tda9840_legacy_probe(struct i2c_adapter *adapter) -{ - /* Let's see whether this is a known adapter we can attach to. - Prevents conflicts with tvaudio.c. */ - return adapter->id == I2C_HW_SAA7146; -} + static const struct i2c_device_id tda9840_id[] = { { "tda9840", 0 }, { } @@ -262,9 +201,7 @@ MODULE_DEVICE_TABLE(i2c, tda9840_id); static struct v4l2_i2c_driver_data v4l2_i2c_data = { .name = "tda9840", - .command = tda9840_command, .probe = tda9840_probe, .remove = tda9840_remove, - .legacy_probe = tda9840_legacy_probe, .id_table = tda9840_id, }; diff --git a/drivers/media/video/tda9840.h b/drivers/media/video/tda9840.h deleted file mode 100644 index dc12ae7caf6f..000000000000 --- a/drivers/media/video/tda9840.h +++ /dev/null @@ -1,14 +0,0 @@ -#ifndef __INCLUDED_TDA9840__ -#define __INCLUDED_TDA9840__ - -#define I2C_ADDR_TDA9840 0x42 - -/* values may range between +2.5 and -2.0; - the value has to be multiplied with 10 */ -#define TDA9840_LEVEL_ADJUST _IOW('v',3,int) - -/* values may range between +2.5 and -2.4; - the value has to be multiplied with 10 */ -#define TDA9840_STEREO_ADJUST _IOW('v',4,int) - -#endif diff --git a/drivers/media/video/tea6415c.c b/drivers/media/video/tea6415c.c index bb9b7780c49f..d61c56f42bcd 100644 --- a/drivers/media/video/tea6415c.c +++ b/drivers/media/video/tea6415c.c @@ -32,7 +32,8 @@ #include #include #include -#include +#include +#include #include "tea6415c.h" MODULE_AUTHOR("Michael Hunold "); @@ -44,25 +45,22 @@ module_param(debug, int, 0644); MODULE_PARM_DESC(debug, "Debug level (0-1)"); -/* addresses to scan, found only at 0x03 and/or 0x43 (7-bit) */ -static unsigned short normal_i2c[] = { I2C_TEA6415C_1, I2C_TEA6415C_2, I2C_CLIENT_END }; -/* magic definition of all other variables and things */ -I2C_CLIENT_INSMOD; - -/* makes a connection between the input-pin 'i' and the output-pin 'o' - for the tea6415c-client 'client' */ -static int switch_matrix(struct i2c_client *client, int i, int o) +/* makes a connection between the input-pin 'i' and the output-pin 'o' */ +static int tea6415c_s_routing(struct v4l2_subdev *sd, const struct v4l2_routing *route) { + struct i2c_client *client = v4l2_get_subdevdata(sd); u8 byte = 0; + u32 i = route->input; + u32 o = route->output; int ret; - v4l_dbg(1, debug, client, "i=%d, o=%d\n", i, o); + v4l2_dbg(1, debug, sd, "i=%d, o=%d\n", i, o); /* check if the pins are valid */ if (0 == ((1 == i || 3 == i || 5 == i || 6 == i || 8 == i || 10 == i || 20 == i || 11 == i) && (18 == o || 17 == o || 16 == o || 15 == o || 14 == o || 13 == o))) - return -1; + return -EINVAL; /* to understand this, have a look at the tea6415c-specs (p.5) */ switch (o) { @@ -115,37 +113,33 @@ static int switch_matrix(struct i2c_client *client, int i, int o) ret = i2c_smbus_write_byte(client, byte); if (ret) { - v4l_dbg(1, debug, client, + v4l2_dbg(1, debug, sd, "i2c_smbus_write_byte() failed, ret:%d\n", ret); return -EIO; } return ret; } -static long tea6415c_ioctl(struct v4l2_subdev *sd, unsigned cmd, void *arg) +static int tea6415c_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip) { - if (cmd == TEA6415C_SWITCH) { - struct i2c_client *client = v4l2_get_subdevdata(sd); - struct tea6415c_multiplex *v = (struct tea6415c_multiplex *)arg; + struct i2c_client *client = v4l2_get_subdevdata(sd); - return switch_matrix(client, v->in, v->out); - } - return -ENOIOCTLCMD; -} - -static int tea6415c_command(struct i2c_client *client, unsigned cmd, void *arg) -{ - return v4l2_subdev_command(i2c_get_clientdata(client), cmd, arg); + return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_TEA6415C, 0); } /* ----------------------------------------------------------------------- */ static const struct v4l2_subdev_core_ops tea6415c_core_ops = { - .ioctl = tea6415c_ioctl, + .g_chip_ident = tea6415c_g_chip_ident, +}; + +static const struct v4l2_subdev_video_ops tea6415c_video_ops = { + .s_routing = tea6415c_s_routing, }; static const struct v4l2_subdev_ops tea6415c_ops = { .core = &tea6415c_core_ops, + .video = &tea6415c_video_ops, }; /* this function is called by i2c_probe */ @@ -176,12 +170,6 @@ static int tea6415c_remove(struct i2c_client *client) return 0; } -static int tea6415c_legacy_probe(struct i2c_adapter *adapter) -{ - /* Let's see whether this is a known adapter we can attach to. - Prevents conflicts with tvaudio.c. */ - return adapter->id == I2C_HW_SAA7146; -} static const struct i2c_device_id tea6415c_id[] = { { "tea6415c", 0 }, @@ -191,9 +179,7 @@ MODULE_DEVICE_TABLE(i2c, tea6415c_id); static struct v4l2_i2c_driver_data v4l2_i2c_data = { .name = "tea6415c", - .command = tea6415c_command, .probe = tea6415c_probe, .remove = tea6415c_remove, - .legacy_probe = tea6415c_legacy_probe, .id_table = tea6415c_id, }; diff --git a/drivers/media/video/tea6415c.h b/drivers/media/video/tea6415c.h index f84ed80050b3..3a47d697536e 100644 --- a/drivers/media/video/tea6415c.h +++ b/drivers/media/video/tea6415c.h @@ -1,10 +1,6 @@ #ifndef __INCLUDED_TEA6415C__ #define __INCLUDED_TEA6415C__ -/* possible i2c-addresses */ -#define I2C_TEA6415C_1 0x03 -#define I2C_TEA6415C_2 0x43 - /* the tea6415c's design is quite brain-dead. although there are 8 inputs and 6 outputs, these aren't enumerated in any way. because I don't want to say "connect input pin 20 to output pin 17", I define @@ -28,12 +24,4 @@ #define TEA6415C_INPUT7 1 #define TEA6415C_INPUT8 11 -struct tea6415c_multiplex -{ - int in; /* input-pin */ - int out; /* output-pin */ -}; - -#define TEA6415C_SWITCH _IOW('v',1,struct tea6415c_multiplex) - #endif diff --git a/drivers/media/video/tea6420.c b/drivers/media/video/tea6420.c index 7546509c8282..34922232402a 100644 --- a/drivers/media/video/tea6420.c +++ b/drivers/media/video/tea6420.c @@ -32,7 +32,8 @@ #include #include #include -#include +#include +#include #include "tea6420.h" MODULE_AUTHOR("Michael Hunold "); @@ -44,24 +45,23 @@ module_param(debug, int, 0644); MODULE_PARM_DESC(debug, "Debug level (0-1)"); -/* addresses to scan, found only at 0x4c and/or 0x4d (7-Bit) */ -static unsigned short normal_i2c[] = { I2C_ADDR_TEA6420_1, I2C_ADDR_TEA6420_2, I2C_CLIENT_END }; - -/* magic definition of all other variables and things */ -I2C_CLIENT_INSMOD; /* make a connection between the input 'i' and the output 'o' - with gain 'g' for the tea6420-client 'client' (note: i = 6 means 'mute') */ -static int tea6420_switch(struct i2c_client *client, int i, int o, int g) + with gain 'g' (note: i = 6 means 'mute') */ +static int tea6420_s_routing(struct v4l2_subdev *sd, const struct v4l2_routing *route) { + struct i2c_client *client = v4l2_get_subdevdata(sd); + int i = route->input; + int o = route->output & 0xf; + int g = (route->output >> 4) & 0xf; u8 byte; int ret; - v4l_dbg(1, debug, client, "i=%d, o=%d, g=%d\n", i, o, g); + v4l2_dbg(1, debug, sd, "i=%d, o=%d, g=%d\n", i, o, g); /* check if the parameters are valid */ if (i < 1 || i > 6 || o < 1 || o > 4 || g < 0 || g > 6 || g % 2 != 0) - return -1; + return -EINVAL; byte = ((o - 1) << 5); byte |= (i - 1); @@ -83,37 +83,33 @@ static int tea6420_switch(struct i2c_client *client, int i, int o, int g) ret = i2c_smbus_write_byte(client, byte); if (ret) { - v4l_dbg(1, debug, client, + v4l2_dbg(1, debug, sd, "i2c_smbus_write_byte() failed, ret:%d\n", ret); return -EIO; } return 0; } -static long tea6420_ioctl(struct v4l2_subdev *sd, unsigned cmd, void *arg) +static int tea6420_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip) { - if (cmd == TEA6420_SWITCH) { - struct i2c_client *client = v4l2_get_subdevdata(sd); - struct tea6420_multiplex *a = (struct tea6420_multiplex *)arg; + struct i2c_client *client = v4l2_get_subdevdata(sd); - return tea6420_switch(client, a->in, a->out, a->gain); - } - return -ENOIOCTLCMD; -} - -static int tea6420_command(struct i2c_client *client, unsigned cmd, void *arg) -{ - return v4l2_subdev_command(i2c_get_clientdata(client), cmd, arg); + return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_TEA6420, 0); } /* ----------------------------------------------------------------------- */ static const struct v4l2_subdev_core_ops tea6420_core_ops = { - .ioctl = tea6420_ioctl, + .g_chip_ident = tea6420_g_chip_ident, +}; + +static const struct v4l2_subdev_audio_ops tea6420_audio_ops = { + .s_routing = tea6420_s_routing, }; static const struct v4l2_subdev_ops tea6420_ops = { .core = &tea6420_core_ops, + .audio = &tea6420_audio_ops, }; /* this function is called by i2c_probe */ @@ -130,20 +126,24 @@ static int tea6420_probe(struct i2c_client *client, v4l_info(client, "chip found @ 0x%x (%s)\n", client->addr << 1, client->adapter->name); + sd = kmalloc(sizeof(struct v4l2_subdev), GFP_KERNEL); + if (sd == NULL) + return -ENOMEM; + v4l2_i2c_subdev_init(sd, client, &tea6420_ops); + /* set initial values: set "mute"-input to all outputs at gain 0 */ err = 0; for (i = 1; i < 5; i++) { - err += tea6420_switch(client, 6, i, 0); + struct v4l2_routing route; + + route.input = 6; + route.output = i; + err += tea6420_s_routing(sd, &route); } if (err) { v4l_dbg(1, debug, client, "could not initialize tea6420\n"); return -ENODEV; } - - sd = kmalloc(sizeof(struct v4l2_subdev), GFP_KERNEL); - if (sd == NULL) - return -ENOMEM; - v4l2_i2c_subdev_init(sd, client, &tea6420_ops); return 0; } @@ -156,12 +156,6 @@ static int tea6420_remove(struct i2c_client *client) return 0; } -static int tea6420_legacy_probe(struct i2c_adapter *adapter) -{ - /* Let's see whether this is a known adapter we can attach to. - Prevents conflicts with tvaudio.c. */ - return adapter->id == I2C_HW_SAA7146; -} static const struct i2c_device_id tea6420_id[] = { { "tea6420", 0 }, @@ -171,9 +165,7 @@ MODULE_DEVICE_TABLE(i2c, tea6420_id); static struct v4l2_i2c_driver_data v4l2_i2c_data = { .name = "tea6420", - .command = tea6420_command, .probe = tea6420_probe, .remove = tea6420_remove, - .legacy_probe = tea6420_legacy_probe, .id_table = tea6420_id, }; diff --git a/drivers/media/video/tea6420.h b/drivers/media/video/tea6420.h index 5ef7c18e0c54..4aa3edb3e193 100644 --- a/drivers/media/video/tea6420.h +++ b/drivers/media/video/tea6420.h @@ -1,17 +1,24 @@ #ifndef __INCLUDED_TEA6420__ #define __INCLUDED_TEA6420__ -/* possible addresses */ -#define I2C_ADDR_TEA6420_1 0x4c -#define I2C_ADDR_TEA6420_2 0x4d +/* input pins */ +#define TEA6420_OUTPUT1 1 +#define TEA6420_OUTPUT2 2 +#define TEA6420_OUTPUT3 3 +#define TEA6420_OUTPUT4 4 -struct tea6420_multiplex -{ - int in; /* input of audio switch */ - int out; /* output of audio switch */ - int gain; /* gain of connection */ -}; +/* output pins */ +#define TEA6420_INPUT1 1 +#define TEA6420_INPUT2 2 +#define TEA6420_INPUT3 3 +#define TEA6420_INPUT4 4 +#define TEA6420_INPUT5 5 +#define TEA6420_INPUT6 6 -#define TEA6420_SWITCH _IOW('v',1,struct tea6420_multiplex) +/* gain on the output pins, ORed with the output pin */ +#define TEA6420_GAIN0 0x00 +#define TEA6420_GAIN2 0x20 +#define TEA6420_GAIN4 0x40 +#define TEA6420_GAIN6 0x60 #endif diff --git a/include/media/v4l2-chip-ident.h b/include/media/v4l2-chip-ident.h index 9aaf652b20ef..4e2182e52a8e 100644 --- a/include/media/v4l2-chip-ident.h +++ b/include/media/v4l2-chip-ident.h @@ -63,6 +63,9 @@ enum { V4L2_IDENT_OV7720 = 251, V4L2_IDENT_OV7725 = 252, + /* module saa7146: reserved range 300-309 */ + V4L2_IDENT_SAA7146 = 300, + /* Conexant MPEG encoder/decoders: reserved range 410-420 */ V4L2_IDENT_CX23415 = 415, V4L2_IDENT_CX23416 = 416, @@ -74,9 +77,21 @@ enum { /* module tvp5150 */ V4L2_IDENT_TVP5150 = 5150, + /* module saa5246a: just ident 5246 */ + V4L2_IDENT_SAA5246A = 5246, + + /* module saa5249: just ident 5249 */ + V4L2_IDENT_SAA5249 = 5249, + /* module cs5345: just ident 5345 */ V4L2_IDENT_CS5345 = 5345, + /* module tea6415c: just ident 6415 */ + V4L2_IDENT_TEA6415C = 6415, + + /* module tea6420: just ident 6420 */ + V4L2_IDENT_TEA6420 = 6420, + /* module saa6752hs: reserved range 6750-6759 */ V4L2_IDENT_SAA6752HS = 6752, V4L2_IDENT_SAA6752HS_AC3 = 6753, @@ -87,6 +102,9 @@ enum { /* module wm8775: just ident 8775 */ V4L2_IDENT_WM8775 = 8775, + /* module tda9840: just ident 9840 */ + V4L2_IDENT_TDA9840 = 9840, + /* module tw9910: just ident 9910 */ V4L2_IDENT_TW9910 = 9910, -- cgit v1.2.3 From 18b1ae7dd83e4ec5ab28711e4b28e4b2e1c0b53c Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sun, 8 Feb 2009 08:50:50 -0300 Subject: V4L/DVB (10506): saa7134: move tuner init code to saa7134-cards On certain devices, before opening a tuner, we need to open the tuner gate via i2c. This patch just moves the tuner probing code to the same place where such i2c commands are handled, to make easier to fix this trouble on later patches. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/saa7134/saa7134-cards.c | 24 ++++++++++++++++++++++++ drivers/media/video/saa7134/saa7134-core.c | 24 ------------------------ 2 files changed, 24 insertions(+), 24 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/saa7134/saa7134-cards.c b/drivers/media/video/saa7134/saa7134-cards.c index 42684d162040..99450cbd42bd 100644 --- a/drivers/media/video/saa7134/saa7134-cards.c +++ b/drivers/media/video/saa7134/saa7134-cards.c @@ -6197,6 +6197,30 @@ int saa7134_board_init2(struct saa7134_dev *dev) unsigned char buf; int board; + /* initialize hardware #2 */ + if (TUNER_ABSENT != dev->tuner_type) { + int has_demod = (dev->tda9887_conf & TDA9887_PRESENT); + + /* Note: radio tuner address is always filled in, + so we do not need to probe for a radio tuner device. */ + if (dev->radio_type != UNSET) + v4l2_i2c_new_subdev(&dev->i2c_adap, + "tuner", "tuner", dev->radio_addr); + if (has_demod) + v4l2_i2c_new_probed_subdev(&dev->i2c_adap, "tuner", + "tuner", v4l2_i2c_tuner_addrs(ADDRS_DEMOD)); + if (dev->tuner_addr == ADDR_UNSET) { + enum v4l2_i2c_tuner_type type = + has_demod ? ADDRS_TV_WITH_DEMOD : ADDRS_TV; + + v4l2_i2c_new_probed_subdev(&dev->i2c_adap, "tuner", + "tuner", v4l2_i2c_tuner_addrs(type)); + } else { + v4l2_i2c_new_subdev(&dev->i2c_adap, + "tuner", "tuner", dev->tuner_addr); + } + } + switch (dev->board) { case SAA7134_BOARD_BMK_MPEX_NOTUNER: case SAA7134_BOARD_BMK_MPEX_TUNER: diff --git a/drivers/media/video/saa7134/saa7134-core.c b/drivers/media/video/saa7134/saa7134-core.c index b0f886e27c60..6a1738dccda7 100644 --- a/drivers/media/video/saa7134/saa7134-core.c +++ b/drivers/media/video/saa7134/saa7134-core.c @@ -973,30 +973,6 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev, /* wait a bit, register i2c bus */ msleep(100); saa7134_i2c_register(dev); - - /* initialize hardware #2 */ - if (TUNER_ABSENT != dev->tuner_type) { - int has_demod = (dev->tda9887_conf & TDA9887_PRESENT); - - /* Note: radio tuner address is always filled in, - so we do not need to probe for a radio tuner device. */ - if (dev->radio_type != UNSET) - v4l2_i2c_new_subdev(&dev->i2c_adap, - "tuner", "tuner", dev->radio_addr); - if (has_demod) - v4l2_i2c_new_probed_subdev(&dev->i2c_adap, "tuner", - "tuner", v4l2_i2c_tuner_addrs(ADDRS_DEMOD)); - if (dev->tuner_addr == ADDR_UNSET) { - enum v4l2_i2c_tuner_type type = - has_demod ? ADDRS_TV_WITH_DEMOD : ADDRS_TV; - - v4l2_i2c_new_probed_subdev(&dev->i2c_adap, "tuner", - "tuner", v4l2_i2c_tuner_addrs(type)); - } else { - v4l2_i2c_new_subdev(&dev->i2c_adap, - "tuner", "tuner", dev->tuner_addr); - } - } saa7134_board_init2(dev); saa7134_hwinit2(dev); -- cgit v1.2.3 From b9348353a7520073ea57ed937730a70986932fe3 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sun, 8 Feb 2009 09:33:15 -0300 Subject: V4L/DVB (10507): saa7134: Fix analog mode on devices that need to open an i2c gate Some saa7134 devices require to open an i2c gate before tuning. This patch fix the initialization for those devices. The nxt200x_gate_ctrl() logic were returned back to the old place, since we don't know how to close the gate. A future pacth could revert that change and provide the proper close gate control, to avoid keeping it open forever. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/saa7134/saa7134-cards.c | 147 +++++++++++++++------------- 1 file changed, 77 insertions(+), 70 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/saa7134/saa7134-cards.c b/drivers/media/video/saa7134/saa7134-cards.c index 99450cbd42bd..3192ccb5fcfe 100644 --- a/drivers/media/video/saa7134/saa7134-cards.c +++ b/drivers/media/video/saa7134/saa7134-cards.c @@ -5896,32 +5896,6 @@ static void hauppauge_eeprom(struct saa7134_dev *dev, u8 *eeprom_data) /* ----------------------------------------------------------- */ -static void nxt200x_gate_ctrl(struct saa7134_dev *dev, int open) -{ - /* enable tuner */ - int i; - static const u8 buffer [][2] = { - { 0x10, 0x12 }, - { 0x13, 0x04 }, - { 0x16, 0x00 }, - { 0x14, 0x04 }, - { 0x17, 0x00 }, - }; - - dev->i2c_client.addr = 0x0a; - - /* FIXME: don't know how to close the i2c gate on NXT200x */ - if (!open) - return; - - for (i = 0; i < ARRAY_SIZE(buffer); i++) - if (2 != i2c_master_send(&dev->i2c_client, - &buffer[i][0], ARRAY_SIZE(buffer[0]))) - printk(KERN_WARNING - "%s: Unable to enable tuner(%i).\n", - dev->name, i); -} - int saa7134_board_init1(struct saa7134_dev *dev) { /* Always print gpio, often manufacturers encode tuner type and other info. */ @@ -6115,10 +6089,6 @@ int saa7134_board_init1(struct saa7134_dev *dev) "are supported for now.\n", dev->name, card(dev).name, dev->name); break; - case SAA7134_BOARD_ADS_INSTANT_HDTV_PCI: - case SAA7134_BOARD_KWORLD_ATSC110: - dev->gate_ctrl = nxt200x_gate_ctrl; - break; } return 0; } @@ -6197,33 +6167,20 @@ int saa7134_board_init2(struct saa7134_dev *dev) unsigned char buf; int board; - /* initialize hardware #2 */ - if (TUNER_ABSENT != dev->tuner_type) { - int has_demod = (dev->tda9887_conf & TDA9887_PRESENT); - - /* Note: radio tuner address is always filled in, - so we do not need to probe for a radio tuner device. */ - if (dev->radio_type != UNSET) - v4l2_i2c_new_subdev(&dev->i2c_adap, - "tuner", "tuner", dev->radio_addr); - if (has_demod) - v4l2_i2c_new_probed_subdev(&dev->i2c_adap, "tuner", - "tuner", v4l2_i2c_tuner_addrs(ADDRS_DEMOD)); - if (dev->tuner_addr == ADDR_UNSET) { - enum v4l2_i2c_tuner_type type = - has_demod ? ADDRS_TV_WITH_DEMOD : ADDRS_TV; - - v4l2_i2c_new_probed_subdev(&dev->i2c_adap, "tuner", - "tuner", v4l2_i2c_tuner_addrs(type)); - } else { - v4l2_i2c_new_subdev(&dev->i2c_adap, - "tuner", "tuner", dev->tuner_addr); - } - } - + /* Put here the code that enables the chips that are needed + for analog mode and doesn't depend on the tuner attachment. + It is also a good idea to get tuner type from eeprom, etc before + initializing tuner, since we can avoid loading tuner driver + on devices that has TUNER_ABSENT + */ switch (dev->board) { case SAA7134_BOARD_BMK_MPEX_NOTUNER: case SAA7134_BOARD_BMK_MPEX_TUNER: + /* Checks if the device has a tuner at 0x60 addr + If the device doesn't have a tuner, TUNER_ABSENT + will be used at tuner_type, avoiding loading tuner + without needing it + */ dev->i2c_client.addr = 0x60; board = (i2c_master_recv(&dev->i2c_client, &buf, 0) < 0) ? SAA7134_BOARD_BMK_MPEX_NOTUNER @@ -6241,11 +6198,15 @@ int saa7134_board_init2(struct saa7134_dev *dev) u8 subaddr; u8 data[3]; int ret, tuner_t; - struct i2c_msg msg[] = {{.addr=0x50, .flags=0, .buf=&subaddr, .len = 1}, {.addr=0x50, .flags=I2C_M_RD, .buf=data, .len = 3}}; + subaddr= 0x14; tuner_t = 0; + + /* Retrieve device data from eeprom, checking for the + proper tuner_type. + */ ret = i2c_transfer(&dev->i2c_adap, msg, 2); if (ret != 2) { printk(KERN_ERR "EEPROM read failure\n"); @@ -6301,12 +6262,14 @@ int saa7134_board_init2(struct saa7134_dev *dev) dev->name, saa7134_boards[dev->board].name); break; } + /* break intentionally omitted */ case SAA7134_BOARD_VIDEOMATE_DVBT_300: case SAA7134_BOARD_ASUS_EUROPA2_HYBRID: { - /* The Philips EUROPA based hybrid boards have the tuner connected through - * the channel decoder. We have to make it transparent to find it + /* The Philips EUROPA based hybrid boards have the tuner + connected through the channel decoder. We have to make it + transparent to find it */ u8 data[] = { 0x07, 0x02}; struct i2c_msg msg = {.addr=0x08, .flags=0, .buf=data, .len = sizeof(data)}; @@ -6327,21 +6290,15 @@ int saa7134_board_init2(struct saa7134_dev *dev) if (dev->board == SAA7134_BOARD_PHILIPS_TIGER_S) { dev->tuner_type = TUNER_PHILIPS_TDA8290; - saa7134_tuner_setup(dev); - data[2] = 0x68; i2c_transfer(&dev->i2c_adap, &msg, 1); - - /* Tuner setup is handled before I2C transfer. - Due to that, there's no need to do it later - */ - return 0; + break; } i2c_transfer(&dev->i2c_adap, &msg, 1); break; } - case SAA7134_BOARD_ASUSTeK_TVFM7135: - /* The card below is detected as card=53, but is different */ + case SAA7134_BOARD_ASUSTeK_TVFM7135: + /* The card below is detected as card=53, but is different */ if (dev->autodetected && (dev->eedata[0x27] == 0x03)) { dev->board = SAA7134_BOARD_ASUSTeK_P7131_ANALOG; printk(KERN_INFO "%s: P7131 analog only, using " @@ -6412,9 +6369,9 @@ int saa7134_board_init2(struct saa7134_dev *dev) /* Don't do this if the board was specifically selected with an * insmod option or if we have the default configuration T200*/ - if(!dev->autodetected || (dev->eedata[0x41] == 0xd0)) + if (!dev->autodetected || (dev->eedata[0x41] == 0xd0)) break; - if(dev->eedata[0x41] == 0x02) { + if (dev->eedata[0x41] == 0x02) { /* Reconfigure board as T200A */ dev->board = SAA7134_BOARD_VIDEOMATE_DVBT_200A; dev->tuner_type = saa7134_boards[dev->board].tuner_type; @@ -6427,6 +6384,58 @@ int saa7134_board_init2(struct saa7134_dev *dev) break; } break; + case SAA7134_BOARD_ADS_INSTANT_HDTV_PCI: + case SAA7134_BOARD_KWORLD_ATSC110: + { + struct i2c_msg msg = { .addr = 0x0a, .flags = 0 }; + int i; + static u8 buffer[][2] = { + { 0x10, 0x12 }, + { 0x13, 0x04 }, + { 0x16, 0x00 }, + { 0x14, 0x04 }, + { 0x17, 0x00 }, + }; + + for (i = 0; i < ARRAY_SIZE(buffer); i++) { + msg.buf = &buffer[i][0]; + msg.len = ARRAY_SIZE(buffer[0]); + if (i2c_transfer(&dev->i2c_adap, &msg, 1) != 1) + printk(KERN_WARNING + "%s: Unable to enable tuner(%i).\n", + dev->name, i); + } + break; + } + } /* switch() */ + + /* initialize tuner */ + if (TUNER_ABSENT != dev->tuner_type) { + int has_demod = (dev->tda9887_conf & TDA9887_PRESENT); + + /* Note: radio tuner address is always filled in, + so we do not need to probe for a radio tuner device. */ + if (dev->radio_type != UNSET) + v4l2_i2c_new_subdev(&dev->i2c_adap, + "tuner", "tuner", dev->radio_addr); + if (has_demod) + v4l2_i2c_new_probed_subdev(&dev->i2c_adap, "tuner", + "tuner", v4l2_i2c_tuner_addrs(ADDRS_DEMOD)); + if (dev->tuner_addr == ADDR_UNSET) { + enum v4l2_i2c_tuner_type type = + has_demod ? ADDRS_TV_WITH_DEMOD : ADDRS_TV; + + v4l2_i2c_new_probed_subdev(&dev->i2c_adap, "tuner", + "tuner", v4l2_i2c_tuner_addrs(type)); + } else { + v4l2_i2c_new_subdev(&dev->i2c_adap, + "tuner", "tuner", dev->tuner_addr); + } + } + + saa7134_tuner_setup(dev); + + switch (dev->board) { case SAA7134_BOARD_BEHOLD_COLUMBUS_TVFM: { struct v4l2_priv_tun_config tea5767_cfg; @@ -6443,7 +6452,5 @@ int saa7134_board_init2(struct saa7134_dev *dev) } } /* switch() */ - saa7134_tuner_setup(dev); - return 0; } -- cgit v1.2.3 From eb47b5f981eaae280cf95b9511243f074d01424b Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 9 Feb 2009 05:29:54 -0300 Subject: V4L/DVB (10508): saa7134: Cleanup: remove unused waitqueue from struct The waitqueue is never used. So, let's just remove it. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/saa7134/saa7134.h | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/saa7134/saa7134.h b/drivers/media/video/saa7134/saa7134.h index 6fbf5088c97a..157f595c3ed1 100644 --- a/drivers/media/video/saa7134/saa7134.h +++ b/drivers/media/video/saa7134/saa7134.h @@ -446,7 +446,6 @@ struct saa7134_dmasound { unsigned int bufsize; struct saa7134_pgtable pt; struct videobuf_dmabuf dma; - wait_queue_head_t wq; unsigned int dma_blk; unsigned int read_offset; unsigned int read_count; -- cgit v1.2.3 From 553d3c5067afceda3cdbfbf51c1e4a512a3b0627 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 9 Feb 2009 05:33:54 -0300 Subject: V4L/DVB (10509): saa7134-video: two int controls lack a step Fix two broken controls where a step weren't specified. Without a step, userspace apps won't allow to adjust such controls. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/saa7134/saa7134-video.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/media/video') diff --git a/drivers/media/video/saa7134/saa7134-video.c b/drivers/media/video/saa7134/saa7134-video.c index 193b07d83d1e..adfdb662c5eb 100644 --- a/drivers/media/video/saa7134/saa7134-video.c +++ b/drivers/media/video/saa7134/saa7134-video.c @@ -452,6 +452,7 @@ static const struct v4l2_queryctrl video_ctrls[] = { .name = "y offset odd field", .minimum = 0, .maximum = 128, + .step = 1, .default_value = 0, .type = V4L2_CTRL_TYPE_INTEGER, },{ @@ -459,6 +460,7 @@ static const struct v4l2_queryctrl video_ctrls[] = { .name = "y offset even field", .minimum = 0, .maximum = 128, + .step = 1, .default_value = 0, .type = V4L2_CTRL_TYPE_INTEGER, },{ -- cgit v1.2.3 From befd6e645cc38eae0cfd4ef98b3daf0986240e2c Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 9 Feb 2009 12:27:03 -0300 Subject: V4L/DVB (10511): saa7134: get rid of KBL KBL is not needed on saa7134, so, let's remove it. However, we should take some care to avoid opening the module while initializing it. This issue exists with newer udev's that opens a device as soon as the driver is registered. So, a proper lock is needed on open. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/saa7134/saa7134-core.c | 44 ++++++++++++++--------------- drivers/media/video/saa7134/saa7134-video.c | 14 ++++----- drivers/media/video/saa7134/saa7134.h | 1 + 3 files changed, 30 insertions(+), 29 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/saa7134/saa7134-core.c b/drivers/media/video/saa7134/saa7134-core.c index 6a1738dccda7..ac574452d01e 100644 --- a/drivers/media/video/saa7134/saa7134-core.c +++ b/drivers/media/video/saa7134/saa7134-core.c @@ -86,8 +86,10 @@ MODULE_PARM_DESC(radio_nr, "radio device number"); MODULE_PARM_DESC(tuner, "tuner type"); MODULE_PARM_DESC(card, "card type"); -static DEFINE_MUTEX(devlist_lock); +DEFINE_MUTEX(saa7134_devlist_lock); +EXPORT_SYMBOL(saa7134_devlist_lock); LIST_HEAD(saa7134_devlist); +EXPORT_SYMBOL(saa7134_devlist); static LIST_HEAD(mops_list); static unsigned int saa7134_devcount; @@ -991,6 +993,18 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev, v4l2_prio_init(&dev->prio); + mutex_lock(&saa7134_devlist_lock); + list_for_each_entry(mops, &mops_list, next) + mpeg_ops_attach(mops, dev); + list_add_tail(&dev->devlist, &saa7134_devlist); + mutex_unlock(&saa7134_devlist_lock); + + /* check for signal */ + saa7134_irq_video_signalchange(dev); + + if (TUNER_ABSENT != dev->tuner_type) + saa_call_all(dev, core, s_standby, 0); + /* register v4l devices */ if (saa7134_no_overlay > 0) printk(KERN_INFO "%s: Overlay support disabled.\n", dev->name); @@ -1028,21 +1042,8 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev, /* everything worked */ saa7134_devcount++; - mutex_lock(&devlist_lock); - list_for_each_entry(mops, &mops_list, next) - mpeg_ops_attach(mops, dev); - list_add_tail(&dev->devlist,&saa7134_devlist); - mutex_unlock(&devlist_lock); - - /* check for signal */ - saa7134_irq_video_signalchange(dev); - - if (saa7134_dmasound_init && !dev->dmasound.priv_data) { + if (saa7134_dmasound_init && !dev->dmasound.priv_data) saa7134_dmasound_init(dev); - } - - if (TUNER_ABSENT != dev->tuner_type) - saa_call_all(dev, core, s_standby, 0); return 0; @@ -1093,11 +1094,11 @@ static void __devexit saa7134_finidev(struct pci_dev *pci_dev) saa7134_hwfini(dev); /* unregister */ - mutex_lock(&devlist_lock); + mutex_lock(&saa7134_devlist_lock); list_del(&dev->devlist); list_for_each_entry(mops, &mops_list, next) mpeg_ops_detach(mops, dev); - mutex_unlock(&devlist_lock); + mutex_unlock(&saa7134_devlist_lock); saa7134_devcount--; saa7134_i2c_unregister(dev); @@ -1254,11 +1255,11 @@ int saa7134_ts_register(struct saa7134_mpeg_ops *ops) { struct saa7134_dev *dev; - mutex_lock(&devlist_lock); + mutex_lock(&saa7134_devlist_lock); list_for_each_entry(dev, &saa7134_devlist, devlist) mpeg_ops_attach(ops, dev); list_add_tail(&ops->next,&mops_list); - mutex_unlock(&devlist_lock); + mutex_unlock(&saa7134_devlist_lock); return 0; } @@ -1266,11 +1267,11 @@ void saa7134_ts_unregister(struct saa7134_mpeg_ops *ops) { struct saa7134_dev *dev; - mutex_lock(&devlist_lock); + mutex_lock(&saa7134_devlist_lock); list_del(&ops->next); list_for_each_entry(dev, &saa7134_devlist, devlist) mpeg_ops_detach(ops, dev); - mutex_unlock(&devlist_lock); + mutex_unlock(&saa7134_devlist_lock); } EXPORT_SYMBOL(saa7134_ts_register); @@ -1314,7 +1315,6 @@ module_exit(saa7134_fini); /* ----------------------------------------------------------- */ EXPORT_SYMBOL(saa7134_set_gpio); -EXPORT_SYMBOL(saa7134_devlist); EXPORT_SYMBOL(saa7134_boards); /* ----------------- for the DMA sound modules --------------- */ diff --git a/drivers/media/video/saa7134/saa7134-video.c b/drivers/media/video/saa7134/saa7134-video.c index adfdb662c5eb..aa7fa1f73a56 100644 --- a/drivers/media/video/saa7134/saa7134-video.c +++ b/drivers/media/video/saa7134/saa7134-video.c @@ -1335,7 +1335,7 @@ static int video_open(struct file *file) enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE; int radio = 0; - lock_kernel(); + mutex_lock(&saa7134_devlist_lock); list_for_each_entry(dev, &saa7134_devlist, devlist) { if (dev->video_dev && (dev->video_dev->minor == minor)) goto found; @@ -1348,19 +1348,20 @@ static int video_open(struct file *file) goto found; } } - unlock_kernel(); + mutex_unlock(&saa7134_devlist_lock); return -ENODEV; - found: + +found: + mutex_unlock(&saa7134_devlist_lock); dprintk("open minor=%d radio=%d type=%s\n",minor,radio, v4l2_type_names[type]); /* allocate + initialize per filehandle data */ fh = kzalloc(sizeof(*fh),GFP_KERNEL); - if (NULL == fh) { - unlock_kernel(); + if (NULL == fh) return -ENOMEM; - } + file->private_data = fh; fh->dev = dev; fh->radio = radio; @@ -1393,7 +1394,6 @@ static int video_open(struct file *file) /* switch to video/vbi mode */ video_mux(dev,dev->ctl_input); } - unlock_kernel(); return 0; } diff --git a/drivers/media/video/saa7134/saa7134.h b/drivers/media/video/saa7134/saa7134.h index 157f595c3ed1..4552a4d6f192 100644 --- a/drivers/media/video/saa7134/saa7134.h +++ b/drivers/media/video/saa7134/saa7134.h @@ -641,6 +641,7 @@ struct saa7134_dev { /* saa7134-core.c */ extern struct list_head saa7134_devlist; +extern struct mutex saa7134_devlist_lock; extern int saa7134_no_overlay; void saa7134_track_gpio(struct saa7134_dev *dev, char *msg); -- cgit v1.2.3 From 0bf4f6ce6d43b135867a78fa1b4ac58e22d2e329 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 11 Feb 2009 14:13:20 -0300 Subject: V4L/DVB (10514): em28xx: Add support for Kaiomy TVnPC U2 stick Thanks to Peter Senna Tschudin for borrow me one of those devices. Signed-off-by: Mauro Carvalho Chehab --- Documentation/video4linux/CARDLIST.em28xx | 1 + drivers/media/video/em28xx/em28xx-cards.c | 43 +++++++++++++++++++++++++++++++ drivers/media/video/em28xx/em28xx.h | 1 + 3 files changed, 45 insertions(+) (limited to 'drivers/media/video') diff --git a/Documentation/video4linux/CARDLIST.em28xx b/Documentation/video4linux/CARDLIST.em28xx index f7a7f48f4d74..e914b1374347 100644 --- a/Documentation/video4linux/CARDLIST.em28xx +++ b/Documentation/video4linux/CARDLIST.em28xx @@ -57,5 +57,6 @@ 57 -> Kworld PlusTV HD Hybrid 330 (em2883) [eb1a:a316] 58 -> Compro VideoMate ForYou/Stereo (em2820/em2840) [185b:2041] 60 -> Hauppauge WinTV HVR 850 (em2883) [2040:651f] + 61 -> Kaiomy TVnPC U2 (em2860) [eb1a:e303] 61 -> Pixelview PlayTV Box 4 USB 2.0 (em2820/em2840) 62 -> Gadmei TVR200 (em2820/em2840) diff --git a/drivers/media/video/em28xx/em28xx-cards.c b/drivers/media/video/em28xx/em28xx-cards.c index 369db26cd721..c62243ef73b4 100644 --- a/drivers/media/video/em28xx/em28xx-cards.c +++ b/drivers/media/video/em28xx/em28xx-cards.c @@ -1252,6 +1252,33 @@ struct em28xx_board em28xx_boards[] = { .amux = EM28XX_AMUX_LINE_IN, } }, }, + [EM2860_BOARD_KAIOMY_TVNPC_U2] = { + .name = "Kaiomy TVnPC U2", + .vchannels = 3, + .tuner_type = TUNER_XC2028, + .tuner_addr = 0x61, + .mts_firmware = 1, + .decoder = EM28XX_TVP5150, + .tuner_gpio = default_tuner_gpio, + .input = { { + .type = EM28XX_VMUX_TELEVISION, + .vmux = TVP5150_COMPOSITE0, + .amux = EM28XX_AMUX_VIDEO, + + }, { + .type = EM28XX_VMUX_COMPOSITE1, + .vmux = TVP5150_COMPOSITE1, + .amux = EM28XX_AMUX_LINE_IN, + }, { + .type = EM28XX_VMUX_SVIDEO, + .vmux = TVP5150_SVIDEO, + .amux = EM28XX_AMUX_LINE_IN, + } }, + .radio = { + .type = EM28XX_RADIO, + .amux = EM28XX_AMUX_LINE_IN, + } + } }; const unsigned int em28xx_bcount = ARRAY_SIZE(em28xx_boards); @@ -1279,6 +1306,8 @@ struct usb_device_id em28xx_id_table [] = { .driver_info = EM2820_BOARD_UNKNOWN }, { USB_DEVICE(0xeb1a, 0xe300), .driver_info = EM2861_BOARD_KWORLD_PVRTV_300U }, + { USB_DEVICE(0xeb1a, 0xe303), + .driver_info = EM2860_BOARD_KAIOMY_TVNPC_U2 }, { USB_DEVICE(0xeb1a, 0xe305), .driver_info = EM2880_BOARD_KWORLD_DVB_305U }, { USB_DEVICE(0xeb1a, 0xe310), @@ -1524,6 +1553,20 @@ void em28xx_pre_card_setup(struct em28xx *dev) /* enables audio for that devices */ em28xx_write_reg(dev, EM28XX_R08_GPIO, 0xfd); break; + + case EM2860_BOARD_KAIOMY_TVNPC_U2: + em28xx_write_regs(dev, EM28XX_R0F_XCLK, "\x07", 1); + em28xx_write_regs(dev, EM28XX_R06_I2C_CLK, "\x40", 1); + em28xx_write_regs(dev, 0x0d, "\x42", 1); + em28xx_write_regs(dev, 0x08, "\xfd", 1); + msleep(10); + em28xx_write_regs(dev, 0x08, "\xff", 1); + msleep(10); + em28xx_write_regs(dev, 0x08, "\x7f", 1); + msleep(10); + em28xx_write_regs(dev, 0x08, "\x6b", 1); + + break; } em28xx_gpio_set(dev, dev->board.tuner_gpio); diff --git a/drivers/media/video/em28xx/em28xx.h b/drivers/media/video/em28xx/em28xx.h index 989e67fdff3e..24fc8b429466 100644 --- a/drivers/media/video/em28xx/em28xx.h +++ b/drivers/media/video/em28xx/em28xx.h @@ -99,6 +99,7 @@ #define EM2883_BOARD_HAUPPAUGE_WINTV_HVR_850 60 #define EM2820_BOARD_PROLINK_PLAYTV_BOX4_USB2 61 #define EM2820_BOARD_GADMEI_TVR200 62 +#define EM2860_BOARD_KAIOMY_TVNPC_U2 61 /* Limits minimum and default number of buffers */ #define EM28XX_MIN_BUF 4 -- cgit v1.2.3 From 9fc2c5ee5d9d797730dd05616757b329f6a227e9 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 11 Feb 2009 14:15:14 -0300 Subject: V4L/DVB (10515): Adds IR table for the IR provided with this board and includes it at Kaiomy entry. Thanks to Peter Senna Tschudin for borrow me one of those devices. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/common/ir-keymaps.c | 49 +++++++++++++++++++++++++++++++ drivers/media/video/em28xx/em28xx-cards.c | 1 + include/media/ir-common.h | 1 + 3 files changed, 51 insertions(+) (limited to 'drivers/media/video') diff --git a/drivers/media/common/ir-keymaps.c b/drivers/media/common/ir-keymaps.c index d8229a0e9a9c..d7b205472e1c 100644 --- a/drivers/media/common/ir-keymaps.c +++ b/drivers/media/common/ir-keymaps.c @@ -2452,6 +2452,55 @@ IR_KEYTAB_TYPE ir_codes_kworld_plus_tv_analog[IR_KEYTAB_SIZE] = { }; EXPORT_SYMBOL_GPL(ir_codes_kworld_plus_tv_analog); +/* Kaiomy TVnPC U2 + Mauro Carvalho Chehab + */ +IR_KEYTAB_TYPE ir_codes_kaiomy[IR_KEYTAB_SIZE] = { + [0x43] = KEY_POWER2, + [0x01] = KEY_LIST, + [0x0b] = KEY_ZOOM, + [0x03] = KEY_POWER, + + [0x04] = KEY_1, + [0x08] = KEY_2, + [0x02] = KEY_3, + + [0x0f] = KEY_4, + [0x05] = KEY_5, + [0x06] = KEY_6, + + [0x0c] = KEY_7, + [0x0d] = KEY_8, + [0x0a] = KEY_9, + + [0x11] = KEY_0, + + [0x09] = KEY_CHANNELUP, + [0x07] = KEY_CHANNELDOWN, + + [0x0e] = KEY_VOLUMEUP, + [0x13] = KEY_VOLUMEDOWN, + + [0x10] = KEY_HOME, + [0x12] = KEY_ENTER, + + [0x14] = KEY_RECORD, + [0x15] = KEY_STOP, + [0x16] = KEY_PLAY, + [0x17] = KEY_MUTE, + + [0x18] = KEY_UP, + [0x19] = KEY_DOWN, + [0x1a] = KEY_LEFT, + [0x1b] = KEY_RIGHT, + + [0x1c] = KEY_RED, + [0x1d] = KEY_GREEN, + [0x1e] = KEY_YELLOW, + [0x1f] = KEY_BLUE, +}; +EXPORT_SYMBOL_GPL(ir_codes_kaiomy); + IR_KEYTAB_TYPE ir_codes_avermedia_a16d[IR_KEYTAB_SIZE] = { [0x20] = KEY_LIST, [0x00] = KEY_POWER, diff --git a/drivers/media/video/em28xx/em28xx-cards.c b/drivers/media/video/em28xx/em28xx-cards.c index c62243ef73b4..2048a8761099 100644 --- a/drivers/media/video/em28xx/em28xx-cards.c +++ b/drivers/media/video/em28xx/em28xx-cards.c @@ -1260,6 +1260,7 @@ struct em28xx_board em28xx_boards[] = { .mts_firmware = 1, .decoder = EM28XX_TVP5150, .tuner_gpio = default_tuner_gpio, + .ir_codes = ir_codes_kaiomy, .input = { { .type = EM28XX_VMUX_TELEVISION, .vmux = TVP5150_COMPOSITE0, diff --git a/include/media/ir-common.h b/include/media/ir-common.h index 5bf2ea00678c..31e62abb59ad 100644 --- a/include/media/ir-common.h +++ b/include/media/ir-common.h @@ -159,6 +159,7 @@ extern IR_KEYTAB_TYPE ir_codes_real_audio_220_32_keys[IR_KEYTAB_SIZE]; extern IR_KEYTAB_TYPE ir_codes_msi_tvanywhere_plus[IR_KEYTAB_SIZE]; extern IR_KEYTAB_TYPE ir_codes_ati_tv_wonder_hd_600[IR_KEYTAB_SIZE]; extern IR_KEYTAB_TYPE ir_codes_kworld_plus_tv_analog[IR_KEYTAB_SIZE]; +extern IR_KEYTAB_TYPE ir_codes_kaiomy[IR_KEYTAB_SIZE]; #endif /* -- cgit v1.2.3 From 56ee38071fe0cf1746d53c5b40a46a835b24fbe4 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 11 Feb 2009 14:18:36 -0300 Subject: V4L/DVB (10516): em28xx: Add support for Easy Cap Capture DC-60 Thanks to Peter Senna Tschudin for borrow me one of those devices. Signed-off-by: Mauro Carvalho Chehab --- Documentation/video4linux/CARDLIST.em28xx | 3 ++- drivers/media/video/em28xx/em28xx-cards.c | 21 ++++++++++++++++++++- drivers/media/video/em28xx/em28xx.h | 3 ++- 3 files changed, 24 insertions(+), 3 deletions(-) (limited to 'drivers/media/video') diff --git a/Documentation/video4linux/CARDLIST.em28xx b/Documentation/video4linux/CARDLIST.em28xx index e914b1374347..b336dcab139c 100644 --- a/Documentation/video4linux/CARDLIST.em28xx +++ b/Documentation/video4linux/CARDLIST.em28xx @@ -57,6 +57,7 @@ 57 -> Kworld PlusTV HD Hybrid 330 (em2883) [eb1a:a316] 58 -> Compro VideoMate ForYou/Stereo (em2820/em2840) [185b:2041] 60 -> Hauppauge WinTV HVR 850 (em2883) [2040:651f] - 61 -> Kaiomy TVnPC U2 (em2860) [eb1a:e303] 61 -> Pixelview PlayTV Box 4 USB 2.0 (em2820/em2840) 62 -> Gadmei TVR200 (em2820/em2840) + 63 -> Kaiomy TVnPC U2 (em2860) [eb1a:e303] + 64 -> Easy Cap Capture DC-60 (em2860) diff --git a/drivers/media/video/em28xx/em28xx-cards.c b/drivers/media/video/em28xx/em28xx-cards.c index 2048a8761099..1f38e35355ce 100644 --- a/drivers/media/video/em28xx/em28xx-cards.c +++ b/drivers/media/video/em28xx/em28xx-cards.c @@ -1279,7 +1279,22 @@ struct em28xx_board em28xx_boards[] = { .type = EM28XX_RADIO, .amux = EM28XX_AMUX_LINE_IN, } - } + }, + [EM2860_BOARD_EASYCAP] = { + .name = "Easy Cap Capture DC-60", + .vchannels = 2, + .tuner_type = TUNER_ABSENT, + .decoder = EM28XX_SAA711X, + .input = { { + .type = EM28XX_VMUX_COMPOSITE1, + .vmux = SAA7115_COMPOSITE0, + .amux = EM28XX_AMUX_LINE_IN, + }, { + .type = EM28XX_VMUX_SVIDEO, + .vmux = SAA7115_SVIDEO3, + .amux = EM28XX_AMUX_LINE_IN, + } }, + }, }; const unsigned int em28xx_bcount = ARRAY_SIZE(em28xx_boards); @@ -1568,6 +1583,10 @@ void em28xx_pre_card_setup(struct em28xx *dev) em28xx_write_regs(dev, 0x08, "\x6b", 1); break; + case EM2860_BOARD_EASYCAP: + em28xx_write_regs(dev, 0x08, "\xf8", 1); + break; + } em28xx_gpio_set(dev, dev->board.tuner_gpio); diff --git a/drivers/media/video/em28xx/em28xx.h b/drivers/media/video/em28xx/em28xx.h index 24fc8b429466..3d94afb55b56 100644 --- a/drivers/media/video/em28xx/em28xx.h +++ b/drivers/media/video/em28xx/em28xx.h @@ -99,7 +99,8 @@ #define EM2883_BOARD_HAUPPAUGE_WINTV_HVR_850 60 #define EM2820_BOARD_PROLINK_PLAYTV_BOX4_USB2 61 #define EM2820_BOARD_GADMEI_TVR200 62 -#define EM2860_BOARD_KAIOMY_TVNPC_U2 61 +#define EM2860_BOARD_KAIOMY_TVNPC_U2 63 +#define EM2860_BOARD_EASYCAP 64 /* Limits minimum and default number of buffers */ #define EM28XX_MIN_BUF 4 -- cgit v1.2.3 From 3e099baff451affd13a93c6fed216943e01b80fd Mon Sep 17 00:00:00 2001 From: Douglas Schilling Landgraf Date: Sun, 8 Feb 2009 10:45:34 -0300 Subject: V4L/DVB (10517): em28xx: remove bad check (changeset a31c595188af) Removed bad check. Thanks to Robert Krakora to report that. Signed-off-by: Douglas Schilling Landgraf Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/em28xx/em28xx-audio.c | 16 ++-------------- 1 file changed, 2 insertions(+), 14 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/em28xx/em28xx-audio.c b/drivers/media/video/em28xx/em28xx-audio.c index 43e8d7d91a96..7a62c77b8485 100644 --- a/drivers/media/video/em28xx/em28xx-audio.c +++ b/drivers/media/video/em28xx/em28xx-audio.c @@ -61,7 +61,7 @@ static int em28xx_isoc_audio_deinit(struct em28xx *dev) int i; dprintk("Stopping isoc\n"); - for (i = 0; i < dev->isoc_ctl.num_bufs; i++) { + for (i = 0; i < EM28XX_AUDIO_BUFS; i++) { if (!irqs_disabled()) usb_kill_urb(dev->adev.urb[i]); else @@ -73,7 +73,6 @@ static int em28xx_isoc_audio_deinit(struct em28xx *dev) dev->adev.transfer_buffer[i] = NULL; } - dev->isoc_ctl.num_bufs = 0; return 0; } @@ -157,8 +156,6 @@ static int em28xx_init_audio_isoc(struct em28xx *dev) dprintk("Starting isoc transfers\n"); - dev->isoc_ctl.num_bufs = 0; - for (i = 0; i < EM28XX_AUDIO_BUFS; i++) { struct urb *urb; int j, k; @@ -200,19 +197,10 @@ static int em28xx_init_audio_isoc(struct em28xx *dev) for (i = 0; i < EM28XX_AUDIO_BUFS; i++) { errCode = usb_submit_urb(dev->adev.urb[i], GFP_ATOMIC); if (errCode) { - if (dev->isoc_ctl.num_bufs == 0) { - usb_free_urb(dev->adev.urb[i]); - dev->adev.urb[i] = NULL; - kfree(dev->adev.transfer_buffer[i]); - dev->adev.transfer_buffer[i] = NULL; - } else - em28xx_isoc_audio_deinit(dev); + em28xx_isoc_audio_deinit(dev); return errCode; } - mutex_lock(&dev->lock); - dev->isoc_ctl.num_bufs++; - mutex_unlock(&dev->lock); } return 0; -- cgit v1.2.3 From aa5a1821859c9c2915bc00e79f6e01e619df6e8f Mon Sep 17 00:00:00 2001 From: Robert Krakora Date: Sun, 8 Feb 2009 13:09:11 -0300 Subject: V4L/DVB (10518): em28xx: Fix for em28xx memory leak and function rename Fix for em28xx memory leak and function rename Signed-off-by: Robert Krakora Signed-off-by: Douglas Schilling Landgraf Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/em28xx/em28xx-audio.c | 22 ++++++++++++++++++---- drivers/media/video/em28xx/em28xx-core.c | 13 +++++++++++++ 2 files changed, 31 insertions(+), 4 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/em28xx/em28xx-audio.c b/drivers/media/video/em28xx/em28xx-audio.c index 7a62c77b8485..c698d3c9690f 100644 --- a/drivers/media/video/em28xx/em28xx-audio.c +++ b/drivers/media/video/em28xx/em28xx-audio.c @@ -56,7 +56,7 @@ MODULE_PARM_DESC(debug, "activates debug info"); static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; -static int em28xx_isoc_audio_deinit(struct em28xx *dev) +static int em28xx_deinit_isoc_audio(struct em28xx *dev) { int i; @@ -66,6 +66,7 @@ static int em28xx_isoc_audio_deinit(struct em28xx *dev) usb_kill_urb(dev->adev.urb[i]); else usb_unlink_urb(dev->adev.urb[i]); + usb_free_urb(dev->adev.urb[i]); dev->adev.urb[i] = NULL; @@ -87,6 +88,20 @@ static void em28xx_audio_isocirq(struct urb *urb) unsigned int stride; struct snd_pcm_substream *substream; struct snd_pcm_runtime *runtime; + + switch (urb->status) { + case 0: /* success */ + case -ETIMEDOUT: /* NAK */ + break; + case -ECONNRESET: /* kill */ + case -ENOENT: + case -ESHUTDOWN: + return; + default: /* error */ + dprintk("urb completition error %d.\n", urb->status); + break; + } + if (dev->adev.capture_pcm_substream) { substream = dev->adev.capture_pcm_substream; runtime = substream->runtime; @@ -197,8 +212,7 @@ static int em28xx_init_audio_isoc(struct em28xx *dev) for (i = 0; i < EM28XX_AUDIO_BUFS; i++) { errCode = usb_submit_urb(dev->adev.urb[i], GFP_ATOMIC); if (errCode) { - em28xx_isoc_audio_deinit(dev); - + em28xx_deinit_isoc_audio(dev); return errCode; } } @@ -218,7 +232,7 @@ static int em28xx_cmd(struct em28xx *dev, int cmd, int arg) em28xx_init_audio_isoc(dev); } else if (dev->adev.capture_stream == STREAM_ON && arg == 0) { dev->adev.capture_stream = STREAM_OFF; - em28xx_isoc_audio_deinit(dev); + em28xx_deinit_isoc_audio(dev); } else { printk(KERN_ERR "An underrun very likely occurred. " "Ignoring it.\n"); diff --git a/drivers/media/video/em28xx/em28xx-core.c b/drivers/media/video/em28xx/em28xx-core.c index 3ac8ce0adec3..43f1d0e4c549 100644 --- a/drivers/media/video/em28xx/em28xx-core.c +++ b/drivers/media/video/em28xx/em28xx-core.c @@ -827,6 +827,19 @@ static void em28xx_irq_callback(struct urb *urb) struct em28xx *dev = container_of(dma_q, struct em28xx, vidq); int rc, i; + switch (urb->status) { + case 0: /* success */ + case -ETIMEDOUT: /* NAK */ + break; + case -ECONNRESET: /* kill */ + case -ENOENT: + case -ESHUTDOWN: + return; + default: /* error */ + em28xx_isocdbg("urb completition error %d.\n", urb->status); + break; + } + /* Copy data from URB */ spin_lock(&dev->slock); rc = dev->isoc_ctl.isoc_copy(dev, urb); -- cgit v1.2.3 From c744dff260e9efb1080d1e823e588f85176a057b Mon Sep 17 00:00:00 2001 From: Robert Krakora Date: Sun, 8 Feb 2009 13:10:39 -0300 Subject: V4L/DVB (10519): em28xx: Fix for em28xx audio startup Essentially if a snd_em28xx_capture_trigger() stop followed by a snd_em28xx_capture_trigger() start would not yield any data because there was some logic put in with an adev->shutdown variable which did not seem warranted in my humble opinion. It would cause snd_em28xx_capture_trigger start never to start up the audio stream until the device was closed and reopened again. Upon re-opening the device adev->shutdown is reset and audio data would again flow. Signed-off-by: Robert Krakora Signed-off-by: Douglas Schilling Landgraf Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/em28xx/em28xx-audio.c | 12 +----------- drivers/media/video/em28xx/em28xx.h | 2 +- 2 files changed, 2 insertions(+), 12 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/em28xx/em28xx-audio.c b/drivers/media/video/em28xx/em28xx-audio.c index c698d3c9690f..52c6657d61cf 100644 --- a/drivers/media/video/em28xx/em28xx-audio.c +++ b/drivers/media/video/em28xx/em28xx-audio.c @@ -152,9 +152,6 @@ static void em28xx_audio_isocirq(struct urb *urb) } urb->status = 0; - if (dev->adev.shutdown) - return; - status = usb_submit_urb(urb, GFP_ATOMIC); if (status < 0) { em28xx_errdev("resubmit of audio urb failed (error=%i)\n", @@ -340,13 +337,6 @@ static int snd_em28xx_pcm_close(struct snd_pcm_substream *substream) em28xx_audio_analog_set(dev); mutex_unlock(&dev->lock); - if (dev->adev.users == 0 && dev->adev.shutdown == 1) { - dprintk("audio users: %d\n", dev->adev.users); - dprintk("disabling audio stream!\n"); - dev->adev.shutdown = 0; - dprintk("released lock\n"); - em28xx_cmd(dev, EM28XX_CAPTURE_STREAM_EN, 0); - } return 0; } @@ -399,7 +389,7 @@ static int snd_em28xx_capture_trigger(struct snd_pcm_substream *substream, em28xx_cmd(dev, EM28XX_CAPTURE_STREAM_EN, 1); return 0; case SNDRV_PCM_TRIGGER_STOP: - dev->adev.shutdown = 1; + em28xx_cmd(dev, EM28XX_CAPTURE_STREAM_EN, 0); return 0; default: return -EINVAL; diff --git a/drivers/media/video/em28xx/em28xx.h b/drivers/media/video/em28xx/em28xx.h index 3d94afb55b56..11f0db650261 100644 --- a/drivers/media/video/em28xx/em28xx.h +++ b/drivers/media/video/em28xx/em28xx.h @@ -423,7 +423,7 @@ struct em28xx_audio { unsigned int hwptr_done_capture; struct snd_card *sndcard; - int users, shutdown; + int users; enum em28xx_stream_state capture_stream; spinlock_t slock; }; -- cgit v1.2.3 From df39ca6437410b9428ebd3ce30fcde193782410d Mon Sep 17 00:00:00 2001 From: Douglas Schilling Landgraf Date: Sun, 8 Feb 2009 14:17:15 -0300 Subject: V4L/DVB (10520): em28xx-audio: Add spinlock for trigger Added spinlock for trigger session Signed-off-by: Douglas Schilling Landgraf Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/em28xx/em28xx-audio.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/em28xx/em28xx-audio.c b/drivers/media/video/em28xx/em28xx-audio.c index 52c6657d61cf..8e9957dbdbec 100644 --- a/drivers/media/video/em28xx/em28xx-audio.c +++ b/drivers/media/video/em28xx/em28xx-audio.c @@ -381,19 +381,27 @@ static int snd_em28xx_capture_trigger(struct snd_pcm_substream *substream, int cmd) { struct em28xx *dev = snd_pcm_substream_chip(substream); + int retval; dprintk("Should %s capture\n", (cmd == SNDRV_PCM_TRIGGER_START)? "start": "stop"); + + spin_lock(&dev->adev.slock); switch (cmd) { case SNDRV_PCM_TRIGGER_START: em28xx_cmd(dev, EM28XX_CAPTURE_STREAM_EN, 1); - return 0; + retval = 0; + break; case SNDRV_PCM_TRIGGER_STOP: em28xx_cmd(dev, EM28XX_CAPTURE_STREAM_EN, 0); - return 0; + retval = 0; + break; default: - return -EINVAL; + retval = -EINVAL; } + + spin_unlock(&dev->adev.slock); + return retval; } static snd_pcm_uframes_t snd_em28xx_capture_pointer(struct snd_pcm_substream -- cgit v1.2.3 From bf510ac380c0e5aac813455fdf7364613cf75b72 Mon Sep 17 00:00:00 2001 From: Douglas Schilling Landgraf Date: Sun, 8 Feb 2009 01:11:13 -0300 Subject: V4L/DVB (10521): em28xx-audio: Add lock for users Added lock for users count Signed-off-by: Douglas Schilling Landgraf Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/em28xx/em28xx-audio.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/em28xx/em28xx-audio.c b/drivers/media/video/em28xx/em28xx-audio.c index 8e9957dbdbec..38436af2164b 100644 --- a/drivers/media/video/em28xx/em28xx-audio.c +++ b/drivers/media/video/em28xx/em28xx-audio.c @@ -313,7 +313,9 @@ static int snd_em28xx_capture_open(struct snd_pcm_substream *substream) dprintk("changing alternate number to 7\n"); } + mutex_lock(&dev->lock); dev->adev.users++; + mutex_unlock(&dev->lock); snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS); dev->adev.capture_pcm_substream = substream; @@ -328,12 +330,12 @@ err: static int snd_em28xx_pcm_close(struct snd_pcm_substream *substream) { struct em28xx *dev = snd_pcm_substream_chip(substream); - dev->adev.users--; dprintk("closing device\n"); dev->mute = 1; mutex_lock(&dev->lock); + dev->adev.users--; em28xx_audio_analog_set(dev); mutex_unlock(&dev->lock); -- cgit v1.2.3 From 5c030de4757f64246897babcaa7091b4b391a660 Mon Sep 17 00:00:00 2001 From: Alexey Klimov Date: Sun, 8 Feb 2009 01:16:32 -0300 Subject: V4L/DVB (10522): em28xx-audio: replace printk with em28xx_errdev Patch removes printk and place em28xx_errdev macros to provide information about driver name to dmesg. Signed-off-by: Alexey Klimov Signed-off-by: Douglas Schilling Landgraf Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/em28xx/em28xx-audio.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/em28xx/em28xx-audio.c b/drivers/media/video/em28xx/em28xx-audio.c index 38436af2164b..05d145f78b6e 100644 --- a/drivers/media/video/em28xx/em28xx-audio.c +++ b/drivers/media/video/em28xx/em28xx-audio.c @@ -231,7 +231,7 @@ static int em28xx_cmd(struct em28xx *dev, int cmd, int arg) dev->adev.capture_stream = STREAM_OFF; em28xx_deinit_isoc_audio(dev); } else { - printk(KERN_ERR "An underrun very likely occurred. " + em28xx_errdev("An underrun very likely occurred. " "Ignoring it.\n"); } return 0; -- cgit v1.2.3 From 22cff7b381eca256d2afb460b3b9815f83810011 Mon Sep 17 00:00:00 2001 From: Douglas Schilling Landgraf Date: Sun, 8 Feb 2009 01:38:10 -0300 Subject: V4L/DVB (10523): em28xx-audio: Add macros EM28XX_START_AUDIO / EM28XX_STOP_AUDIO Added macros EM28XX_START_AUDIO and EM28XX_STOP_AUDIO for em28xx_cmd(). Signed-off-by: Douglas Schilling Landgraf Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/em28xx/em28xx-audio.c | 10 +++++----- drivers/media/video/em28xx/em28xx.h | 4 ++++ 2 files changed, 9 insertions(+), 5 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/em28xx/em28xx-audio.c b/drivers/media/video/em28xx/em28xx-audio.c index 05d145f78b6e..abbf9ee0d39a 100644 --- a/drivers/media/video/em28xx/em28xx-audio.c +++ b/drivers/media/video/em28xx/em28xx-audio.c @@ -224,10 +224,10 @@ static int em28xx_cmd(struct em28xx *dev, int cmd, int arg) switch (cmd) { case EM28XX_CAPTURE_STREAM_EN: - if (dev->adev.capture_stream == STREAM_OFF && arg == 1) { + if (dev->adev.capture_stream == STREAM_OFF && arg == EM28XX_START_AUDIO) { dev->adev.capture_stream = STREAM_ON; em28xx_init_audio_isoc(dev); - } else if (dev->adev.capture_stream == STREAM_ON && arg == 0) { + } else if (dev->adev.capture_stream == STREAM_ON && arg == EM28XX_STOP_AUDIO) { dev->adev.capture_stream = STREAM_OFF; em28xx_deinit_isoc_audio(dev); } else { @@ -369,7 +369,7 @@ static int snd_em28xx_hw_capture_free(struct snd_pcm_substream *substream) dprintk("Stop capture, if needed\n"); if (dev->adev.capture_stream == STREAM_ON) - em28xx_cmd(dev, EM28XX_CAPTURE_STREAM_EN, 0); + em28xx_cmd(dev, EM28XX_CAPTURE_STREAM_EN, EM28XX_STOP_AUDIO); return 0; } @@ -391,11 +391,11 @@ static int snd_em28xx_capture_trigger(struct snd_pcm_substream *substream, spin_lock(&dev->adev.slock); switch (cmd) { case SNDRV_PCM_TRIGGER_START: - em28xx_cmd(dev, EM28XX_CAPTURE_STREAM_EN, 1); + em28xx_cmd(dev, EM28XX_CAPTURE_STREAM_EN, EM28XX_START_AUDIO); retval = 0; break; case SNDRV_PCM_TRIGGER_STOP: - em28xx_cmd(dev, EM28XX_CAPTURE_STREAM_EN, 0); + em28xx_cmd(dev, EM28XX_CAPTURE_STREAM_EN, EM28XX_STOP_AUDIO); retval = 0; break; default: diff --git a/drivers/media/video/em28xx/em28xx.h b/drivers/media/video/em28xx/em28xx.h index 11f0db650261..6844b98e1b67 100644 --- a/drivers/media/video/em28xx/em28xx.h +++ b/drivers/media/video/em28xx/em28xx.h @@ -113,6 +113,10 @@ #define EM28XX_BOARD_NOT_VALIDATED 1 #define EM28XX_BOARD_VALIDATED 0 +/* Params for em28xx_cmd() audio */ +#define EM28XX_START_AUDIO 1 +#define EM28XX_STOP_AUDIO 0 + /* maximum number of em28xx boards */ #define EM28XX_MAXBOARDS 4 /*FIXME: should be bigger */ -- cgit v1.2.3 From 7aa0eabde08259c47586df934921c67cff36e7dc Mon Sep 17 00:00:00 2001 From: Douglas Schilling Landgraf Date: Tue, 10 Feb 2009 22:00:06 -0300 Subject: V4L/DVB (10524): em28xx: Add DVC 101 model to Pinnacle Dazzle description Added DVC 101 model to Pinnacle Dazzle description Signed-off-by: Douglas Schilling Landgraf Signed-off-by: Mauro Carvalho Chehab --- Documentation/video4linux/CARDLIST.em28xx | 2 +- drivers/media/video/em28xx/em28xx-cards.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/media/video') diff --git a/Documentation/video4linux/CARDLIST.em28xx b/Documentation/video4linux/CARDLIST.em28xx index b336dcab139c..69601089f0a5 100644 --- a/Documentation/video4linux/CARDLIST.em28xx +++ b/Documentation/video4linux/CARDLIST.em28xx @@ -7,7 +7,7 @@ 6 -> Terratec Cinergy 200 USB (em2800) 7 -> Leadtek Winfast USB II (em2800) [0413:6023] 8 -> Kworld USB2800 (em2800) - 9 -> Pinnacle Dazzle DVC 90/DVC 100 (em2820/em2840) [2304:0207,2304:021a] + 9 -> Pinnacle Dazzle DVC 90/DVC 100/DVC 101 (em2820/em2840) [2304:0207,2304:021a] 10 -> Hauppauge WinTV HVR 900 (em2880) [2040:6500] 11 -> Terratec Hybrid XS (em2880) [0ccd:0042] 12 -> Kworld PVR TV 2800 RF (em2820/em2840) diff --git a/drivers/media/video/em28xx/em28xx-cards.c b/drivers/media/video/em28xx/em28xx-cards.c index 1f38e35355ce..89a8f2657b13 100644 --- a/drivers/media/video/em28xx/em28xx-cards.c +++ b/drivers/media/video/em28xx/em28xx-cards.c @@ -916,7 +916,7 @@ struct em28xx_board em28xx_boards[] = { } }, }, [EM2820_BOARD_PINNACLE_DVC_90] = { - .name = "Pinnacle Dazzle DVC 90/DVC 100", + .name = "Pinnacle Dazzle DVC 90/DVC 100/DVC 101", .tuner_type = TUNER_ABSENT, /* capture only board */ .decoder = EM28XX_SAA711X, .input = { { -- cgit v1.2.3 From a1a6ee74f2c68918f2e145dccba3637eea91a52a Mon Sep 17 00:00:00 2001 From: Nicola Soranzo Date: Tue, 10 Feb 2009 23:28:24 -0300 Subject: V4L/DVB (10525): em28xx: Coding style fixes and a typo correction Lots of coding style fixes and a typo correction for em28xx. [dougsland@redhat.com: fixed a reject due to a change on em28xx-audio.c] Signed-off-by: Nicola Soranzo Signed-off-by: Douglas Schilling Landgraf Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/em28xx/em28xx-audio.c | 5 ++-- drivers/media/video/em28xx/em28xx-cards.c | 24 +++++++++-------- drivers/media/video/em28xx/em28xx-core.c | 19 +++++++------- drivers/media/video/em28xx/em28xx-i2c.c | 6 +++-- drivers/media/video/em28xx/em28xx-video.c | 43 ++++++++++++++++++------------- drivers/media/video/em28xx/em28xx.h | 6 +++-- 6 files changed, 58 insertions(+), 45 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/em28xx/em28xx-audio.c b/drivers/media/video/em28xx/em28xx-audio.c index abbf9ee0d39a..6296697d025f 100644 --- a/drivers/media/video/em28xx/em28xx-audio.c +++ b/drivers/media/video/em28xx/em28xx-audio.c @@ -245,7 +245,7 @@ static int snd_pcm_alloc_vmalloc_buffer(struct snd_pcm_substream *subs, { struct snd_pcm_runtime *runtime = subs->runtime; - dprintk("Alocating vbuffer\n"); + dprintk("Allocating vbuffer\n"); if (runtime->dma_area) { if (runtime->dma_bytes > size) return 0; @@ -409,8 +409,7 @@ static int snd_em28xx_capture_trigger(struct snd_pcm_substream *substream, static snd_pcm_uframes_t snd_em28xx_capture_pointer(struct snd_pcm_substream *substream) { - unsigned long flags; - + unsigned long flags; struct em28xx *dev; snd_pcm_uframes_t hwptr_done; diff --git a/drivers/media/video/em28xx/em28xx-cards.c b/drivers/media/video/em28xx/em28xx-cards.c index 89a8f2657b13..419304d31256 100644 --- a/drivers/media/video/em28xx/em28xx-cards.c +++ b/drivers/media/video/em28xx/em28xx-cards.c @@ -244,7 +244,7 @@ struct em28xx_board em28xx_boards[] = { .name = "Hauppauge WinTV USB 2", .tuner_type = TUNER_PHILIPS_FM1236_MK3, .tda9887_conf = TDA9887_PRESENT | - TDA9887_PORT1_ACTIVE| + TDA9887_PORT1_ACTIVE | TDA9887_PORT2_ACTIVE, .decoder = EM28XX_TVP5150, .has_msp34xx = 1, @@ -517,7 +517,7 @@ struct em28xx_board em28xx_boards[] = { }, [EM2861_BOARD_YAKUMO_MOVIE_MIXER] = { .name = "Yakumo MovieMixer", - .tuner_type = TUNER_ABSENT, /* Capture only device */ + .tuner_type = TUNER_ABSENT, /* Capture only device */ .decoder = EM28XX_TVP5150, .input = { { .type = EM28XX_VMUX_TELEVISION, @@ -861,11 +861,11 @@ struct em28xx_board em28xx_boards[] = { } }, }, [EM2800_BOARD_GRABBEEX_USB2800] = { - .name = "eMPIA Technology, Inc. GrabBeeX+ Video Encoder", - .is_em2800 = 1, - .decoder = EM28XX_SAA711X, - .tuner_type = TUNER_ABSENT, /* capture only board */ - .input = { { + .name = "eMPIA Technology, Inc. GrabBeeX+ Video Encoder", + .is_em2800 = 1, + .decoder = EM28XX_SAA711X, + .tuner_type = TUNER_ABSENT, /* capture only board */ + .input = { { .type = EM28XX_VMUX_COMPOSITE1, .vmux = SAA7115_COMPOSITE0, .amux = EM28XX_AMUX_LINE_IN, @@ -1217,7 +1217,9 @@ struct em28xx_board em28xx_boards[] = { .has_dvb = 1, .dvb_gpio = kworld_330u_digital, .xclk = EM28XX_XCLK_FREQUENCY_12MHZ, - .i2c_speed = EM28XX_I2C_CLK_WAIT_ENABLE | EM28XX_I2C_EEPROM_ON_BOARD | EM28XX_I2C_EEPROM_KEY_VALID, + .i2c_speed = EM28XX_I2C_CLK_WAIT_ENABLE | + EM28XX_I2C_EEPROM_ON_BOARD | + EM28XX_I2C_EEPROM_KEY_VALID, .input = { { .type = EM28XX_VMUX_TELEVISION, .vmux = TVP5150_COMPOSITE0, @@ -1299,7 +1301,7 @@ struct em28xx_board em28xx_boards[] = { const unsigned int em28xx_bcount = ARRAY_SIZE(em28xx_boards); /* table of devices that work with this driver */ -struct usb_device_id em28xx_id_table [] = { +struct usb_device_id em28xx_id_table[] = { { USB_DEVICE(0xeb1a, 0x2750), .driver_info = EM2750_BOARD_UNKNOWN }, { USB_DEVICE(0xeb1a, 0x2751), @@ -1401,7 +1403,7 @@ MODULE_DEVICE_TABLE(usb, em28xx_id_table); /* * EEPROM hash table for devices with generic USB IDs */ -static struct em28xx_hash_table em28xx_eeprom_hash [] = { +static struct em28xx_hash_table em28xx_eeprom_hash[] = { /* P/N: SA 60002070465 Tuner: TVF7533-MF */ {0x6ce05a8f, EM2820_BOARD_PROLINK_PLAYTV_USB2, TUNER_YMEC_TVF_5533MF}, {0x72cc5a8b, EM2820_BOARD_PROLINK_PLAYTV_BOX4_USB2, TUNER_YMEC_TVF_5533MF}, @@ -1433,7 +1435,7 @@ int em28xx_tuner_callback(void *ptr, int component, int command, int arg) } EXPORT_SYMBOL_GPL(em28xx_tuner_callback); -static void inline em28xx_set_model(struct em28xx *dev) +static inline void em28xx_set_model(struct em28xx *dev) { memcpy(&dev->board, &em28xx_boards[dev->model], sizeof(dev->board)); diff --git a/drivers/media/video/em28xx/em28xx-core.c b/drivers/media/video/em28xx/em28xx-core.c index 43f1d0e4c549..eee8d015b249 100644 --- a/drivers/media/video/em28xx/em28xx-core.c +++ b/drivers/media/video/em28xx/em28xx-core.c @@ -33,8 +33,8 @@ /* #define ENABLE_DEBUG_ISOC_FRAMES */ static unsigned int core_debug; -module_param(core_debug,int,0644); -MODULE_PARM_DESC(core_debug,"enable debug messages [core]"); +module_param(core_debug, int, 0644); +MODULE_PARM_DESC(core_debug, "enable debug messages [core]"); #define em28xx_coredbg(fmt, arg...) do {\ if (core_debug) \ @@ -42,8 +42,8 @@ MODULE_PARM_DESC(core_debug,"enable debug messages [core]"); dev->name, __func__ , ##arg); } while (0) static unsigned int reg_debug; -module_param(reg_debug,int,0644); -MODULE_PARM_DESC(reg_debug,"enable debug messages [URB reg]"); +module_param(reg_debug, int, 0644); +MODULE_PARM_DESC(reg_debug, "enable debug messages [URB reg]"); #define em28xx_regdbg(fmt, arg...) do {\ if (reg_debug) \ @@ -77,7 +77,7 @@ int em28xx_read_reg_req_len(struct em28xx *dev, u8 req, u16 reg, return -EINVAL; if (reg_debug) { - printk( KERN_DEBUG "(pipe 0x%08x): " + printk(KERN_DEBUG "(pipe 0x%08x): " "IN: %02x %02x %02x %02x %02x %02x %02x %02x ", pipe, USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, @@ -154,7 +154,7 @@ int em28xx_write_regs_req(struct em28xx *dev, u8 req, u16 reg, char *buf, if (reg_debug) { int byte; - printk( KERN_DEBUG "(pipe 0x%08x): " + printk(KERN_DEBUG "(pipe 0x%08x): " "OUT: %02x %02x %02x %02x %02x %02x %02x %02x >>>", pipe, USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, @@ -462,7 +462,8 @@ int em28xx_audio_analog_set(struct em28xx *dev) if (dev->ctl_aoutput & EM28XX_AOUT_PCM_IN) { int sel = ac97_return_record_select(dev->ctl_aoutput); - /* Use the same input for both left and right channels */ + /* Use the same input for both left and right + channels */ sel |= (sel << 8); em28xx_write_ac97(dev, AC97_RECORD_SELECT, sel); @@ -698,7 +699,7 @@ static int em28xx_scaler_set(struct em28xx *dev, u16 h, u16 v) em28xx_write_regs(dev, EM28XX_R32_VSCALELOW, (char *)buf, 2); /* it seems that both H and V scalers must be active to work correctly */ - mode = (h || v)? 0x30: 0x00; + mode = (h || v) ? 0x30 : 0x00; } return em28xx_write_reg_bits(dev, EM28XX_R26_COMPR, mode, 0x30); } @@ -958,7 +959,7 @@ int em28xx_init_isoc(struct em28xx *dev, int max_packets, em28xx_err("unable to allocate %i bytes for transfer" " buffer %i%s\n", sb_size, i, - in_interrupt()?" while in int":""); + in_interrupt() ? " while in int" : ""); em28xx_uninit_isoc(dev); return -ENOMEM; } diff --git a/drivers/media/video/em28xx/em28xx-i2c.c b/drivers/media/video/em28xx/em28xx-i2c.c index d69f0efcc9aa..2dab43d22da2 100644 --- a/drivers/media/video/em28xx/em28xx-i2c.c +++ b/drivers/media/video/em28xx/em28xx-i2c.c @@ -402,10 +402,12 @@ static int em28xx_i2c_eeprom(struct em28xx *dev, unsigned char *eedata, int len) dev->name); break; case 2: - printk(KERN_INFO "%s:\tI2S audio, sample rate=32k\n", dev->name); + printk(KERN_INFO "%s:\tI2S audio, sample rate=32k\n", + dev->name); break; case 3: - printk(KERN_INFO "%s:\tI2S audio, 3 sample rates\n", dev->name); + printk(KERN_INFO "%s:\tI2S audio, 3 sample rates\n", + dev->name); break; } diff --git a/drivers/media/video/em28xx/em28xx-video.c b/drivers/media/video/em28xx/em28xx-video.c index 5b2a19b0cca6..efd641587e04 100644 --- a/drivers/media/video/em28xx/em28xx-video.c +++ b/drivers/media/video/em28xx/em28xx-video.c @@ -186,7 +186,8 @@ static void em28xx_copy_video(struct em28xx *dev, em28xx_isocdbg("Overflow of %zi bytes past buffer end (1)\n", ((char *)startwrite + lencopy) - ((char *)outp + buf->vb.size)); - lencopy = remain = (char *)outp + buf->vb.size - (char *)startwrite; + remain = (char *)outp + buf->vb.size - (char *)startwrite; + lencopy = remain; } if (lencopy <= 0) return; @@ -202,7 +203,8 @@ static void em28xx_copy_video(struct em28xx *dev, else lencopy = bytesperline; - if ((char *)startwrite + lencopy > (char *)outp + buf->vb.size) { + if ((char *)startwrite + lencopy > (char *)outp + + buf->vb.size) { em28xx_isocdbg("Overflow of %zi bytes past buffer end (2)\n", ((char *)startwrite + lencopy) - ((char *)outp + buf->vb.size)); @@ -347,7 +349,7 @@ static inline int em28xx_isoc_copy(struct em28xx *dev, struct urb *urb) } if (p[0] == 0x22 && p[1] == 0x5a) { em28xx_isocdbg("Video frame %d, length=%i, %s\n", p[2], - len, (p[2] & 1)? "odd" : "even"); + len, (p[2] & 1) ? "odd" : "even"); if (!(p[2] & 1)) { if (buf != NULL) @@ -476,7 +478,9 @@ fail: static void buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb) { - struct em28xx_buffer *buf = container_of(vb, struct em28xx_buffer, vb); + struct em28xx_buffer *buf = container_of(vb, + struct em28xx_buffer, + vb); struct em28xx_fh *fh = vq->priv_data; struct em28xx *dev = fh->dev; struct em28xx_dmaqueue *vidq = &dev->vidq; @@ -489,7 +493,9 @@ buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb) static void buffer_release(struct videobuf_queue *vq, struct videobuf_buffer *vb) { - struct em28xx_buffer *buf = container_of(vb, struct em28xx_buffer, vb); + struct em28xx_buffer *buf = container_of(vb, + struct em28xx_buffer, + vb); struct em28xx_fh *fh = vq->priv_data; struct em28xx *dev = (struct em28xx *)fh->dev; @@ -557,7 +563,7 @@ static int res_get(struct em28xx_fh *fh) static int res_check(struct em28xx_fh *fh) { - return (fh->stream_on); + return fh->stream_on; } static void res_free(struct em28xx_fh *fh) @@ -791,7 +797,7 @@ out: return rc; } -static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id * norm) +static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *norm) { struct em28xx_fh *fh = priv; struct em28xx *dev = fh->dev; @@ -1436,7 +1442,7 @@ static int vidioc_reqbufs(struct file *file, void *priv, if (rc < 0) return rc; - return (videobuf_reqbufs(&fh->vb_vidq, rb)); + return videobuf_reqbufs(&fh->vb_vidq, rb); } static int vidioc_querybuf(struct file *file, void *priv, @@ -1450,7 +1456,7 @@ static int vidioc_querybuf(struct file *file, void *priv, if (rc < 0) return rc; - return (videobuf_querybuf(&fh->vb_vidq, b)); + return videobuf_querybuf(&fh->vb_vidq, b); } static int vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *b) @@ -1463,7 +1469,7 @@ static int vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *b) if (rc < 0) return rc; - return (videobuf_qbuf(&fh->vb_vidq, b)); + return videobuf_qbuf(&fh->vb_vidq, b); } static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *b) @@ -1476,8 +1482,7 @@ static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *b) if (rc < 0) return rc; - return (videobuf_dqbuf(&fh->vb_vidq, b, - file->f_flags & O_NONBLOCK)); + return videobuf_dqbuf(&fh->vb_vidq, b, file->f_flags & O_NONBLOCK); } #ifdef CONFIG_VIDEO_V4L1_COMPAT @@ -1786,7 +1791,7 @@ em28xx_v4l2_read(struct file *filp, char __user *buf, size_t count, * em28xx_v4l2_poll() * will allocate buffers when called for the first time */ -static unsigned int em28xx_v4l2_poll(struct file *filp, poll_table * wait) +static unsigned int em28xx_v4l2_poll(struct file *filp, poll_table *wait) { struct em28xx_fh *fh = filp->private_data; struct em28xx *dev = fh->dev; @@ -1939,8 +1944,8 @@ static struct video_device em28xx_radio_template = { static struct video_device *em28xx_vdev_init(struct em28xx *dev, - const struct video_device *template, - const char *type_name) + const struct video_device *template, + const char *type_name) { struct video_device *vfd; @@ -1989,8 +1994,9 @@ int em28xx_register_analog_devices(struct em28xx *dev) /* enable vbi capturing */ /* em28xx_write_reg(dev, EM28XX_R0E_AUDIOSRC, 0xc0); audio register */ - val = (u8)em28xx_read_reg(dev, EM28XX_R0F_XCLK); - em28xx_write_reg(dev, EM28XX_R0F_XCLK, (EM28XX_XCLK_AUDIO_UNMUTE | val)); + val = (u8)em28xx_read_reg(dev, EM28XX_R0F_XCLK); + em28xx_write_reg(dev, EM28XX_R0F_XCLK, + (EM28XX_XCLK_AUDIO_UNMUTE | val)); em28xx_write_reg(dev, EM28XX_R11_VINCTRL, 0x51); em28xx_set_outfmt(dev); @@ -2025,7 +2031,8 @@ int em28xx_register_analog_devices(struct em28xx *dev) } if (em28xx_boards[dev->model].radio.type == EM28XX_RADIO) { - dev->radio_dev = em28xx_vdev_init(dev, &em28xx_radio_template, "radio"); + dev->radio_dev = em28xx_vdev_init(dev, &em28xx_radio_template, + "radio"); if (!dev->radio_dev) { em28xx_errdev("cannot allocate video_device.\n"); return -ENODEV; diff --git a/drivers/media/video/em28xx/em28xx.h b/drivers/media/video/em28xx/em28xx.h index 6844b98e1b67..5115db3a76a6 100644 --- a/drivers/media/video/em28xx/em28xx.h +++ b/drivers/media/video/em28xx/em28xx.h @@ -161,7 +161,8 @@ */ /* time to wait when stopping the isoc transfer */ -#define EM28XX_URB_TIMEOUT msecs_to_jiffies(EM28XX_NUM_BUFS * EM28XX_NUM_PACKETS) +#define EM28XX_URB_TIMEOUT \ + msecs_to_jiffies(EM28XX_NUM_BUFS * EM28XX_NUM_PACKETS) /* time in msecs to wait for i2c writes to finish */ #define EM2800_I2C_WRITE_TIMEOUT 20 @@ -530,7 +531,8 @@ struct em28xx { int num_alt; /* Number of alternative settings */ unsigned int *alt_max_pkt_size; /* array of wMaxPacketSize */ struct urb *urb[EM28XX_NUM_BUFS]; /* urb for isoc transfers */ - char *transfer_buffer[EM28XX_NUM_BUFS]; /* transfer buffers for isoc transfer */ + char *transfer_buffer[EM28XX_NUM_BUFS]; /* transfer buffers for isoc + transfer */ char urb_buf[URB_MAX_CTRL_SIZE]; /* urb control msg buffer */ /* helper funcs that call usb_control_msg */ -- cgit v1.2.3 From f74a61e3c6f218053742c2caf3e247fb41bf395e Mon Sep 17 00:00:00 2001 From: Indika Katugampala Date: Wed, 11 Feb 2009 11:13:05 -0300 Subject: V4L/DVB (10528): em28xx: support added for IO-DATA GV/MVP SZ - EMPIA-2820 chipset [dougsland@redhat.com: Fixed CodingStyle] Signed-off-by: Indika Katugampala Signed-off-by: Douglas Schilling Landgraf Signed-off-by: Mauro Carvalho Chehab --- Documentation/video4linux/CARDLIST.em28xx | 1 + drivers/media/video/em28xx/em28xx-cards.c | 32 +++++++++++++++++++++++++++++++ drivers/media/video/em28xx/em28xx.h | 1 + 3 files changed, 34 insertions(+) (limited to 'drivers/media/video') diff --git a/Documentation/video4linux/CARDLIST.em28xx b/Documentation/video4linux/CARDLIST.em28xx index 69601089f0a5..f97c8533d01a 100644 --- a/Documentation/video4linux/CARDLIST.em28xx +++ b/Documentation/video4linux/CARDLIST.em28xx @@ -61,3 +61,4 @@ 62 -> Gadmei TVR200 (em2820/em2840) 63 -> Kaiomy TVnPC U2 (em2860) [eb1a:e303] 64 -> Easy Cap Capture DC-60 (em2860) + 65 -> IO-DATA GV-MVP/SZ (em2820/em2840) [04bb:0515] diff --git a/drivers/media/video/em28xx/em28xx-cards.c b/drivers/media/video/em28xx/em28xx-cards.c index 419304d31256..c16c28e1ec48 100644 --- a/drivers/media/video/em28xx/em28xx-cards.c +++ b/drivers/media/video/em28xx/em28xx-cards.c @@ -1297,6 +1297,26 @@ struct em28xx_board em28xx_boards[] = { .amux = EM28XX_AMUX_LINE_IN, } }, }, + [EM2820_BOARD_IODATA_GVMVP_SZ] = { + .name = "IO-DATA GV-MVP/SZ", + .tuner_type = TUNER_PHILIPS_FM1236_MK3, + .tuner_gpio = default_tuner_gpio, + .tda9887_conf = TDA9887_PRESENT, + .decoder = EM28XX_TVP5150, + .input = { { + .type = EM28XX_VMUX_TELEVISION, + .vmux = TVP5150_COMPOSITE0, + .amux = EM28XX_AMUX_VIDEO, + }, { /* Composite has not been tested yet */ + .type = EM28XX_VMUX_COMPOSITE1, + .vmux = TVP5150_COMPOSITE1, + .amux = EM28XX_AMUX_VIDEO, + }, { /* S-video has not been tested yet */ + .type = EM28XX_VMUX_SVIDEO, + .vmux = TVP5150_SVIDEO, + .amux = EM28XX_AMUX_VIDEO, + } }, + }, }; const unsigned int em28xx_bcount = ARRAY_SIZE(em28xx_boards); @@ -1396,6 +1416,8 @@ struct usb_device_id em28xx_id_table[] = { .driver_info = EM2800_BOARD_LEADTEK_WINFAST_USBII }, { USB_DEVICE(0x093b, 0xa005), .driver_info = EM2861_BOARD_PLEXTOR_PX_TV100U }, + { USB_DEVICE(0x04bb, 0x0515), + .driver_info = EM2820_BOARD_IODATA_GVMVP_SZ }, { }, }; MODULE_DEVICE_TABLE(usb, em28xx_id_table); @@ -1589,6 +1611,16 @@ void em28xx_pre_card_setup(struct em28xx *dev) em28xx_write_regs(dev, 0x08, "\xf8", 1); break; + case EM2820_BOARD_IODATA_GVMVP_SZ: + em28xx_write_reg(dev, EM28XX_R08_GPIO, 0xff); + msleep(70); + em28xx_write_reg(dev, EM28XX_R08_GPIO, 0xf7); + msleep(10); + em28xx_write_reg(dev, EM28XX_R08_GPIO, 0xfe); + msleep(70); + em28xx_write_reg(dev, EM28XX_R08_GPIO, 0xfd); + msleep(70); + break; } em28xx_gpio_set(dev, dev->board.tuner_gpio); diff --git a/drivers/media/video/em28xx/em28xx.h b/drivers/media/video/em28xx/em28xx.h index 5115db3a76a6..3e82d818c0cd 100644 --- a/drivers/media/video/em28xx/em28xx.h +++ b/drivers/media/video/em28xx/em28xx.h @@ -101,6 +101,7 @@ #define EM2820_BOARD_GADMEI_TVR200 62 #define EM2860_BOARD_KAIOMY_TVNPC_U2 63 #define EM2860_BOARD_EASYCAP 64 +#define EM2820_BOARD_IODATA_GVMVP_SZ 65 /* Limits minimum and default number of buffers */ #define EM28XX_MIN_BUF 4 -- cgit v1.2.3 From b5ffc223e48417c2db0a4ce1beacdbab6503a472 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 11 Feb 2009 19:14:09 -0300 Subject: V4L/DVB (10536): saa6588: convert to v4l2-i2c-drv-legacy.h Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/saa6588.c | 82 ++++++++++++++----------------------------- 1 file changed, 27 insertions(+), 55 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/saa6588.c b/drivers/media/video/saa6588.c index f05024259f01..7c74ac4dd183 100644 --- a/drivers/media/video/saa6588.c +++ b/drivers/media/video/saa6588.c @@ -32,6 +32,8 @@ #include #include +#include +#include /* Addresses to scan */ static unsigned short normal_i2c[] = { @@ -72,7 +74,7 @@ MODULE_LICENSE("GPL"); #define dprintk if (debug) printk struct saa6588 { - struct i2c_client client; + struct i2c_client *client; struct work_struct work; struct timer_list timer; spinlock_t lock; @@ -86,9 +88,6 @@ struct saa6588 { int data_available_for_read; }; -static struct i2c_driver driver; -static struct i2c_client client_template; - /* ---------------------------------------------------------------------- */ /* @@ -265,7 +264,7 @@ static void saa6588_i2c_poll(struct saa6588 *s) /* Although we only need 3 bytes, we have to read at least 6. SAA6588 returns garbage otherwise */ - if (6 != i2c_master_recv(&s->client, &tmpbuf[0], 6)) { + if (6 != i2c_master_recv(s->client, &tmpbuf[0], 6)) { if (debug > 1) dprintk(PREFIX "read error!\n"); return; @@ -380,7 +379,8 @@ static int saa6588_configure(struct saa6588 *s) dprintk(PREFIX "writing: 0w=0x%02x 1w=0x%02x 2w=0x%02x\n", buf[0], buf[1], buf[2]); - if (3 != (rc = i2c_master_send(&s->client, buf, 3))) + rc = i2c_master_send(s->client, buf, 3); + if (rc != 3) printk(PREFIX "i2c i/o error: rc == %d (should be 3)\n", rc); return 0; @@ -388,33 +388,34 @@ static int saa6588_configure(struct saa6588 *s) /* ---------------------------------------------------------------------- */ -static int saa6588_attach(struct i2c_adapter *adap, int addr, int kind) +static int saa6588_probe(struct i2c_client *client, + const struct i2c_device_id *id) { struct saa6588 *s; - client_template.adapter = adap; - client_template.addr = addr; - printk(PREFIX "chip found @ 0x%x\n", addr << 1); + v4l_info(client, "saa6588 found @ 0x%x (%s)\n", + client->addr << 1, client->adapter->name); - if (NULL == (s = kmalloc(sizeof(*s), GFP_KERNEL))) + s = kzalloc(sizeof(*s), GFP_KERNEL); + if (s == NULL) return -ENOMEM; + s->client = client; s->buf_size = bufblocks * 3; - if (NULL == (s->buffer = kmalloc(s->buf_size, GFP_KERNEL))) { + s->buffer = kmalloc(s->buf_size, GFP_KERNEL); + if (s->buffer == NULL) { kfree(s); return -ENOMEM; } spin_lock_init(&s->lock); - s->client = client_template; s->block_count = 0; s->wr_index = 0; s->rd_index = 0; s->last_blocknum = 0xff; init_waitqueue_head(&s->read_queue); s->data_available_for_read = 0; - i2c_set_clientdata(&s->client, s); - i2c_attach_client(&s->client); + i2c_set_clientdata(client, s); saa6588_configure(s); @@ -427,21 +428,13 @@ static int saa6588_attach(struct i2c_adapter *adap, int addr, int kind) return 0; } -static int saa6588_probe(struct i2c_adapter *adap) -{ - if (adap->class & I2C_CLASS_TV_ANALOG) - return i2c_probe(adap, &addr_data, saa6588_attach); - return 0; -} - -static int saa6588_detach(struct i2c_client *client) +static int saa6588_remove(struct i2c_client *client) { struct saa6588 *s = i2c_get_clientdata(client); del_timer_sync(&s->timer); flush_scheduled_work(); - i2c_detach_client(client); kfree(s->buffer); kfree(s); return 0; @@ -486,38 +479,17 @@ static int saa6588_command(struct i2c_client *client, unsigned int cmd, /* ----------------------------------------------------------------------- */ -static struct i2c_driver driver = { - .driver = { - .name = "saa6588", - }, - .id = -1, /* FIXME */ - .attach_adapter = saa6588_probe, - .detach_client = saa6588_detach, - .command = saa6588_command, +static const struct i2c_device_id saa6588_id[] = { + { "saa6588", 0 }, + { } }; +MODULE_DEVICE_TABLE(i2c, saa6588_id); -static struct i2c_client client_template = { +static struct v4l2_i2c_driver_data v4l2_i2c_data = { .name = "saa6588", - .driver = &driver, + .command = saa6588_command, + .probe = saa6588_probe, + .remove = saa6588_remove, + .legacy_class = I2C_CLASS_TV_ANALOG, + .id_table = saa6588_id, }; - -static int __init saa6588_init_module(void) -{ - return i2c_add_driver(&driver); -} - -static void __exit saa6588_cleanup_module(void) -{ - i2c_del_driver(&driver); -} - -module_init(saa6588_init_module); -module_exit(saa6588_cleanup_module); - -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * --------------------------------------------------------------------------- - * Local variables: - * c-basic-offset: 8 - * End: - */ -- cgit v1.2.3 From c3fda7f835b025f3c020fa0865086fd23609e7ca Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 11 Feb 2009 19:23:57 -0300 Subject: V4L/DVB (10537): saa6588: convert to v4l2_subdev. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/saa6588.c | 115 ++++++++++++++++++++++++++---------------- 1 file changed, 71 insertions(+), 44 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/saa6588.c b/drivers/media/video/saa6588.c index 7c74ac4dd183..4d31c320ac17 100644 --- a/drivers/media/video/saa6588.c +++ b/drivers/media/video/saa6588.c @@ -32,7 +32,7 @@ #include #include -#include +#include #include /* Addresses to scan */ @@ -74,7 +74,7 @@ MODULE_LICENSE("GPL"); #define dprintk if (debug) printk struct saa6588 { - struct i2c_client *client; + struct v4l2_subdev sd; struct work_struct work; struct timer_list timer; spinlock_t lock; @@ -88,6 +88,11 @@ struct saa6588 { int data_available_for_read; }; +static inline struct saa6588 *to_saa6588(struct v4l2_subdev *sd) +{ + return container_of(sd, struct saa6588, sd); +} + /* ---------------------------------------------------------------------- */ /* @@ -257,6 +262,7 @@ static void block_to_buf(struct saa6588 *s, unsigned char *blockbuf) static void saa6588_i2c_poll(struct saa6588 *s) { + struct i2c_client *client = v4l2_get_subdevdata(&s->sd); unsigned long flags; unsigned char tmpbuf[6]; unsigned char blocknum; @@ -264,7 +270,7 @@ static void saa6588_i2c_poll(struct saa6588 *s) /* Although we only need 3 bytes, we have to read at least 6. SAA6588 returns garbage otherwise */ - if (6 != i2c_master_recv(s->client, &tmpbuf[0], 6)) { + if (6 != i2c_master_recv(client, &tmpbuf[0], 6)) { if (debug > 1) dprintk(PREFIX "read error!\n"); return; @@ -332,6 +338,7 @@ static void saa6588_work(struct work_struct *work) static int saa6588_configure(struct saa6588 *s) { + struct i2c_client *client = v4l2_get_subdevdata(&s->sd); unsigned char buf[3]; int rc; @@ -379,7 +386,7 @@ static int saa6588_configure(struct saa6588 *s) dprintk(PREFIX "writing: 0w=0x%02x 1w=0x%02x 2w=0x%02x\n", buf[0], buf[1], buf[2]); - rc = i2c_master_send(s->client, buf, 3); + rc = i2c_master_send(client, buf, 3); if (rc != 3) printk(PREFIX "i2c i/o error: rc == %d (should be 3)\n", rc); @@ -388,10 +395,64 @@ static int saa6588_configure(struct saa6588 *s) /* ---------------------------------------------------------------------- */ +static long saa6588_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg) +{ + struct saa6588 *s = to_saa6588(sd); + struct rds_command *a = arg; + + switch (cmd) { + /* --- open() for /dev/radio --- */ + case RDS_CMD_OPEN: + a->result = 0; /* return error if chip doesn't work ??? */ + break; + /* --- close() for /dev/radio --- */ + case RDS_CMD_CLOSE: + s->data_available_for_read = 1; + wake_up_interruptible(&s->read_queue); + a->result = 0; + break; + /* --- read() for /dev/radio --- */ + case RDS_CMD_READ: + read_from_buf(s, a); + break; + /* --- poll() for /dev/radio --- */ + case RDS_CMD_POLL: + a->result = 0; + if (s->data_available_for_read) { + a->result |= POLLIN | POLLRDNORM; + } + poll_wait(a->instance, &s->read_queue, a->event_list); + break; + + default: + /* nothing */ + return -ENOIOCTLCMD; + } + return 0; +} + +static int saa6588_command(struct i2c_client *client, unsigned cmd, void *arg) +{ + return v4l2_subdev_command(i2c_get_clientdata(client), cmd, arg); +} + +/* ----------------------------------------------------------------------- */ + +static const struct v4l2_subdev_core_ops saa6588_core_ops = { + .ioctl = saa6588_ioctl, +}; + +static const struct v4l2_subdev_ops saa6588_ops = { + .core = &saa6588_core_ops, +}; + +/* ---------------------------------------------------------------------- */ + static int saa6588_probe(struct i2c_client *client, const struct i2c_device_id *id) { struct saa6588 *s; + struct v4l2_subdev *sd; v4l_info(client, "saa6588 found @ 0x%x (%s)\n", client->addr << 1, client->adapter->name); @@ -400,7 +461,6 @@ static int saa6588_probe(struct i2c_client *client, if (s == NULL) return -ENOMEM; - s->client = client; s->buf_size = bufblocks * 3; s->buffer = kmalloc(s->buf_size, GFP_KERNEL); @@ -408,6 +468,8 @@ static int saa6588_probe(struct i2c_client *client, kfree(s); return -ENOMEM; } + sd = &s->sd; + v4l2_i2c_subdev_init(sd, client, &saa6588_ops); spin_lock_init(&s->lock); s->block_count = 0; s->wr_index = 0; @@ -415,7 +477,6 @@ static int saa6588_probe(struct i2c_client *client, s->last_blocknum = 0xff; init_waitqueue_head(&s->read_queue); s->data_available_for_read = 0; - i2c_set_clientdata(client, s); saa6588_configure(s); @@ -430,7 +491,10 @@ static int saa6588_probe(struct i2c_client *client, static int saa6588_remove(struct i2c_client *client) { - struct saa6588 *s = i2c_get_clientdata(client); + struct v4l2_subdev *sd = i2c_get_clientdata(client); + struct saa6588 *s = to_saa6588(sd); + + v4l2_device_unregister_subdev(sd); del_timer_sync(&s->timer); flush_scheduled_work(); @@ -440,43 +504,6 @@ static int saa6588_remove(struct i2c_client *client) return 0; } -static int saa6588_command(struct i2c_client *client, unsigned int cmd, - void *arg) -{ - struct saa6588 *s = i2c_get_clientdata(client); - struct rds_command *a = (struct rds_command *)arg; - - switch (cmd) { - /* --- open() for /dev/radio --- */ - case RDS_CMD_OPEN: - a->result = 0; /* return error if chip doesn't work ??? */ - break; - /* --- close() for /dev/radio --- */ - case RDS_CMD_CLOSE: - s->data_available_for_read = 1; - wake_up_interruptible(&s->read_queue); - a->result = 0; - break; - /* --- read() for /dev/radio --- */ - case RDS_CMD_READ: - read_from_buf(s, a); - break; - /* --- poll() for /dev/radio --- */ - case RDS_CMD_POLL: - a->result = 0; - if (s->data_available_for_read) { - a->result |= POLLIN | POLLRDNORM; - } - poll_wait(a->instance, &s->read_queue, a->event_list); - break; - - default: - /* nothing */ - break; - } - return 0; -} - /* ----------------------------------------------------------------------- */ static const struct i2c_device_id saa6588_id[] = { -- cgit v1.2.3 From f1f8c907b752ed281b1b4e6ca3605db50a8d6250 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 11 Feb 2009 19:28:30 -0300 Subject: V4L/DVB (10538): saa6588: add g_chip_ident support. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/saa6588.c | 9 +++++++++ include/media/v4l2-chip-ident.h | 3 +++ 2 files changed, 12 insertions(+) (limited to 'drivers/media/video') diff --git a/drivers/media/video/saa6588.c b/drivers/media/video/saa6588.c index 4d31c320ac17..5f4e9858cb9d 100644 --- a/drivers/media/video/saa6588.c +++ b/drivers/media/video/saa6588.c @@ -33,6 +33,7 @@ #include #include +#include #include /* Addresses to scan */ @@ -431,6 +432,13 @@ static long saa6588_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg) return 0; } +static int saa6588_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip) +{ + struct i2c_client *client = v4l2_get_subdevdata(sd); + + return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_SAA6588, 0); +} + static int saa6588_command(struct i2c_client *client, unsigned cmd, void *arg) { return v4l2_subdev_command(i2c_get_clientdata(client), cmd, arg); @@ -439,6 +447,7 @@ static int saa6588_command(struct i2c_client *client, unsigned cmd, void *arg) /* ----------------------------------------------------------------------- */ static const struct v4l2_subdev_core_ops saa6588_core_ops = { + .g_chip_ident = saa6588_g_chip_ident, .ioctl = saa6588_ioctl, }; diff --git a/include/media/v4l2-chip-ident.h b/include/media/v4l2-chip-ident.h index 4e2182e52a8e..bbe2bb6a596a 100644 --- a/include/media/v4l2-chip-ident.h +++ b/include/media/v4l2-chip-ident.h @@ -92,6 +92,9 @@ enum { /* module tea6420: just ident 6420 */ V4L2_IDENT_TEA6420 = 6420, + /* module saa6588: just ident 6588 */ + V4L2_IDENT_SAA6588 = 6588, + /* module saa6752hs: reserved range 6750-6759 */ V4L2_IDENT_SAA6752HS = 6752, V4L2_IDENT_SAA6752HS_AC3 = 6753, -- cgit v1.2.3 From 7911a709581bcebc2a2b915adb1b00b37e40a641 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 13 Feb 2009 05:08:27 -0300 Subject: V4L/DVB (10539): saa6588: remove legacy_class, not needed for saa6588 Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/saa6588.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/saa6588.c b/drivers/media/video/saa6588.c index 5f4e9858cb9d..258b7b2a1e99 100644 --- a/drivers/media/video/saa6588.c +++ b/drivers/media/video/saa6588.c @@ -526,6 +526,5 @@ static struct v4l2_i2c_driver_data v4l2_i2c_data = { .command = saa6588_command, .probe = saa6588_probe, .remove = saa6588_remove, - .legacy_class = I2C_CLASS_TV_ANALOG, .id_table = saa6588_id, }; -- cgit v1.2.3 From ee6f78cd03caae54baafb2e79a39b4aee90e6931 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 13 Feb 2009 05:12:02 -0300 Subject: V4L/DVB (10540): cx2341x: fixed bug causing several audio controls to be no longer listed The cx2341x_mpeg_ctrls array must be ordered by control ID. I know that this is bad design, but for now I will just fix this bug and revisit it when all drivers have moved to v4l2_device/v4l2_subdev, since that will allow me to do greatly improve control handling. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx2341x.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/cx2341x.c b/drivers/media/video/cx2341x.c index 6f4821616f75..4d09078c13b9 100644 --- a/drivers/media/video/cx2341x.c +++ b/drivers/media/video/cx2341x.c @@ -45,12 +45,12 @@ const u32 cx2341x_mpeg_ctrls[] = { V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ, V4L2_CID_MPEG_AUDIO_ENCODING, V4L2_CID_MPEG_AUDIO_L2_BITRATE, - V4L2_CID_MPEG_AUDIO_AC3_BITRATE, V4L2_CID_MPEG_AUDIO_MODE, V4L2_CID_MPEG_AUDIO_MODE_EXTENSION, V4L2_CID_MPEG_AUDIO_EMPHASIS, V4L2_CID_MPEG_AUDIO_CRC, V4L2_CID_MPEG_AUDIO_MUTE, + V4L2_CID_MPEG_AUDIO_AC3_BITRATE, V4L2_CID_MPEG_VIDEO_ENCODING, V4L2_CID_MPEG_VIDEO_ASPECT, V4L2_CID_MPEG_VIDEO_B_FRAMES, -- cgit v1.2.3 From 1b6f1d9603a46a73ceed8daf7a3285559727fec3 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 13 Feb 2009 07:48:21 -0300 Subject: V4L/DVB (10542): v4l2-subdev: add querystd and g_input_status In order to convert the v4l1 zoran and vino i2c drivers to v4l2 these extra ops are required. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/v4l2-subdev.c | 4 ++++ include/media/v4l2-common.h | 3 +++ include/media/v4l2-subdev.h | 2 ++ 3 files changed, 9 insertions(+) (limited to 'drivers/media/video') diff --git a/drivers/media/video/v4l2-subdev.c b/drivers/media/video/v4l2-subdev.c index 158bc55de166..923ec8d01991 100644 --- a/drivers/media/video/v4l2-subdev.c +++ b/drivers/media/video/v4l2-subdev.c @@ -104,6 +104,10 @@ int v4l2_subdev_command(struct v4l2_subdev *sd, unsigned cmd, void *arg) return v4l2_subdev_call(sd, video, g_fmt, arg); case VIDIOC_INT_S_STD_OUTPUT: return v4l2_subdev_call(sd, video, s_std_output, *(v4l2_std_id *)arg); + case VIDIOC_QUERYSTD: + return v4l2_subdev_call(sd, video, querystd, arg); + case VIDIOC_INT_G_INPUT_STATUS: + return v4l2_subdev_call(sd, video, g_input_status, arg); case VIDIOC_STREAMON: return v4l2_subdev_call(sd, video, s_stream, 1); case VIDIOC_STREAMOFF: diff --git a/include/media/v4l2-common.h b/include/media/v4l2-common.h index 0f864f8daaf2..1637cc302697 100644 --- a/include/media/v4l2-common.h +++ b/include/media/v4l2-common.h @@ -297,4 +297,7 @@ struct v4l2_crystal_freq { a v4l2_gpio struct if a direction is also needed. */ #define VIDIOC_INT_S_GPIO _IOW('d', 117, u32) +/* Get input status. Same as the status field in the v4l2_input struct. */ +#define VIDIOC_INT_G_INPUT_STATUS _IOR('d', 118, u32) + #endif /* V4L2_COMMON_H_ */ diff --git a/include/media/v4l2-subdev.h b/include/media/v4l2-subdev.h index 9c1663d91224..cd640c6f039b 100644 --- a/include/media/v4l2-subdev.h +++ b/include/media/v4l2-subdev.h @@ -115,6 +115,8 @@ struct v4l2_subdev_video_ops { int (*g_vbi_data)(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_data *vbi_data); int (*g_sliced_vbi_cap)(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_cap *cap); int (*s_std_output)(struct v4l2_subdev *sd, v4l2_std_id std); + int (*querystd)(struct v4l2_subdev *sd, v4l2_std_id *std); + int (*g_input_status)(struct v4l2_subdev *sd, u32 *status); int (*s_stream)(struct v4l2_subdev *sd, int enable); int (*s_fmt)(struct v4l2_subdev *sd, struct v4l2_format *fmt); int (*g_fmt)(struct v4l2_subdev *sd, struct v4l2_format *fmt); -- cgit v1.2.3 From 2ba588942c45a03a29a7a097e62bf0beceddb0e8 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 13 Feb 2009 10:57:48 -0300 Subject: V4L/DVB (10544): v4l2-common: add comments warning that about the sort order Control arrays as are used with v4l2_ctrl_next must be sorted from low to high. Add a comment at the top of all such arrays to warn about this. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx18/cx18-controls.c | 1 + drivers/media/video/cx2341x.c | 1 + drivers/media/video/cx23885/cx23885-video.c | 1 + drivers/media/video/cx88/cx88-video.c | 1 + drivers/media/video/ivtv/ivtv-controls.c | 1 + drivers/media/video/saa7134/saa7134-empress.c | 2 ++ drivers/media/video/v4l2-common.c | 2 +- include/media/v4l2-common.h | 5 +++++ 8 files changed, 13 insertions(+), 1 deletion(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/cx18/cx18-controls.c b/drivers/media/video/cx18/cx18-controls.c index 6af4d5c190e1..10a4e07b7aca 100644 --- a/drivers/media/video/cx18/cx18-controls.c +++ b/drivers/media/video/cx18/cx18-controls.c @@ -30,6 +30,7 @@ #include "cx18-mailbox.h" #include "cx18-controls.h" +/* Must be sorted from low to high control ID! */ static const u32 user_ctrls[] = { V4L2_CID_USER_CLASS, V4L2_CID_BRIGHTNESS, diff --git a/drivers/media/video/cx2341x.c b/drivers/media/video/cx2341x.c index 4d09078c13b9..b36f522d2c55 100644 --- a/drivers/media/video/cx2341x.c +++ b/drivers/media/video/cx2341x.c @@ -38,6 +38,7 @@ static int debug; module_param(debug, int, 0644); MODULE_PARM_DESC(debug, "Debug level (0-1)"); +/* Must be sorted from low to high control ID! */ const u32 cx2341x_mpeg_ctrls[] = { V4L2_CID_MPEG_CLASS, V4L2_CID_MPEG_STREAM_TYPE, diff --git a/drivers/media/video/cx23885/cx23885-video.c b/drivers/media/video/cx23885/cx23885-video.c index eaa11893bfe9..c2ed2505b725 100644 --- a/drivers/media/video/cx23885/cx23885-video.c +++ b/drivers/media/video/cx23885/cx23885-video.c @@ -244,6 +244,7 @@ static struct cx23885_ctrl cx23885_ctls[] = { }; static const int CX23885_CTLS = ARRAY_SIZE(cx23885_ctls); +/* Must be sorted from low to high control ID! */ static const u32 cx23885_user_ctrls[] = { V4L2_CID_USER_CLASS, V4L2_CID_BRIGHTNESS, diff --git a/drivers/media/video/cx88/cx88-video.c b/drivers/media/video/cx88/cx88-video.c index 791e69d804f9..5ed1c5a52cdd 100644 --- a/drivers/media/video/cx88/cx88-video.c +++ b/drivers/media/video/cx88/cx88-video.c @@ -298,6 +298,7 @@ static struct cx88_ctrl cx8800_ctls[] = { }; static const int CX8800_CTLS = ARRAY_SIZE(cx8800_ctls); +/* Must be sorted from low to high control ID! */ const u32 cx88_user_ctrls[] = { V4L2_CID_USER_CLASS, V4L2_CID_BRIGHTNESS, diff --git a/drivers/media/video/ivtv/ivtv-controls.c b/drivers/media/video/ivtv/ivtv-controls.c index 62aa06f5d168..84995bcf4a75 100644 --- a/drivers/media/video/ivtv/ivtv-controls.c +++ b/drivers/media/video/ivtv/ivtv-controls.c @@ -26,6 +26,7 @@ #include "ivtv-mailbox.h" #include "ivtv-controls.h" +/* Must be sorted from low to high control ID! */ static const u32 user_ctrls[] = { V4L2_CID_USER_CLASS, V4L2_CID_BRIGHTNESS, diff --git a/drivers/media/video/saa7134/saa7134-empress.c b/drivers/media/video/saa7134/saa7134-empress.c index d9d9607044a7..2e15bb7c3f0a 100644 --- a/drivers/media/video/saa7134/saa7134-empress.c +++ b/drivers/media/video/saa7134/saa7134-empress.c @@ -352,6 +352,7 @@ static int empress_s_ctrl(struct file *file, void *priv, static int empress_queryctrl(struct file *file, void *priv, struct v4l2_queryctrl *c) { + /* Must be sorted from low to high control ID! */ static const u32 user_ctrls[] = { V4L2_CID_USER_CLASS, V4L2_CID_BRIGHTNESS, @@ -364,6 +365,7 @@ static int empress_queryctrl(struct file *file, void *priv, 0 }; + /* Must be sorted from low to high control ID! */ static const u32 mpeg_ctrls[] = { V4L2_CID_MPEG_CLASS, V4L2_CID_MPEG_STREAM_TYPE, diff --git a/drivers/media/video/v4l2-common.c b/drivers/media/video/v4l2-common.c index 26e162f13f7f..7086f9f3c785 100644 --- a/drivers/media/video/v4l2-common.c +++ b/drivers/media/video/v4l2-common.c @@ -749,7 +749,7 @@ EXPORT_SYMBOL(v4l2_ctrl_query_menu_valid_items); /* ctrl_classes points to an array of u32 pointers, the last element is a NULL pointer. Each u32 array is a 0-terminated array of control IDs. Each array must be sorted low to high and belong to the same control - class. The array of u32 pointer must also be sorted, from low class IDs + class. The array of u32 pointers must also be sorted, from low class IDs to high class IDs. This function returns the first ID that follows after the given ID. diff --git a/include/media/v4l2-common.h b/include/media/v4l2-common.h index 1637cc302697..de785da4564c 100644 --- a/include/media/v4l2-common.h +++ b/include/media/v4l2-common.h @@ -107,6 +107,11 @@ int v4l2_ctrl_query_menu(struct v4l2_querymenu *qmenu, struct v4l2_queryctrl *qctrl, const char **menu_items); #define V4L2_CTRL_MENU_IDS_END (0xffffffff) int v4l2_ctrl_query_menu_valid_items(struct v4l2_querymenu *qmenu, const u32 *ids); + +/* Note: ctrl_classes points to an array of u32 pointers. Each u32 array is a + 0-terminated array of control IDs. Each array must be sorted low to high + and belong to the same control class. The array of u32 pointers must also + be sorted, from low class IDs to high class IDs. */ u32 v4l2_ctrl_next(const u32 * const *ctrl_classes, u32 id); /* ------------------------------------------------------------------------- */ -- cgit v1.2.3 From 55bf0e7013c2204aba3897987284ced7d3b8ff8b Mon Sep 17 00:00:00 2001 From: Nicola Soranzo Date: Thu, 12 Feb 2009 14:21:52 -0300 Subject: V4L/DVB (10555): em28xx: CodingStyle fixes Coding style fixes for recent changesets in em28xx. Signed-off-by: Nicola Soranzo Signed-off-by: Douglas Schilling Landgraf Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/em28xx/em28xx-audio.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/em28xx/em28xx-audio.c b/drivers/media/video/em28xx/em28xx-audio.c index 6296697d025f..0131322475bf 100644 --- a/drivers/media/video/em28xx/em28xx-audio.c +++ b/drivers/media/video/em28xx/em28xx-audio.c @@ -224,10 +224,12 @@ static int em28xx_cmd(struct em28xx *dev, int cmd, int arg) switch (cmd) { case EM28XX_CAPTURE_STREAM_EN: - if (dev->adev.capture_stream == STREAM_OFF && arg == EM28XX_START_AUDIO) { + if (dev->adev.capture_stream == STREAM_OFF && + arg == EM28XX_START_AUDIO) { dev->adev.capture_stream = STREAM_ON; em28xx_init_audio_isoc(dev); - } else if (dev->adev.capture_stream == STREAM_ON && arg == EM28XX_STOP_AUDIO) { + } else if (dev->adev.capture_stream == STREAM_ON && + arg == EM28XX_STOP_AUDIO) { dev->adev.capture_stream = STREAM_OFF; em28xx_deinit_isoc_audio(dev); } else { @@ -385,8 +387,8 @@ static int snd_em28xx_capture_trigger(struct snd_pcm_substream *substream, struct em28xx *dev = snd_pcm_substream_chip(substream); int retval; - dprintk("Should %s capture\n", (cmd == SNDRV_PCM_TRIGGER_START)? - "start": "stop"); + dprintk("Should %s capture\n", (cmd == SNDRV_PCM_TRIGGER_START) ? + "start" : "stop"); spin_lock(&dev->adev.slock); switch (cmd) { -- cgit v1.2.3 From 1d6af821a91df15e3fc2720c223ec514ae83dc86 Mon Sep 17 00:00:00 2001 From: Douglas Schilling Landgraf Date: Thu, 12 Feb 2009 14:22:42 -0300 Subject: V4L/DVB (10556): em28xx-cards: Add Pinnacle Dazzle Video Creator Plus DVC107 description Added board Pinnacle Dazzle Video Creator Plus DVC107 to name description field. Signed-off-by: Douglas Schilling Landgraf Signed-off-by: Mauro Carvalho Chehab --- Documentation/video4linux/CARDLIST.em28xx | 2 +- drivers/media/video/em28xx/em28xx-cards.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/media/video') diff --git a/Documentation/video4linux/CARDLIST.em28xx b/Documentation/video4linux/CARDLIST.em28xx index f97c8533d01a..77874bd20550 100644 --- a/Documentation/video4linux/CARDLIST.em28xx +++ b/Documentation/video4linux/CARDLIST.em28xx @@ -7,7 +7,7 @@ 6 -> Terratec Cinergy 200 USB (em2800) 7 -> Leadtek Winfast USB II (em2800) [0413:6023] 8 -> Kworld USB2800 (em2800) - 9 -> Pinnacle Dazzle DVC 90/DVC 100/DVC 101 (em2820/em2840) [2304:0207,2304:021a] + 9 -> Pinnacle Dazzle DVC 90/DVC 100/DVC 101/DVC 107 (em2820/em2840) [2304:0207,2304:021a] 10 -> Hauppauge WinTV HVR 900 (em2880) [2040:6500] 11 -> Terratec Hybrid XS (em2880) [0ccd:0042] 12 -> Kworld PVR TV 2800 RF (em2820/em2840) diff --git a/drivers/media/video/em28xx/em28xx-cards.c b/drivers/media/video/em28xx/em28xx-cards.c index c16c28e1ec48..615cf362e79c 100644 --- a/drivers/media/video/em28xx/em28xx-cards.c +++ b/drivers/media/video/em28xx/em28xx-cards.c @@ -916,7 +916,7 @@ struct em28xx_board em28xx_boards[] = { } }, }, [EM2820_BOARD_PINNACLE_DVC_90] = { - .name = "Pinnacle Dazzle DVC 90/DVC 100/DVC 101", + .name = "Pinnacle Dazzle DVC 90/DVC 100/DVC 101/DVC 107", .tuner_type = TUNER_ABSENT, /* capture only board */ .decoder = EM28XX_SAA711X, .input = { { -- cgit v1.2.3 From 4ef2ccc2611456667ea78c6f418ce87e1fa9fac5 Mon Sep 17 00:00:00 2001 From: Trent Piepho Date: Wed, 28 Jan 2009 21:32:58 -0300 Subject: V4L/DVB (10558): bttv: norm value should be unsigned The norm value in the driver is an index into an array and the the driver doesn't allow it to be negative or otherwise invalid. It should be unsigned but wasn't in all places. Fix some structs and functions to have the norm be unsigned. Get rid of useless checks for "< 0". Most of the driver code can't handle a norm value that's out of range, so change some ">= BTTV_TVNORMS" checks to BUG_ON(). There's no point in silently ignoring invalid driver state just to crash because of it later. Reported-by: Roel Kluin Signed-off-by: Trent Piepho Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/bt8xx/bttv-cards.c | 2 +- drivers/media/video/bt8xx/bttv-driver.c | 13 +++++-------- drivers/media/video/bt8xx/bttv-vbi.c | 2 +- drivers/media/video/bt8xx/bttv.h | 2 +- drivers/media/video/bt8xx/bttvp.h | 9 +++++---- 5 files changed, 13 insertions(+), 15 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/bt8xx/bttv-cards.c b/drivers/media/video/bt8xx/bttv-cards.c index 9dfd8c70e4fb..2df0ce2afe98 100644 --- a/drivers/media/video/bt8xx/bttv-cards.c +++ b/drivers/media/video/bt8xx/bttv-cards.c @@ -4085,7 +4085,7 @@ static void __devinit avermedia_eeprom(struct bttv *btv) } /* used on Voodoo TV/FM (Voodoo 200), S0 wired to 0x10000 */ -void bttv_tda9880_setnorm(struct bttv *btv, int norm) +void bttv_tda9880_setnorm(struct bttv *btv, unsigned int norm) { /* fix up our card entry */ if(norm==V4L2_STD_NTSC) { diff --git a/drivers/media/video/bt8xx/bttv-driver.c b/drivers/media/video/bt8xx/bttv-driver.c index c71f394fc0ea..4ec476a9c0e4 100644 --- a/drivers/media/video/bt8xx/bttv-driver.c +++ b/drivers/media/video/bt8xx/bttv-driver.c @@ -1277,7 +1277,7 @@ bttv_crop_calc_limits(struct bttv_crop *c) } static void -bttv_crop_reset(struct bttv_crop *c, int norm) +bttv_crop_reset(struct bttv_crop *c, unsigned int norm) { c->rect = bttv_tvnorms[norm].cropcap.defrect; bttv_crop_calc_limits(c); @@ -1290,16 +1290,13 @@ set_tvnorm(struct bttv *btv, unsigned int norm) const struct bttv_tvnorm *tvnorm; v4l2_std_id id; - if (norm < 0 || norm >= BTTV_TVNORMS) - return -EINVAL; + BUG_ON(norm >= BTTV_TVNORMS); + BUG_ON(btv->tvnorm >= BTTV_TVNORMS); tvnorm = &bttv_tvnorms[norm]; - if (btv->tvnorm < 0 || - btv->tvnorm >= BTTV_TVNORMS || - 0 != memcmp(&bttv_tvnorms[btv->tvnorm].cropcap, - &tvnorm->cropcap, - sizeof (tvnorm->cropcap))) { + if (!memcmp(&bttv_tvnorms[btv->tvnorm].cropcap, &tvnorm->cropcap, + sizeof (tvnorm->cropcap))) { bttv_crop_reset(&btv->crop[0], norm); btv->crop[1] = btv->crop[0]; /* current = default */ diff --git a/drivers/media/video/bt8xx/bttv-vbi.c b/drivers/media/video/bt8xx/bttv-vbi.c index 6819e21a3773..e79a402fa6cd 100644 --- a/drivers/media/video/bt8xx/bttv-vbi.c +++ b/drivers/media/video/bt8xx/bttv-vbi.c @@ -411,7 +411,7 @@ int bttv_g_fmt_vbi_cap(struct file *file, void *f, struct v4l2_format *frt) return 0; } -void bttv_vbi_fmt_reset(struct bttv_vbi_fmt *f, int norm) +void bttv_vbi_fmt_reset(struct bttv_vbi_fmt *f, unsigned int norm) { const struct bttv_tvnorm *tvnorm; unsigned int real_samples_per_line; diff --git a/drivers/media/video/bt8xx/bttv.h b/drivers/media/video/bt8xx/bttv.h index a7bcad171823..b1986b94d29f 100644 --- a/drivers/media/video/bt8xx/bttv.h +++ b/drivers/media/video/bt8xx/bttv.h @@ -265,7 +265,7 @@ extern void bttv_init_card2(struct bttv *btv); /* card-specific funtions */ extern void tea5757_set_freq(struct bttv *btv, unsigned short freq); -extern void bttv_tda9880_setnorm(struct bttv *btv, int norm); +extern void bttv_tda9880_setnorm(struct bttv *btv, unsigned int norm); /* extra tweaks for some chipsets */ extern void bttv_check_chipset(void); diff --git a/drivers/media/video/bt8xx/bttvp.h b/drivers/media/video/bt8xx/bttvp.h index 199a4d225caf..230e148e78fe 100644 --- a/drivers/media/video/bt8xx/bttvp.h +++ b/drivers/media/video/bt8xx/bttvp.h @@ -135,7 +135,7 @@ struct bttv_buffer { /* bttv specific */ const struct bttv_format *fmt; - int tvnorm; + unsigned int tvnorm; int btformat; int btswap; struct bttv_geometry geo; @@ -154,7 +154,7 @@ struct bttv_buffer_set { }; struct bttv_overlay { - int tvnorm; + unsigned int tvnorm; struct v4l2_rect w; enum v4l2_field field; struct v4l2_clip *clips; @@ -174,7 +174,7 @@ struct bttv_vbi_fmt { }; /* bttv-vbi.c */ -void bttv_vbi_fmt_reset(struct bttv_vbi_fmt *f, int norm); +void bttv_vbi_fmt_reset(struct bttv_vbi_fmt *f, unsigned int norm); struct bttv_crop { /* A cropping rectangle in struct bttv_tvnorm.cropcap units. */ @@ -378,7 +378,8 @@ struct bttv { unsigned int audio; unsigned int mute; unsigned long freq; - int tvnorm,hue,contrast,bright,saturation; + unsigned int tvnorm; + int hue, contrast, bright, saturation; struct v4l2_framebuffer fbuf; unsigned int field_count; -- cgit v1.2.3 From 72134a6d5199c3f5c8efe914e49072bde95948b3 Mon Sep 17 00:00:00 2001 From: Trent Piepho Date: Wed, 28 Jan 2009 21:32:59 -0300 Subject: V4L/DVB (10559): bttv: Fix TDA9880 norm setting code The code to set the norm for the TDA9880 analog demod was comparing btv->norm, an index into the bttv driver's norm array, to V4L2_STD_NTSC, which is a bit flag that's part of the V4L2 API. This doesn't work of course and results in the PAL path always being taken. What's more, it modified the bttv_tvcards[] entries for cards using the TDA9880. This is wrong because changing the norm on one card will also affect other cards of the same type. Writing to bttv_tvcards is also bad because it should be read-only or even devinitdata. Changing the norm would also cause the audio to become unmuted. Have the code get called for both norm setting and audio input setting (which where the gpios are set) to avoid needed to modify bttv_tvcards. Signed-off-by: Trent Piepho Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/bt8xx/bttv-cards.c | 37 ++++++++++++++++----------------- drivers/media/video/bt8xx/bttv-driver.c | 13 ++++++++++-- drivers/media/video/bt8xx/bttv.h | 2 +- 3 files changed, 30 insertions(+), 22 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/bt8xx/bttv-cards.c b/drivers/media/video/bt8xx/bttv-cards.c index 2df0ce2afe98..5c558e48e423 100644 --- a/drivers/media/video/bt8xx/bttv-cards.c +++ b/drivers/media/video/bt8xx/bttv-cards.c @@ -4084,27 +4084,26 @@ static void __devinit avermedia_eeprom(struct bttv *btv) btv->has_remote ? "yes" : "no"); } -/* used on Voodoo TV/FM (Voodoo 200), S0 wired to 0x10000 */ -void bttv_tda9880_setnorm(struct bttv *btv, unsigned int norm) +/* + * For Voodoo TV/FM and Voodoo 200. These cards' tuners use a TDA9880 + * analog demod, which is not I2C controlled like the newer and more common + * TDA9887 series. Instead is has two tri-state input pins, S0 and S1, + * that control the IF for the video and audio. Apparently, bttv GPIO + * 0x10000 is connected to S0. S0 low selects a 38.9 MHz VIF for B/G/D/K/I + * (i.e., PAL) while high selects 45.75 MHz for M/N (i.e., NTSC). + */ +u32 bttv_tda9880_setnorm(struct bttv *btv, u32 gpiobits) { - /* fix up our card entry */ - if(norm==V4L2_STD_NTSC) { - bttv_tvcards[BTTV_BOARD_VOODOOTV_FM].gpiomux[TVAUDIO_INPUT_TUNER]=0x957fff; - bttv_tvcards[BTTV_BOARD_VOODOOTV_FM].gpiomute=0x957fff; - bttv_tvcards[BTTV_BOARD_VOODOOTV_200].gpiomux[TVAUDIO_INPUT_TUNER]=0x957fff; - bttv_tvcards[BTTV_BOARD_VOODOOTV_200].gpiomute=0x957fff; - dprintk("bttv_tda9880_setnorm to NTSC\n"); - } - else { - bttv_tvcards[BTTV_BOARD_VOODOOTV_FM].gpiomux[TVAUDIO_INPUT_TUNER]=0x947fff; - bttv_tvcards[BTTV_BOARD_VOODOOTV_FM].gpiomute=0x947fff; - bttv_tvcards[BTTV_BOARD_VOODOOTV_200].gpiomux[TVAUDIO_INPUT_TUNER]=0x947fff; - bttv_tvcards[BTTV_BOARD_VOODOOTV_200].gpiomute=0x947fff; - dprintk("bttv_tda9880_setnorm to PAL\n"); + + if (btv->audio == TVAUDIO_INPUT_TUNER) { + if (bttv_tvnorms[btv->tvnorm].v4l2_id & V4L2_STD_MN) + gpiobits |= 0x10000; + else + gpiobits &= ~0x10000; } - /* set GPIO according */ - gpio_bits(bttv_tvcards[btv->c.type].gpiomask, - bttv_tvcards[btv->c.type].gpiomux[btv->audio]); + + gpio_bits(bttv_tvcards[btv->c.type].gpiomask, gpiobits); + return gpiobits; } diff --git a/drivers/media/video/bt8xx/bttv-driver.c b/drivers/media/video/bt8xx/bttv-driver.c index 4ec476a9c0e4..89e0cd191531 100644 --- a/drivers/media/video/bt8xx/bttv-driver.c +++ b/drivers/media/video/bt8xx/bttv-driver.c @@ -1180,7 +1180,16 @@ audio_mux(struct bttv *btv, int input, int mute) else gpio_val = bttv_tvcards[btv->c.type].gpiomux[input]; - gpio_bits(bttv_tvcards[btv->c.type].gpiomask, gpio_val); + switch (btv->c.type) { + case BTTV_BOARD_VOODOOTV_FM: + case BTTV_BOARD_VOODOOTV_200: + gpio_val = bttv_tda9880_setnorm(btv, gpio_val); + break; + + default: + gpio_bits(bttv_tvcards[btv->c.type].gpiomask, gpio_val); + } + if (bttv_gpio) bttv_gpio_tracking(btv, audio_modes[mute ? 4 : input]); if (in_interrupt()) @@ -1319,7 +1328,7 @@ set_tvnorm(struct bttv *btv, unsigned int norm) switch (btv->c.type) { case BTTV_BOARD_VOODOOTV_FM: case BTTV_BOARD_VOODOOTV_200: - bttv_tda9880_setnorm(btv,norm); + bttv_tda9880_setnorm(btv, gpio_read()); break; } id = tvnorm->v4l2_id; diff --git a/drivers/media/video/bt8xx/bttv.h b/drivers/media/video/bt8xx/bttv.h index b1986b94d29f..6bf2fa03a585 100644 --- a/drivers/media/video/bt8xx/bttv.h +++ b/drivers/media/video/bt8xx/bttv.h @@ -265,7 +265,7 @@ extern void bttv_init_card2(struct bttv *btv); /* card-specific funtions */ extern void tea5757_set_freq(struct bttv *btv, unsigned short freq); -extern void bttv_tda9880_setnorm(struct bttv *btv, unsigned int norm); +extern u32 bttv_tda9880_setnorm(struct bttv *btv, u32 gpiobits); /* extra tweaks for some chipsets */ extern void bttv_check_chipset(void); -- cgit v1.2.3 From abb0362f49c361f71b5aa6d244d4847145ed53c1 Mon Sep 17 00:00:00 2001 From: Trent Piepho Date: Wed, 28 Jan 2009 21:32:59 -0300 Subject: V4L/DVB (10560): bttv: make tuner card info more consistent The bttv card database structure had a "tuner" field that was the input number of the tuner input or UNSET for no tuner. However, the only values it could ever be are 0 and UNSET. Having a tuner on an input other than 0 didn't work and was never used. There is also a "tuner_type" field that can be set to TUNER_ABSENT to indicate no tuner, which makes "tuner = UNSET" redundant. In many cases, tuner_type was set to UNSET when there was no tuner, which isn't quite correct. tuner_type == UNSET is supposed to mean the tuner type isn't yet known. So, I changed cards where "tuner == UNSET" to always have tuner_type of TUNER_ABSENT. At this point the tuner field is redundant, so I deleted it. I have the card setup code set the card's tuner_type (not the card type's tuner_type!) to TUNER_ABSENT if it hasn't yet been set at the end of the setup code. Various places that check if the card has a tuner will now look for this instead of checking the card type's "tuner" field. Also autoload the tuner module before issuing the TUNER_SET_TYPE_ADDR I2C client call instead of after issuing it. Overall, on ia32 this decreases compiled code size by about 24 bytes and reduces the data size by 640 bytes. Signed-off-by: Trent Piepho Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/bt8xx/bttv-cards.c | 285 ++++++++------------------------ drivers/media/video/bt8xx/bttv-driver.c | 15 +- drivers/media/video/bt8xx/bttv-i2c.c | 6 +- drivers/media/video/bt8xx/bttv.h | 1 - 4 files changed, 77 insertions(+), 230 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/bt8xx/bttv-cards.c b/drivers/media/video/bt8xx/bttv-cards.c index 5c558e48e423..edf8d2505f0b 100644 --- a/drivers/media/video/bt8xx/bttv-cards.c +++ b/drivers/media/video/bt8xx/bttv-cards.c @@ -321,7 +321,6 @@ struct tvcard bttv_tvcards[] = { .name = " *** UNKNOWN/GENERIC *** ", .video_inputs = 4, .audio_inputs = 1, - .tuner = 0, .svhs = 2, .muxsel = { 2, 3, 1, 0 }, .tuner_type = UNSET, @@ -332,7 +331,6 @@ struct tvcard bttv_tvcards[] = { .name = "MIRO PCTV", .video_inputs = 4, .audio_inputs = 1, - .tuner = 0, .svhs = 2, .gpiomask = 15, .muxsel = { 2, 3, 1, 1 }, @@ -347,7 +345,6 @@ struct tvcard bttv_tvcards[] = { .name = "Hauppauge (bt848)", .video_inputs = 4, .audio_inputs = 1, - .tuner = 0, .svhs = 2, .gpiomask = 7, .muxsel = { 2, 3, 1, 1 }, @@ -362,7 +359,6 @@ struct tvcard bttv_tvcards[] = { .name = "STB, Gateway P/N 6000699 (bt848)", .video_inputs = 3, .audio_inputs = 1, - .tuner = 0, .svhs = 2, .gpiomask = 7, .muxsel = { 2, 3, 1, 1 }, @@ -382,7 +378,6 @@ struct tvcard bttv_tvcards[] = { .name = "Intel Create and Share PCI/ Smart Video Recorder III", .video_inputs = 4, .audio_inputs = 0, - .tuner = UNSET, .svhs = 2, .gpiomask = 0, .muxsel = { 2, 3, 1, 1 }, @@ -396,7 +391,6 @@ struct tvcard bttv_tvcards[] = { .name = "Diamond DTV2000", .video_inputs = 4, .audio_inputs = 1, - .tuner = 0, .svhs = 2, .gpiomask = 3, .muxsel = { 2, 3, 1, 0 }, @@ -411,7 +405,6 @@ struct tvcard bttv_tvcards[] = { .name = "AVerMedia TVPhone", .video_inputs = 3, .audio_inputs = 1, - .tuner = 0, .svhs = 3, .muxsel = { 2, 3, 1, 1 }, .gpiomask = 0x0f, @@ -428,13 +421,12 @@ struct tvcard bttv_tvcards[] = { .name = "MATRIX-Vision MV-Delta", .video_inputs = 5, .audio_inputs = 1, - .tuner = UNSET, .svhs = 3, .gpiomask = 0, .muxsel = { 2, 3, 1, 0, 0 }, .gpiomux = { 0 }, .needs_tvaudio = 1, - .tuner_type = UNSET, + .tuner_type = TUNER_ABSENT, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, }, @@ -444,7 +436,6 @@ struct tvcard bttv_tvcards[] = { .name = "Lifeview FlyVideo II (Bt848) LR26 / MAXI TV Video PCI2 LR26", .video_inputs = 4, .audio_inputs = 1, - .tuner = 0, .svhs = 2, .gpiomask = 0xc00, .muxsel = { 2, 3, 1, 1 }, @@ -460,7 +451,6 @@ struct tvcard bttv_tvcards[] = { .name = "IMS/IXmicro TurboTV", .video_inputs = 3, .audio_inputs = 1, - .tuner = 0, .svhs = 2, .gpiomask = 3, .muxsel = { 2, 3, 1, 1 }, @@ -475,7 +465,6 @@ struct tvcard bttv_tvcards[] = { .name = "Hauppauge (bt878)", .video_inputs = 4, .audio_inputs = 1, - .tuner = 0, .svhs = 2, .gpiomask = 0x0f, /* old: 7 */ .muxsel = { 2, 0, 1, 1 }, @@ -491,7 +480,6 @@ struct tvcard bttv_tvcards[] = { .name = "MIRO PCTV pro", .video_inputs = 3, .audio_inputs = 1, - .tuner = 0, .svhs = 2, .gpiomask = 0x3014f, .muxsel = { 2, 3, 1, 1 }, @@ -508,7 +496,6 @@ struct tvcard bttv_tvcards[] = { .name = "ADS Technologies Channel Surfer TV (bt848)", .video_inputs = 3, .audio_inputs = 1, - .tuner = 0, .svhs = 2, .gpiomask = 15, .muxsel = { 2, 3, 1, 1 }, @@ -522,7 +509,6 @@ struct tvcard bttv_tvcards[] = { .name = "AVerMedia TVCapture 98", .video_inputs = 3, .audio_inputs = 4, - .tuner = 0, .svhs = 2, .gpiomask = 15, .muxsel = { 2, 3, 1, 1 }, @@ -540,7 +526,6 @@ struct tvcard bttv_tvcards[] = { .name = "Aimslab Video Highway Xtreme (VHX)", .video_inputs = 3, .audio_inputs = 1, - .tuner = 0, .svhs = 2, .gpiomask = 7, .muxsel = { 2, 3, 1, 1 }, @@ -556,7 +541,6 @@ struct tvcard bttv_tvcards[] = { .name = "Zoltrix TV-Max", .video_inputs = 3, .audio_inputs = 1, - .tuner = 0, .svhs = 2, .gpiomask = 15, .muxsel = { 2, 3, 1, 1 }, @@ -573,7 +557,6 @@ struct tvcard bttv_tvcards[] = { .name = "Prolink Pixelview PlayTV (bt878)", .video_inputs = 3, .audio_inputs = 1, - .tuner = 0, .svhs = 2, .gpiomask = 0x01fe00, .muxsel = { 2, 3, 1, 1 }, @@ -590,7 +573,6 @@ struct tvcard bttv_tvcards[] = { .name = "Leadtek WinView 601", .video_inputs = 3, .audio_inputs = 1, - .tuner = 0, .svhs = 2, .gpiomask = 0x8300f8, .muxsel = { 2, 3, 1, 1,0 }, @@ -607,7 +589,6 @@ struct tvcard bttv_tvcards[] = { .name = "AVEC Intercapture", .video_inputs = 3, .audio_inputs = 2, - .tuner = 0, .svhs = 2, .gpiomask = 0, .muxsel = { 2, 3, 1, 1 }, @@ -621,13 +602,12 @@ struct tvcard bttv_tvcards[] = { .name = "Lifeview FlyVideo II EZ /FlyKit LR38 Bt848 (capture only)", .video_inputs = 4, .audio_inputs = 1, - .tuner = UNSET, .svhs = UNSET, .gpiomask = 0x8dff00, .muxsel = { 2, 3, 1, 1 }, .gpiomux = { 0 }, .no_msp34xx = 1, - .tuner_type = UNSET, + .tuner_type = TUNER_ABSENT, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, }, @@ -637,7 +617,6 @@ struct tvcard bttv_tvcards[] = { .name = "CEI Raffles Card", .video_inputs = 3, .audio_inputs = 3, - .tuner = 0, .svhs = 2, .muxsel = { 2, 3, 1, 1 }, .tuner_type = UNSET, @@ -648,7 +627,6 @@ struct tvcard bttv_tvcards[] = { .name = "Lifeview FlyVideo 98/ Lucky Star Image World ConferenceTV LR50", .video_inputs = 4, .audio_inputs = 2, /* tuner, line in */ - .tuner = 0, .svhs = 2, .gpiomask = 0x1800, .muxsel = { 2, 3, 1, 1 }, @@ -663,7 +641,6 @@ struct tvcard bttv_tvcards[] = { .name = "Askey CPH050/ Phoebe Tv Master + FM", .video_inputs = 3, .audio_inputs = 1, - .tuner = 0, .svhs = 2, .gpiomask = 0xc00, .muxsel = { 2, 3, 1, 1 }, @@ -679,7 +656,6 @@ struct tvcard bttv_tvcards[] = { .name = "Modular Technology MM201/MM202/MM205/MM210/MM215 PCTV, bt878", .video_inputs = 3, .audio_inputs = 1, - .tuner = 0, .svhs = UNSET, .gpiomask = 7, .muxsel = { 2, 3, -1 }, @@ -697,7 +673,6 @@ struct tvcard bttv_tvcards[] = { .name = "Askey CPH05X/06X (bt878) [many vendors]", .video_inputs = 3, .audio_inputs = 1, - .tuner = 0, .svhs = 2, .gpiomask = 0xe00, .muxsel = { 2, 3, 1, 1 }, @@ -714,7 +689,6 @@ struct tvcard bttv_tvcards[] = { .name = "Terratec TerraTV+ Version 1.0 (Bt848)/ Terra TValue Version 1.0/ Vobis TV-Boostar", .video_inputs = 3, .audio_inputs = 1, - .tuner = 0, .svhs = 2, .gpiomask = 0x1f0fff, .muxsel = { 2, 3, 1, 1 }, @@ -730,7 +704,6 @@ struct tvcard bttv_tvcards[] = { .name = "Hauppauge WinCam newer (bt878)", .video_inputs = 4, .audio_inputs = 1, - .tuner = 0, .svhs = 3, .gpiomask = 7, .muxsel = { 2, 0, 1, 1 }, @@ -745,7 +718,6 @@ struct tvcard bttv_tvcards[] = { .name = "Lifeview FlyVideo 98/ MAXI TV Video PCI2 LR50", .video_inputs = 4, .audio_inputs = 2, - .tuner = 0, .svhs = 2, .gpiomask = 0x1800, .muxsel = { 2, 3, 1, 1 }, @@ -762,7 +734,6 @@ struct tvcard bttv_tvcards[] = { .name = "Terratec TerraTV+ Version 1.1 (bt878)", .video_inputs = 3, .audio_inputs = 1, - .tuner = 0, .svhs = 2, .gpiomask = 0x1f0fff, .muxsel = { 2, 3, 1, 1 }, @@ -810,13 +781,12 @@ struct tvcard bttv_tvcards[] = { .name = "Imagenation PXC200", .video_inputs = 5, .audio_inputs = 1, - .tuner = UNSET, .svhs = 1, /* was: 4 */ .gpiomask = 0, .muxsel = { 2, 3, 1, 0, 0}, .gpiomux = { 0 }, .needs_tvaudio = 1, - .tuner_type = UNSET, + .tuner_type = TUNER_ABSENT, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, .muxsel_hook = PXC200_muxsel, @@ -826,7 +796,6 @@ struct tvcard bttv_tvcards[] = { .name = "Lifeview FlyVideo 98 LR50", .video_inputs = 4, .audio_inputs = 1, - .tuner = 0, .svhs = 2, .gpiomask = 0x1800, /* 0x8dfe00 */ .muxsel = { 2, 3, 1, 1 }, @@ -841,7 +810,6 @@ struct tvcard bttv_tvcards[] = { .name = "Formac iProTV, Formac ProTV I (bt848)", .video_inputs = 4, .audio_inputs = 1, - .tuner = 0, .svhs = 3, .gpiomask = 1, .muxsel = { 2, 3, 1, 1 }, @@ -857,7 +825,6 @@ struct tvcard bttv_tvcards[] = { .name = "Intel Create and Share PCI/ Smart Video Recorder III", .video_inputs = 4, .audio_inputs = 0, - .tuner = UNSET, .svhs = 2, .gpiomask = 0, .muxsel = { 2, 3, 1, 1 }, @@ -871,7 +838,6 @@ struct tvcard bttv_tvcards[] = { .name = "Terratec TerraTValue Version Bt878", .video_inputs = 3, .audio_inputs = 1, - .tuner = 0, .svhs = 2, .gpiomask = 0xffff00, .muxsel = { 2, 3, 1, 1 }, @@ -887,7 +853,6 @@ struct tvcard bttv_tvcards[] = { .name = "Leadtek WinFast 2000/ WinFast 2000 XP", .video_inputs = 4, .audio_inputs = 1, - .tuner = 0, .svhs = 2, .muxsel = { 2, 3, 1, 1, 0 }, /* TV, CVid, SVid, CVid over SVid connector */ /* Alexander Varakin [stereo version] */ @@ -918,7 +883,6 @@ struct tvcard bttv_tvcards[] = { .name = "Lifeview FlyVideo 98 LR50 / Chronos Video Shuttle II", .video_inputs = 4, .audio_inputs = 3, - .tuner = 0, .svhs = 2, .gpiomask = 0x1800, .muxsel = { 2, 3, 1, 1 }, @@ -935,7 +899,6 @@ struct tvcard bttv_tvcards[] = { .name = "Lifeview FlyVideo 98FM LR50 / Typhoon TView TV/FM Tuner", .video_inputs = 4, .audio_inputs = 3, - .tuner = 0, .svhs = 2, .gpiomask = 0x1800, .muxsel = { 2, 3, 1, 1 }, @@ -951,7 +914,6 @@ struct tvcard bttv_tvcards[] = { .name = "Prolink PixelView PlayTV pro", .video_inputs = 3, .audio_inputs = 1, - .tuner = 0, .svhs = 2, .gpiomask = 0xff, .muxsel = { 2, 3, 1, 1 }, @@ -967,7 +929,6 @@ struct tvcard bttv_tvcards[] = { .name = "Askey CPH06X TView99", .video_inputs = 4, .audio_inputs = 1, - .tuner = 0, .svhs = 2, .gpiomask = 0x551e00, .muxsel = { 2, 3, 1, 0 }, @@ -984,7 +945,6 @@ struct tvcard bttv_tvcards[] = { .name = "Pinnacle PCTV Studio/Rave", .video_inputs = 3, .audio_inputs = 1, - .tuner = 0, .svhs = 2, .gpiomask = 0x03000F, .muxsel = { 2, 3, 1, 1 }, @@ -1002,7 +962,6 @@ struct tvcard bttv_tvcards[] = { .name = "STB TV PCI FM, Gateway P/N 6000704 (bt878), 3Dfx VoodooTV 100", .video_inputs = 3, .audio_inputs = 1, - .tuner = 0, .svhs = 2, .gpiomask = 7, .muxsel = { 2, 3, 1, 1 }, @@ -1020,7 +979,6 @@ struct tvcard bttv_tvcards[] = { .name = "AVerMedia TVPhone 98", .video_inputs = 3, .audio_inputs = 4, - .tuner = 0, .svhs = 2, .gpiomask = 15, .muxsel = { 2, 3, 1, 1 }, @@ -1037,7 +995,6 @@ struct tvcard bttv_tvcards[] = { .name = "ProVideo PV951", /* pic16c54 */ .video_inputs = 3, .audio_inputs = 1, - .tuner = 0, .svhs = 2, .gpiomask = 0, .muxsel = { 2, 3, 1, 1}, @@ -1053,7 +1010,6 @@ struct tvcard bttv_tvcards[] = { .name = "Little OnAir TV", .video_inputs = 3, .audio_inputs = 1, - .tuner = 0, .svhs = 2, .gpiomask = 0xe00b, .muxsel = { 2, 3, 1, 1 }, @@ -1070,7 +1026,6 @@ struct tvcard bttv_tvcards[] = { .name = "Sigma TVII-FM", .video_inputs = 2, .audio_inputs = 1, - .tuner = 0, .svhs = UNSET, .gpiomask = 3, .muxsel = { 2, 3, 1, 1 }, @@ -1086,14 +1041,13 @@ struct tvcard bttv_tvcards[] = { .name = "MATRIX-Vision MV-Delta 2", .video_inputs = 5, .audio_inputs = 1, - .tuner = UNSET, .svhs = 3, .gpiomask = 0, .muxsel = { 2, 3, 1, 0, 0 }, .gpiomux = { 0 }, .no_msp34xx = 1, .pll = PLL_28, - .tuner_type = UNSET, + .tuner_type = TUNER_ABSENT, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, }, @@ -1101,7 +1055,6 @@ struct tvcard bttv_tvcards[] = { .name = "Zoltrix Genie TV/FM", .video_inputs = 3, .audio_inputs = 1, - .tuner = 0, .svhs = 2, .gpiomask = 0xbcf03f, .muxsel = { 2, 3, 1, 1 }, @@ -1117,7 +1070,6 @@ struct tvcard bttv_tvcards[] = { .name = "Terratec TV/Radio+", .video_inputs = 3, .audio_inputs = 1, - .tuner = 0, .svhs = 2, .gpiomask = 0x70000, .muxsel = { 2, 3, 1, 1 }, @@ -1137,7 +1089,6 @@ struct tvcard bttv_tvcards[] = { .name = "Askey CPH03x/ Dynalink Magic TView", .video_inputs = 3, .audio_inputs = 1, - .tuner = 0, .svhs = 2, .gpiomask = 15, .muxsel = { 2, 3, 1, 1 }, @@ -1153,7 +1104,6 @@ struct tvcard bttv_tvcards[] = { .name = "IODATA GV-BCTV3/PCI", .video_inputs = 3, .audio_inputs = 1, - .tuner = 0, .svhs = 2, .gpiomask = 0x010f00, .muxsel = {2, 3, 0, 0 }, @@ -1169,7 +1119,6 @@ struct tvcard bttv_tvcards[] = { .name = "Prolink PV-BT878P+4E / PixelView PlayTV PAK / Lenco MXTV-9578 CP", .video_inputs = 5, .audio_inputs = 1, - .tuner = 0, .svhs = 3, .gpiomask = 0xAA0000, .muxsel = { 2,3,1,1,-1 }, @@ -1196,7 +1145,6 @@ struct tvcard bttv_tvcards[] = { .name = "Eagle Wireless Capricorn2 (bt878A)", .video_inputs = 4, .audio_inputs = 1, - .tuner = 0, .svhs = 2, .gpiomask = 7, .muxsel = { 2, 0, 1, 1 }, @@ -1214,7 +1162,6 @@ struct tvcard bttv_tvcards[] = { .name = "Pinnacle PCTV Studio Pro", .video_inputs = 4, .audio_inputs = 1, - .tuner = 0, .svhs = 3, .gpiomask = 0x03000F, .muxsel = { 2, 3, 1, 1 }, @@ -1241,7 +1188,6 @@ struct tvcard bttv_tvcards[] = { .name = "Typhoon TView RDS + FM Stereo / KNC1 TV Station RDS", .video_inputs = 4, .audio_inputs = 3, - .tuner = 0, .svhs = 2, .gpiomask = 0x1c, .muxsel = { 2, 3, 1, 1 }, @@ -1263,7 +1209,6 @@ struct tvcard bttv_tvcards[] = { .name = "Lifeview FlyVideo 2000 /FlyVideo A2/ Lifetec LT 9415 TV [LR90]", .video_inputs = 4, .audio_inputs = 1, - .tuner = 0, .svhs = 2, .gpiomask = 0x18e0, .muxsel = { 2, 3, 1, 1 }, @@ -1284,7 +1229,6 @@ struct tvcard bttv_tvcards[] = { .name = "Askey CPH031/ BESTBUY Easy TV", .video_inputs = 4, .audio_inputs = 1, - .tuner = 0, .svhs = 2, .gpiomask = 0xF, .muxsel = { 2, 3, 1, 0 }, @@ -1303,7 +1247,6 @@ struct tvcard bttv_tvcards[] = { .name = "Lifeview FlyVideo 98FM LR50", .video_inputs = 4, .audio_inputs = 3, - .tuner = 0, .svhs = 2, .gpiomask = 0x1800, .muxsel = { 2, 3, 1, 1 }, @@ -1321,7 +1264,6 @@ struct tvcard bttv_tvcards[] = { .name = "GrandTec 'Grand Video Capture' (Bt848)", .video_inputs = 2, .audio_inputs = 0, - .tuner = UNSET, .svhs = 1, .gpiomask = 0, .muxsel = { 3, 1 }, @@ -1329,7 +1271,7 @@ struct tvcard bttv_tvcards[] = { .needs_tvaudio = 0, .no_msp34xx = 1, .pll = PLL_35, - .tuner_type = UNSET, + .tuner_type = TUNER_ABSENT, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, }, @@ -1338,7 +1280,6 @@ struct tvcard bttv_tvcards[] = { .name = "Askey CPH060/ Phoebe TV Master Only (No FM)", .video_inputs = 3, .audio_inputs = 1, - .tuner = 0, .svhs = 2, .gpiomask = 0xe00, .muxsel = { 2, 3, 1, 1}, @@ -1355,7 +1296,6 @@ struct tvcard bttv_tvcards[] = { .name = "Askey CPH03x TV Capturer", .video_inputs = 4, .audio_inputs = 1, - .tuner = 0, .svhs = 2, .gpiomask = 0x03000F, .muxsel = { 2, 3, 1, 0 }, @@ -1373,7 +1313,6 @@ struct tvcard bttv_tvcards[] = { .name = "Modular Technology MM100PCTV", .video_inputs = 2, .audio_inputs = 2, - .tuner = 0, .svhs = UNSET, .gpiomask = 11, .muxsel = { 2, 3, 1, 1 }, @@ -1389,7 +1328,6 @@ struct tvcard bttv_tvcards[] = { .name = "AG Electronics GMV1", .video_inputs = 2, .audio_inputs = 0, - .tuner = UNSET, .svhs = 1, .gpiomask = 0xF, .muxsel = { 2, 2 }, @@ -1397,7 +1335,7 @@ struct tvcard bttv_tvcards[] = { .no_msp34xx = 1, .needs_tvaudio = 0, .pll = PLL_28, - .tuner_type = UNSET, + .tuner_type = TUNER_ABSENT, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, }, @@ -1408,7 +1346,6 @@ struct tvcard bttv_tvcards[] = { .name = "Askey CPH061/ BESTBUY Easy TV (bt878)", .video_inputs = 3, .audio_inputs = 2, - .tuner = 0, .svhs = 2, .gpiomask = 0xFF, .muxsel = { 2, 3, 1, 0 }, @@ -1425,7 +1362,6 @@ struct tvcard bttv_tvcards[] = { .name = "ATI TV-Wonder", .video_inputs = 3, .audio_inputs = 1, - .tuner = 0, .svhs = 2, .gpiomask = 0xf03f, .muxsel = { 2, 3, 1, 0 }, @@ -1443,7 +1379,6 @@ struct tvcard bttv_tvcards[] = { .name = "ATI TV-Wonder VE", .video_inputs = 2, .audio_inputs = 1, - .tuner = 0, .svhs = UNSET, .gpiomask = 1, .muxsel = { 2, 3, 0, 1 }, @@ -1459,7 +1394,6 @@ struct tvcard bttv_tvcards[] = { .name = "Lifeview FlyVideo 2000S LR90", .video_inputs = 3, .audio_inputs = 3, - .tuner = 0, .svhs = 2, .gpiomask = 0x18e0, .muxsel = { 2, 3, 0, 1 }, @@ -1481,7 +1415,6 @@ struct tvcard bttv_tvcards[] = { .name = "Terratec TValueRadio", .video_inputs = 3, .audio_inputs = 1, - .tuner = 0, .svhs = 2, .gpiomask = 0xffff00, .muxsel = { 2, 3, 1, 1 }, @@ -1499,7 +1432,6 @@ struct tvcard bttv_tvcards[] = { .name = "IODATA GV-BCTV4/PCI", .video_inputs = 3, .audio_inputs = 1, - .tuner = 0, .svhs = 2, .gpiomask = 0x010f00, .muxsel = {2, 3, 0, 0 }, @@ -1519,7 +1451,6 @@ struct tvcard bttv_tvcards[] = { * sound problems with this card. */ .video_inputs = 4, .audio_inputs = 1, - .tuner = 0, .svhs = UNSET, .gpiomask = 0x4f8a00, /* 0x100000: 1=MSP enabled (0=disable again) @@ -1541,7 +1472,6 @@ struct tvcard bttv_tvcards[] = { * sound problems with this card. */ .video_inputs = 4, .audio_inputs = 1, - .tuner = 0, .svhs = UNSET, .gpiomask = 0x4f8a00, /* 0x100000: 1=MSP enabled (0=disable again) @@ -1562,8 +1492,7 @@ struct tvcard bttv_tvcards[] = { .name = "Active Imaging AIMMS", .video_inputs = 1, .audio_inputs = 0, - .tuner = UNSET, - .tuner_type = UNSET, + .tuner_type = TUNER_ABSENT, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, .pll = PLL_28, @@ -1575,7 +1504,6 @@ struct tvcard bttv_tvcards[] = { .name = "Prolink Pixelview PV-BT878P+ (Rev.4C,8E)", .video_inputs = 3, .audio_inputs = 4, - .tuner = 0, .svhs = 2, .gpiomask = 15, .muxsel = { 2, 3, 1, 1 }, @@ -1599,12 +1527,11 @@ struct tvcard bttv_tvcards[] = { .name = "Lifeview FlyVideo 98EZ (capture only) LR51", .video_inputs = 4, .audio_inputs = 0, - .tuner = UNSET, .svhs = 2, .muxsel = { 2, 3, 1, 1 }, /* AV1, AV2, SVHS, CVid adapter on SVHS */ .pll = PLL_28, .no_msp34xx = 1, - .tuner_type = UNSET, + .tuner_type = TUNER_ABSENT, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, }, @@ -1615,7 +1542,6 @@ struct tvcard bttv_tvcards[] = { .name = "Prolink Pixelview PV-BT878P+9B (PlayTV Pro rev.9B FM+NICAM)", .video_inputs = 4, .audio_inputs = 1, - .tuner = 0, .svhs = 2, .gpiomask = 0x3f, .muxsel = { 2, 3, 1, 1 }, @@ -1645,13 +1571,12 @@ struct tvcard bttv_tvcards[] = { .name = "Sensoray 311", .video_inputs = 5, .audio_inputs = 0, - .tuner = UNSET, .svhs = 4, .gpiomask = 0, .muxsel = { 2, 3, 1, 0, 0 }, .gpiomux = { 0 }, .needs_tvaudio = 0, - .tuner_type = UNSET, + .tuner_type = TUNER_ABSENT, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, }, @@ -1660,7 +1585,6 @@ struct tvcard bttv_tvcards[] = { .name = "RemoteVision MX (RV605)", .video_inputs = 16, .audio_inputs = 0, - .tuner = UNSET, .svhs = UNSET, .gpiomask = 0x00, .gpiomask2 = 0x07ff, @@ -1668,7 +1592,7 @@ struct tvcard bttv_tvcards[] = { 0xd3, 0xb3, 0xc3, 0x63, 0x93, 0x53, 0x83, 0xa3 }, .no_msp34xx = 1, .no_tda9875 = 1, - .tuner_type = UNSET, + .tuner_type = TUNER_ABSENT, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, .muxsel_hook = rv605_muxsel, @@ -1677,7 +1601,6 @@ struct tvcard bttv_tvcards[] = { .name = "Powercolor MTV878/ MTV878R/ MTV878F", .video_inputs = 3, .audio_inputs = 2, - .tuner = 0, .svhs = 2, .gpiomask = 0x1C800F, /* Bit0-2: Audio select, 8-12:remote control 14:remote valid 15:remote reset */ .muxsel = { 2, 1, 1, }, @@ -1697,7 +1620,6 @@ struct tvcard bttv_tvcards[] = { .name = "Canopus WinDVR PCI (COMPAQ Presario 3524JP, 5112JP)", .video_inputs = 3, .audio_inputs = 1, - .tuner = 0, .svhs = 2, .gpiomask = 0x140007, .muxsel = { 2, 3, 1, 1 }, @@ -1712,7 +1634,6 @@ struct tvcard bttv_tvcards[] = { .name = "GrandTec Multi Capture Card (Bt878)", .video_inputs = 4, .audio_inputs = 0, - .tuner = UNSET, .svhs = UNSET, .gpiomask = 0, .muxsel = { 2, 3, 1, 0 }, @@ -1720,7 +1641,7 @@ struct tvcard bttv_tvcards[] = { .needs_tvaudio = 0, .no_msp34xx = 1, .pll = PLL_28, - .tuner_type = UNSET, + .tuner_type = TUNER_ABSENT, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, }, @@ -1728,7 +1649,6 @@ struct tvcard bttv_tvcards[] = { .name = "Jetway TV/Capture JW-TV878-FBK, Kworld KW-TV878RF", .video_inputs = 4, .audio_inputs = 3, - .tuner = 0, .svhs = 2, .gpiomask = 7, .muxsel = { 2, 3, 1, 1 }, /* Tuner, SVid, SVHS, SVid to SVHS connector */ @@ -1776,7 +1696,6 @@ struct tvcard bttv_tvcards[] = { .name = "Hauppauge WinTV PVR", .video_inputs = 4, .audio_inputs = 1, - .tuner = 0, .svhs = 2, .muxsel = { 2, 0, 1, 1 }, .needs_tvaudio = 1, @@ -1792,7 +1711,6 @@ struct tvcard bttv_tvcards[] = { .name = "IODATA GV-BCTV5/PCI", .video_inputs = 3, .audio_inputs = 1, - .tuner = 0, .svhs = 2, .gpiomask = 0x0f0f80, .muxsel = {2, 3, 1, 0 }, @@ -1810,11 +1728,10 @@ struct tvcard bttv_tvcards[] = { .name = "Osprey 100/150 (878)", /* 0x1(2|3)-45C6-C1 */ .video_inputs = 4, /* id-inputs-clock */ .audio_inputs = 0, - .tuner = UNSET, .svhs = 3, .muxsel = { 3, 2, 0, 1 }, .pll = PLL_28, - .tuner_type = UNSET, + .tuner_type = TUNER_ABSENT, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, .no_msp34xx = 1, @@ -1825,11 +1742,10 @@ struct tvcard bttv_tvcards[] = { .name = "Osprey 100/150 (848)", /* 0x04-54C0-C1 & older boards */ .video_inputs = 3, .audio_inputs = 0, - .tuner = UNSET, .svhs = 2, .muxsel = { 2, 3, 1 }, .pll = PLL_28, - .tuner_type = UNSET, + .tuner_type = TUNER_ABSENT, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, .no_msp34xx = 1, @@ -1842,11 +1758,10 @@ struct tvcard bttv_tvcards[] = { .name = "Osprey 101 (848)", /* 0x05-40C0-C1 */ .video_inputs = 2, .audio_inputs = 0, - .tuner = UNSET, .svhs = 1, .muxsel = { 3, 1 }, .pll = PLL_28, - .tuner_type = UNSET, + .tuner_type = TUNER_ABSENT, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, .no_msp34xx = 1, @@ -1857,11 +1772,10 @@ struct tvcard bttv_tvcards[] = { .name = "Osprey 101/151", /* 0x1(4|5)-0004-C4 */ .video_inputs = 1, .audio_inputs = 0, - .tuner = UNSET, .svhs = UNSET, .muxsel = { 0 }, .pll = PLL_28, - .tuner_type = UNSET, + .tuner_type = TUNER_ABSENT, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, .no_msp34xx = 1, @@ -1872,11 +1786,10 @@ struct tvcard bttv_tvcards[] = { .name = "Osprey 101/151 w/ svid", /* 0x(16|17|20)-00C4-C1 */ .video_inputs = 2, .audio_inputs = 0, - .tuner = UNSET, .svhs = 1, .muxsel = { 0, 1 }, .pll = PLL_28, - .tuner_type = UNSET, + .tuner_type = TUNER_ABSENT, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, .no_msp34xx = 1, @@ -1887,11 +1800,10 @@ struct tvcard bttv_tvcards[] = { .name = "Osprey 200/201/250/251", /* 0x1(8|9|E|F)-0004-C4 */ .video_inputs = 1, .audio_inputs = 1, - .tuner = UNSET, .svhs = UNSET, .muxsel = { 0 }, .pll = PLL_28, - .tuner_type = UNSET, + .tuner_type = TUNER_ABSENT, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, .no_msp34xx = 1, @@ -1904,11 +1816,10 @@ struct tvcard bttv_tvcards[] = { .name = "Osprey 200/250", /* 0x1(A|B)-00C4-C1 */ .video_inputs = 2, .audio_inputs = 1, - .tuner = UNSET, .svhs = 1, .muxsel = { 0, 1 }, .pll = PLL_28, - .tuner_type = UNSET, + .tuner_type = TUNER_ABSENT, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, .no_msp34xx = 1, @@ -1919,11 +1830,10 @@ struct tvcard bttv_tvcards[] = { .name = "Osprey 210/220/230", /* 0x1(A|B)-04C0-C1 */ .video_inputs = 2, .audio_inputs = 1, - .tuner = UNSET, .svhs = 1, .muxsel = { 2, 3 }, .pll = PLL_28, - .tuner_type = UNSET, + .tuner_type = TUNER_ABSENT, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, .no_msp34xx = 1, @@ -1934,11 +1844,10 @@ struct tvcard bttv_tvcards[] = { .name = "Osprey 500", /* 500 */ .video_inputs = 2, .audio_inputs = 1, - .tuner = UNSET, .svhs = 1, .muxsel = { 2, 3 }, .pll = PLL_28, - .tuner_type = UNSET, + .tuner_type = TUNER_ABSENT, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, .no_msp34xx = 1, @@ -1949,9 +1858,8 @@ struct tvcard bttv_tvcards[] = { .name = "Osprey 540", /* 540 */ .video_inputs = 4, .audio_inputs = 1, - .tuner = UNSET, .pll = PLL_28, - .tuner_type = UNSET, + .tuner_type = TUNER_ABSENT, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, .no_msp34xx = 1, @@ -1964,11 +1872,10 @@ struct tvcard bttv_tvcards[] = { .name = "Osprey 2000", /* 2000 */ .video_inputs = 2, .audio_inputs = 1, - .tuner = UNSET, .svhs = 1, .muxsel = { 2, 3 }, .pll = PLL_28, - .tuner_type = UNSET, + .tuner_type = TUNER_ABSENT, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, .no_msp34xx = 1, @@ -1980,8 +1887,7 @@ struct tvcard bttv_tvcards[] = { .name = "IDS Eagle", .video_inputs = 4, .audio_inputs = 0, - .tuner = UNSET, - .tuner_type = UNSET, + .tuner_type = TUNER_ABSENT, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, .svhs = UNSET, @@ -1997,8 +1903,7 @@ struct tvcard bttv_tvcards[] = { .video_inputs = 2, .audio_inputs = 0, .svhs = 1, - .tuner = UNSET, - .tuner_type = UNSET, + .tuner_type = TUNER_ABSENT, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, .no_msp34xx = 1, @@ -2013,7 +1918,6 @@ struct tvcard bttv_tvcards[] = { .name = "Formac ProTV II (bt878)", .video_inputs = 4, .audio_inputs = 1, - .tuner = 0, .svhs = 3, .gpiomask = 2, /* TV, Comp1, Composite over SVID con, SVID */ @@ -2038,7 +1942,6 @@ struct tvcard bttv_tvcards[] = { .name = "MachTV", .video_inputs = 3, .audio_inputs = 1, - .tuner = 0, .svhs = UNSET, .gpiomask = 7, .muxsel = { 2, 3, 1, 1}, @@ -2054,7 +1957,6 @@ struct tvcard bttv_tvcards[] = { .name = "Euresys Picolo", .video_inputs = 3, .audio_inputs = 0, - .tuner = UNSET, .svhs = 2, .gpiomask = 0, .no_msp34xx = 1, @@ -2062,7 +1964,7 @@ struct tvcard bttv_tvcards[] = { .no_tda7432 = 1, .muxsel = { 2, 0, 1}, .pll = PLL_28, - .tuner_type = UNSET, + .tuner_type = TUNER_ABSENT, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, }, @@ -2071,7 +1973,6 @@ struct tvcard bttv_tvcards[] = { .name = "ProVideo PV150", /* 0x4f */ .video_inputs = 2, .audio_inputs = 0, - .tuner = UNSET, .svhs = UNSET, .gpiomask = 0, .muxsel = { 2, 3 }, @@ -2079,7 +1980,7 @@ struct tvcard bttv_tvcards[] = { .needs_tvaudio = 0, .no_msp34xx = 1, .pll = PLL_28, - .tuner_type = UNSET, + .tuner_type = TUNER_ABSENT, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, }, @@ -2089,7 +1990,6 @@ struct tvcard bttv_tvcards[] = { .name = "AD-TVK503", /* 0x63 */ .video_inputs = 4, .audio_inputs = 1, - .tuner = 0, .svhs = 2, .gpiomask = 0x001e8007, .muxsel = { 2, 3, 1, 0 }, @@ -2110,7 +2010,6 @@ struct tvcard bttv_tvcards[] = { .name = "Hercules Smart TV Stereo", .video_inputs = 4, .audio_inputs = 1, - .tuner = 0, .svhs = 2, .gpiomask = 0x00, .muxsel = { 2, 3, 1, 1 }, @@ -2134,7 +2033,6 @@ struct tvcard bttv_tvcards[] = { .name = "Pace TV & Radio Card", .video_inputs = 4, .audio_inputs = 1, - .tuner = 0, .svhs = 2, .muxsel = { 2, 3, 1, 1 }, /* Tuner, CVid, SVid, CVid over SVid connector */ .gpiomask = 0, @@ -2157,8 +2055,7 @@ struct tvcard bttv_tvcards[] = { .name = "IVC-200", .video_inputs = 1, .audio_inputs = 0, - .tuner = UNSET, - .tuner_type = UNSET, + .tuner_type = TUNER_ABSENT, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, .svhs = UNSET, @@ -2170,8 +2067,7 @@ struct tvcard bttv_tvcards[] = { .name = "IVCE-8784", .video_inputs = 1, .audio_inputs = 0, - .tuner = UNSET, - .tuner_type = UNSET, + .tuner_type = TUNER_ABSENT, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, .svhs = UNSET, @@ -2183,7 +2079,6 @@ struct tvcard bttv_tvcards[] = { .name = "Grand X-Guard / Trust 814PCI", .video_inputs = 16, .audio_inputs = 0, - .tuner = UNSET, .svhs = UNSET, .tuner_type = TUNER_ABSENT, .tuner_addr = ADDR_UNSET, @@ -2201,14 +2096,13 @@ struct tvcard bttv_tvcards[] = { [BTTV_BOARD_NEBULA_DIGITV] = { .name = "Nebula Electronics DigiTV", .video_inputs = 1, - .tuner = UNSET, .svhs = UNSET, .muxsel = { 2, 3, 1, 0 }, .no_msp34xx = 1, .no_tda9875 = 1, .no_tda7432 = 1, .pll = PLL_28, - .tuner_type = UNSET, + .tuner_type = TUNER_ABSENT, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, .has_dvb = 1, @@ -2221,7 +2115,6 @@ struct tvcard bttv_tvcards[] = { .name = "ProVideo PV143", .video_inputs = 4, .audio_inputs = 0, - .tuner = UNSET, .svhs = UNSET, .gpiomask = 0, .muxsel = { 2, 3, 1, 0 }, @@ -2229,7 +2122,7 @@ struct tvcard bttv_tvcards[] = { .needs_tvaudio = 0, .no_msp34xx = 1, .pll = PLL_28, - .tuner_type = UNSET, + .tuner_type = TUNER_ABSENT, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, }, @@ -2238,14 +2131,13 @@ struct tvcard bttv_tvcards[] = { .name = "PHYTEC VD-009-X1 VD-011 MiniDIN (bt878)", .video_inputs = 4, .audio_inputs = 0, - .tuner = UNSET, /* card has no tuner */ .svhs = 3, .gpiomask = 0x00, .muxsel = { 2, 3, 1, 0 }, .gpiomux = { 0, 0, 0, 0 }, /* card has no audio */ .needs_tvaudio = 0, .pll = PLL_28, - .tuner_type = UNSET, + .tuner_type = TUNER_ABSENT, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, }, @@ -2253,14 +2145,13 @@ struct tvcard bttv_tvcards[] = { .name = "PHYTEC VD-009-X1 VD-011 Combi (bt878)", .video_inputs = 4, .audio_inputs = 0, - .tuner = UNSET, /* card has no tuner */ .svhs = 3, .gpiomask = 0x00, .muxsel = { 2, 3, 1, 1 }, .gpiomux = { 0, 0, 0, 0 }, /* card has no audio */ .needs_tvaudio = 0, .pll = PLL_28, - .tuner_type = UNSET, + .tuner_type = TUNER_ABSENT, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, }, @@ -2270,7 +2161,6 @@ struct tvcard bttv_tvcards[] = { .name = "PHYTEC VD-009 MiniDIN (bt878)", .video_inputs = 10, .audio_inputs = 0, - .tuner = UNSET, /* card has no tuner */ .svhs = 9, .gpiomask = 0x00, .gpiomask2 = 0x03, /* gpiomask2 defines the bits used to switch audio @@ -2280,7 +2170,7 @@ struct tvcard bttv_tvcards[] = { .gpiomux = { 0, 0, 0, 0 }, /* card has no audio */ .needs_tvaudio = 1, .pll = PLL_28, - .tuner_type = UNSET, + .tuner_type = TUNER_ABSENT, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, }, @@ -2288,7 +2178,6 @@ struct tvcard bttv_tvcards[] = { .name = "PHYTEC VD-009 Combi (bt878)", .video_inputs = 10, .audio_inputs = 0, - .tuner = UNSET, /* card has no tuner */ .svhs = 9, .gpiomask = 0x00, .gpiomask2 = 0x03, /* gpiomask2 defines the bits used to switch audio @@ -2298,7 +2187,7 @@ struct tvcard bttv_tvcards[] = { .gpiomux = { 0, 0, 0, 0 }, /* card has no audio */ .needs_tvaudio = 1, .pll = PLL_28, - .tuner_type = UNSET, + .tuner_type = TUNER_ABSENT, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, }, @@ -2306,8 +2195,7 @@ struct tvcard bttv_tvcards[] = { .name = "IVC-100", .video_inputs = 4, .audio_inputs = 0, - .tuner = UNSET, - .tuner_type = UNSET, + .tuner_type = TUNER_ABSENT, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, .svhs = UNSET, @@ -2320,8 +2208,7 @@ struct tvcard bttv_tvcards[] = { .name = "IVC-120G", .video_inputs = 16, .audio_inputs = 0, /* card has no audio */ - .tuner = UNSET, /* card has no tuner */ - .tuner_type = UNSET, + .tuner_type = TUNER_ABSENT, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, .svhs = UNSET, /* card has no svhs */ @@ -2341,7 +2228,6 @@ struct tvcard bttv_tvcards[] = { .name = "pcHDTV HD-2000 TV", .video_inputs = 4, .audio_inputs = 1, - .tuner = 0, .svhs = 2, .muxsel = { 2, 3, 1, 0 }, .tuner_type = TUNER_PHILIPS_FCV1236D, @@ -2365,7 +2251,6 @@ struct tvcard bttv_tvcards[] = { .video_inputs = 3, .audio_inputs = 0, .svhs = 1, - .tuner = UNSET, .muxsel = { 3, 1, 1, 3 }, /* Vid In, SVid In, Vid over SVid in connector */ .no_msp34xx = 1, .no_tda9875 = 1, @@ -2379,7 +2264,6 @@ struct tvcard bttv_tvcards[] = { .name = "Teppro TEV-560/InterVision IV-560", .video_inputs = 3, .audio_inputs = 1, - .tuner = 0, .svhs = 2, .gpiomask = 3, .muxsel = { 2, 3, 1, 1 }, @@ -2396,9 +2280,8 @@ struct tvcard bttv_tvcards[] = { .name = "SIMUS GVC1100", .video_inputs = 4, .audio_inputs = 0, - .tuner = UNSET, .svhs = UNSET, - .tuner_type = UNSET, + .tuner_type = TUNER_ABSENT, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, .pll = PLL_28, @@ -2410,7 +2293,6 @@ struct tvcard bttv_tvcards[] = { /* Carlos Silva r3pek@r3pek.homelinux.org || card 0x75 */ .name = "NGS NGSTV+", .video_inputs = 3, - .tuner = 0, .svhs = 2, .gpiomask = 0x008007, .muxsel = { 2, 3, 0, 0 }, @@ -2427,14 +2309,13 @@ struct tvcard bttv_tvcards[] = { .name = "LMLBT4", .video_inputs = 4, /* IN1,IN2,IN3,IN4 */ .audio_inputs = 0, - .tuner = UNSET, .svhs = UNSET, .muxsel = { 2, 3, 1, 0 }, .no_msp34xx = 1, .no_tda9875 = 1, .no_tda7432 = 1, .needs_tvaudio = 0, - .tuner_type = UNSET, + .tuner_type = TUNER_ABSENT, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, }, @@ -2443,7 +2324,6 @@ struct tvcard bttv_tvcards[] = { .name = "Tekram M205 PRO", .video_inputs = 3, .audio_inputs = 1, - .tuner = 0, .tuner_type = TUNER_PHILIPS_PAL, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, @@ -2462,7 +2342,6 @@ struct tvcard bttv_tvcards[] = { .name = "Conceptronic CONTVFMi", .video_inputs = 3, .audio_inputs = 1, - .tuner = 0, .svhs = 2, .gpiomask = 0x008007, .muxsel = { 2, 3, 1, 1 }, @@ -2484,7 +2363,6 @@ struct tvcard bttv_tvcards[] = { .name = "Euresys Picolo Tetra", .video_inputs = 4, .audio_inputs = 0, - .tuner = UNSET, .svhs = UNSET, .gpiomask = 0, .gpiomask2 = 0x3C<<16,/*Set the GPIO[18]->GPIO[21] as output pin.==> drive the video inputs through analog multiplexers*/ @@ -2496,7 +2374,7 @@ struct tvcard bttv_tvcards[] = { .pll = PLL_28, .needs_tvaudio = 0, .muxsel_hook = picolo_tetra_muxsel,/*Required as it doesn't follow the classic input selection policy*/ - .tuner_type = UNSET, + .tuner_type = TUNER_ABSENT, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, }, @@ -2506,7 +2384,6 @@ struct tvcard bttv_tvcards[] = { .name = "Spirit TV Tuner", .video_inputs = 3, .audio_inputs = 1, - .tuner = 0, .svhs = 2, .gpiomask = 0x0000000f, .muxsel = { 2, 1, 1 }, @@ -2522,7 +2399,6 @@ struct tvcard bttv_tvcards[] = { .name = "AVerMedia AVerTV DVB-T 771", .video_inputs = 2, .svhs = 1, - .tuner = UNSET, .tuner_type = TUNER_ABSENT, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, @@ -2541,14 +2417,13 @@ struct tvcard bttv_tvcards[] = { /* Based on the Nebula card data - added remote and new card number - BTTV_BOARD_AVDVBT_761, see also ir-kbd-gpio.c */ .name = "AverMedia AverTV DVB-T 761", .video_inputs = 2, - .tuner = UNSET, .svhs = 1, .muxsel = { 3, 1, 2, 0 }, /* Comp0, S-Video, ?, ? */ .no_msp34xx = 1, .no_tda9875 = 1, .no_tda7432 = 1, .pll = PLL_28, - .tuner_type = UNSET, + .tuner_type = TUNER_ABSENT, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, .has_dvb = 1, @@ -2560,7 +2435,6 @@ struct tvcard bttv_tvcards[] = { .name = "MATRIX Vision Sigma-SQ", .video_inputs = 16, .audio_inputs = 0, - .tuner = UNSET, .svhs = UNSET, .gpiomask = 0x0, .muxsel = { 2, 2, 2, 2, 2, 2, 2, 2, @@ -2569,7 +2443,7 @@ struct tvcard bttv_tvcards[] = { .gpiomux = { 0 }, .no_msp34xx = 1, .pll = PLL_28, - .tuner_type = UNSET, + .tuner_type = TUNER_ABSENT, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, }, @@ -2578,7 +2452,6 @@ struct tvcard bttv_tvcards[] = { .name = "MATRIX Vision Sigma-SLC", .video_inputs = 4, .audio_inputs = 0, - .tuner = UNSET, .svhs = UNSET, .gpiomask = 0x0, .muxsel = { 2, 2, 2, 2 }, @@ -2586,7 +2459,7 @@ struct tvcard bttv_tvcards[] = { .gpiomux = { 0 }, .no_msp34xx = 1, .pll = PLL_28, - .tuner_type = UNSET, + .tuner_type = TUNER_ABSENT, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, }, @@ -2597,7 +2470,6 @@ struct tvcard bttv_tvcards[] = { .name = "APAC Viewcomp 878(AMAX)", .video_inputs = 2, .audio_inputs = 1, - .tuner = 0, .svhs = UNSET, .gpiomask = 0xFF, .muxsel = { 2, 3, 1, 1 }, @@ -2616,14 +2488,13 @@ struct tvcard bttv_tvcards[] = { [BTTV_BOARD_DVICO_DVBT_LITE] = { /* Chris Pascoe */ .name = "DViCO FusionHDTV DVB-T Lite", - .tuner = UNSET, .no_msp34xx = 1, .no_tda9875 = 1, .no_tda7432 = 1, .pll = PLL_28, .no_video = 1, .has_dvb = 1, - .tuner_type = UNSET, + .tuner_type = TUNER_ABSENT, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, }, @@ -2632,7 +2503,6 @@ struct tvcard bttv_tvcards[] = { .name = "V-Gear MyVCD", .video_inputs = 3, .audio_inputs = 1, - .tuner = 0, .svhs = 2, .gpiomask = 0x3f, .muxsel = {2, 3, 1, 0 }, @@ -2650,7 +2520,6 @@ struct tvcard bttv_tvcards[] = { .name = "Super TV Tuner", .video_inputs = 4, .audio_inputs = 1, - .tuner = 0, .svhs = 2, .muxsel = { 2, 3, 1, 0 }, .tuner_type = TUNER_PHILIPS_NTSC, @@ -2666,14 +2535,13 @@ struct tvcard bttv_tvcards[] = { .name = "Tibet Systems 'Progress DVR' CS16", .video_inputs = 16, .audio_inputs = 0, - .tuner = UNSET, .svhs = UNSET, .muxsel = { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 }, .pll = PLL_28, .no_msp34xx = 1, .no_tda9875 = 1, .no_tda7432 = 1, - .tuner_type = UNSET, + .tuner_type = TUNER_ABSENT, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, .muxsel_hook = tibetCS16_muxsel, @@ -2693,8 +2561,7 @@ struct tvcard bttv_tvcards[] = { .name = "Kodicom 4400R (master)", .video_inputs = 16, .audio_inputs = 0, - .tuner = UNSET, - .tuner_type = UNSET, + .tuner_type = TUNER_ABSENT, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, .svhs = UNSET, @@ -2725,8 +2592,7 @@ struct tvcard bttv_tvcards[] = { .name = "Kodicom 4400R (slave)", .video_inputs = 16, .audio_inputs = 0, - .tuner = UNSET, - .tuner_type = UNSET, + .tuner_type = TUNER_ABSENT, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, .svhs = UNSET, @@ -2746,7 +2612,6 @@ struct tvcard bttv_tvcards[] = { .name = "Adlink RTV24", .video_inputs = 4, .audio_inputs = 1, - .tuner = 0, .svhs = 2, .muxsel = { 2, 3, 1, 0 }, .tuner_type = UNSET, @@ -2758,7 +2623,6 @@ struct tvcard bttv_tvcards[] = { [BTTV_BOARD_DVICO_FUSIONHDTV_5_LITE] = { /* Michael Krufky */ .name = "DViCO FusionHDTV 5 Lite", - .tuner = 0, .tuner_type = TUNER_LG_TDVS_H06XF, /* TDVS-H064F */ .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, @@ -2780,7 +2644,6 @@ struct tvcard bttv_tvcards[] = { .name = "Acorp Y878F", .video_inputs = 3, .audio_inputs = 1, - .tuner = 0, .svhs = 2, .gpiomask = 0x01fe00, .muxsel = { 2, 3, 1, 1 }, @@ -2798,7 +2661,6 @@ struct tvcard bttv_tvcards[] = { .name = "Conceptronic CTVFMi v2", .video_inputs = 3, .audio_inputs = 1, - .tuner = 0, .svhs = 2, .gpiomask = 0x001c0007, .muxsel = { 2, 3, 1, 1 }, @@ -2817,7 +2679,6 @@ struct tvcard bttv_tvcards[] = { .name = "Prolink Pixelview PV-BT878P+ (Rev.2E)", .video_inputs = 5, .audio_inputs = 1, - .tuner = 0, .svhs = 3, .gpiomask = 0x01fe00, .muxsel = { 2,3,1,1,-1 }, @@ -2837,7 +2698,6 @@ struct tvcard bttv_tvcards[] = { .name = "Prolink PixelView PlayTV MPEG2 PV-M4900", .video_inputs = 3, .audio_inputs = 1, - .tuner = 0, .svhs = 2, .gpiomask = 0x3f, .muxsel = { 2, 3, 1, 1 }, @@ -2868,14 +2728,13 @@ struct tvcard bttv_tvcards[] = { .name = "Osprey 440", .video_inputs = 4, .audio_inputs = 2, /* this is meaningless */ - .tuner = UNSET, .svhs = UNSET, .muxsel = { 2, 3, 0, 1 }, /* 3,0,1 are guesses */ .gpiomask = 0x303, .gpiomute = 0x000, /* int + 32kHz */ .gpiomux = { 0, 0, 0x000, 0x100}, .pll = PLL_28, - .tuner_type = UNSET, + .tuner_type = TUNER_ABSENT, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, .no_msp34xx = 1, @@ -2887,7 +2746,6 @@ struct tvcard bttv_tvcards[] = { .name = "Asound Skyeye PCTV", .video_inputs = 3, .audio_inputs = 1, - .tuner = 0, .svhs = 2, .gpiomask = 15, .muxsel = { 2, 3, 1, 1 }, @@ -2904,7 +2762,6 @@ struct tvcard bttv_tvcards[] = { .name = "Sabrent TV-FM (bttv version)", .video_inputs = 3, .audio_inputs = 1, - .tuner = 0, .svhs = 2, .gpiomask = 0x108007, .muxsel = { 2, 3, 1, 1 }, @@ -2922,14 +2779,13 @@ struct tvcard bttv_tvcards[] = { .name = "Hauppauge ImpactVCB (bt878)", .video_inputs = 4, .audio_inputs = 0, - .tuner = UNSET, .svhs = UNSET, .gpiomask = 0x0f, /* old: 7 */ .muxsel = { 0, 1, 3, 2 }, /* Composite 0-3 */ .no_msp34xx = 1, .no_tda9875 = 1, .no_tda7432 = 1, - .tuner_type = UNSET, + .tuner_type = TUNER_ABSENT, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, }, @@ -2944,7 +2800,6 @@ struct tvcard bttv_tvcards[] = { .name = "MagicTV", /* rebranded MachTV */ .video_inputs = 3, .audio_inputs = 1, - .tuner = 0, .svhs = 2, .gpiomask = 7, .muxsel = { 2, 3, 1, 1 }, @@ -2961,10 +2816,9 @@ struct tvcard bttv_tvcards[] = { .name = "SSAI Security Video Interface", .video_inputs = 4, .audio_inputs = 0, - .tuner = UNSET, .svhs = UNSET, .muxsel = { 0, 1, 2, 3 }, - .tuner_type = UNSET, + .tuner_type = TUNER_ABSENT, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, }, @@ -2972,17 +2826,15 @@ struct tvcard bttv_tvcards[] = { .name = "SSAI Ultrasound Video Interface", .video_inputs = 2, .audio_inputs = 0, - .tuner = UNSET, .svhs = 1, .muxsel = { 2, 0, 1, 3 }, - .tuner_type = UNSET, + .tuner_type = TUNER_ABSENT, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, }, /* ---- card 0x94---------------------------------- */ [BTTV_BOARD_DVICO_FUSIONHDTV_2] = { .name = "DViCO FusionHDTV 2", - .tuner = 0, .tuner_type = TUNER_PHILIPS_FCV1236D, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, @@ -3002,7 +2854,6 @@ struct tvcard bttv_tvcards[] = { .name = "Typhoon TV-Tuner PCI (50684)", .video_inputs = 3, .audio_inputs = 1, - .tuner = 0, .svhs = 2, .gpiomask = 0x3014f, .muxsel = { 2, 3, 1, 1 }, @@ -3019,7 +2870,6 @@ struct tvcard bttv_tvcards[] = { .name = "Geovision GV-600", .video_inputs = 16, .audio_inputs = 0, - .tuner = UNSET, .svhs = UNSET, .gpiomask = 0x0, .muxsel = { 2, 2, 2, 2, 2, 2, 2, 2, @@ -3028,7 +2878,7 @@ struct tvcard bttv_tvcards[] = { .gpiomux = { 0 }, .no_msp34xx = 1, .pll = PLL_28, - .tuner_type = UNSET, + .tuner_type = TUNER_ABSENT, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, }, @@ -3039,7 +2889,6 @@ struct tvcard bttv_tvcards[] = { .name = "Kozumi KTV-01C", .video_inputs = 3, .audio_inputs = 1, - .tuner = 0, .svhs = 2, .gpiomask = 0x008007, .muxsel = { 2, 3, 1, 1 }, @@ -3059,7 +2908,6 @@ struct tvcard bttv_tvcards[] = { .name = "Encore ENL TV-FM-2", .video_inputs = 3, .audio_inputs = 1, - .tuner = 0, .svhs = 2, /* bit 6 -> IR disabled bit 18/17 = 00 -> mute @@ -3083,14 +2931,13 @@ struct tvcard bttv_tvcards[] = { .name = "PHYTEC VD-012 (bt878)", .video_inputs = 4, .audio_inputs = 0, - .tuner = UNSET, /* card has no tuner */ .svhs = UNSET, /* card has no s-video */ .gpiomask = 0x00, .muxsel = { 0, 2, 3, 1 }, .gpiomux = { 0, 0, 0, 0 }, /* card has no audio */ .needs_tvaudio = 0, .pll = PLL_28, - .tuner_type = UNSET, + .tuner_type = TUNER_ABSENT, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, }, @@ -3099,14 +2946,13 @@ struct tvcard bttv_tvcards[] = { .name = "PHYTEC VD-012-X1 (bt878)", .video_inputs = 4, .audio_inputs = 0, - .tuner = UNSET, /* card has no tuner */ .svhs = 3, .gpiomask = 0x00, .muxsel = { 2, 3, 1 }, .gpiomux = { 0, 0, 0, 0 }, /* card has no audio */ .needs_tvaudio = 0, .pll = PLL_28, - .tuner_type = UNSET, + .tuner_type = TUNER_ABSENT, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, }, @@ -3115,14 +2961,13 @@ struct tvcard bttv_tvcards[] = { .name = "PHYTEC VD-012-X2 (bt878)", .video_inputs = 4, .audio_inputs = 0, - .tuner = UNSET, /* card has no tuner */ .svhs = 3, .gpiomask = 0x00, .muxsel = { 3, 2, 1 }, .gpiomux = { 0, 0, 0, 0 }, /* card has no audio */ .needs_tvaudio = 0, .pll = PLL_28, - .tuner_type = UNSET, + .tuner_type = TUNER_ABSENT, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, } @@ -3687,13 +3532,12 @@ void __devinit bttv_init_card2(struct bttv *btv) addr = bttv_tvcards[btv->c.type].tuner_addr; if (UNSET != bttv_tvcards[btv->c.type].tuner_type) - if(UNSET == btv->tuner_type) + if (UNSET == btv->tuner_type) btv->tuner_type = bttv_tvcards[btv->c.type].tuner_type; if (UNSET != tuner[btv->c.nr]) btv->tuner_type = tuner[btv->c.nr]; - if (btv->tuner_type == TUNER_ABSENT || - bttv_tvcards[btv->c.type].tuner == UNSET) + if (btv->tuner_type == TUNER_ABSENT) printk(KERN_INFO "bttv%d: tuner absent\n", btv->c.nr); else if(btv->tuner_type == UNSET) printk(KERN_WARNING "bttv%d: tuner type unset\n", btv->c.nr); @@ -3701,13 +3545,23 @@ void __devinit bttv_init_card2(struct bttv *btv) printk(KERN_INFO "bttv%d: tuner type=%d\n", btv->c.nr, btv->tuner_type); - if (btv->tuner_type != UNSET) { + if (UNSET == btv->tuner_type) + btv->tuner_type = TUNER_ABSENT; + + if (btv->tuner_type != TUNER_ABSENT) { struct tuner_setup tun_setup; + /* Load tuner module before issuing tuner config call! */ + if (autoload) + request_module("tuner"); + tun_setup.mode_mask = T_ANALOG_TV | T_DIGITAL_TV; tun_setup.type = btv->tuner_type; tun_setup.addr = addr; + if (bttv_tvcards[btv->c.type].has_radio) + tun_setup.mode_mask |= T_RADIO; + bttv_call_i2c_clients(btv, TUNER_SET_TYPE_ADDR, &tun_setup); } @@ -3740,7 +3594,7 @@ void __devinit bttv_init_card2(struct bttv *btv) if (!autoload) return; - if (bttv_tvcards[btv->c.type].tuner == UNSET) + if (btv->tuner_type == TUNER_ABSENT) return; /* no tuner or related drivers to load */ /* try to detect audio/fader chips */ @@ -3762,9 +3616,6 @@ void __devinit bttv_init_card2(struct bttv *btv) if (bttv_tvcards[btv->c.type].needs_tvaudio) request_module("tvaudio"); - - if (btv->tuner_type != UNSET && btv->tuner_type != TUNER_ABSENT) - request_module("tuner"); } diff --git a/drivers/media/video/bt8xx/bttv-driver.c b/drivers/media/video/bt8xx/bttv-driver.c index 89e0cd191531..1bb6c2df366a 100644 --- a/drivers/media/video/bt8xx/bttv-driver.c +++ b/drivers/media/video/bt8xx/bttv-driver.c @@ -1356,8 +1356,8 @@ set_input(struct bttv *btv, unsigned int input, unsigned int norm) } else { video_mux(btv,input); } - audio_input(btv,(input == bttv_tvcards[btv->c.type].tuner ? - TVAUDIO_INPUT_TUNER : TVAUDIO_INPUT_EXTERN)); + audio_input(btv, (btv->tuner_type != TUNER_ABSENT && input == 0) ? + TVAUDIO_INPUT_TUNER : TVAUDIO_INPUT_EXTERN); set_tvnorm(btv, norm); } @@ -1907,7 +1907,7 @@ static int bttv_enum_input(struct file *file, void *priv, i->type = V4L2_INPUT_TYPE_CAMERA; i->audioset = 1; - if (i->index == bttv_tvcards[btv->c.type].tuner) { + if (btv->tuner_type != TUNER_ABSENT && i->index == 0) { sprintf(i->name, "Television"); i->type = V4L2_INPUT_TYPE_TUNER; i->tuner = 0; @@ -1971,7 +1971,7 @@ static int bttv_s_tuner(struct file *file, void *priv, if (0 != err) return err; - if (UNSET == bttv_tvcards[btv->c.type].tuner) + if (btv->tuner_type == TUNER_ABSENT) return -EINVAL; if (0 != t->index) @@ -2665,8 +2665,7 @@ static int bttv_querycap(struct file *file, void *priv, if (no_overlay <= 0) cap->capabilities |= V4L2_CAP_VIDEO_OVERLAY; - if (bttv_tvcards[btv->c.type].tuner != UNSET && - bttv_tvcards[btv->c.type].tuner != TUNER_ABSENT) + if (btv->tuner_type != TUNER_ABSENT) cap->capabilities |= V4L2_CAP_TUNER; return 0; } @@ -2949,7 +2948,7 @@ static int bttv_g_tuner(struct file *file, void *priv, struct bttv_fh *fh = priv; struct bttv *btv = fh->btv; - if (UNSET == bttv_tvcards[btv->c.type].tuner) + if (btv->tuner_type == TUNER_ABSENT) return -EINVAL; if (0 != t->index) return -EINVAL; @@ -3509,7 +3508,7 @@ static int radio_g_tuner(struct file *file, void *priv, struct v4l2_tuner *t) struct bttv_fh *fh = priv; struct bttv *btv = fh->btv; - if (UNSET == bttv_tvcards[btv->c.type].tuner) + if (btv->tuner_type == TUNER_ABSENT) return -EINVAL; if (0 != t->index) return -EINVAL; diff --git a/drivers/media/video/bt8xx/bttv-i2c.c b/drivers/media/video/bt8xx/bttv-i2c.c index bcd2cd240a16..511d2bf176f1 100644 --- a/drivers/media/video/bt8xx/bttv-i2c.c +++ b/drivers/media/video/bt8xx/bttv-i2c.c @@ -286,12 +286,10 @@ static int attach_inform(struct i2c_client *client) btv->i2c_msp34xx_client = client; if (client->driver->id == I2C_DRIVERID_TVAUDIO) btv->i2c_tvaudio_client = client; - if (btv->tuner_type != UNSET) { + if (btv->tuner_type != TUNER_ABSENT) { struct tuner_setup tun_setup; - if ((addr==ADDR_UNSET) || - (addr==client->addr)) { - + if (addr == ADDR_UNSET || addr == client->addr) { tun_setup.mode_mask = T_ANALOG_TV | T_DIGITAL_TV | T_RADIO; tun_setup.type = btv->tuner_type; tun_setup.addr = addr; diff --git a/drivers/media/video/bt8xx/bttv.h b/drivers/media/video/bt8xx/bttv.h index 6bf2fa03a585..861ff2f8f985 100644 --- a/drivers/media/video/bt8xx/bttv.h +++ b/drivers/media/video/bt8xx/bttv.h @@ -216,7 +216,6 @@ struct tvcard char *name; unsigned int video_inputs; unsigned int audio_inputs; - unsigned int tuner; unsigned int svhs; unsigned int digital_mode; // DIGITAL_MODE_CAMERA or DIGITAL_MODE_VIDEO u32 gpiomask; -- cgit v1.2.3 From 4c548d4b28c0c65938914b2790fd2ca2e9c61d63 Mon Sep 17 00:00:00 2001 From: Trent Piepho Date: Wed, 28 Jan 2009 21:32:59 -0300 Subject: V4L/DVB (10561): bttv: store card database more efficiently The bttv card database is quite large and the data structure used to store it wasn't very efficient. Most of the field are only used at card initialization time so it doesn't matter if they aren't efficient to access. Overall the changes reduce code size by 60 bytes in ia32. The data size is decreased by 5024 byes. It is probably even more for 64-bit kernels. Move the fields in the struct around to be sorted from largest to smallest. This saves on padding space used for alignment. Get rid of the unused digital_mode field. Leave the setting as a comment in the few cards entries that set it, in case someone ever writes the code. Get rid of the unused audio_inputs field. Leave the values in the card entries in case someone ever writes code that might use it. Get ride of the unused radio_addr field. No card entries even set it to anything interesting so it's not left as comments. All the code that used it was removed in commit v2.6.14-3466-g291d1d7 from Nov 8th 2005. Reduce video_inputs to u8 as no card has more than 255 inputs (the most is 16). Change tuner_addr to u8. I2C addresses are only seven bits and 255 means ADDR_UNSET, so everything fits. Make has_radio a one bit flag. Make the pll setting a two bit field. Reduce svhs to four bits as no card has an s-video input above 9. Change the value for no s-video input from UNSET (which is -1U and out of range of four bits) to NO_SVHS (which is now 15). Signed-off-by: Trent Piepho Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/bt8xx/bttv-cards.c | 626 +++++++++++++-------------------- drivers/media/video/bt8xx/bttv.h | 40 +-- 2 files changed, 249 insertions(+), 417 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/bt8xx/bttv-cards.c b/drivers/media/video/bt8xx/bttv-cards.c index edf8d2505f0b..f49e6e686628 100644 --- a/drivers/media/video/bt8xx/bttv-cards.c +++ b/drivers/media/video/bt8xx/bttv-cards.c @@ -320,17 +320,15 @@ struct tvcard bttv_tvcards[] = { [BTTV_BOARD_UNKNOWN] = { .name = " *** UNKNOWN/GENERIC *** ", .video_inputs = 4, - .audio_inputs = 1, .svhs = 2, .muxsel = { 2, 3, 1, 0 }, .tuner_type = UNSET, .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, }, [BTTV_BOARD_MIRO] = { .name = "MIRO PCTV", .video_inputs = 4, - .audio_inputs = 1, + /* .audio_inputs= 1, */ .svhs = 2, .gpiomask = 15, .muxsel = { 2, 3, 1, 1 }, @@ -339,12 +337,11 @@ struct tvcard bttv_tvcards[] = { .needs_tvaudio = 1, .tuner_type = UNSET, .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, }, [BTTV_BOARD_HAUPPAUGE] = { .name = "Hauppauge (bt848)", .video_inputs = 4, - .audio_inputs = 1, + /* .audio_inputs= 1, */ .svhs = 2, .gpiomask = 7, .muxsel = { 2, 3, 1, 1 }, @@ -353,12 +350,11 @@ struct tvcard bttv_tvcards[] = { .needs_tvaudio = 1, .tuner_type = UNSET, .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, }, [BTTV_BOARD_STB] = { .name = "STB, Gateway P/N 6000699 (bt848)", .video_inputs = 3, - .audio_inputs = 1, + /* .audio_inputs= 1, */ .svhs = 2, .gpiomask = 7, .muxsel = { 2, 3, 1, 1 }, @@ -368,7 +364,6 @@ struct tvcard bttv_tvcards[] = { .needs_tvaudio = 1, .tuner_type = TUNER_PHILIPS_NTSC, .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, .pll = PLL_28, .has_radio = 1, }, @@ -377,7 +372,7 @@ struct tvcard bttv_tvcards[] = { [BTTV_BOARD_INTEL] = { .name = "Intel Create and Share PCI/ Smart Video Recorder III", .video_inputs = 4, - .audio_inputs = 0, + /* .audio_inputs= 0, */ .svhs = 2, .gpiomask = 0, .muxsel = { 2, 3, 1, 1 }, @@ -385,12 +380,11 @@ struct tvcard bttv_tvcards[] = { .needs_tvaudio = 0, .tuner_type = TUNER_ABSENT, .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, }, [BTTV_BOARD_DIAMOND] = { .name = "Diamond DTV2000", .video_inputs = 4, - .audio_inputs = 1, + /* .audio_inputs= 1, */ .svhs = 2, .gpiomask = 3, .muxsel = { 2, 3, 1, 0 }, @@ -399,12 +393,11 @@ struct tvcard bttv_tvcards[] = { .needs_tvaudio = 1, .tuner_type = UNSET, .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, }, [BTTV_BOARD_AVERMEDIA] = { .name = "AVerMedia TVPhone", .video_inputs = 3, - .audio_inputs = 1, + /* .audio_inputs= 1, */ .svhs = 3, .muxsel = { 2, 3, 1, 1 }, .gpiomask = 0x0f, @@ -413,14 +406,13 @@ struct tvcard bttv_tvcards[] = { .needs_tvaudio = 1, .tuner_type = UNSET, .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, .audio_mode_gpio= avermedia_tvphone_audio, .has_remote = 1, }, [BTTV_BOARD_MATRIX_VISION] = { .name = "MATRIX-Vision MV-Delta", .video_inputs = 5, - .audio_inputs = 1, + /* .audio_inputs= 1, */ .svhs = 3, .gpiomask = 0, .muxsel = { 2, 3, 1, 0, 0 }, @@ -428,14 +420,13 @@ struct tvcard bttv_tvcards[] = { .needs_tvaudio = 1, .tuner_type = TUNER_ABSENT, .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, }, /* ---- card 0x08 ---------------------------------- */ [BTTV_BOARD_FLYVIDEO] = { .name = "Lifeview FlyVideo II (Bt848) LR26 / MAXI TV Video PCI2 LR26", .video_inputs = 4, - .audio_inputs = 1, + /* .audio_inputs= 1, */ .svhs = 2, .gpiomask = 0xc00, .muxsel = { 2, 3, 1, 1 }, @@ -445,12 +436,11 @@ struct tvcard bttv_tvcards[] = { .pll = PLL_28, .tuner_type = UNSET, .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, }, [BTTV_BOARD_TURBOTV] = { .name = "IMS/IXmicro TurboTV", .video_inputs = 3, - .audio_inputs = 1, + /* .audio_inputs= 1, */ .svhs = 2, .gpiomask = 3, .muxsel = { 2, 3, 1, 1 }, @@ -459,12 +449,11 @@ struct tvcard bttv_tvcards[] = { .pll = PLL_28, .tuner_type = TUNER_TEMIC_PAL, .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, }, [BTTV_BOARD_HAUPPAUGE878] = { .name = "Hauppauge (bt878)", .video_inputs = 4, - .audio_inputs = 1, + /* .audio_inputs= 1, */ .svhs = 2, .gpiomask = 0x0f, /* old: 7 */ .muxsel = { 2, 0, 1, 1 }, @@ -474,12 +463,11 @@ struct tvcard bttv_tvcards[] = { .pll = PLL_28, .tuner_type = UNSET, .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, }, [BTTV_BOARD_MIROPRO] = { .name = "MIRO PCTV pro", .video_inputs = 3, - .audio_inputs = 1, + /* .audio_inputs= 1, */ .svhs = 2, .gpiomask = 0x3014f, .muxsel = { 2, 3, 1, 1 }, @@ -488,14 +476,13 @@ struct tvcard bttv_tvcards[] = { .needs_tvaudio = 1, .tuner_type = UNSET, .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, }, /* ---- card 0x0c ---------------------------------- */ [BTTV_BOARD_ADSTECH_TV] = { .name = "ADS Technologies Channel Surfer TV (bt848)", .video_inputs = 3, - .audio_inputs = 1, + /* .audio_inputs= 1, */ .svhs = 2, .gpiomask = 15, .muxsel = { 2, 3, 1, 1 }, @@ -503,12 +490,11 @@ struct tvcard bttv_tvcards[] = { .needs_tvaudio = 1, .tuner_type = UNSET, .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, }, [BTTV_BOARD_AVERMEDIA98] = { .name = "AVerMedia TVCapture 98", .video_inputs = 3, - .audio_inputs = 4, + /* .audio_inputs= 4, */ .svhs = 2, .gpiomask = 15, .muxsel = { 2, 3, 1, 1 }, @@ -518,14 +504,13 @@ struct tvcard bttv_tvcards[] = { .pll = PLL_28, .tuner_type = TUNER_PHILIPS_PAL, .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, .audio_mode_gpio= avermedia_tv_stereo_audio, .no_gpioirq = 1, }, [BTTV_BOARD_VHX] = { .name = "Aimslab Video Highway Xtreme (VHX)", .video_inputs = 3, - .audio_inputs = 1, + /* .audio_inputs= 1, */ .svhs = 2, .gpiomask = 7, .muxsel = { 2, 3, 1, 1 }, @@ -535,12 +520,11 @@ struct tvcard bttv_tvcards[] = { .pll = PLL_28, .tuner_type = UNSET, .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, }, [BTTV_BOARD_ZOLTRIX] = { .name = "Zoltrix TV-Max", .video_inputs = 3, - .audio_inputs = 1, + /* .audio_inputs= 1, */ .svhs = 2, .gpiomask = 15, .muxsel = { 2, 3, 1, 1 }, @@ -549,14 +533,13 @@ struct tvcard bttv_tvcards[] = { .needs_tvaudio = 1, .tuner_type = UNSET, .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, }, /* ---- card 0x10 ---------------------------------- */ [BTTV_BOARD_PIXVIEWPLAYTV] = { .name = "Prolink Pixelview PlayTV (bt878)", .video_inputs = 3, - .audio_inputs = 1, + /* .audio_inputs= 1, */ .svhs = 2, .gpiomask = 0x01fe00, .muxsel = { 2, 3, 1, 1 }, @@ -567,12 +550,11 @@ struct tvcard bttv_tvcards[] = { .pll = PLL_28, .tuner_type = UNSET, .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, }, [BTTV_BOARD_WINVIEW_601] = { .name = "Leadtek WinView 601", .video_inputs = 3, - .audio_inputs = 1, + /* .audio_inputs= 1, */ .svhs = 2, .gpiomask = 0x8300f8, .muxsel = { 2, 3, 1, 1,0 }, @@ -581,14 +563,13 @@ struct tvcard bttv_tvcards[] = { .needs_tvaudio = 1, .tuner_type = UNSET, .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, .volume_gpio = winview_volume, .has_radio = 1, }, [BTTV_BOARD_AVEC_INTERCAP] = { .name = "AVEC Intercapture", .video_inputs = 3, - .audio_inputs = 2, + /* .audio_inputs= 2, */ .svhs = 2, .gpiomask = 0, .muxsel = { 2, 3, 1, 1 }, @@ -596,37 +577,34 @@ struct tvcard bttv_tvcards[] = { .needs_tvaudio = 1, .tuner_type = UNSET, .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, }, [BTTV_BOARD_LIFE_FLYKIT] = { .name = "Lifeview FlyVideo II EZ /FlyKit LR38 Bt848 (capture only)", .video_inputs = 4, - .audio_inputs = 1, - .svhs = UNSET, + /* .audio_inputs= 1, */ + .svhs = NO_SVHS, .gpiomask = 0x8dff00, .muxsel = { 2, 3, 1, 1 }, .gpiomux = { 0 }, .no_msp34xx = 1, .tuner_type = TUNER_ABSENT, .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, }, /* ---- card 0x14 ---------------------------------- */ [BTTV_BOARD_CEI_RAFFLES] = { .name = "CEI Raffles Card", .video_inputs = 3, - .audio_inputs = 3, + /* .audio_inputs= 3, */ .svhs = 2, .muxsel = { 2, 3, 1, 1 }, .tuner_type = UNSET, .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, }, [BTTV_BOARD_CONFERENCETV] = { .name = "Lifeview FlyVideo 98/ Lucky Star Image World ConferenceTV LR50", .video_inputs = 4, - .audio_inputs = 2, /* tuner, line in */ + /* .audio_inputs= 2, tuner, line in */ .svhs = 2, .gpiomask = 0x1800, .muxsel = { 2, 3, 1, 1 }, @@ -635,12 +613,11 @@ struct tvcard bttv_tvcards[] = { .pll = PLL_28, .tuner_type = TUNER_PHILIPS_PAL_I, .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, }, [BTTV_BOARD_PHOEBE_TVMAS] = { .name = "Askey CPH050/ Phoebe Tv Master + FM", .video_inputs = 3, - .audio_inputs = 1, + /* .audio_inputs= 1, */ .svhs = 2, .gpiomask = 0xc00, .muxsel = { 2, 3, 1, 1 }, @@ -650,29 +627,27 @@ struct tvcard bttv_tvcards[] = { .pll = PLL_28, .tuner_type = UNSET, .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, }, [BTTV_BOARD_MODTEC_205] = { .name = "Modular Technology MM201/MM202/MM205/MM210/MM215 PCTV, bt878", .video_inputs = 3, - .audio_inputs = 1, - .svhs = UNSET, + /* .audio_inputs= 1, */ + .svhs = NO_SVHS, .gpiomask = 7, .muxsel = { 2, 3, -1 }, - .digital_mode = DIGITAL_MODE_CAMERA, + /* .digital_mode= DIGITAL_MODE_CAMERA, */ .gpiomux = { 0, 0, 0, 0 }, .no_msp34xx = 1, .pll = PLL_28, .tuner_type = TUNER_ALPS_TSBB5_PAL_I, .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, }, /* ---- card 0x18 ---------------------------------- */ [BTTV_BOARD_MAGICTVIEW061] = { .name = "Askey CPH05X/06X (bt878) [many vendors]", .video_inputs = 3, - .audio_inputs = 1, + /* .audio_inputs= 1, */ .svhs = 2, .gpiomask = 0xe00, .muxsel = { 2, 3, 1, 1 }, @@ -682,13 +657,12 @@ struct tvcard bttv_tvcards[] = { .pll = PLL_28, .tuner_type = UNSET, .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, .has_remote = 1, }, [BTTV_BOARD_VOBIS_BOOSTAR] = { .name = "Terratec TerraTV+ Version 1.0 (Bt848)/ Terra TValue Version 1.0/ Vobis TV-Boostar", .video_inputs = 3, - .audio_inputs = 1, + /* .audio_inputs= 1, */ .svhs = 2, .gpiomask = 0x1f0fff, .muxsel = { 2, 3, 1, 1 }, @@ -697,13 +671,12 @@ struct tvcard bttv_tvcards[] = { .needs_tvaudio = 0, .tuner_type = TUNER_PHILIPS_PAL, .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, .audio_mode_gpio= terratv_audio, }, [BTTV_BOARD_HAUPPAUG_WCAM] = { .name = "Hauppauge WinCam newer (bt878)", .video_inputs = 4, - .audio_inputs = 1, + /* .audio_inputs= 1, */ .svhs = 3, .gpiomask = 7, .muxsel = { 2, 0, 1, 1 }, @@ -712,12 +685,11 @@ struct tvcard bttv_tvcards[] = { .needs_tvaudio = 1, .tuner_type = UNSET, .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, }, [BTTV_BOARD_MAXI] = { .name = "Lifeview FlyVideo 98/ MAXI TV Video PCI2 LR50", .video_inputs = 4, - .audio_inputs = 2, + /* .audio_inputs= 2, */ .svhs = 2, .gpiomask = 0x1800, .muxsel = { 2, 3, 1, 1 }, @@ -726,14 +698,13 @@ struct tvcard bttv_tvcards[] = { .pll = PLL_28, .tuner_type = TUNER_PHILIPS_SECAM, .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, }, /* ---- card 0x1c ---------------------------------- */ [BTTV_BOARD_TERRATV] = { .name = "Terratec TerraTV+ Version 1.1 (bt878)", .video_inputs = 3, - .audio_inputs = 1, + /* .audio_inputs= 1, */ .svhs = 2, .gpiomask = 0x1f0fff, .muxsel = { 2, 3, 1, 1 }, @@ -742,7 +713,6 @@ struct tvcard bttv_tvcards[] = { .needs_tvaudio = 0, .tuner_type = TUNER_PHILIPS_PAL, .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, .audio_mode_gpio= terratv_audio, /* GPIO wiring: External 20 pin connector (for Active Radio Upgrade board) @@ -780,7 +750,7 @@ struct tvcard bttv_tvcards[] = { /* Jannik Fritsch */ .name = "Imagenation PXC200", .video_inputs = 5, - .audio_inputs = 1, + /* .audio_inputs= 1, */ .svhs = 1, /* was: 4 */ .gpiomask = 0, .muxsel = { 2, 3, 1, 0, 0}, @@ -788,14 +758,13 @@ struct tvcard bttv_tvcards[] = { .needs_tvaudio = 1, .tuner_type = TUNER_ABSENT, .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, .muxsel_hook = PXC200_muxsel, }, [BTTV_BOARD_FLYVIDEO_98] = { .name = "Lifeview FlyVideo 98 LR50", .video_inputs = 4, - .audio_inputs = 1, + /* .audio_inputs= 1, */ .svhs = 2, .gpiomask = 0x1800, /* 0x8dfe00 */ .muxsel = { 2, 3, 1, 1 }, @@ -804,12 +773,11 @@ struct tvcard bttv_tvcards[] = { .pll = PLL_28, .tuner_type = UNSET, .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, }, [BTTV_BOARD_IPROTV] = { .name = "Formac iProTV, Formac ProTV I (bt848)", .video_inputs = 4, - .audio_inputs = 1, + /* .audio_inputs= 1, */ .svhs = 3, .gpiomask = 1, .muxsel = { 2, 3, 1, 1 }, @@ -817,14 +785,13 @@ struct tvcard bttv_tvcards[] = { .pll = PLL_28, .tuner_type = TUNER_PHILIPS_PAL, .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, }, /* ---- card 0x20 ---------------------------------- */ [BTTV_BOARD_INTEL_C_S_PCI] = { .name = "Intel Create and Share PCI/ Smart Video Recorder III", .video_inputs = 4, - .audio_inputs = 0, + /* .audio_inputs= 0, */ .svhs = 2, .gpiomask = 0, .muxsel = { 2, 3, 1, 1 }, @@ -832,12 +799,11 @@ struct tvcard bttv_tvcards[] = { .needs_tvaudio = 0, .tuner_type = TUNER_ABSENT, .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, }, [BTTV_BOARD_TERRATVALUE] = { .name = "Terratec TerraTValue Version Bt878", .video_inputs = 3, - .audio_inputs = 1, + /* .audio_inputs= 1, */ .svhs = 2, .gpiomask = 0xffff00, .muxsel = { 2, 3, 1, 1 }, @@ -847,12 +813,11 @@ struct tvcard bttv_tvcards[] = { .pll = PLL_28, .tuner_type = TUNER_PHILIPS_PAL, .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, }, [BTTV_BOARD_WINFAST2000] = { .name = "Leadtek WinFast 2000/ WinFast 2000 XP", .video_inputs = 4, - .audio_inputs = 1, + /* .audio_inputs= 1, */ .svhs = 2, .muxsel = { 2, 3, 1, 1, 0 }, /* TV, CVid, SVid, CVid over SVid connector */ /* Alexander Varakin [stereo version] */ @@ -875,14 +840,13 @@ struct tvcard bttv_tvcards[] = { .has_radio = 1, .tuner_type = TUNER_PHILIPS_PAL, /* default for now, gpio reads BFFF06 for Pal bg+dk */ .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, .audio_mode_gpio= winfast2000_audio, .has_remote = 1, }, [BTTV_BOARD_CHRONOS_VS2] = { .name = "Lifeview FlyVideo 98 LR50 / Chronos Video Shuttle II", .video_inputs = 4, - .audio_inputs = 3, + /* .audio_inputs= 3, */ .svhs = 2, .gpiomask = 0x1800, .muxsel = { 2, 3, 1, 1 }, @@ -891,14 +855,13 @@ struct tvcard bttv_tvcards[] = { .pll = PLL_28, .tuner_type = UNSET, .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, }, /* ---- card 0x24 ---------------------------------- */ [BTTV_BOARD_TYPHOON_TVIEW] = { .name = "Lifeview FlyVideo 98FM LR50 / Typhoon TView TV/FM Tuner", .video_inputs = 4, - .audio_inputs = 3, + /* .audio_inputs= 3, */ .svhs = 2, .gpiomask = 0x1800, .muxsel = { 2, 3, 1, 1 }, @@ -907,13 +870,12 @@ struct tvcard bttv_tvcards[] = { .pll = PLL_28, .tuner_type = UNSET, .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, .has_radio = 1, }, [BTTV_BOARD_PXELVWPLTVPRO] = { .name = "Prolink PixelView PlayTV pro", .video_inputs = 3, - .audio_inputs = 1, + /* .audio_inputs= 1, */ .svhs = 2, .gpiomask = 0xff, .muxsel = { 2, 3, 1, 1 }, @@ -923,12 +885,11 @@ struct tvcard bttv_tvcards[] = { .pll = PLL_28, .tuner_type = UNSET, .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, }, [BTTV_BOARD_MAGICTVIEW063] = { .name = "Askey CPH06X TView99", .video_inputs = 4, - .audio_inputs = 1, + /* .audio_inputs= 1, */ .svhs = 2, .gpiomask = 0x551e00, .muxsel = { 2, 3, 1, 0 }, @@ -938,13 +899,12 @@ struct tvcard bttv_tvcards[] = { .pll = PLL_28, .tuner_type = TUNER_PHILIPS_PAL_I, .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, .has_remote = 1, }, [BTTV_BOARD_PINNACLE] = { .name = "Pinnacle PCTV Studio/Rave", .video_inputs = 3, - .audio_inputs = 1, + /* .audio_inputs= 1, */ .svhs = 2, .gpiomask = 0x03000F, .muxsel = { 2, 3, 1, 1 }, @@ -954,14 +914,13 @@ struct tvcard bttv_tvcards[] = { .pll = PLL_28, .tuner_type = UNSET, .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, }, /* ---- card 0x28 ---------------------------------- */ [BTTV_BOARD_STB2] = { .name = "STB TV PCI FM, Gateway P/N 6000704 (bt878), 3Dfx VoodooTV 100", .video_inputs = 3, - .audio_inputs = 1, + /* .audio_inputs= 1, */ .svhs = 2, .gpiomask = 7, .muxsel = { 2, 3, 1, 1 }, @@ -971,14 +930,13 @@ struct tvcard bttv_tvcards[] = { .needs_tvaudio = 1, .tuner_type = TUNER_PHILIPS_NTSC, .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, .pll = PLL_28, .has_radio = 1, }, [BTTV_BOARD_AVPHONE98] = { .name = "AVerMedia TVPhone 98", .video_inputs = 3, - .audio_inputs = 4, + /* .audio_inputs= 4, */ .svhs = 2, .gpiomask = 15, .muxsel = { 2, 3, 1, 1 }, @@ -987,14 +945,13 @@ struct tvcard bttv_tvcards[] = { .pll = PLL_28, .tuner_type = UNSET, .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, .has_radio = 1, .audio_mode_gpio= avermedia_tvphone_audio, }, [BTTV_BOARD_PV951] = { .name = "ProVideo PV951", /* pic16c54 */ .video_inputs = 3, - .audio_inputs = 1, + /* .audio_inputs= 1, */ .svhs = 2, .gpiomask = 0, .muxsel = { 2, 3, 1, 1}, @@ -1004,12 +961,11 @@ struct tvcard bttv_tvcards[] = { .pll = PLL_28, .tuner_type = TUNER_PHILIPS_PAL_I, .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, }, [BTTV_BOARD_ONAIR_TV] = { .name = "Little OnAir TV", .video_inputs = 3, - .audio_inputs = 1, + /* .audio_inputs= 1, */ .svhs = 2, .gpiomask = 0xe00b, .muxsel = { 2, 3, 1, 1 }, @@ -1018,15 +974,14 @@ struct tvcard bttv_tvcards[] = { .no_msp34xx = 1, .tuner_type = UNSET, .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, }, /* ---- card 0x2c ---------------------------------- */ [BTTV_BOARD_SIGMA_TVII_FM] = { .name = "Sigma TVII-FM", .video_inputs = 2, - .audio_inputs = 1, - .svhs = UNSET, + /* .audio_inputs= 1, */ + .svhs = NO_SVHS, .gpiomask = 3, .muxsel = { 2, 3, 1, 1 }, .gpiomux = { 1, 1, 0, 2 }, @@ -1035,12 +990,11 @@ struct tvcard bttv_tvcards[] = { .pll = PLL_NONE, .tuner_type = UNSET, .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, }, [BTTV_BOARD_MATRIX_VISION2] = { .name = "MATRIX-Vision MV-Delta 2", .video_inputs = 5, - .audio_inputs = 1, + /* .audio_inputs= 1, */ .svhs = 3, .gpiomask = 0, .muxsel = { 2, 3, 1, 0, 0 }, @@ -1049,12 +1003,11 @@ struct tvcard bttv_tvcards[] = { .pll = PLL_28, .tuner_type = TUNER_ABSENT, .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, }, [BTTV_BOARD_ZOLTRIX_GENIE] = { .name = "Zoltrix Genie TV/FM", .video_inputs = 3, - .audio_inputs = 1, + /* .audio_inputs= 1, */ .svhs = 2, .gpiomask = 0xbcf03f, .muxsel = { 2, 3, 1, 1 }, @@ -1064,12 +1017,11 @@ struct tvcard bttv_tvcards[] = { .pll = PLL_28, .tuner_type = TUNER_TEMIC_4039FR5_NTSC, .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, }, [BTTV_BOARD_TERRATVRADIO] = { .name = "Terratec TV/Radio+", .video_inputs = 3, - .audio_inputs = 1, + /* .audio_inputs= 1, */ .svhs = 2, .gpiomask = 0x70000, .muxsel = { 2, 3, 1, 1 }, @@ -1080,7 +1032,6 @@ struct tvcard bttv_tvcards[] = { .pll = PLL_35, .tuner_type = TUNER_PHILIPS_PAL_I, .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, .has_radio = 1, }, @@ -1088,7 +1039,7 @@ struct tvcard bttv_tvcards[] = { [BTTV_BOARD_DYNALINK] = { .name = "Askey CPH03x/ Dynalink Magic TView", .video_inputs = 3, - .audio_inputs = 1, + /* .audio_inputs= 1, */ .svhs = 2, .gpiomask = 15, .muxsel = { 2, 3, 1, 1 }, @@ -1098,12 +1049,11 @@ struct tvcard bttv_tvcards[] = { .pll = PLL_28, .tuner_type = UNSET, .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, }, [BTTV_BOARD_GVBCTV3PCI] = { .name = "IODATA GV-BCTV3/PCI", .video_inputs = 3, - .audio_inputs = 1, + /* .audio_inputs= 1, */ .svhs = 2, .gpiomask = 0x010f00, .muxsel = {2, 3, 0, 0 }, @@ -1112,24 +1062,22 @@ struct tvcard bttv_tvcards[] = { .pll = PLL_28, .tuner_type = TUNER_ALPS_TSHC6_NTSC, .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, .audio_mode_gpio= gvbctv3pci_audio, }, [BTTV_BOARD_PXELVWPLTVPAK] = { .name = "Prolink PV-BT878P+4E / PixelView PlayTV PAK / Lenco MXTV-9578 CP", .video_inputs = 5, - .audio_inputs = 1, + /* .audio_inputs= 1, */ .svhs = 3, .gpiomask = 0xAA0000, - .muxsel = { 2,3,1,1,-1 }, - .digital_mode = DIGITAL_MODE_CAMERA, + .muxsel = { 2, 3, 1, 1, -1 }, + /* .digital_mode= DIGITAL_MODE_CAMERA, */ .gpiomux = { 0x20000, 0, 0x80000, 0x80000 }, .gpiomute = 0xa8000, .no_msp34xx = 1, .pll = PLL_28, .tuner_type = TUNER_PHILIPS_PAL_I, .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, .has_remote = 1, /* GPIO wiring: (different from Rev.4C !) GPIO17: U4.A0 (first hef4052bt) @@ -1144,7 +1092,7 @@ struct tvcard bttv_tvcards[] = { [BTTV_BOARD_EAGLE] = { .name = "Eagle Wireless Capricorn2 (bt878A)", .video_inputs = 4, - .audio_inputs = 1, + /* .audio_inputs= 1, */ .svhs = 2, .gpiomask = 7, .muxsel = { 2, 0, 1, 1 }, @@ -1153,7 +1101,6 @@ struct tvcard bttv_tvcards[] = { .pll = PLL_28, .tuner_type = UNSET /* TUNER_ALPS_TMDH2_NTSC */, .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, }, /* ---- card 0x34 ---------------------------------- */ @@ -1161,7 +1108,7 @@ struct tvcard bttv_tvcards[] = { /* David Härdeman */ .name = "Pinnacle PCTV Studio Pro", .video_inputs = 4, - .audio_inputs = 1, + /* .audio_inputs= 1, */ .svhs = 3, .gpiomask = 0x03000F, .muxsel = { 2, 3, 1, 1 }, @@ -1180,14 +1127,13 @@ struct tvcard bttv_tvcards[] = { .pll = PLL_28, .tuner_type = UNSET, .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, }, [BTTV_BOARD_TVIEW_RDS_FM] = { /* Claas Langbehn , Sven Grothklags */ .name = "Typhoon TView RDS + FM Stereo / KNC1 TV Station RDS", .video_inputs = 4, - .audio_inputs = 3, + /* .audio_inputs= 3, */ .svhs = 2, .gpiomask = 0x1c, .muxsel = { 2, 3, 1, 1 }, @@ -1197,7 +1143,6 @@ struct tvcard bttv_tvcards[] = { .pll = PLL_28, .tuner_type = TUNER_PHILIPS_PAL, .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, .has_radio = 1, }, [BTTV_BOARD_LIFETEC_9415] = { @@ -1208,7 +1153,7 @@ struct tvcard bttv_tvcards[] = { options tuner type=5 */ .name = "Lifeview FlyVideo 2000 /FlyVideo A2/ Lifetec LT 9415 TV [LR90]", .video_inputs = 4, - .audio_inputs = 1, + /* .audio_inputs= 1, */ .svhs = 2, .gpiomask = 0x18e0, .muxsel = { 2, 3, 1, 1 }, @@ -1221,14 +1166,13 @@ struct tvcard bttv_tvcards[] = { .pll = PLL_28, .tuner_type = UNSET, .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, }, [BTTV_BOARD_BESTBUY_EASYTV] = { /* Miguel Angel Alvarez old Easy TV BT848 version (model CPH031) */ .name = "Askey CPH031/ BESTBUY Easy TV", .video_inputs = 4, - .audio_inputs = 1, + /* .audio_inputs= 1, */ .svhs = 2, .gpiomask = 0xF, .muxsel = { 2, 3, 1, 0 }, @@ -1238,7 +1182,6 @@ struct tvcard bttv_tvcards[] = { .pll = PLL_28, .tuner_type = TUNER_TEMIC_PAL, .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, }, /* ---- card 0x38 ---------------------------------- */ @@ -1246,7 +1189,7 @@ struct tvcard bttv_tvcards[] = { /* Gordon Heydon */ .name = "Askey CPH060/ Phoebe TV Master Only (No FM)", .video_inputs = 3, - .audio_inputs = 1, + /* .audio_inputs= 1, */ .svhs = 2, .gpiomask = 0xe00, .muxsel = { 2, 3, 1, 1}, @@ -1289,13 +1230,12 @@ struct tvcard bttv_tvcards[] = { .pll = PLL_28, .tuner_type = TUNER_TEMIC_4036FY5_NTSC, .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, }, [BTTV_BOARD_ASKEY_CPH03X] = { /* Matti Mottus */ .name = "Askey CPH03x TV Capturer", .video_inputs = 4, - .audio_inputs = 1, + /* .audio_inputs= 1, */ .svhs = 2, .gpiomask = 0x03000F, .muxsel = { 2, 3, 1, 0 }, @@ -1304,7 +1244,6 @@ struct tvcard bttv_tvcards[] = { .pll = PLL_28, .tuner_type = TUNER_TEMIC_PAL, .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, }, /* ---- card 0x3c ---------------------------------- */ @@ -1312,8 +1251,8 @@ struct tvcard bttv_tvcards[] = { /* Philip Blundell */ .name = "Modular Technology MM100PCTV", .video_inputs = 2, - .audio_inputs = 2, - .svhs = UNSET, + /* .audio_inputs= 2, */ + .svhs = NO_SVHS, .gpiomask = 11, .muxsel = { 2, 3, 1, 1 }, .gpiomux = { 2, 0, 0, 1 }, @@ -1321,13 +1260,12 @@ struct tvcard bttv_tvcards[] = { .pll = PLL_35, .tuner_type = TUNER_TEMIC_PAL, .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, }, [BTTV_BOARD_GMV1] = { /* Adrian Cox @@ -1345,7 +1282,7 @@ struct tvcard bttv_tvcards[] = { special thanks to Informatica Mieres for providing the card */ .name = "Askey CPH061/ BESTBUY Easy TV (bt878)", .video_inputs = 3, - .audio_inputs = 2, + /* .audio_inputs= 2, */ .svhs = 2, .gpiomask = 0xFF, .muxsel = { 2, 3, 1, 0 }, @@ -1355,13 +1292,12 @@ struct tvcard bttv_tvcards[] = { .pll = PLL_28, .tuner_type = TUNER_PHILIPS_PAL, .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, }, [BTTV_BOARD_ATI_TVWONDER] = { /* Lukas Gebauer */ .name = "ATI TV-Wonder", .video_inputs = 3, - .audio_inputs = 1, + /* .audio_inputs= 1, */ .svhs = 2, .gpiomask = 0xf03f, .muxsel = { 2, 3, 1, 0 }, @@ -1370,7 +1306,6 @@ struct tvcard bttv_tvcards[] = { .pll = PLL_28, .tuner_type = TUNER_TEMIC_4006FN5_MULTI_PAL, .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, }, /* ---- card 0x40 ---------------------------------- */ @@ -1378,8 +1313,8 @@ struct tvcard bttv_tvcards[] = { /* Lukas Gebauer */ .name = "ATI TV-Wonder VE", .video_inputs = 2, - .audio_inputs = 1, - .svhs = UNSET, + /* .audio_inputs= 1, */ + .svhs = NO_SVHS, .gpiomask = 1, .muxsel = { 2, 3, 0, 1 }, .gpiomux = { 0, 0, 1, 0 }, @@ -1387,13 +1322,12 @@ struct tvcard bttv_tvcards[] = { .pll = PLL_28, .tuner_type = TUNER_TEMIC_4006FN5_MULTI_PAL, .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, }, [BTTV_BOARD_FLYVIDEO2000] = { /* DeeJay */ .name = "IODATA GV-BCTV4/PCI", .video_inputs = 3, - .audio_inputs = 1, + /* .audio_inputs= 1, */ .svhs = 2, .gpiomask = 0x010f00, .muxsel = {2, 3, 0, 0 }, @@ -1440,7 +1372,6 @@ struct tvcard bttv_tvcards[] = { .pll = PLL_28, .tuner_type = TUNER_SHARP_2U5JF5540_NTSC, .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, .audio_mode_gpio= gvbctv3pci_audio, }, @@ -1450,8 +1381,8 @@ struct tvcard bttv_tvcards[] = { /* try "insmod msp3400 simple=0" if you have * sound problems with this card. */ .video_inputs = 4, - .audio_inputs = 1, - .svhs = UNSET, + /* .audio_inputs= 1, */ + .svhs = NO_SVHS, .gpiomask = 0x4f8a00, /* 0x100000: 1=MSP enabled (0=disable again) * 0x010000: Connected to "S0" on tda9880 (0=Pal/BG, 1=NTSC) */ @@ -1462,7 +1393,6 @@ struct tvcard bttv_tvcards[] = { .muxsel = { 2, 3 ,0 ,1 }, .tuner_type = TUNER_MT2032, .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, .pll = PLL_28, .has_radio = 1, }, @@ -1471,8 +1401,8 @@ struct tvcard bttv_tvcards[] = { /* try "insmod msp3400 simple=0" if you have * sound problems with this card. */ .video_inputs = 4, - .audio_inputs = 1, - .svhs = UNSET, + /* .audio_inputs= 1, */ + .svhs = NO_SVHS, .gpiomask = 0x4f8a00, /* 0x100000: 1=MSP enabled (0=disable again) * 0x010000: Connected to "S0" on tda9880 (0=Pal/BG, 1=NTSC) */ @@ -1483,7 +1413,6 @@ struct tvcard bttv_tvcards[] = { .muxsel = { 2, 3 ,0 ,1 }, .tuner_type = TUNER_MT2032, .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, .pll = PLL_28, .has_radio = 1, }, @@ -1491,10 +1420,9 @@ struct tvcard bttv_tvcards[] = { /* Philip Blundell */ .name = "Active Imaging AIMMS", .video_inputs = 1, - .audio_inputs = 0, + /* .audio_inputs= 0, */ .tuner_type = TUNER_ABSENT, .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, .pll = PLL_28, .muxsel = { 2 }, .gpiomask = 0 @@ -1503,7 +1431,7 @@ struct tvcard bttv_tvcards[] = { /* Tomasz Pyra */ .name = "Prolink Pixelview PV-BT878P+ (Rev.4C,8E)", .video_inputs = 3, - .audio_inputs = 4, + /* .audio_inputs= 4, */ .svhs = 2, .gpiomask = 15, .muxsel = { 2, 3, 1, 1 }, @@ -1513,7 +1441,6 @@ struct tvcard bttv_tvcards[] = { .pll = PLL_28, .tuner_type = TUNER_LG_PAL_I_FM, .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, .has_remote = 1, /* GPIO wiring: GPIO0: U4.A0 (hef4052bt) @@ -1526,14 +1453,13 @@ struct tvcard bttv_tvcards[] = { [BTTV_BOARD_FLYVIDEO98EZ] = { .name = "Lifeview FlyVideo 98EZ (capture only) LR51", .video_inputs = 4, - .audio_inputs = 0, + /* .audio_inputs= 0, */ .svhs = 2, .muxsel = { 2, 3, 1, 1 }, /* AV1, AV2, SVHS, CVid adapter on SVHS */ .pll = PLL_28, .no_msp34xx = 1, .tuner_type = TUNER_ABSENT, .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, }, /* ---- card 0x48 ---------------------------------- */ @@ -1541,7 +1467,7 @@ struct tvcard bttv_tvcards[] = { /* Dariusz Kowalewski */ .name = "Prolink Pixelview PV-BT878P+9B (PlayTV Pro rev.9B FM+NICAM)", .video_inputs = 4, - .audio_inputs = 1, + /* .audio_inputs= 1, */ .svhs = 2, .gpiomask = 0x3f, .muxsel = { 2, 3, 1, 1 }, @@ -1553,7 +1479,6 @@ struct tvcard bttv_tvcards[] = { .pll = PLL_28, .tuner_type = TUNER_PHILIPS_PAL, .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, .audio_mode_gpio= pvbt878p9b_audio, /* Note: not all cards have stereo */ .has_radio = 1, /* Note: not all cards have radio */ .has_remote = 1, @@ -1570,7 +1495,7 @@ struct tvcard bttv_tvcards[] = { /* you must jumper JP5 for the card to work */ .name = "Sensoray 311", .video_inputs = 5, - .audio_inputs = 0, + /* .audio_inputs= 0, */ .svhs = 4, .gpiomask = 0, .muxsel = { 2, 3, 1, 0, 0 }, @@ -1578,14 +1503,13 @@ struct tvcard bttv_tvcards[] = { .needs_tvaudio = 0, .tuner_type = TUNER_ABSENT, .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, }, [BTTV_BOARD_RV605] = { /* Miguel Freitas */ .name = "RemoteVision MX (RV605)", .video_inputs = 16, - .audio_inputs = 0, - .svhs = UNSET, + /* .audio_inputs= 0, */ + .svhs = NO_SVHS, .gpiomask = 0x00, .gpiomask2 = 0x07ff, .muxsel = { 0x33, 0x13, 0x23, 0x43, 0xf3, 0x73, 0xe3, 0x03, @@ -1594,13 +1518,12 @@ struct tvcard bttv_tvcards[] = { .no_tda9875 = 1, .tuner_type = TUNER_ABSENT, .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, .muxsel_hook = rv605_muxsel, }, [BTTV_BOARD_POWERCLR_MTV878] = { .name = "Powercolor MTV878/ MTV878R/ MTV878F", .video_inputs = 3, - .audio_inputs = 2, + /* .audio_inputs= 2, */ .svhs = 2, .gpiomask = 0x1C800F, /* Bit0-2: Audio select, 8-12:remote control 14:remote valid 15:remote reset */ .muxsel = { 2, 1, 1, }, @@ -1609,7 +1532,6 @@ struct tvcard bttv_tvcards[] = { .needs_tvaudio = 0, .tuner_type = TUNER_PHILIPS_PAL, .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, .pll = PLL_28, .has_radio = 1, }, @@ -1619,7 +1541,7 @@ struct tvcard bttv_tvcards[] = { /* Masaki Suzuki */ .name = "Canopus WinDVR PCI (COMPAQ Presario 3524JP, 5112JP)", .video_inputs = 3, - .audio_inputs = 1, + /* .audio_inputs= 1, */ .svhs = 2, .gpiomask = 0x140007, .muxsel = { 2, 3, 1, 1 }, @@ -1627,14 +1549,13 @@ struct tvcard bttv_tvcards[] = { .gpiomute = 4, .tuner_type = TUNER_PHILIPS_NTSC, .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, .audio_mode_gpio= windvr_audio, }, [BTTV_BOARD_GRANDTEC_MULTI] = { .name = "GrandTec Multi Capture Card (Bt878)", .video_inputs = 4, - .audio_inputs = 0, - .svhs = UNSET, + /* .audio_inputs= 0, */ + .svhs = NO_SVHS, .gpiomask = 0, .muxsel = { 2, 3, 1, 0 }, .gpiomux = { 0 }, @@ -1643,12 +1564,11 @@ struct tvcard bttv_tvcards[] = { .pll = PLL_28, .tuner_type = TUNER_ABSENT, .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, }, [BTTV_BOARD_KWORLD] = { .name = "Jetway TV/Capture JW-TV878-FBK, Kworld KW-TV878RF", .video_inputs = 4, - .audio_inputs = 3, + /* .audio_inputs= 3, */ .svhs = 2, .gpiomask = 7, .muxsel = { 2, 3, 1, 1 }, /* Tuner, SVid, SVHS, SVid to SVHS connector */ @@ -1665,7 +1585,6 @@ struct tvcard bttv_tvcards[] = { .pll = PLL_28, .tuner_type = TUNER_PHILIPS_PAL, .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, /* Samsung TCPA9095PC27A (BG+DK), philips compatible, w/FM, stereo and radio signal strength indicators work fine. */ .has_radio = 1, @@ -1683,26 +1602,24 @@ struct tvcard bttv_tvcards[] = { /* Arthur Tetzlaff-Deas, DSP Design Ltd */ .name = "DSP Design TCVIDEO", .video_inputs = 4, - .svhs = UNSET, + .svhs = NO_SVHS, .muxsel = { 2, 3, 1, 0 }, .pll = PLL_28, .tuner_type = UNSET, .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, }, /* ---- card 0x50 ---------------------------------- */ [BTTV_BOARD_HAUPPAUGEPVR] = { .name = "Hauppauge WinTV PVR", .video_inputs = 4, - .audio_inputs = 1, + /* .audio_inputs= 1, */ .svhs = 2, .muxsel = { 2, 0, 1, 1 }, .needs_tvaudio = 1, .pll = PLL_28, .tuner_type = UNSET, .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, .gpiomask = 7, .gpiomux = {7}, @@ -1710,7 +1627,7 @@ struct tvcard bttv_tvcards[] = { [BTTV_BOARD_GVBCTV5PCI] = { .name = "IODATA GV-BCTV5/PCI", .video_inputs = 3, - .audio_inputs = 1, + /* .audio_inputs= 1, */ .svhs = 2, .gpiomask = 0x0f0f80, .muxsel = {2, 3, 1, 0 }, @@ -1720,20 +1637,18 @@ struct tvcard bttv_tvcards[] = { .pll = PLL_28, .tuner_type = TUNER_PHILIPS_NTSC_M, .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, .audio_mode_gpio= gvbctv5pci_audio, .has_radio = 1, }, [BTTV_BOARD_OSPREY1x0] = { .name = "Osprey 100/150 (878)", /* 0x1(2|3)-45C6-C1 */ .video_inputs = 4, /* id-inputs-clock */ - .audio_inputs = 0, + /* .audio_inputs= 0, */ .svhs = 3, .muxsel = { 3, 2, 0, 1 }, .pll = PLL_28, .tuner_type = TUNER_ABSENT, .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, .no_msp34xx = 1, .no_tda9875 = 1, .no_tda7432 = 1, @@ -1741,13 +1656,12 @@ struct tvcard bttv_tvcards[] = { [BTTV_BOARD_OSPREY1x0_848] = { .name = "Osprey 100/150 (848)", /* 0x04-54C0-C1 & older boards */ .video_inputs = 3, - .audio_inputs = 0, + /* .audio_inputs= 0, */ .svhs = 2, .muxsel = { 2, 3, 1 }, .pll = PLL_28, .tuner_type = TUNER_ABSENT, .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, .no_msp34xx = 1, .no_tda9875 = 1, .no_tda7432 = 1, @@ -1757,13 +1671,12 @@ struct tvcard bttv_tvcards[] = { [BTTV_BOARD_OSPREY101_848] = { .name = "Osprey 101 (848)", /* 0x05-40C0-C1 */ .video_inputs = 2, - .audio_inputs = 0, + /* .audio_inputs= 0, */ .svhs = 1, .muxsel = { 3, 1 }, .pll = PLL_28, .tuner_type = TUNER_ABSENT, .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, .no_msp34xx = 1, .no_tda9875 = 1, .no_tda7432 = 1, @@ -1771,13 +1684,12 @@ struct tvcard bttv_tvcards[] = { [BTTV_BOARD_OSPREY1x1] = { .name = "Osprey 101/151", /* 0x1(4|5)-0004-C4 */ .video_inputs = 1, - .audio_inputs = 0, - .svhs = UNSET, + /* .audio_inputs= 0, */ + .svhs = NO_SVHS, .muxsel = { 0 }, .pll = PLL_28, .tuner_type = TUNER_ABSENT, .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, .no_msp34xx = 1, .no_tda9875 = 1, .no_tda7432 = 1, @@ -1785,13 +1697,12 @@ struct tvcard bttv_tvcards[] = { [BTTV_BOARD_OSPREY1x1_SVID] = { .name = "Osprey 101/151 w/ svid", /* 0x(16|17|20)-00C4-C1 */ .video_inputs = 2, - .audio_inputs = 0, + /* .audio_inputs= 0, */ .svhs = 1, .muxsel = { 0, 1 }, .pll = PLL_28, .tuner_type = TUNER_ABSENT, .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, .no_msp34xx = 1, .no_tda9875 = 1, .no_tda7432 = 1, @@ -1799,13 +1710,12 @@ struct tvcard bttv_tvcards[] = { [BTTV_BOARD_OSPREY2xx] = { .name = "Osprey 200/201/250/251", /* 0x1(8|9|E|F)-0004-C4 */ .video_inputs = 1, - .audio_inputs = 1, - .svhs = UNSET, + /* .audio_inputs= 1, */ + .svhs = NO_SVHS, .muxsel = { 0 }, .pll = PLL_28, .tuner_type = TUNER_ABSENT, .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, .no_msp34xx = 1, .no_tda9875 = 1, .no_tda7432 = 1, @@ -1815,13 +1725,12 @@ struct tvcard bttv_tvcards[] = { [BTTV_BOARD_OSPREY2x0_SVID] = { .name = "Osprey 200/250", /* 0x1(A|B)-00C4-C1 */ .video_inputs = 2, - .audio_inputs = 1, + /* .audio_inputs= 1, */ .svhs = 1, .muxsel = { 0, 1 }, .pll = PLL_28, .tuner_type = TUNER_ABSENT, .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, .no_msp34xx = 1, .no_tda9875 = 1, .no_tda7432 = 1, @@ -1829,13 +1738,12 @@ struct tvcard bttv_tvcards[] = { [BTTV_BOARD_OSPREY2x0] = { .name = "Osprey 210/220/230", /* 0x1(A|B)-04C0-C1 */ .video_inputs = 2, - .audio_inputs = 1, + /* .audio_inputs= 1, */ .svhs = 1, .muxsel = { 2, 3 }, .pll = PLL_28, .tuner_type = TUNER_ABSENT, .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, .no_msp34xx = 1, .no_tda9875 = 1, .no_tda7432 = 1, @@ -1843,13 +1751,12 @@ struct tvcard bttv_tvcards[] = { [BTTV_BOARD_OSPREY500] = { .name = "Osprey 500", /* 500 */ .video_inputs = 2, - .audio_inputs = 1, + /* .audio_inputs= 1, */ .svhs = 1, .muxsel = { 2, 3 }, .pll = PLL_28, .tuner_type = TUNER_ABSENT, .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, .no_msp34xx = 1, .no_tda9875 = 1, .no_tda7432 = 1, @@ -1857,11 +1764,10 @@ struct tvcard bttv_tvcards[] = { [BTTV_BOARD_OSPREY540] = { .name = "Osprey 540", /* 540 */ .video_inputs = 4, - .audio_inputs = 1, + /* .audio_inputs= 1, */ .pll = PLL_28, .tuner_type = TUNER_ABSENT, .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, .no_msp34xx = 1, .no_tda9875 = 1, .no_tda7432 = 1, @@ -1871,13 +1777,12 @@ struct tvcard bttv_tvcards[] = { [BTTV_BOARD_OSPREY2000] = { .name = "Osprey 2000", /* 2000 */ .video_inputs = 2, - .audio_inputs = 1, + /* .audio_inputs= 1, */ .svhs = 1, .muxsel = { 2, 3 }, .pll = PLL_28, .tuner_type = TUNER_ABSENT, .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, .no_msp34xx = 1, .no_tda9875 = 1, .no_tda7432 = 1, /* must avoid, conflicts with the bt860 */ @@ -1886,11 +1791,10 @@ struct tvcard bttv_tvcards[] = { /* M G Berberich */ .name = "IDS Eagle", .video_inputs = 4, - .audio_inputs = 0, + /* .audio_inputs= 0, */ .tuner_type = TUNER_ABSENT, .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - .svhs = UNSET, + .svhs = NO_SVHS, .gpiomask = 0, .muxsel = { 0, 1, 2, 3 }, .muxsel_hook = eagle_muxsel, @@ -1901,11 +1805,10 @@ struct tvcard bttv_tvcards[] = { [BTTV_BOARD_PINNACLESAT] = { .name = "Pinnacle PCTV Sat", .video_inputs = 2, - .audio_inputs = 0, + /* .audio_inputs= 0, */ .svhs = 1, .tuner_type = TUNER_ABSENT, .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, .no_msp34xx = 1, .no_tda9875 = 1, .no_tda7432 = 1, @@ -1917,7 +1820,7 @@ struct tvcard bttv_tvcards[] = { [BTTV_BOARD_FORMAC_PROTV] = { .name = "Formac ProTV II (bt878)", .video_inputs = 4, - .audio_inputs = 1, + /* .audio_inputs= 1, */ .svhs = 3, .gpiomask = 2, /* TV, Comp1, Composite over SVID con, SVID */ @@ -1927,7 +1830,6 @@ struct tvcard bttv_tvcards[] = { .has_radio = 1, .tuner_type = TUNER_PHILIPS_PAL, .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, /* sound routing: GPIO=0x00,0x01,0x03: mute (?) 0x02: both TV and radio (tuner: FM1216/I) @@ -1941,8 +1843,8 @@ struct tvcard bttv_tvcards[] = { [BTTV_BOARD_MACHTV] = { .name = "MachTV", .video_inputs = 3, - .audio_inputs = 1, - .svhs = UNSET, + /* .audio_inputs= 1, */ + .svhs = NO_SVHS, .gpiomask = 7, .muxsel = { 2, 3, 1, 1}, .gpiomux = { 0, 1, 2, 3}, @@ -1950,13 +1852,12 @@ struct tvcard bttv_tvcards[] = { .needs_tvaudio = 1, .tuner_type = TUNER_PHILIPS_PAL, .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, .pll = PLL_28, }, [BTTV_BOARD_EURESYS_PICOLO] = { .name = "Euresys Picolo", .video_inputs = 3, - .audio_inputs = 0, + /* .audio_inputs= 0, */ .svhs = 2, .gpiomask = 0, .no_msp34xx = 1, @@ -1966,14 +1867,13 @@ struct tvcard bttv_tvcards[] = { .pll = PLL_28, .tuner_type = TUNER_ABSENT, .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, }, [BTTV_BOARD_PV150] = { /* Luc Van Hoeylandt */ .name = "ProVideo PV150", /* 0x4f */ .video_inputs = 2, - .audio_inputs = 0, - .svhs = UNSET, + /* .audio_inputs= 0, */ + .svhs = NO_SVHS, .gpiomask = 0, .muxsel = { 2, 3 }, .gpiomux = { 0 }, @@ -1982,14 +1882,13 @@ struct tvcard bttv_tvcards[] = { .pll = PLL_28, .tuner_type = TUNER_ABSENT, .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, }, [BTTV_BOARD_AD_TVK503] = { /* Hiroshi Takekawa */ /* This card lacks subsystem ID */ .name = "AD-TVK503", /* 0x63 */ .video_inputs = 4, - .audio_inputs = 1, + /* .audio_inputs= 1, */ .svhs = 2, .gpiomask = 0x001e8007, .muxsel = { 2, 3, 1, 0 }, @@ -2001,7 +1900,6 @@ struct tvcard bttv_tvcards[] = { .pll = PLL_28, .tuner_type = TUNER_PHILIPS_NTSC, .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, .audio_mode_gpio= adtvk503_audio, }, @@ -2009,7 +1907,7 @@ struct tvcard bttv_tvcards[] = { [BTTV_BOARD_HERCULES_SM_TV] = { .name = "Hercules Smart TV Stereo", .video_inputs = 4, - .audio_inputs = 1, + /* .audio_inputs= 1, */ .svhs = 2, .gpiomask = 0x00, .muxsel = { 2, 3, 1, 1 }, @@ -2018,7 +1916,6 @@ struct tvcard bttv_tvcards[] = { .pll = PLL_28, .tuner_type = TUNER_PHILIPS_PAL, .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, /* Notes: - card lacks subsystem ID - stereo variant w/ daughter board with tda9874a @0xb0 @@ -2032,7 +1929,7 @@ struct tvcard bttv_tvcards[] = { [BTTV_BOARD_PACETV] = { .name = "Pace TV & Radio Card", .video_inputs = 4, - .audio_inputs = 1, + /* .audio_inputs= 1, */ .svhs = 2, .muxsel = { 2, 3, 1, 1 }, /* Tuner, CVid, SVid, CVid over SVid connector */ .gpiomask = 0, @@ -2040,7 +1937,6 @@ struct tvcard bttv_tvcards[] = { .no_tda7432 = 1, .tuner_type = TUNER_PHILIPS_PAL_I, .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, .has_radio = 1, .pll = PLL_28, /* Bt878, Bt832, FI1246 tuner; no pci subsystem id @@ -2054,11 +1950,10 @@ struct tvcard bttv_tvcards[] = { /* Chris Willing */ .name = "IVC-200", .video_inputs = 1, - .audio_inputs = 0, + /* .audio_inputs= 0, */ .tuner_type = TUNER_ABSENT, .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - .svhs = UNSET, + .svhs = NO_SVHS, .gpiomask = 0xdf, .muxsel = { 2 }, .pll = PLL_28, @@ -2066,11 +1961,10 @@ struct tvcard bttv_tvcards[] = { [BTTV_BOARD_IVCE8784] = { .name = "IVCE-8784", .video_inputs = 1, - .audio_inputs = 0, + /* .audio_inputs= 0, */ .tuner_type = TUNER_ABSENT, .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - .svhs = UNSET, + .svhs = NO_SVHS, .gpiomask = 0xdf, .muxsel = { 2 }, .pll = PLL_28, @@ -2078,11 +1972,10 @@ struct tvcard bttv_tvcards[] = { [BTTV_BOARD_XGUARD] = { .name = "Grand X-Guard / Trust 814PCI", .video_inputs = 16, - .audio_inputs = 0, - .svhs = UNSET, + /* .audio_inputs= 0, */ + .svhs = NO_SVHS, .tuner_type = TUNER_ABSENT, .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, .gpiomask2 = 0xff, .muxsel = { 2,2,2,2, 3,3,3,3, 1,1,1,1, 0,0,0,0 }, .muxsel_hook = xguard_muxsel, @@ -2096,7 +1989,7 @@ struct tvcard bttv_tvcards[] = { [BTTV_BOARD_NEBULA_DIGITV] = { .name = "Nebula Electronics DigiTV", .video_inputs = 1, - .svhs = UNSET, + .svhs = NO_SVHS, .muxsel = { 2, 3, 1, 0 }, .no_msp34xx = 1, .no_tda9875 = 1, @@ -2104,7 +1997,6 @@ struct tvcard bttv_tvcards[] = { .pll = PLL_28, .tuner_type = TUNER_ABSENT, .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, .has_dvb = 1, .has_remote = 1, .gpiomask = 0x1b, @@ -2114,8 +2006,8 @@ struct tvcard bttv_tvcards[] = { /* Jorge Boncompte - DTI2 */ .name = "ProVideo PV143", .video_inputs = 4, - .audio_inputs = 0, - .svhs = UNSET, + /* .audio_inputs= 0, */ + .svhs = NO_SVHS, .gpiomask = 0, .muxsel = { 2, 3, 1, 0 }, .gpiomux = { 0 }, @@ -2124,13 +2016,12 @@ struct tvcard bttv_tvcards[] = { .pll = PLL_28, .tuner_type = TUNER_ABSENT, .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, }, [BTTV_BOARD_VD009X1_VD011_MINIDIN] = { /* M.Klahr@phytec.de */ .name = "PHYTEC VD-009-X1 VD-011 MiniDIN (bt878)", .video_inputs = 4, - .audio_inputs = 0, + /* .audio_inputs= 0, */ .svhs = 3, .gpiomask = 0x00, .muxsel = { 2, 3, 1, 0 }, @@ -2139,12 +2030,11 @@ struct tvcard bttv_tvcards[] = { .pll = PLL_28, .tuner_type = TUNER_ABSENT, .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, }, [BTTV_BOARD_VD009X1_VD011_COMBI] = { .name = "PHYTEC VD-009-X1 VD-011 Combi (bt878)", .video_inputs = 4, - .audio_inputs = 0, + /* .audio_inputs= 0, */ .svhs = 3, .gpiomask = 0x00, .muxsel = { 2, 3, 1, 1 }, @@ -2153,14 +2043,13 @@ struct tvcard bttv_tvcards[] = { .pll = PLL_28, .tuner_type = TUNER_ABSENT, .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, }, /* ---- card 0x6c ---------------------------------- */ [BTTV_BOARD_VD009_MINIDIN] = { .name = "PHYTEC VD-009 MiniDIN (bt878)", .video_inputs = 10, - .audio_inputs = 0, + /* .audio_inputs= 0, */ .svhs = 9, .gpiomask = 0x00, .gpiomask2 = 0x03, /* gpiomask2 defines the bits used to switch audio @@ -2172,12 +2061,11 @@ struct tvcard bttv_tvcards[] = { .pll = PLL_28, .tuner_type = TUNER_ABSENT, .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, }, [BTTV_BOARD_VD009_COMBI] = { .name = "PHYTEC VD-009 Combi (bt878)", .video_inputs = 10, - .audio_inputs = 0, + /* .audio_inputs= 0, */ .svhs = 9, .gpiomask = 0x00, .gpiomask2 = 0x03, /* gpiomask2 defines the bits used to switch audio @@ -2189,16 +2077,14 @@ struct tvcard bttv_tvcards[] = { .pll = PLL_28, .tuner_type = TUNER_ABSENT, .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, }, [BTTV_BOARD_IVC100] = { .name = "IVC-100", .video_inputs = 4, - .audio_inputs = 0, + /* .audio_inputs= 0, */ .tuner_type = TUNER_ABSENT, .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - .svhs = UNSET, + .svhs = NO_SVHS, .gpiomask = 0xdf, .muxsel = { 2, 3, 1, 0 }, .pll = PLL_28, @@ -2207,11 +2093,10 @@ struct tvcard bttv_tvcards[] = { /* IVC-120G - Alan Garfield */ .name = "IVC-120G", .video_inputs = 16, - .audio_inputs = 0, /* card has no audio */ + /* .audio_inputs= 0, */ .tuner_type = TUNER_ABSENT, .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - .svhs = UNSET, /* card has no svhs */ + .svhs = NO_SVHS, /* card has no svhs */ .needs_tvaudio = 0, .no_msp34xx = 1, .no_tda9875 = 1, @@ -2227,12 +2112,11 @@ struct tvcard bttv_tvcards[] = { [BTTV_BOARD_PC_HDTV] = { .name = "pcHDTV HD-2000 TV", .video_inputs = 4, - .audio_inputs = 1, + /* .audio_inputs= 1, */ .svhs = 2, .muxsel = { 2, 3, 1, 0 }, .tuner_type = TUNER_PHILIPS_FCV1236D, .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, .has_dvb = 1, }, [BTTV_BOARD_TWINHAN_DST] = { @@ -2242,14 +2126,13 @@ struct tvcard bttv_tvcards[] = { .no_tda7432 = 1, .tuner_type = TUNER_ABSENT, .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, .no_video = 1, .has_dvb = 1, }, [BTTV_BOARD_WINFASTVC100] = { .name = "Winfast VC100", .video_inputs = 3, - .audio_inputs = 0, + /* .audio_inputs= 0, */ .svhs = 1, .muxsel = { 3, 1, 1, 3 }, /* Vid In, SVid In, Vid over SVid in connector */ .no_msp34xx = 1, @@ -2257,13 +2140,12 @@ struct tvcard bttv_tvcards[] = { .no_tda7432 = 1, .tuner_type = TUNER_ABSENT, .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, .pll = PLL_28, }, [BTTV_BOARD_TEV560] = { .name = "Teppro TEV-560/InterVision IV-560", .video_inputs = 3, - .audio_inputs = 1, + /* .audio_inputs= 1, */ .svhs = 2, .gpiomask = 3, .muxsel = { 2, 3, 1, 1 }, @@ -2271,7 +2153,6 @@ struct tvcard bttv_tvcards[] = { .needs_tvaudio = 1, .tuner_type = TUNER_PHILIPS_PAL, .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, .pll = PLL_35, }, @@ -2279,11 +2160,10 @@ struct tvcard bttv_tvcards[] = { [BTTV_BOARD_SIMUS_GVC1100] = { .name = "SIMUS GVC1100", .video_inputs = 4, - .audio_inputs = 0, - .svhs = UNSET, + /* .audio_inputs= 0, */ + .svhs = NO_SVHS, .tuner_type = TUNER_ABSENT, .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, .pll = PLL_28, .muxsel = { 2, 2, 2, 2 }, .gpiomask = 0x3F, @@ -2301,15 +2181,14 @@ struct tvcard bttv_tvcards[] = { .pll = PLL_28, .tuner_type = TUNER_PHILIPS_PAL, .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, .has_remote = 1, }, [BTTV_BOARD_LMLBT4] = { /* http://linuxmedialabs.com */ .name = "LMLBT4", .video_inputs = 4, /* IN1,IN2,IN3,IN4 */ - .audio_inputs = 0, - .svhs = UNSET, + /* .audio_inputs= 0, */ + .svhs = NO_SVHS, .muxsel = { 2, 3, 1, 0 }, .no_msp34xx = 1, .no_tda9875 = 1, @@ -2317,16 +2196,14 @@ struct tvcard bttv_tvcards[] = { .needs_tvaudio = 0, .tuner_type = TUNER_ABSENT, .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, }, [BTTV_BOARD_TEKRAM_M205] = { /* Helmroos Harri */ .name = "Tekram M205 PRO", .video_inputs = 3, - .audio_inputs = 1, + /* .audio_inputs= 1, */ .tuner_type = TUNER_PHILIPS_PAL, .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, .svhs = 2, .needs_tvaudio = 0, .gpiomask = 0x68, @@ -2341,7 +2218,7 @@ struct tvcard bttv_tvcards[] = { /* bt878 TV + FM without subsystem ID */ .name = "Conceptronic CONTVFMi", .video_inputs = 3, - .audio_inputs = 1, + /* .audio_inputs= 1, */ .svhs = 2, .gpiomask = 0x008007, .muxsel = { 2, 3, 1, 1 }, @@ -2351,7 +2228,6 @@ struct tvcard bttv_tvcards[] = { .pll = PLL_28, .tuner_type = TUNER_PHILIPS_PAL, .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, .has_remote = 1, .has_radio = 1, }, @@ -2362,8 +2238,8 @@ struct tvcard bttv_tvcards[] = { /*0x79 in bttv.h*/ .name = "Euresys Picolo Tetra", .video_inputs = 4, - .audio_inputs = 0, - .svhs = UNSET, + /* .audio_inputs= 0, */ + .svhs = NO_SVHS, .gpiomask = 0, .gpiomask2 = 0x3C<<16,/*Set the GPIO[18]->GPIO[21] as output pin.==> drive the video inputs through analog multiplexers*/ .no_msp34xx = 1, @@ -2376,21 +2252,19 @@ struct tvcard bttv_tvcards[] = { .muxsel_hook = picolo_tetra_muxsel,/*Required as it doesn't follow the classic input selection policy*/ .tuner_type = TUNER_ABSENT, .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, }, [BTTV_BOARD_SPIRIT_TV] = { /* Spirit TV Tuner from http://spiritmodems.com.au */ /* Stafford Goodsell */ .name = "Spirit TV Tuner", .video_inputs = 3, - .audio_inputs = 1, + /* .audio_inputs= 1, */ .svhs = 2, .gpiomask = 0x0000000f, .muxsel = { 2, 1, 1 }, .gpiomux = { 0x02, 0x00, 0x00, 0x00 }, .tuner_type = TUNER_TEMIC_PAL, .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, .no_msp34xx = 1, .no_tda9875 = 1, }, @@ -2401,7 +2275,6 @@ struct tvcard bttv_tvcards[] = { .svhs = 1, .tuner_type = TUNER_ABSENT, .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, .muxsel = { 3 , 3 }, .no_msp34xx = 1, .no_tda9875 = 1, @@ -2425,43 +2298,40 @@ struct tvcard bttv_tvcards[] = { .pll = PLL_28, .tuner_type = TUNER_ABSENT, .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, .has_dvb = 1, .no_gpioirq = 1, .has_remote = 1, }, [BTTV_BOARD_MATRIX_VISIONSQ] = { /* andre.schwarz@matrix-vision.de */ - .name = "MATRIX Vision Sigma-SQ", - .video_inputs = 16, - .audio_inputs = 0, - .svhs = UNSET, - .gpiomask = 0x0, - .muxsel = { 2, 2, 2, 2, 2, 2, 2, 2, - 3, 3, 3, 3, 3, 3, 3, 3 }, - .muxsel_hook = sigmaSQ_muxsel, - .gpiomux = { 0 }, - .no_msp34xx = 1, - .pll = PLL_28, - .tuner_type = TUNER_ABSENT, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, + .name = "MATRIX Vision Sigma-SQ", + .video_inputs = 16, + /* .audio_inputs= 0, */ + .svhs = NO_SVHS, + .gpiomask = 0x0, + .muxsel = { 2, 2, 2, 2, 2, 2, 2, 2, + 3, 3, 3, 3, 3, 3, 3, 3 }, + .muxsel_hook = sigmaSQ_muxsel, + .gpiomux = { 0 }, + .no_msp34xx = 1, + .pll = PLL_28, + .tuner_type = TUNER_ABSENT, + .tuner_addr = ADDR_UNSET, }, [BTTV_BOARD_MATRIX_VISIONSLC] = { /* andre.schwarz@matrix-vision.de */ - .name = "MATRIX Vision Sigma-SLC", - .video_inputs = 4, - .audio_inputs = 0, - .svhs = UNSET, - .gpiomask = 0x0, - .muxsel = { 2, 2, 2, 2 }, - .muxsel_hook = sigmaSLC_muxsel, - .gpiomux = { 0 }, - .no_msp34xx = 1, - .pll = PLL_28, - .tuner_type = TUNER_ABSENT, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, + .name = "MATRIX Vision Sigma-SLC", + .video_inputs = 4, + /* .audio_inputs= 0, */ + .svhs = NO_SVHS, + .gpiomask = 0x0, + .muxsel = { 2, 2, 2, 2 }, + .muxsel_hook = sigmaSLC_muxsel, + .gpiomux = { 0 }, + .no_msp34xx = 1, + .pll = PLL_28, + .tuner_type = TUNER_ABSENT, + .tuner_addr = ADDR_UNSET, }, /* BTTV_BOARD_APAC_VIEWCOMP */ [BTTV_BOARD_APAC_VIEWCOMP] = { @@ -2469,8 +2339,8 @@ struct tvcard bttv_tvcards[] = { /* bt878 TV + FM 0x00000000 subsystem ID */ .name = "APAC Viewcomp 878(AMAX)", .video_inputs = 2, - .audio_inputs = 1, - .svhs = UNSET, + /* .audio_inputs= 1, */ + .svhs = NO_SVHS, .gpiomask = 0xFF, .muxsel = { 2, 3, 1, 1 }, .gpiomux = { 2, 0, 0, 0 }, @@ -2479,7 +2349,6 @@ struct tvcard bttv_tvcards[] = { .pll = PLL_28, .tuner_type = TUNER_PHILIPS_PAL, .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, .has_remote = 1, /* miniremote works, see ir-kbd-gpio.c */ .has_radio = 1, /* not every card has radio */ }, @@ -2496,13 +2365,12 @@ struct tvcard bttv_tvcards[] = { .has_dvb = 1, .tuner_type = TUNER_ABSENT, .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, }, [BTTV_BOARD_VGEAR_MYVCD] = { /* Steven */ .name = "V-Gear MyVCD", .video_inputs = 3, - .audio_inputs = 1, + /* .audio_inputs= 1, */ .svhs = 2, .gpiomask = 0x3f, .muxsel = {2, 3, 1, 0 }, @@ -2512,19 +2380,17 @@ struct tvcard bttv_tvcards[] = { .pll = PLL_28, .tuner_type = TUNER_PHILIPS_NTSC_M, .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, .has_radio = 0, }, [BTTV_BOARD_SUPER_TV] = { /* Rick C */ .name = "Super TV Tuner", .video_inputs = 4, - .audio_inputs = 1, + /* .audio_inputs= 1, */ .svhs = 2, .muxsel = { 2, 3, 1, 0 }, .tuner_type = TUNER_PHILIPS_NTSC, .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, .gpiomask = 0x008007, .gpiomux = { 0, 0x000001,0,0 }, .needs_tvaudio = 1, @@ -2534,8 +2400,8 @@ struct tvcard bttv_tvcards[] = { /* Chris Fanning */ .name = "Tibet Systems 'Progress DVR' CS16", .video_inputs = 16, - .audio_inputs = 0, - .svhs = UNSET, + /* .audio_inputs= 0, */ + .svhs = NO_SVHS, .muxsel = { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 }, .pll = PLL_28, .no_msp34xx = 1, @@ -2543,7 +2409,6 @@ struct tvcard bttv_tvcards[] = { .no_tda7432 = 1, .tuner_type = TUNER_ABSENT, .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, .muxsel_hook = tibetCS16_muxsel, }, [BTTV_BOARD_KODICOM_4400R] = { @@ -2560,11 +2425,10 @@ struct tvcard bttv_tvcards[] = { */ .name = "Kodicom 4400R (master)", .video_inputs = 16, - .audio_inputs = 0, + /* .audio_inputs= 0, */ .tuner_type = TUNER_ABSENT, .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - .svhs = UNSET, + .svhs = NO_SVHS, /* GPIO bits 0-9 used for analog switch: * 00 - 03: camera selector * 04 - 06: channel (controller) selector @@ -2591,11 +2455,10 @@ struct tvcard bttv_tvcards[] = { */ .name = "Kodicom 4400R (slave)", .video_inputs = 16, - .audio_inputs = 0, + /* .audio_inputs= 0, */ .tuner_type = TUNER_ABSENT, .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - .svhs = UNSET, + .svhs = NO_SVHS, .gpiomask = 0x010000, .no_gpioirq = 1, .muxsel = { 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 }, @@ -2611,12 +2474,11 @@ struct tvcard bttv_tvcards[] = { /* Adlink RTV24 with special unlock codes */ .name = "Adlink RTV24", .video_inputs = 4, - .audio_inputs = 1, + /* .audio_inputs= 1, */ .svhs = 2, .muxsel = { 2, 3, 1, 0 }, .tuner_type = UNSET, .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, .pll = PLL_28, }, /* ---- card 0x87---------------------------------- */ @@ -2625,9 +2487,8 @@ struct tvcard bttv_tvcards[] = { .name = "DViCO FusionHDTV 5 Lite", .tuner_type = TUNER_LG_TDVS_H06XF, /* TDVS-H064F */ .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, .video_inputs = 3, - .audio_inputs = 1, + /* .audio_inputs= 1, */ .svhs = 2, .muxsel = { 2, 3, 1 }, .gpiomask = 0x00e00007, @@ -2643,7 +2504,7 @@ struct tvcard bttv_tvcards[] = { /* Mauro Carvalho Chehab */ .name = "Acorp Y878F", .video_inputs = 3, - .audio_inputs = 1, + /* .audio_inputs= 1, */ .svhs = 2, .gpiomask = 0x01fe00, .muxsel = { 2, 3, 1, 1 }, @@ -2653,14 +2514,13 @@ struct tvcard bttv_tvcards[] = { .pll = PLL_28, .tuner_type = TUNER_YMEC_TVF66T5_B_DFF, .tuner_addr = 0xc1 >>1, - .radio_addr = 0xc1 >>1, .has_radio = 1, }, /* ---- card 0x89 ---------------------------------- */ [BTTV_BOARD_CONCEPTRONIC_CTVFMI2] = { .name = "Conceptronic CTVFMi v2", .video_inputs = 3, - .audio_inputs = 1, + /* .audio_inputs= 1, */ .svhs = 2, .gpiomask = 0x001c0007, .muxsel = { 2, 3, 1, 1 }, @@ -2670,34 +2530,32 @@ struct tvcard bttv_tvcards[] = { .pll = PLL_28, .tuner_type = TUNER_TENA_9533_DI, .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, .has_remote = 1, .has_radio = 1, }, /* ---- card 0x8a ---------------------------------- */ [BTTV_BOARD_PV_BT878P_2E] = { - .name = "Prolink Pixelview PV-BT878P+ (Rev.2E)", - .video_inputs = 5, - .audio_inputs = 1, - .svhs = 3, - .gpiomask = 0x01fe00, - .muxsel = { 2,3,1,1,-1 }, - .digital_mode = DIGITAL_MODE_CAMERA, - .gpiomux = { 0x00400, 0x10400, 0x04400, 0x80000 }, - .gpiomute = 0x12400, - .no_msp34xx = 1, - .pll = PLL_28, - .tuner_type = TUNER_LG_PAL_FM, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - .has_remote = 1, + .name = "Prolink Pixelview PV-BT878P+ (Rev.2E)", + .video_inputs = 5, + /* .audio_inputs= 1, */ + .svhs = 3, + .gpiomask = 0x01fe00, + .muxsel = { 2, 3, 1, 1, -1 }, + /* .digital_mode= DIGITAL_MODE_CAMERA, */ + .gpiomux = { 0x00400, 0x10400, 0x04400, 0x80000 }, + .gpiomute = 0x12400, + .no_msp34xx = 1, + .pll = PLL_28, + .tuner_type = TUNER_LG_PAL_FM, + .tuner_addr = ADDR_UNSET, + .has_remote = 1, }, /* ---- card 0x8b ---------------------------------- */ [BTTV_BOARD_PV_M4900] = { /* Sérgio Fortier */ .name = "Prolink PixelView PlayTV MPEG2 PV-M4900", .video_inputs = 3, - .audio_inputs = 1, + /* .audio_inputs= 1, */ .svhs = 2, .gpiomask = 0x3f, .muxsel = { 2, 3, 1, 1 }, @@ -2707,7 +2565,6 @@ struct tvcard bttv_tvcards[] = { .pll = PLL_28, .tuner_type = TUNER_YMEC_TVF_5533MF, .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, .has_radio = 1, .has_remote = 1, }, @@ -2727,8 +2584,8 @@ struct tvcard bttv_tvcards[] = { [BTTV_BOARD_OSPREY440] = { .name = "Osprey 440", .video_inputs = 4, - .audio_inputs = 2, /* this is meaningless */ - .svhs = UNSET, + /* .audio_inputs= 2, */ + .svhs = NO_SVHS, .muxsel = { 2, 3, 0, 1 }, /* 3,0,1 are guesses */ .gpiomask = 0x303, .gpiomute = 0x000, /* int + 32kHz */ @@ -2736,7 +2593,6 @@ struct tvcard bttv_tvcards[] = { .pll = PLL_28, .tuner_type = TUNER_ABSENT, .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, .no_msp34xx = 1, .no_tda9875 = 1, .no_tda7432 = 1, @@ -2745,7 +2601,7 @@ struct tvcard bttv_tvcards[] = { [BTTV_BOARD_ASOUND_SKYEYE] = { .name = "Asound Skyeye PCTV", .video_inputs = 3, - .audio_inputs = 1, + /* .audio_inputs= 1, */ .svhs = 2, .gpiomask = 15, .muxsel = { 2, 3, 1, 1 }, @@ -2755,13 +2611,12 @@ struct tvcard bttv_tvcards[] = { .pll = PLL_28, .tuner_type = TUNER_PHILIPS_NTSC, .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, }, /* ---- card 0x8e ---------------------------------- */ [BTTV_BOARD_SABRENT_TVFM] = { .name = "Sabrent TV-FM (bttv version)", .video_inputs = 3, - .audio_inputs = 1, + /* .audio_inputs= 1, */ .svhs = 2, .gpiomask = 0x108007, .muxsel = { 2, 3, 1, 1 }, @@ -2778,8 +2633,8 @@ struct tvcard bttv_tvcards[] = { [BTTV_BOARD_HAUPPAUGE_IMPACTVCB] = { .name = "Hauppauge ImpactVCB (bt878)", .video_inputs = 4, - .audio_inputs = 0, - .svhs = UNSET, + /* .audio_inputs= 0, */ + .svhs = NO_SVHS, .gpiomask = 0x0f, /* old: 7 */ .muxsel = { 0, 1, 3, 2 }, /* Composite 0-3 */ .no_msp34xx = 1, @@ -2787,7 +2642,6 @@ struct tvcard bttv_tvcards[] = { .no_tda7432 = 1, .tuner_type = TUNER_ABSENT, .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, }, [BTTV_BOARD_MACHTV_MAGICTV] = { /* Julian Calaby @@ -2799,7 +2653,7 @@ struct tvcard bttv_tvcards[] = { .name = "MagicTV", /* rebranded MachTV */ .video_inputs = 3, - .audio_inputs = 1, + /* .audio_inputs= 1, */ .svhs = 2, .gpiomask = 7, .muxsel = { 2, 3, 1, 1 }, @@ -2807,7 +2661,6 @@ struct tvcard bttv_tvcards[] = { .gpiomute = 4, .tuner_type = TUNER_TEMIC_4009FR5_PAL, .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, .pll = PLL_28, .has_radio = 1, .has_remote = 1, @@ -2815,31 +2668,28 @@ struct tvcard bttv_tvcards[] = { [BTTV_BOARD_SSAI_SECURITY] = { .name = "SSAI Security Video Interface", .video_inputs = 4, - .audio_inputs = 0, - .svhs = UNSET, + /* .audio_inputs= 0, */ + .svhs = NO_SVHS, .muxsel = { 0, 1, 2, 3 }, .tuner_type = TUNER_ABSENT, .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, }, [BTTV_BOARD_SSAI_ULTRASOUND] = { .name = "SSAI Ultrasound Video Interface", .video_inputs = 2, - .audio_inputs = 0, + /* .audio_inputs= 0, */ .svhs = 1, .muxsel = { 2, 0, 1, 3 }, .tuner_type = TUNER_ABSENT, .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, }, /* ---- card 0x94---------------------------------- */ [BTTV_BOARD_DVICO_FUSIONHDTV_2] = { .name = "DViCO FusionHDTV 2", .tuner_type = TUNER_PHILIPS_FCV1236D, .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, .video_inputs = 3, - .audio_inputs = 1, + /* .audio_inputs= 1, */ .svhs = 2, .muxsel = { 2, 3, 1 }, .gpiomask = 0x00e00007, @@ -2853,7 +2703,7 @@ struct tvcard bttv_tvcards[] = { [BTTV_BOARD_TYPHOON_TVTUNERPCI] = { .name = "Typhoon TV-Tuner PCI (50684)", .video_inputs = 3, - .audio_inputs = 1, + /* .audio_inputs= 1, */ .svhs = 2, .gpiomask = 0x3014f, .muxsel = { 2, 3, 1, 1 }, @@ -2863,24 +2713,22 @@ struct tvcard bttv_tvcards[] = { .pll = PLL_28, .tuner_type = TUNER_PHILIPS_PAL_I, .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, }, [BTTV_BOARD_GEOVISION_GV600] = { /* emhn@usb.ve */ - .name = "Geovision GV-600", - .video_inputs = 16, - .audio_inputs = 0, - .svhs = UNSET, - .gpiomask = 0x0, - .muxsel = { 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2 }, - .muxsel_hook = geovision_muxsel, - .gpiomux = { 0 }, - .no_msp34xx = 1, - .pll = PLL_28, - .tuner_type = TUNER_ABSENT, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, + .name = "Geovision GV-600", + .video_inputs = 16, + /* .audio_inputs= 0, */ + .svhs = NO_SVHS, + .gpiomask = 0x0, + .muxsel = { 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2 }, + .muxsel_hook = geovision_muxsel, + .gpiomux = { 0 }, + .no_msp34xx = 1, + .pll = PLL_28, + .tuner_type = TUNER_ABSENT, + .tuner_addr = ADDR_UNSET, }, [BTTV_BOARD_KOZUMI_KTV_01C] = { /* Mauro Lacy @@ -2888,7 +2736,7 @@ struct tvcard bttv_tvcards[] = { .name = "Kozumi KTV-01C", .video_inputs = 3, - .audio_inputs = 1, + /* .audio_inputs= 1, */ .svhs = 2, .gpiomask = 0x008007, .muxsel = { 2, 3, 1, 1 }, @@ -2897,7 +2745,6 @@ struct tvcard bttv_tvcards[] = { .needs_tvaudio = 0, .tuner_type = TUNER_PHILIPS_FM1216ME_MK3, /* TCL MK3 */ .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, .pll = PLL_28, .has_radio = 1, .has_remote = 1, @@ -2907,7 +2754,7 @@ struct tvcard bttv_tvcards[] = { Mauro Carvalho Chehab IR disabled bit 18/17 = 00 -> mute @@ -2921,7 +2768,6 @@ struct tvcard bttv_tvcards[] = { .gpiomute = 0, .tuner_type = TUNER_TCL_MF02GIP_5N, .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, .pll = PLL_28, .has_radio = 1, .has_remote = 1, @@ -2930,8 +2776,8 @@ struct tvcard bttv_tvcards[] = { /* D.Heer@Phytec.de */ .name = "PHYTEC VD-012 (bt878)", .video_inputs = 4, - .audio_inputs = 0, - .svhs = UNSET, /* card has no s-video */ + /* .audio_inputs= 0, */ + .svhs = NO_SVHS, .gpiomask = 0x00, .muxsel = { 0, 2, 3, 1 }, .gpiomux = { 0, 0, 0, 0 }, /* card has no audio */ @@ -2939,13 +2785,12 @@ struct tvcard bttv_tvcards[] = { .pll = PLL_28, .tuner_type = TUNER_ABSENT, .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, }, [BTTV_BOARD_VD012_X1] = { /* D.Heer@Phytec.de */ .name = "PHYTEC VD-012-X1 (bt878)", .video_inputs = 4, - .audio_inputs = 0, + /* .audio_inputs= 0, */ .svhs = 3, .gpiomask = 0x00, .muxsel = { 2, 3, 1 }, @@ -2954,13 +2799,12 @@ struct tvcard bttv_tvcards[] = { .pll = PLL_28, .tuner_type = TUNER_ABSENT, .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, }, [BTTV_BOARD_VD012_X2] = { /* D.Heer@Phytec.de */ .name = "PHYTEC VD-012-X2 (bt878)", .video_inputs = 4, - .audio_inputs = 0, + /* .audio_inputs= 0, */ .svhs = 3, .gpiomask = 0x00, .muxsel = { 3, 2, 1 }, @@ -2969,7 +2813,6 @@ struct tvcard bttv_tvcards[] = { .pll = PLL_28, .tuner_type = TUNER_ABSENT, .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, } }; @@ -3574,7 +3417,8 @@ void __devinit bttv_init_card2(struct bttv *btv) bttv_call_i2c_clients(btv, TUNER_SET_CONFIG, &tda9887_cfg); } - btv->svhs = bttv_tvcards[btv->c.type].svhs; + btv->svhs = bttv_tvcards[btv->c.type].svhs == NO_SVHS ? + UNSET : bttv_tvcards[btv->c.type].svhs; if (svhs[btv->c.nr] != UNSET) btv->svhs = svhs[btv->c.nr]; if (remote[btv->c.nr] != UNSET) diff --git a/drivers/media/video/bt8xx/bttv.h b/drivers/media/video/bt8xx/bttv.h index 861ff2f8f985..a2e140a25df6 100644 --- a/drivers/media/video/bt8xx/bttv.h +++ b/drivers/media/video/bt8xx/bttv.h @@ -192,10 +192,6 @@ #define WINVIEW_PT2254_DATA 0x20 #define WINVIEW_PT2254_STROBE 0x80 -/* digital_mode */ -#define DIGITAL_MODE_VIDEO 1 -#define DIGITAL_MODE_CAMERA 2 - struct bttv_core { /* device structs */ struct pci_dev *pci; @@ -211,19 +207,24 @@ struct bttv_core { struct bttv; -struct tvcard -{ +struct tvcard { char *name; - unsigned int video_inputs; - unsigned int audio_inputs; - unsigned int svhs; - unsigned int digital_mode; // DIGITAL_MODE_CAMERA or DIGITAL_MODE_VIDEO + void (*volume_gpio)(struct bttv *btv, __u16 volume); + void (*audio_mode_gpio)(struct bttv *btv, struct v4l2_tuner *tuner, int set); + void (*muxsel_hook)(struct bttv *btv, unsigned int input); + u32 gpiomask; u32 muxsel[16]; u32 gpiomux[4]; /* Tuner, Radio, external, internal */ u32 gpiomute; /* GPIO mute setting */ u32 gpiomask2; /* GPIO MUX mask */ + unsigned int tuner_type; + u8 tuner_addr; + u8 video_inputs; /* Number of inputs */ + unsigned int svhs:4; /* Which input is s-video */ +#define NO_SVHS 15 + /* i2c audio flags */ unsigned int no_msp34xx:1; unsigned int no_tda9875:1; @@ -231,28 +232,15 @@ struct tvcard unsigned int needs_tvaudio:1; unsigned int msp34xx_alt:1; - /* flag: video pci function is unused */ - unsigned int no_video:1; + unsigned int no_video:1; /* video pci function is unused */ unsigned int has_dvb:1; unsigned int has_remote:1; + unsigned int has_radio:1; unsigned int no_gpioirq:1; - - /* other settings */ - unsigned int pll; + unsigned int pll:2; #define PLL_NONE 0 #define PLL_28 1 #define PLL_35 2 - - unsigned int tuner_type; - unsigned int tuner_addr; - unsigned int radio_addr; - - unsigned int has_radio; - - void (*volume_gpio)(struct bttv *btv, __u16 volume); - void (*audio_mode_gpio)(struct bttv *btv, struct v4l2_tuner *tuner, int set); - - void (*muxsel_hook)(struct bttv *btv, unsigned int input); }; extern struct tvcard bttv_tvcards[]; -- cgit v1.2.3 From 5221e21e5ecd3aebd2e8e3234bd18883ce720945 Mon Sep 17 00:00:00 2001 From: Trent Piepho Date: Wed, 28 Jan 2009 21:32:59 -0300 Subject: V4L/DVB (10562): bttv: rework the way digital inputs are indicated The code was using a muxsel value of -1U to indicate a digital input. A couple places in were checking of muxsel < 0 to detect this, which doesn't work of course because muxsel is unsigned and can't be negative. Only a couple cards had digital inputs and it was always the last one, so for the card database create a one bit field that indicates the last input is digital. On init, this is used to set a new field in the bttv struct to the digital input's number or UNSET for none. This makes it easier to check if the current input is digital. Signed-off-by: Trent Piepho Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/bt8xx/bttv-cards.c | 11 ++++++++--- drivers/media/video/bt8xx/bttv-driver.c | 2 +- drivers/media/video/bt8xx/bttv-risc.c | 4 ++-- drivers/media/video/bt8xx/bttv.h | 9 +++++---- drivers/media/video/bt8xx/bttvp.h | 2 +- 5 files changed, 17 insertions(+), 11 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/bt8xx/bttv-cards.c b/drivers/media/video/bt8xx/bttv-cards.c index f49e6e686628..d545d48fac58 100644 --- a/drivers/media/video/bt8xx/bttv-cards.c +++ b/drivers/media/video/bt8xx/bttv-cards.c @@ -633,8 +633,9 @@ struct tvcard bttv_tvcards[] = { .video_inputs = 3, /* .audio_inputs= 1, */ .svhs = NO_SVHS, + .has_dig_in = 1, .gpiomask = 7, - .muxsel = { 2, 3, -1 }, + .muxsel = { 2, 3, 0 }, /* input 2 is digital */ /* .digital_mode= DIGITAL_MODE_CAMERA, */ .gpiomux = { 0, 0, 0, 0 }, .no_msp34xx = 1, @@ -1069,8 +1070,9 @@ struct tvcard bttv_tvcards[] = { .video_inputs = 5, /* .audio_inputs= 1, */ .svhs = 3, + .has_dig_in = 1, .gpiomask = 0xAA0000, - .muxsel = { 2, 3, 1, 1, -1 }, + .muxsel = { 2, 3, 1, 1, 0 }, /* input 4 is digital */ /* .digital_mode= DIGITAL_MODE_CAMERA, */ .gpiomux = { 0x20000, 0, 0x80000, 0x80000 }, .gpiomute = 0xa8000, @@ -2539,8 +2541,9 @@ struct tvcard bttv_tvcards[] = { .video_inputs = 5, /* .audio_inputs= 1, */ .svhs = 3, + .has_dig_in = 1, .gpiomask = 0x01fe00, - .muxsel = { 2, 3, 1, 1, -1 }, + .muxsel = { 2, 3, 1, 1, 0 }, /* in 4 is digital */ /* .digital_mode= DIGITAL_MODE_CAMERA, */ .gpiomux = { 0x00400, 0x10400, 0x04400, 0x80000 }, .gpiomute = 0x12400, @@ -3417,6 +3420,8 @@ void __devinit bttv_init_card2(struct bttv *btv) bttv_call_i2c_clients(btv, TUNER_SET_CONFIG, &tda9887_cfg); } + btv->dig = bttv_tvcards[btv->c.type].has_dig_in ? + bttv_tvcards[btv->c.type].video_inputs - 1 : UNSET; btv->svhs = bttv_tvcards[btv->c.type].svhs == NO_SVHS ? UNSET : bttv_tvcards[btv->c.type].svhs; if (svhs[btv->c.nr] != UNSET) diff --git a/drivers/media/video/bt8xx/bttv-driver.c b/drivers/media/video/bt8xx/bttv-driver.c index 1bb6c2df366a..8d9756b9587e 100644 --- a/drivers/media/video/bt8xx/bttv-driver.c +++ b/drivers/media/video/bt8xx/bttv-driver.c @@ -1040,7 +1040,7 @@ static void bt848A_set_timing(struct bttv *btv) int table_idx = bttv_tvnorms[btv->tvnorm].sram; int fsc = bttv_tvnorms[btv->tvnorm].Fsc; - if (UNSET == bttv_tvcards[btv->c.type].muxsel[btv->input]) { + if (btv->input == btv->dig) { dprintk("bttv%d: load digital timing table (table_idx=%d)\n", btv->c.nr,table_idx); diff --git a/drivers/media/video/bt8xx/bttv-risc.c b/drivers/media/video/bt8xx/bttv-risc.c index 5b1b8e4c78ba..d16af2836379 100644 --- a/drivers/media/video/bt8xx/bttv-risc.c +++ b/drivers/media/video/bt8xx/bttv-risc.c @@ -341,7 +341,7 @@ bttv_calc_geo_old(struct bttv *btv, struct bttv_geometry *geo, int totalwidth = tvnorm->totalwidth; int scaledtwidth = tvnorm->scaledtwidth; - if (bttv_tvcards[btv->c.type].muxsel[btv->input] < 0) { + if (btv->input == btv->dig) { swidth = 720; totalwidth = 858; scaledtwidth = 858; @@ -391,7 +391,7 @@ bttv_calc_geo (struct bttv * btv, && crop->width == tvnorm->cropcap.defrect.width && crop->height == tvnorm->cropcap.defrect.height && width <= tvnorm->swidth /* see PAL-Nc et al */) - || bttv_tvcards[btv->c.type].muxsel[btv->input] < 0) { + || btv->input == btv->dig) { bttv_calc_geo_old(btv, geo, width, height, both_fields, tvnorm); return; diff --git a/drivers/media/video/bt8xx/bttv.h b/drivers/media/video/bt8xx/bttv.h index a2e140a25df6..e377e2887a53 100644 --- a/drivers/media/video/bt8xx/bttv.h +++ b/drivers/media/video/bt8xx/bttv.h @@ -224,6 +224,10 @@ struct tvcard { u8 video_inputs; /* Number of inputs */ unsigned int svhs:4; /* Which input is s-video */ #define NO_SVHS 15 + unsigned int pll:2; +#define PLL_NONE 0 +#define PLL_28 1 +#define PLL_35 2 /* i2c audio flags */ unsigned int no_msp34xx:1; @@ -236,11 +240,8 @@ struct tvcard { unsigned int has_dvb:1; unsigned int has_remote:1; unsigned int has_radio:1; + unsigned int has_dig_in:1; /* Has digital input (always last input) */ unsigned int no_gpioirq:1; - unsigned int pll:2; -#define PLL_NONE 0 -#define PLL_28 1 -#define PLL_35 2 }; extern struct tvcard bttv_tvcards[]; diff --git a/drivers/media/video/bt8xx/bttvp.h b/drivers/media/video/bt8xx/bttvp.h index 230e148e78fe..23ab1c9527e4 100644 --- a/drivers/media/video/bt8xx/bttvp.h +++ b/drivers/media/video/bt8xx/bttvp.h @@ -329,7 +329,7 @@ struct bttv { unsigned int cardid; /* pci subsystem id (bt878 based ones) */ unsigned int tuner_type; /* tuner chip type */ unsigned int tda9887_conf; - unsigned int svhs; + unsigned int svhs, dig; struct bttv_pll_info pll; int triton1; int gpioirq; -- cgit v1.2.3 From fb5deb1b9ecc3c64b713f33ec56781c01a0b11b9 Mon Sep 17 00:00:00 2001 From: Trent Piepho Date: Wed, 28 Jan 2009 21:32:59 -0300 Subject: V4L/DVB (10563): bttv: clean up mux code for IVC-120G The card data for BTTV_BOARD_IVC120 set muxsel to a bunch of bogus values (1 to 16), which the common mux code would use to set the Bt878's mux to some random value. Then the custom code in ivc120_muxsel() would change the Bt878's mux to the right value (always MUX0). Better to just make the muxsel data correct (all zeros, easy!) and get the mux right to begin with. Then the extra Bt878 mux setting code in ivc120_muxsel() can be eliminated (the rest of the code for the IVC-120G's external mux is still there of course). This will help me clean up muxsel for some other changes. It should also get rid of an unnecessary mux switch when changing from certain inputs to certain other inputs on the IVC-120G. Cc: Alan Garfield Signed-off-by: Trent Piepho Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/bt8xx/bttv-cards.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/bt8xx/bttv-cards.c b/drivers/media/video/bt8xx/bttv-cards.c index d545d48fac58..d055c2770469 100644 --- a/drivers/media/video/bt8xx/bttv-cards.c +++ b/drivers/media/video/bt8xx/bttv-cards.c @@ -2104,8 +2104,7 @@ struct tvcard bttv_tvcards[] = { .no_tda9875 = 1, .no_tda7432 = 1, .gpiomask = 0x00, - .muxsel = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, - 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10 }, + .muxsel = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, .muxsel_hook = ivc120_muxsel, .pll = PLL_28, }, @@ -4445,8 +4444,7 @@ static void ivc120_muxsel(struct bttv *btv, unsigned int input) bttv_I2CWrite(btv, I2C_TDA8540_ALT6, 0x02, ((matrix == 2) ? 0x03 : 0x00), 1); /* 9-12 */ - /* Selects MUX0 for input on the 878 */ - btaor((0)<<5, ~(3<<5), BT848_IFORM); + /* 878's MUX0 is already selected for input via muxsel values */ } -- cgit v1.2.3 From 15f8eeb2a86b969d82bfca5d54f1fb30c35cf243 Mon Sep 17 00:00:00 2001 From: Trent Piepho Date: Wed, 28 Jan 2009 21:32:59 -0300 Subject: V4L/DVB (10564): bttv: fix external mux for PHYTEC VD-009 Old versions of the bttv driver would use the high nibble of an input's muxsel value to program the GPIO lines enabled via gpiomask2. Apparently this was supposed to be for switching external audio muxes. Anyway, the code that did this was removed sometime in the pre-git 2.6 series. These phytec boards used this feature to control an external video mux and I guess no one noticed when they removed the code. So add a muxsel_hook for these boards that does the necessary gpio setting. BTW, I doubt the needs_tvaudio setting for these cards is correct. Cc: Dirk Heer Signed-off-by: Trent Piepho Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/bt8xx/bttv-cards.c | 26 ++++++++++++++++++-------- 1 file changed, 18 insertions(+), 8 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/bt8xx/bttv-cards.c b/drivers/media/video/bt8xx/bttv-cards.c index d055c2770469..2832bafa3695 100644 --- a/drivers/media/video/bt8xx/bttv-cards.c +++ b/drivers/media/video/bt8xx/bttv-cards.c @@ -73,6 +73,8 @@ static void sigmaSQ_muxsel(struct bttv *btv, unsigned int input); static void geovision_muxsel(struct bttv *btv, unsigned int input); +static void phytec_muxsel(struct bttv *btv, unsigned int input); + static int terratec_active_radio_upgrade(struct bttv *btv); static int tea5757_read(struct bttv *btv); static int tea5757_write(struct bttv *btv, int value); @@ -2054,10 +2056,9 @@ struct tvcard bttv_tvcards[] = { /* .audio_inputs= 0, */ .svhs = 9, .gpiomask = 0x00, - .gpiomask2 = 0x03, /* gpiomask2 defines the bits used to switch audio - via the upper nibble of muxsel. here: used for - xternal video-mux */ - .muxsel = { 0x02, 0x12, 0x22, 0x32, 0x03, 0x13, 0x23, 0x33, 0x01, 0x00 }, + .gpiomask2 = 0x03, /* used for external vodeo mux */ + .muxsel = { 2, 2, 2, 2, 3, 3, 3, 3, 1, 0 }, + .muxsel_hook = phytec_muxsel, .gpiomux = { 0, 0, 0, 0 }, /* card has no audio */ .needs_tvaudio = 1, .pll = PLL_28, @@ -2070,10 +2071,9 @@ struct tvcard bttv_tvcards[] = { /* .audio_inputs= 0, */ .svhs = 9, .gpiomask = 0x00, - .gpiomask2 = 0x03, /* gpiomask2 defines the bits used to switch audio - via the upper nibble of muxsel. here: used for - xternal video-mux */ - .muxsel = { 0x02, 0x12, 0x22, 0x32, 0x03, 0x13, 0x23, 0x33, 0x01, 0x01 }, + .gpiomask2 = 0x03, /* used for external vodeo mux */ + .muxsel = { 2, 2, 2, 2, 3, 3, 3, 3, 1, 1 }, + .muxsel_hook = phytec_muxsel, .gpiomux = { 0, 0, 0, 0 }, /* card has no audio */ .needs_tvaudio = 1, .pll = PLL_28, @@ -4528,6 +4528,16 @@ static void PXC200_muxsel(struct bttv *btv, unsigned int input) printk(KERN_DEBUG "bttv%d: setting input channel to:%d\n", btv->c.nr,(int)mux); } +static void phytec_muxsel(struct bttv *btv, unsigned int input) +{ + unsigned int mux = input % 4; + + if (input == btv->svhs) + mux = 0; + + gpio_bits(0x3, mux); +} + /* ----------------------------------------------------------------------- */ /* motherboard chipset specific stuff */ -- cgit v1.2.3 From 13afaefc0392d377d23ce5b7e1f4f3944a00e1f1 Mon Sep 17 00:00:00 2001 From: Trent Piepho Date: Wed, 28 Jan 2009 21:32:59 -0300 Subject: V4L/DVB (10565): bttv: fix external mux for RemoteVision MX Old versions of the bttv driver would use the high nibble of an input's muxsel value to program the GPIO lines enabled via gpiomask2. Apparently this was supposed to be for switching external audio muxes. Anyway, the code that did this was removed sometime in the pre-git 2.6 series. The RemoteVision MX board used this feature to control an external video mux and I guess no one noticed when they removed the code. Move the extra gpio mux data out of the high nibble of muxsel and to rv605_muxsel(), then have that function set the gpio lines with it. From looking at the CD22M3494E datasheet, it seems like the mdelay(1) is a much longer delay than necessary. It looks like only around 20 ns is necessary. Cc: Miguel Freitas Signed-off-by: Trent Piepho Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/bt8xx/bttv-cards.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/bt8xx/bttv-cards.c b/drivers/media/video/bt8xx/bttv-cards.c index 2832bafa3695..df4d7752eb77 100644 --- a/drivers/media/video/bt8xx/bttv-cards.c +++ b/drivers/media/video/bt8xx/bttv-cards.c @@ -1516,8 +1516,7 @@ struct tvcard bttv_tvcards[] = { .svhs = NO_SVHS, .gpiomask = 0x00, .gpiomask2 = 0x07ff, - .muxsel = { 0x33, 0x13, 0x23, 0x43, 0xf3, 0x73, 0xe3, 0x03, - 0xd3, 0xb3, 0xc3, 0x63, 0x93, 0x53, 0x83, 0xa3 }, + .muxsel = { 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 }, .no_msp34xx = 1, .no_tda9875 = 1, .tuner_type = TUNER_ABSENT, @@ -4178,6 +4177,11 @@ void tea5757_set_freq(struct bttv *btv, unsigned short freq) */ static void rv605_muxsel(struct bttv *btv, unsigned int input) { + static const u8 muxgpio[] = { 0x3, 0x1, 0x2, 0x4, 0xf, 0x7, 0xe, 0x0, + 0xd, 0xb, 0xc, 0x6, 0x9, 0x5, 0x8, 0xa }; + + gpio_bits(0x07f, muxgpio[input]); + /* reset all conections */ gpio_bits(0x200,0x200); mdelay(1); @@ -4185,7 +4189,6 @@ static void rv605_muxsel(struct bttv *btv, unsigned int input) mdelay(1); /* create a new connection */ - gpio_bits(0x480,0x080); gpio_bits(0x480,0x480); mdelay(1); gpio_bits(0x480,0x080); -- cgit v1.2.3 From 430390e67b39ccf56d98286f5e5a72d903c9cf87 Mon Sep 17 00:00:00 2001 From: Trent Piepho Date: Wed, 28 Jan 2009 21:32:59 -0300 Subject: V4L/DVB (10566): bttv: clean up mux code for IDS Eagle This card apparently uses an external mux and the Bt878's mux should always be set to MUX2. The values for the external mux control bits were stored in the muxsel field. This meant that when changing inputs the driver would switch the Bt878's mux to whatever value the external mux was supposed to be set to, then eagle_muxsel() would switch it back to MUX2 and program the external mux. This creates an unnecessary switch of the Bt878's mux. So change muxsel to be 2 for each input. The external mux bits are just "input&3" so they don't really need to be stored anywhere. This also eliminates the last non-standard use of the muxsel data. Cc: M G Berberich Signed-off-by: Trent Piepho Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/bt8xx/bttv-cards.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/bt8xx/bttv-cards.c b/drivers/media/video/bt8xx/bttv-cards.c index df4d7752eb77..fc2b796b25fc 100644 --- a/drivers/media/video/bt8xx/bttv-cards.c +++ b/drivers/media/video/bt8xx/bttv-cards.c @@ -1799,7 +1799,7 @@ struct tvcard bttv_tvcards[] = { .tuner_addr = ADDR_UNSET, .svhs = NO_SVHS, .gpiomask = 0, - .muxsel = { 0, 1, 2, 3 }, + .muxsel = { 2, 2, 2, 2 }, .muxsel_hook = eagle_muxsel, .no_msp34xx = 1, .no_tda9875 = 1, @@ -3109,8 +3109,7 @@ static void init_ids_eagle(struct bttv *btv) * has its own multiplexer */ static void eagle_muxsel(struct bttv *btv, unsigned int input) { - btaor((2)<<5, ~(3<<5), BT848_IFORM); - gpio_bits(3,bttv_tvcards[btv->c.type].muxsel[input&7]); + gpio_bits(3, input & 3); /* composite */ /* set chroma ADC to sleep */ -- cgit v1.2.3 From 6f98700a5bb8d218162b04db1b8a3921a0dcc7ce Mon Sep 17 00:00:00 2001 From: Trent Piepho Date: Wed, 28 Jan 2009 21:32:59 -0300 Subject: V4L/DVB (10567): bttv: shrink muxsel data in card database Over half of the card database was used to store muxsel data. 64 bytes were used to store one 32 bit word for each of up to 16 inputs. The Bt8x8 only has two bits to control its mux, so muxsel data for 16 inputs will fit into a single 32 bit word. There were a couple cards that had special muxsel data that didn't fit in two bits, but I cleaned them up in earlier patches. Unfortunately, C doesn't allow us to have an array of bit fields. This makes initializing the structure more of a pain. But with some cpp magic, we can do it by changing: .muxsel = { 2, 3, 0, 1 }, .muxsel = { 2, 2, 2, 2, 3, 3, 3, 3, 1, 1 }, Into: .muxsel = MUXSEL(2, 3, 0, 1), .muxsel = MUXSEL(2, 2, 2, 2, 3, 3, 3, 3, 1, 1), That's not so bad. MUXSEL is a fancy macro that packs the arguments (of which there can be one to sixteen!) into a single word two bits at a time. It's a compile time constant (a variadic function wouldn't be) so we can use it to initialize the structure. It's important the the arguments to the macro only be plain decimal integers. Stuff like "0x01", "(2)", or "MUX3" won't work properly. I also created an accessor function, bttv_muxsel(btv, input), that gets the mux bits for the selected input. It makes it cleaner to change the way the muxsel data is stored. This patch doesn't change the code size and decreases the datasegment by 9440 bytes. Signed-off-by: Trent Piepho Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/bt8xx/bttv-cards.c | 316 ++++++++++++++++---------------- drivers/media/video/bt8xx/bttv-driver.c | 2 +- drivers/media/video/bt8xx/bttv.h | 30 ++- drivers/media/video/bt8xx/bttvp.h | 6 + 4 files changed, 195 insertions(+), 159 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/bt8xx/bttv-cards.c b/drivers/media/video/bt8xx/bttv-cards.c index fc2b796b25fc..fd1ab7a15cd4 100644 --- a/drivers/media/video/bt8xx/bttv-cards.c +++ b/drivers/media/video/bt8xx/bttv-cards.c @@ -323,7 +323,7 @@ struct tvcard bttv_tvcards[] = { .name = " *** UNKNOWN/GENERIC *** ", .video_inputs = 4, .svhs = 2, - .muxsel = { 2, 3, 1, 0 }, + .muxsel = MUXSEL(2, 3, 1, 0), .tuner_type = UNSET, .tuner_addr = ADDR_UNSET, }, @@ -333,7 +333,7 @@ struct tvcard bttv_tvcards[] = { /* .audio_inputs= 1, */ .svhs = 2, .gpiomask = 15, - .muxsel = { 2, 3, 1, 1 }, + .muxsel = MUXSEL(2, 3, 1, 1), .gpiomux = { 2, 0, 0, 0 }, .gpiomute = 10, .needs_tvaudio = 1, @@ -346,7 +346,7 @@ struct tvcard bttv_tvcards[] = { /* .audio_inputs= 1, */ .svhs = 2, .gpiomask = 7, - .muxsel = { 2, 3, 1, 1 }, + .muxsel = MUXSEL(2, 3, 1, 1), .gpiomux = { 0, 1, 2, 3 }, .gpiomute = 4, .needs_tvaudio = 1, @@ -359,7 +359,7 @@ struct tvcard bttv_tvcards[] = { /* .audio_inputs= 1, */ .svhs = 2, .gpiomask = 7, - .muxsel = { 2, 3, 1, 1 }, + .muxsel = MUXSEL(2, 3, 1, 1), .gpiomux = { 4, 0, 2, 3 }, .gpiomute = 1, .no_msp34xx = 1, @@ -377,7 +377,7 @@ struct tvcard bttv_tvcards[] = { /* .audio_inputs= 0, */ .svhs = 2, .gpiomask = 0, - .muxsel = { 2, 3, 1, 1 }, + .muxsel = MUXSEL(2, 3, 1, 1), .gpiomux = { 0 }, .needs_tvaudio = 0, .tuner_type = TUNER_ABSENT, @@ -389,7 +389,7 @@ struct tvcard bttv_tvcards[] = { /* .audio_inputs= 1, */ .svhs = 2, .gpiomask = 3, - .muxsel = { 2, 3, 1, 0 }, + .muxsel = MUXSEL(2, 3, 1, 0), .gpiomux = { 0, 1, 0, 1 }, .gpiomute = 3, .needs_tvaudio = 1, @@ -401,7 +401,7 @@ struct tvcard bttv_tvcards[] = { .video_inputs = 3, /* .audio_inputs= 1, */ .svhs = 3, - .muxsel = { 2, 3, 1, 1 }, + .muxsel = MUXSEL(2, 3, 1, 1), .gpiomask = 0x0f, .gpiomux = { 0x0c, 0x04, 0x08, 0x04 }, /* 0x04 for some cards ?? */ @@ -417,7 +417,7 @@ struct tvcard bttv_tvcards[] = { /* .audio_inputs= 1, */ .svhs = 3, .gpiomask = 0, - .muxsel = { 2, 3, 1, 0, 0 }, + .muxsel = MUXSEL(2, 3, 1, 0, 0), .gpiomux = { 0 }, .needs_tvaudio = 1, .tuner_type = TUNER_ABSENT, @@ -431,7 +431,7 @@ struct tvcard bttv_tvcards[] = { /* .audio_inputs= 1, */ .svhs = 2, .gpiomask = 0xc00, - .muxsel = { 2, 3, 1, 1 }, + .muxsel = MUXSEL(2, 3, 1, 1), .gpiomux = { 0, 0xc00, 0x800, 0x400 }, .gpiomute = 0xc00, .needs_tvaudio = 1, @@ -445,7 +445,7 @@ struct tvcard bttv_tvcards[] = { /* .audio_inputs= 1, */ .svhs = 2, .gpiomask = 3, - .muxsel = { 2, 3, 1, 1 }, + .muxsel = MUXSEL(2, 3, 1, 1), .gpiomux = { 1, 1, 2, 3 }, .needs_tvaudio = 0, .pll = PLL_28, @@ -458,7 +458,7 @@ struct tvcard bttv_tvcards[] = { /* .audio_inputs= 1, */ .svhs = 2, .gpiomask = 0x0f, /* old: 7 */ - .muxsel = { 2, 0, 1, 1 }, + .muxsel = MUXSEL(2, 0, 1, 1), .gpiomux = { 0, 1, 2, 3 }, .gpiomute = 4, .needs_tvaudio = 1, @@ -472,7 +472,7 @@ struct tvcard bttv_tvcards[] = { /* .audio_inputs= 1, */ .svhs = 2, .gpiomask = 0x3014f, - .muxsel = { 2, 3, 1, 1 }, + .muxsel = MUXSEL(2, 3, 1, 1), .gpiomux = { 0x20001,0x10001, 0, 0 }, .gpiomute = 10, .needs_tvaudio = 1, @@ -487,7 +487,7 @@ struct tvcard bttv_tvcards[] = { /* .audio_inputs= 1, */ .svhs = 2, .gpiomask = 15, - .muxsel = { 2, 3, 1, 1 }, + .muxsel = MUXSEL(2, 3, 1, 1), .gpiomux = { 13, 14, 11, 7 }, .needs_tvaudio = 1, .tuner_type = UNSET, @@ -499,7 +499,7 @@ struct tvcard bttv_tvcards[] = { /* .audio_inputs= 4, */ .svhs = 2, .gpiomask = 15, - .muxsel = { 2, 3, 1, 1 }, + .muxsel = MUXSEL(2, 3, 1, 1), .gpiomux = { 13, 14, 11, 7 }, .needs_tvaudio = 1, .msp34xx_alt = 1, @@ -515,7 +515,7 @@ struct tvcard bttv_tvcards[] = { /* .audio_inputs= 1, */ .svhs = 2, .gpiomask = 7, - .muxsel = { 2, 3, 1, 1 }, + .muxsel = MUXSEL(2, 3, 1, 1), .gpiomux = { 0, 2, 1, 3 }, /* old: {0, 1, 2, 3, 4} */ .gpiomute = 4, .needs_tvaudio = 1, @@ -529,7 +529,7 @@ struct tvcard bttv_tvcards[] = { /* .audio_inputs= 1, */ .svhs = 2, .gpiomask = 15, - .muxsel = { 2, 3, 1, 1 }, + .muxsel = MUXSEL(2, 3, 1, 1), .gpiomux = { 0, 0, 1, 0 }, .gpiomute = 10, .needs_tvaudio = 1, @@ -544,7 +544,7 @@ struct tvcard bttv_tvcards[] = { /* .audio_inputs= 1, */ .svhs = 2, .gpiomask = 0x01fe00, - .muxsel = { 2, 3, 1, 1 }, + .muxsel = MUXSEL(2, 3, 1, 1), /* 2003-10-20 by "Anton A. Arapov" */ .gpiomux = { 0x001e00, 0, 0x018000, 0x014000 }, .gpiomute = 0x002000, @@ -559,7 +559,7 @@ struct tvcard bttv_tvcards[] = { /* .audio_inputs= 1, */ .svhs = 2, .gpiomask = 0x8300f8, - .muxsel = { 2, 3, 1, 1,0 }, + .muxsel = MUXSEL(2, 3, 1, 1, 0), .gpiomux = { 0x4fa007,0xcfa007,0xcfa007,0xcfa007 }, .gpiomute = 0xcfa007, .needs_tvaudio = 1, @@ -574,7 +574,7 @@ struct tvcard bttv_tvcards[] = { /* .audio_inputs= 2, */ .svhs = 2, .gpiomask = 0, - .muxsel = { 2, 3, 1, 1 }, + .muxsel = MUXSEL(2, 3, 1, 1), .gpiomux = { 1, 0, 0, 0 }, .needs_tvaudio = 1, .tuner_type = UNSET, @@ -586,7 +586,7 @@ struct tvcard bttv_tvcards[] = { /* .audio_inputs= 1, */ .svhs = NO_SVHS, .gpiomask = 0x8dff00, - .muxsel = { 2, 3, 1, 1 }, + .muxsel = MUXSEL(2, 3, 1, 1), .gpiomux = { 0 }, .no_msp34xx = 1, .tuner_type = TUNER_ABSENT, @@ -599,7 +599,7 @@ struct tvcard bttv_tvcards[] = { .video_inputs = 3, /* .audio_inputs= 3, */ .svhs = 2, - .muxsel = { 2, 3, 1, 1 }, + .muxsel = MUXSEL(2, 3, 1, 1), .tuner_type = UNSET, .tuner_addr = ADDR_UNSET, }, @@ -609,7 +609,7 @@ struct tvcard bttv_tvcards[] = { /* .audio_inputs= 2, tuner, line in */ .svhs = 2, .gpiomask = 0x1800, - .muxsel = { 2, 3, 1, 1 }, + .muxsel = MUXSEL(2, 3, 1, 1), .gpiomux = { 0, 0x800, 0x1000, 0x1000 }, .gpiomute = 0x1800, .pll = PLL_28, @@ -622,7 +622,7 @@ struct tvcard bttv_tvcards[] = { /* .audio_inputs= 1, */ .svhs = 2, .gpiomask = 0xc00, - .muxsel = { 2, 3, 1, 1 }, + .muxsel = MUXSEL(2, 3, 1, 1), .gpiomux = { 0, 1, 0x800, 0x400 }, .gpiomute = 0xc00, .needs_tvaudio = 1, @@ -637,7 +637,7 @@ struct tvcard bttv_tvcards[] = { .svhs = NO_SVHS, .has_dig_in = 1, .gpiomask = 7, - .muxsel = { 2, 3, 0 }, /* input 2 is digital */ + .muxsel = MUXSEL(2, 3, 0), /* input 2 is digital */ /* .digital_mode= DIGITAL_MODE_CAMERA, */ .gpiomux = { 0, 0, 0, 0 }, .no_msp34xx = 1, @@ -653,7 +653,7 @@ struct tvcard bttv_tvcards[] = { /* .audio_inputs= 1, */ .svhs = 2, .gpiomask = 0xe00, - .muxsel = { 2, 3, 1, 1 }, + .muxsel = MUXSEL(2, 3, 1, 1), .gpiomux = {0x400, 0x400, 0x400, 0x400 }, .gpiomute = 0xc00, .needs_tvaudio = 1, @@ -668,7 +668,7 @@ struct tvcard bttv_tvcards[] = { /* .audio_inputs= 1, */ .svhs = 2, .gpiomask = 0x1f0fff, - .muxsel = { 2, 3, 1, 1 }, + .muxsel = MUXSEL(2, 3, 1, 1), .gpiomux = { 0x20000, 0x30000, 0x10000, 0 }, .gpiomute = 0x40000, .needs_tvaudio = 0, @@ -682,7 +682,7 @@ struct tvcard bttv_tvcards[] = { /* .audio_inputs= 1, */ .svhs = 3, .gpiomask = 7, - .muxsel = { 2, 0, 1, 1 }, + .muxsel = MUXSEL(2, 0, 1, 1), .gpiomux = { 0, 1, 2, 3 }, .gpiomute = 4, .needs_tvaudio = 1, @@ -695,7 +695,7 @@ struct tvcard bttv_tvcards[] = { /* .audio_inputs= 2, */ .svhs = 2, .gpiomask = 0x1800, - .muxsel = { 2, 3, 1, 1 }, + .muxsel = MUXSEL(2, 3, 1, 1), .gpiomux = { 0, 0x800, 0x1000, 0x1000 }, .gpiomute = 0x1800, .pll = PLL_28, @@ -710,7 +710,7 @@ struct tvcard bttv_tvcards[] = { /* .audio_inputs= 1, */ .svhs = 2, .gpiomask = 0x1f0fff, - .muxsel = { 2, 3, 1, 1 }, + .muxsel = MUXSEL(2, 3, 1, 1), .gpiomux = { 0x20000, 0x30000, 0x10000, 0x00000 }, .gpiomute = 0x40000, .needs_tvaudio = 0, @@ -756,7 +756,7 @@ struct tvcard bttv_tvcards[] = { /* .audio_inputs= 1, */ .svhs = 1, /* was: 4 */ .gpiomask = 0, - .muxsel = { 2, 3, 1, 0, 0}, + .muxsel = MUXSEL(2, 3, 1, 0, 0), .gpiomux = { 0 }, .needs_tvaudio = 1, .tuner_type = TUNER_ABSENT, @@ -770,7 +770,7 @@ struct tvcard bttv_tvcards[] = { /* .audio_inputs= 1, */ .svhs = 2, .gpiomask = 0x1800, /* 0x8dfe00 */ - .muxsel = { 2, 3, 1, 1 }, + .muxsel = MUXSEL(2, 3, 1, 1), .gpiomux = { 0, 0x0800, 0x1000, 0x1000 }, .gpiomute = 0x1800, .pll = PLL_28, @@ -783,7 +783,7 @@ struct tvcard bttv_tvcards[] = { /* .audio_inputs= 1, */ .svhs = 3, .gpiomask = 1, - .muxsel = { 2, 3, 1, 1 }, + .muxsel = MUXSEL(2, 3, 1, 1), .gpiomux = { 1, 0, 0, 0 }, .pll = PLL_28, .tuner_type = TUNER_PHILIPS_PAL, @@ -797,7 +797,7 @@ struct tvcard bttv_tvcards[] = { /* .audio_inputs= 0, */ .svhs = 2, .gpiomask = 0, - .muxsel = { 2, 3, 1, 1 }, + .muxsel = MUXSEL(2, 3, 1, 1), .gpiomux = { 0 }, .needs_tvaudio = 0, .tuner_type = TUNER_ABSENT, @@ -809,7 +809,7 @@ struct tvcard bttv_tvcards[] = { /* .audio_inputs= 1, */ .svhs = 2, .gpiomask = 0xffff00, - .muxsel = { 2, 3, 1, 1 }, + .muxsel = MUXSEL(2, 3, 1, 1), .gpiomux = { 0x500, 0, 0x300, 0x900 }, .gpiomute = 0x900, .needs_tvaudio = 1, @@ -822,7 +822,8 @@ struct tvcard bttv_tvcards[] = { .video_inputs = 4, /* .audio_inputs= 1, */ .svhs = 2, - .muxsel = { 2, 3, 1, 1, 0 }, /* TV, CVid, SVid, CVid over SVid connector */ + /* TV, CVid, SVid, CVid over SVid connector */ + .muxsel = MUXSEL(2, 3, 1, 1, 0), /* Alexander Varakin [stereo version] */ .gpiomask = 0xb33000, .gpiomux = { 0x122000,0x1000,0x0000,0x620000 }, @@ -852,7 +853,7 @@ struct tvcard bttv_tvcards[] = { /* .audio_inputs= 3, */ .svhs = 2, .gpiomask = 0x1800, - .muxsel = { 2, 3, 1, 1 }, + .muxsel = MUXSEL(2, 3, 1, 1), .gpiomux = { 0, 0x800, 0x1000, 0x1000 }, .gpiomute = 0x1800, .pll = PLL_28, @@ -867,7 +868,7 @@ struct tvcard bttv_tvcards[] = { /* .audio_inputs= 3, */ .svhs = 2, .gpiomask = 0x1800, - .muxsel = { 2, 3, 1, 1 }, + .muxsel = MUXSEL(2, 3, 1, 1), .gpiomux = { 0, 0x800, 0x1000, 0x1000 }, .gpiomute = 0x1800, .pll = PLL_28, @@ -881,7 +882,7 @@ struct tvcard bttv_tvcards[] = { /* .audio_inputs= 1, */ .svhs = 2, .gpiomask = 0xff, - .muxsel = { 2, 3, 1, 1 }, + .muxsel = MUXSEL(2, 3, 1, 1), .gpiomux = { 0x21, 0x20, 0x24, 0x2c }, .gpiomute = 0x29, .no_msp34xx = 1, @@ -895,7 +896,7 @@ struct tvcard bttv_tvcards[] = { /* .audio_inputs= 1, */ .svhs = 2, .gpiomask = 0x551e00, - .muxsel = { 2, 3, 1, 0 }, + .muxsel = MUXSEL(2, 3, 1, 0), .gpiomux = { 0x551400, 0x551200, 0, 0 }, .gpiomute = 0x551c00, .needs_tvaudio = 1, @@ -910,7 +911,7 @@ struct tvcard bttv_tvcards[] = { /* .audio_inputs= 1, */ .svhs = 2, .gpiomask = 0x03000F, - .muxsel = { 2, 3, 1, 1 }, + .muxsel = MUXSEL(2, 3, 1, 1), .gpiomux = { 2, 0xd0001, 0, 0 }, .gpiomute = 1, .needs_tvaudio = 0, @@ -926,7 +927,7 @@ struct tvcard bttv_tvcards[] = { /* .audio_inputs= 1, */ .svhs = 2, .gpiomask = 7, - .muxsel = { 2, 3, 1, 1 }, + .muxsel = MUXSEL(2, 3, 1, 1), .gpiomux = { 4, 0, 2, 3 }, .gpiomute = 1, .no_msp34xx = 1, @@ -942,7 +943,7 @@ struct tvcard bttv_tvcards[] = { /* .audio_inputs= 4, */ .svhs = 2, .gpiomask = 15, - .muxsel = { 2, 3, 1, 1 }, + .muxsel = MUXSEL(2, 3, 1, 1), .gpiomux = { 13, 4, 11, 7 }, .needs_tvaudio = 1, .pll = PLL_28, @@ -957,7 +958,7 @@ struct tvcard bttv_tvcards[] = { /* .audio_inputs= 1, */ .svhs = 2, .gpiomask = 0, - .muxsel = { 2, 3, 1, 1}, + .muxsel = MUXSEL(2, 3, 1, 1), .gpiomux = { 0, 0, 0, 0}, .needs_tvaudio = 1, .no_msp34xx = 1, @@ -971,7 +972,7 @@ struct tvcard bttv_tvcards[] = { /* .audio_inputs= 1, */ .svhs = 2, .gpiomask = 0xe00b, - .muxsel = { 2, 3, 1, 1 }, + .muxsel = MUXSEL(2, 3, 1, 1), .gpiomux = { 0xff9ff6, 0xff9ff6, 0xff1ff7, 0 }, .gpiomute = 0xff3ffc, .no_msp34xx = 1, @@ -986,7 +987,7 @@ struct tvcard bttv_tvcards[] = { /* .audio_inputs= 1, */ .svhs = NO_SVHS, .gpiomask = 3, - .muxsel = { 2, 3, 1, 1 }, + .muxsel = MUXSEL(2, 3, 1, 1), .gpiomux = { 1, 1, 0, 2 }, .gpiomute = 3, .no_msp34xx = 1, @@ -1000,7 +1001,7 @@ struct tvcard bttv_tvcards[] = { /* .audio_inputs= 1, */ .svhs = 3, .gpiomask = 0, - .muxsel = { 2, 3, 1, 0, 0 }, + .muxsel = MUXSEL(2, 3, 1, 0, 0), .gpiomux = { 0 }, .no_msp34xx = 1, .pll = PLL_28, @@ -1013,7 +1014,7 @@ struct tvcard bttv_tvcards[] = { /* .audio_inputs= 1, */ .svhs = 2, .gpiomask = 0xbcf03f, - .muxsel = { 2, 3, 1, 1 }, + .muxsel = MUXSEL(2, 3, 1, 1), .gpiomux = { 0xbc803f, 0xbc903f, 0xbcb03f, 0 }, .gpiomute = 0xbcb03f, .no_msp34xx = 1, @@ -1027,7 +1028,7 @@ struct tvcard bttv_tvcards[] = { /* .audio_inputs= 1, */ .svhs = 2, .gpiomask = 0x70000, - .muxsel = { 2, 3, 1, 1 }, + .muxsel = MUXSEL(2, 3, 1, 1), .gpiomux = { 0x20000, 0x30000, 0x10000, 0 }, .gpiomute = 0x40000, .needs_tvaudio = 1, @@ -1045,7 +1046,7 @@ struct tvcard bttv_tvcards[] = { /* .audio_inputs= 1, */ .svhs = 2, .gpiomask = 15, - .muxsel = { 2, 3, 1, 1 }, + .muxsel = MUXSEL(2, 3, 1, 1), .gpiomux = {2,0,0,0 }, .gpiomute = 1, .needs_tvaudio = 1, @@ -1059,7 +1060,7 @@ struct tvcard bttv_tvcards[] = { /* .audio_inputs= 1, */ .svhs = 2, .gpiomask = 0x010f00, - .muxsel = {2, 3, 0, 0 }, + .muxsel = MUXSEL(2, 3, 0, 0), .gpiomux = {0x10000, 0, 0x10000, 0 }, .no_msp34xx = 1, .pll = PLL_28, @@ -1074,7 +1075,7 @@ struct tvcard bttv_tvcards[] = { .svhs = 3, .has_dig_in = 1, .gpiomask = 0xAA0000, - .muxsel = { 2, 3, 1, 1, 0 }, /* input 4 is digital */ + .muxsel = MUXSEL(2, 3, 1, 1, 0), /* in 4 is digital */ /* .digital_mode= DIGITAL_MODE_CAMERA, */ .gpiomux = { 0x20000, 0, 0x80000, 0x80000 }, .gpiomute = 0xa8000, @@ -1099,7 +1100,7 @@ struct tvcard bttv_tvcards[] = { /* .audio_inputs= 1, */ .svhs = 2, .gpiomask = 7, - .muxsel = { 2, 0, 1, 1 }, + .muxsel = MUXSEL(2, 0, 1, 1), .gpiomux = { 0, 1, 2, 3 }, .gpiomute = 4, .pll = PLL_28, @@ -1115,7 +1116,7 @@ struct tvcard bttv_tvcards[] = { /* .audio_inputs= 1, */ .svhs = 3, .gpiomask = 0x03000F, - .muxsel = { 2, 3, 1, 1 }, + .muxsel = MUXSEL(2, 3, 1, 1), .gpiomux = { 1, 0xd0001, 0, 0 }, .gpiomute = 10, /* sound path (5 sources): @@ -1140,7 +1141,7 @@ struct tvcard bttv_tvcards[] = { /* .audio_inputs= 3, */ .svhs = 2, .gpiomask = 0x1c, - .muxsel = { 2, 3, 1, 1 }, + .muxsel = MUXSEL(2, 3, 1, 1), .gpiomux = { 0, 0, 0x10, 8 }, .gpiomute = 4, .needs_tvaudio = 1, @@ -1160,7 +1161,7 @@ struct tvcard bttv_tvcards[] = { /* .audio_inputs= 1, */ .svhs = 2, .gpiomask = 0x18e0, - .muxsel = { 2, 3, 1, 1 }, + .muxsel = MUXSEL(2, 3, 1, 1), .gpiomux = { 0x0000,0x0800,0x1000,0x1000 }, .gpiomute = 0x18e0, /* For cards with tda9820/tda9821: @@ -1179,7 +1180,7 @@ struct tvcard bttv_tvcards[] = { /* .audio_inputs= 1, */ .svhs = 2, .gpiomask = 0xF, - .muxsel = { 2, 3, 1, 0 }, + .muxsel = MUXSEL(2, 3, 1, 0), .gpiomux = { 2, 0, 0, 0 }, .gpiomute = 10, .needs_tvaudio = 0, @@ -1196,7 +1197,7 @@ struct tvcard bttv_tvcards[] = { /* .audio_inputs= 3, */ .svhs = 2, .gpiomask = 0x1800, - .muxsel = { 2, 3, 1, 1 }, + .muxsel = MUXSEL(2, 3, 1, 1), .gpiomux = { 0, 0x800, 0x1000, 0x1000 }, .gpiomute = 0x1800, .pll = PLL_28, @@ -1212,7 +1213,7 @@ struct tvcard bttv_tvcards[] = { /* .audio_inputs= 0, */ .svhs = 1, .gpiomask = 0, - .muxsel = { 3, 1 }, + .muxsel = MUXSEL(3, 1), .gpiomux = { 0 }, .needs_tvaudio = 0, .no_msp34xx = 1, @@ -1227,7 +1228,7 @@ struct tvcard bttv_tvcards[] = { /* .audio_inputs= 1, */ .svhs = 2, .gpiomask = 0xe00, - .muxsel = { 2, 3, 1, 1}, + .muxsel = MUXSEL(2, 3, 1, 1), .gpiomux = { 0x400, 0x400, 0x400, 0x400 }, .gpiomute = 0x800, .needs_tvaudio = 1, @@ -1242,7 +1243,7 @@ struct tvcard bttv_tvcards[] = { /* .audio_inputs= 1, */ .svhs = 2, .gpiomask = 0x03000F, - .muxsel = { 2, 3, 1, 0 }, + .muxsel = MUXSEL(2, 3, 1, 0), .gpiomux = { 2, 0, 0, 0 }, .gpiomute = 1, .pll = PLL_28, @@ -1258,7 +1259,7 @@ struct tvcard bttv_tvcards[] = { /* .audio_inputs= 2, */ .svhs = NO_SVHS, .gpiomask = 11, - .muxsel = { 2, 3, 1, 1 }, + .muxsel = MUXSEL(2, 3, 1, 1), .gpiomux = { 2, 0, 0, 1 }, .gpiomute = 8, .pll = PLL_35, @@ -1272,7 +1273,7 @@ struct tvcard bttv_tvcards[] = { /* .audio_inputs= 0, */ .svhs = 1, .gpiomask = 0xF, - .muxsel = { 2, 2 }, + .muxsel = MUXSEL(2, 2), .gpiomux = { }, .no_msp34xx = 1, .needs_tvaudio = 0, @@ -1289,7 +1290,7 @@ struct tvcard bttv_tvcards[] = { /* .audio_inputs= 2, */ .svhs = 2, .gpiomask = 0xFF, - .muxsel = { 2, 3, 1, 0 }, + .muxsel = MUXSEL(2, 3, 1, 0), .gpiomux = { 1, 0, 4, 4 }, .gpiomute = 9, .needs_tvaudio = 0, @@ -1304,7 +1305,7 @@ struct tvcard bttv_tvcards[] = { /* .audio_inputs= 1, */ .svhs = 2, .gpiomask = 0xf03f, - .muxsel = { 2, 3, 1, 0 }, + .muxsel = MUXSEL(2, 3, 1, 0), .gpiomux = { 0xbffe, 0, 0xbfff, 0 }, .gpiomute = 0xbffe, .pll = PLL_28, @@ -1320,7 +1321,7 @@ struct tvcard bttv_tvcards[] = { /* .audio_inputs= 1, */ .svhs = NO_SVHS, .gpiomask = 1, - .muxsel = { 2, 3, 0, 1 }, + .muxsel = MUXSEL(2, 3, 0, 1), .gpiomux = { 0, 0, 1, 0 }, .no_msp34xx = 1, .pll = PLL_28, @@ -1334,7 +1335,7 @@ struct tvcard bttv_tvcards[] = { /* .audio_inputs= 3, */ .svhs = 2, .gpiomask = 0x18e0, - .muxsel = { 2, 3, 0, 1 }, + .muxsel = MUXSEL(2, 3, 0, 1), /* Radio changed from 1e80 to 0x800 to make FlyVideo2000S in .hu happy (gm)*/ /* -dk-???: set mute=0x1800 for tda9874h daughterboard */ @@ -1354,7 +1355,7 @@ struct tvcard bttv_tvcards[] = { /* .audio_inputs= 1, */ .svhs = 2, .gpiomask = 0xffff00, - .muxsel = { 2, 3, 1, 1 }, + .muxsel = MUXSEL(2, 3, 1, 1), .gpiomux = { 0x500, 0x500, 0x300, 0x900 }, .gpiomute = 0x900, .needs_tvaudio = 1, @@ -1370,7 +1371,7 @@ struct tvcard bttv_tvcards[] = { /* .audio_inputs= 1, */ .svhs = 2, .gpiomask = 0x010f00, - .muxsel = {2, 3, 0, 0 }, + .muxsel = MUXSEL(2, 3, 0, 0), .gpiomux = {0x10000, 0, 0x10000, 0 }, .no_msp34xx = 1, .pll = PLL_28, @@ -1394,7 +1395,7 @@ struct tvcard bttv_tvcards[] = { .gpiomute = 0x947fff, /* tvtuner, radio, external,internal, mute, stereo * tuner, Composit, SVid, Composit-on-Svid-adapter */ - .muxsel = { 2, 3 ,0 ,1 }, + .muxsel = MUXSEL(2, 3, 0, 1), .tuner_type = TUNER_MT2032, .tuner_addr = ADDR_UNSET, .pll = PLL_28, @@ -1414,7 +1415,7 @@ struct tvcard bttv_tvcards[] = { .gpiomute = 0x947fff, /* tvtuner, radio, external,internal, mute, stereo * tuner, Composit, SVid, Composit-on-Svid-adapter */ - .muxsel = { 2, 3 ,0 ,1 }, + .muxsel = MUXSEL(2, 3, 0, 1), .tuner_type = TUNER_MT2032, .tuner_addr = ADDR_UNSET, .pll = PLL_28, @@ -1428,7 +1429,7 @@ struct tvcard bttv_tvcards[] = { .tuner_type = TUNER_ABSENT, .tuner_addr = ADDR_UNSET, .pll = PLL_28, - .muxsel = { 2 }, + .muxsel = MUXSEL(2), .gpiomask = 0 }, [BTTV_BOARD_PV_BT878P_PLUS] = { @@ -1438,7 +1439,7 @@ struct tvcard bttv_tvcards[] = { /* .audio_inputs= 4, */ .svhs = 2, .gpiomask = 15, - .muxsel = { 2, 3, 1, 1 }, + .muxsel = MUXSEL(2, 3, 1, 1), .gpiomux = { 0, 0, 11, 7 }, /* TV and Radio with same GPIO ! */ .gpiomute = 13, .needs_tvaudio = 1, @@ -1459,7 +1460,8 @@ struct tvcard bttv_tvcards[] = { .video_inputs = 4, /* .audio_inputs= 0, */ .svhs = 2, - .muxsel = { 2, 3, 1, 1 }, /* AV1, AV2, SVHS, CVid adapter on SVHS */ + /* AV1, AV2, SVHS, CVid adapter on SVHS */ + .muxsel = MUXSEL(2, 3, 1, 1), .pll = PLL_28, .no_msp34xx = 1, .tuner_type = TUNER_ABSENT, @@ -1474,7 +1476,7 @@ struct tvcard bttv_tvcards[] = { /* .audio_inputs= 1, */ .svhs = 2, .gpiomask = 0x3f, - .muxsel = { 2, 3, 1, 1 }, + .muxsel = MUXSEL(2, 3, 1, 1), .gpiomux = { 0x01, 0x00, 0x03, 0x03 }, .gpiomute = 0x09, .needs_tvaudio = 1, @@ -1502,7 +1504,7 @@ struct tvcard bttv_tvcards[] = { /* .audio_inputs= 0, */ .svhs = 4, .gpiomask = 0, - .muxsel = { 2, 3, 1, 0, 0 }, + .muxsel = MUXSEL(2, 3, 1, 0, 0), .gpiomux = { 0 }, .needs_tvaudio = 0, .tuner_type = TUNER_ABSENT, @@ -1516,7 +1518,7 @@ struct tvcard bttv_tvcards[] = { .svhs = NO_SVHS, .gpiomask = 0x00, .gpiomask2 = 0x07ff, - .muxsel = { 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 }, + .muxsel = MUXSEL(3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3), .no_msp34xx = 1, .no_tda9875 = 1, .tuner_type = TUNER_ABSENT, @@ -1529,7 +1531,7 @@ struct tvcard bttv_tvcards[] = { /* .audio_inputs= 2, */ .svhs = 2, .gpiomask = 0x1C800F, /* Bit0-2: Audio select, 8-12:remote control 14:remote valid 15:remote reset */ - .muxsel = { 2, 1, 1, }, + .muxsel = MUXSEL(2, 1, 1), .gpiomux = { 0, 1, 2, 2 }, .gpiomute = 4, .needs_tvaudio = 0, @@ -1547,7 +1549,7 @@ struct tvcard bttv_tvcards[] = { /* .audio_inputs= 1, */ .svhs = 2, .gpiomask = 0x140007, - .muxsel = { 2, 3, 1, 1 }, + .muxsel = MUXSEL(2, 3, 1, 1), .gpiomux = { 0, 1, 2, 3 }, .gpiomute = 4, .tuner_type = TUNER_PHILIPS_NTSC, @@ -1560,7 +1562,7 @@ struct tvcard bttv_tvcards[] = { /* .audio_inputs= 0, */ .svhs = NO_SVHS, .gpiomask = 0, - .muxsel = { 2, 3, 1, 0 }, + .muxsel = MUXSEL(2, 3, 1, 0), .gpiomux = { 0 }, .needs_tvaudio = 0, .no_msp34xx = 1, @@ -1574,7 +1576,8 @@ struct tvcard bttv_tvcards[] = { /* .audio_inputs= 3, */ .svhs = 2, .gpiomask = 7, - .muxsel = { 2, 3, 1, 1 }, /* Tuner, SVid, SVHS, SVid to SVHS connector */ + /* Tuner, SVid, SVHS, SVid to SVHS connector */ + .muxsel = MUXSEL(2, 3, 1, 1), .gpiomux = { 0, 0, 4, 4 },/* Yes, this tuner uses the same audio output for TV and FM radio! * This card lacks external Audio In, so we mute it on Ext. & Int. * The PCB can take a sbx1637/sbx1673, wiring unknown. @@ -1606,7 +1609,7 @@ struct tvcard bttv_tvcards[] = { .name = "DSP Design TCVIDEO", .video_inputs = 4, .svhs = NO_SVHS, - .muxsel = { 2, 3, 1, 0 }, + .muxsel = MUXSEL(2, 3, 1, 0), .pll = PLL_28, .tuner_type = UNSET, .tuner_addr = ADDR_UNSET, @@ -1618,7 +1621,7 @@ struct tvcard bttv_tvcards[] = { .video_inputs = 4, /* .audio_inputs= 1, */ .svhs = 2, - .muxsel = { 2, 0, 1, 1 }, + .muxsel = MUXSEL(2, 0, 1, 1), .needs_tvaudio = 1, .pll = PLL_28, .tuner_type = UNSET, @@ -1633,7 +1636,7 @@ struct tvcard bttv_tvcards[] = { /* .audio_inputs= 1, */ .svhs = 2, .gpiomask = 0x0f0f80, - .muxsel = {2, 3, 1, 0 }, + .muxsel = MUXSEL(2, 3, 1, 0), .gpiomux = {0x030000, 0x010000, 0, 0 }, .gpiomute = 0x020000, .no_msp34xx = 1, @@ -1648,7 +1651,7 @@ struct tvcard bttv_tvcards[] = { .video_inputs = 4, /* id-inputs-clock */ /* .audio_inputs= 0, */ .svhs = 3, - .muxsel = { 3, 2, 0, 1 }, + .muxsel = MUXSEL(3, 2, 0, 1), .pll = PLL_28, .tuner_type = TUNER_ABSENT, .tuner_addr = ADDR_UNSET, @@ -1661,7 +1664,7 @@ struct tvcard bttv_tvcards[] = { .video_inputs = 3, /* .audio_inputs= 0, */ .svhs = 2, - .muxsel = { 2, 3, 1 }, + .muxsel = MUXSEL(2, 3, 1), .pll = PLL_28, .tuner_type = TUNER_ABSENT, .tuner_addr = ADDR_UNSET, @@ -1676,7 +1679,7 @@ struct tvcard bttv_tvcards[] = { .video_inputs = 2, /* .audio_inputs= 0, */ .svhs = 1, - .muxsel = { 3, 1 }, + .muxsel = MUXSEL(3, 1), .pll = PLL_28, .tuner_type = TUNER_ABSENT, .tuner_addr = ADDR_UNSET, @@ -1689,7 +1692,7 @@ struct tvcard bttv_tvcards[] = { .video_inputs = 1, /* .audio_inputs= 0, */ .svhs = NO_SVHS, - .muxsel = { 0 }, + .muxsel = MUXSEL(0), .pll = PLL_28, .tuner_type = TUNER_ABSENT, .tuner_addr = ADDR_UNSET, @@ -1702,7 +1705,7 @@ struct tvcard bttv_tvcards[] = { .video_inputs = 2, /* .audio_inputs= 0, */ .svhs = 1, - .muxsel = { 0, 1 }, + .muxsel = MUXSEL(0, 1), .pll = PLL_28, .tuner_type = TUNER_ABSENT, .tuner_addr = ADDR_UNSET, @@ -1715,7 +1718,7 @@ struct tvcard bttv_tvcards[] = { .video_inputs = 1, /* .audio_inputs= 1, */ .svhs = NO_SVHS, - .muxsel = { 0 }, + .muxsel = MUXSEL(0), .pll = PLL_28, .tuner_type = TUNER_ABSENT, .tuner_addr = ADDR_UNSET, @@ -1730,7 +1733,7 @@ struct tvcard bttv_tvcards[] = { .video_inputs = 2, /* .audio_inputs= 1, */ .svhs = 1, - .muxsel = { 0, 1 }, + .muxsel = MUXSEL(0, 1), .pll = PLL_28, .tuner_type = TUNER_ABSENT, .tuner_addr = ADDR_UNSET, @@ -1743,7 +1746,7 @@ struct tvcard bttv_tvcards[] = { .video_inputs = 2, /* .audio_inputs= 1, */ .svhs = 1, - .muxsel = { 2, 3 }, + .muxsel = MUXSEL(2, 3), .pll = PLL_28, .tuner_type = TUNER_ABSENT, .tuner_addr = ADDR_UNSET, @@ -1756,7 +1759,7 @@ struct tvcard bttv_tvcards[] = { .video_inputs = 2, /* .audio_inputs= 1, */ .svhs = 1, - .muxsel = { 2, 3 }, + .muxsel = MUXSEL(2, 3), .pll = PLL_28, .tuner_type = TUNER_ABSENT, .tuner_addr = ADDR_UNSET, @@ -1782,7 +1785,7 @@ struct tvcard bttv_tvcards[] = { .video_inputs = 2, /* .audio_inputs= 1, */ .svhs = 1, - .muxsel = { 2, 3 }, + .muxsel = MUXSEL(2, 3), .pll = PLL_28, .tuner_type = TUNER_ABSENT, .tuner_addr = ADDR_UNSET, @@ -1799,7 +1802,7 @@ struct tvcard bttv_tvcards[] = { .tuner_addr = ADDR_UNSET, .svhs = NO_SVHS, .gpiomask = 0, - .muxsel = { 2, 2, 2, 2 }, + .muxsel = MUXSEL(2, 2, 2, 2), .muxsel_hook = eagle_muxsel, .no_msp34xx = 1, .no_tda9875 = 1, @@ -1815,7 +1818,7 @@ struct tvcard bttv_tvcards[] = { .no_msp34xx = 1, .no_tda9875 = 1, .no_tda7432 = 1, - .muxsel = { 3, 1 }, + .muxsel = MUXSEL(3, 1), .pll = PLL_28, .no_gpioirq = 1, .has_dvb = 1, @@ -1827,7 +1830,7 @@ struct tvcard bttv_tvcards[] = { .svhs = 3, .gpiomask = 2, /* TV, Comp1, Composite over SVID con, SVID */ - .muxsel = { 2, 3, 1, 1 }, + .muxsel = MUXSEL(2, 3, 1, 1), .gpiomux = { 2, 2, 0, 0 }, .pll = PLL_28, .has_radio = 1, @@ -1849,7 +1852,7 @@ struct tvcard bttv_tvcards[] = { /* .audio_inputs= 1, */ .svhs = NO_SVHS, .gpiomask = 7, - .muxsel = { 2, 3, 1, 1}, + .muxsel = MUXSEL(2, 3, 1, 1), .gpiomux = { 0, 1, 2, 3}, .gpiomute = 4, .needs_tvaudio = 1, @@ -1866,7 +1869,7 @@ struct tvcard bttv_tvcards[] = { .no_msp34xx = 1, .no_tda9875 = 1, .no_tda7432 = 1, - .muxsel = { 2, 0, 1}, + .muxsel = MUXSEL(2, 0, 1), .pll = PLL_28, .tuner_type = TUNER_ABSENT, .tuner_addr = ADDR_UNSET, @@ -1878,7 +1881,7 @@ struct tvcard bttv_tvcards[] = { /* .audio_inputs= 0, */ .svhs = NO_SVHS, .gpiomask = 0, - .muxsel = { 2, 3 }, + .muxsel = MUXSEL(2, 3), .gpiomux = { 0 }, .needs_tvaudio = 0, .no_msp34xx = 1, @@ -1894,7 +1897,7 @@ struct tvcard bttv_tvcards[] = { /* .audio_inputs= 1, */ .svhs = 2, .gpiomask = 0x001e8007, - .muxsel = { 2, 3, 1, 0 }, + .muxsel = MUXSEL(2, 3, 1, 0), /* Tuner, Radio, external, internal, off, on */ .gpiomux = { 0x08, 0x0f, 0x0a, 0x08 }, .gpiomute = 0x0f, @@ -1913,7 +1916,7 @@ struct tvcard bttv_tvcards[] = { /* .audio_inputs= 1, */ .svhs = 2, .gpiomask = 0x00, - .muxsel = { 2, 3, 1, 1 }, + .muxsel = MUXSEL(2, 3, 1, 1), .needs_tvaudio = 1, .no_msp34xx = 1, .pll = PLL_28, @@ -1934,7 +1937,8 @@ struct tvcard bttv_tvcards[] = { .video_inputs = 4, /* .audio_inputs= 1, */ .svhs = 2, - .muxsel = { 2, 3, 1, 1 }, /* Tuner, CVid, SVid, CVid over SVid connector */ + /* Tuner, CVid, SVid, CVid over SVid connector */ + .muxsel = MUXSEL(2, 3, 1, 1), .gpiomask = 0, .no_tda9875 = 1, .no_tda7432 = 1, @@ -1958,7 +1962,7 @@ struct tvcard bttv_tvcards[] = { .tuner_addr = ADDR_UNSET, .svhs = NO_SVHS, .gpiomask = 0xdf, - .muxsel = { 2 }, + .muxsel = MUXSEL(2), .pll = PLL_28, }, [BTTV_BOARD_IVCE8784] = { @@ -1969,7 +1973,7 @@ struct tvcard bttv_tvcards[] = { .tuner_addr = ADDR_UNSET, .svhs = NO_SVHS, .gpiomask = 0xdf, - .muxsel = { 2 }, + .muxsel = MUXSEL(2), .pll = PLL_28, }, [BTTV_BOARD_XGUARD] = { @@ -1980,7 +1984,7 @@ struct tvcard bttv_tvcards[] = { .tuner_type = TUNER_ABSENT, .tuner_addr = ADDR_UNSET, .gpiomask2 = 0xff, - .muxsel = { 2,2,2,2, 3,3,3,3, 1,1,1,1, 0,0,0,0 }, + .muxsel = MUXSEL(2,2,2,2, 3,3,3,3, 1,1,1,1, 0,0,0,0), .muxsel_hook = xguard_muxsel, .no_msp34xx = 1, .no_tda9875 = 1, @@ -1993,7 +1997,7 @@ struct tvcard bttv_tvcards[] = { .name = "Nebula Electronics DigiTV", .video_inputs = 1, .svhs = NO_SVHS, - .muxsel = { 2, 3, 1, 0 }, + .muxsel = MUXSEL(2, 3, 1, 0), .no_msp34xx = 1, .no_tda9875 = 1, .no_tda7432 = 1, @@ -2012,7 +2016,7 @@ struct tvcard bttv_tvcards[] = { /* .audio_inputs= 0, */ .svhs = NO_SVHS, .gpiomask = 0, - .muxsel = { 2, 3, 1, 0 }, + .muxsel = MUXSEL(2, 3, 1, 0), .gpiomux = { 0 }, .needs_tvaudio = 0, .no_msp34xx = 1, @@ -2027,7 +2031,7 @@ struct tvcard bttv_tvcards[] = { /* .audio_inputs= 0, */ .svhs = 3, .gpiomask = 0x00, - .muxsel = { 2, 3, 1, 0 }, + .muxsel = MUXSEL(2, 3, 1, 0), .gpiomux = { 0, 0, 0, 0 }, /* card has no audio */ .needs_tvaudio = 0, .pll = PLL_28, @@ -2040,7 +2044,7 @@ struct tvcard bttv_tvcards[] = { /* .audio_inputs= 0, */ .svhs = 3, .gpiomask = 0x00, - .muxsel = { 2, 3, 1, 1 }, + .muxsel = MUXSEL(2, 3, 1, 1), .gpiomux = { 0, 0, 0, 0 }, /* card has no audio */ .needs_tvaudio = 0, .pll = PLL_28, @@ -2056,7 +2060,7 @@ struct tvcard bttv_tvcards[] = { .svhs = 9, .gpiomask = 0x00, .gpiomask2 = 0x03, /* used for external vodeo mux */ - .muxsel = { 2, 2, 2, 2, 3, 3, 3, 3, 1, 0 }, + .muxsel = MUXSEL(2, 2, 2, 2, 3, 3, 3, 3, 1, 0), .muxsel_hook = phytec_muxsel, .gpiomux = { 0, 0, 0, 0 }, /* card has no audio */ .needs_tvaudio = 1, @@ -2071,7 +2075,7 @@ struct tvcard bttv_tvcards[] = { .svhs = 9, .gpiomask = 0x00, .gpiomask2 = 0x03, /* used for external vodeo mux */ - .muxsel = { 2, 2, 2, 2, 3, 3, 3, 3, 1, 1 }, + .muxsel = MUXSEL(2, 2, 2, 2, 3, 3, 3, 3, 1, 1), .muxsel_hook = phytec_muxsel, .gpiomux = { 0, 0, 0, 0 }, /* card has no audio */ .needs_tvaudio = 1, @@ -2087,7 +2091,7 @@ struct tvcard bttv_tvcards[] = { .tuner_addr = ADDR_UNSET, .svhs = NO_SVHS, .gpiomask = 0xdf, - .muxsel = { 2, 3, 1, 0 }, + .muxsel = MUXSEL(2, 3, 1, 0), .pll = PLL_28, }, [BTTV_BOARD_IVC120] = { @@ -2103,7 +2107,7 @@ struct tvcard bttv_tvcards[] = { .no_tda9875 = 1, .no_tda7432 = 1, .gpiomask = 0x00, - .muxsel = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + .muxsel = MUXSEL(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), .muxsel_hook = ivc120_muxsel, .pll = PLL_28, }, @@ -2114,7 +2118,7 @@ struct tvcard bttv_tvcards[] = { .video_inputs = 4, /* .audio_inputs= 1, */ .svhs = 2, - .muxsel = { 2, 3, 1, 0 }, + .muxsel = MUXSEL(2, 3, 1, 0), .tuner_type = TUNER_PHILIPS_FCV1236D, .tuner_addr = ADDR_UNSET, .has_dvb = 1, @@ -2134,7 +2138,8 @@ struct tvcard bttv_tvcards[] = { .video_inputs = 3, /* .audio_inputs= 0, */ .svhs = 1, - .muxsel = { 3, 1, 1, 3 }, /* Vid In, SVid In, Vid over SVid in connector */ + /* Vid In, SVid In, Vid over SVid in connector */ + .muxsel = MUXSEL(3, 1, 1, 3), .no_msp34xx = 1, .no_tda9875 = 1, .no_tda7432 = 1, @@ -2148,7 +2153,7 @@ struct tvcard bttv_tvcards[] = { /* .audio_inputs= 1, */ .svhs = 2, .gpiomask = 3, - .muxsel = { 2, 3, 1, 1 }, + .muxsel = MUXSEL(2, 3, 1, 1), .gpiomux = { 1, 1, 1, 1 }, .needs_tvaudio = 1, .tuner_type = TUNER_PHILIPS_PAL, @@ -2165,7 +2170,7 @@ struct tvcard bttv_tvcards[] = { .tuner_type = TUNER_ABSENT, .tuner_addr = ADDR_UNSET, .pll = PLL_28, - .muxsel = { 2, 2, 2, 2 }, + .muxsel = MUXSEL(2, 2, 2, 2), .gpiomask = 0x3F, .muxsel_hook = gvc1100_muxsel, }, @@ -2175,7 +2180,7 @@ struct tvcard bttv_tvcards[] = { .video_inputs = 3, .svhs = 2, .gpiomask = 0x008007, - .muxsel = { 2, 3, 0, 0 }, + .muxsel = MUXSEL(2, 3, 0, 0), .gpiomux = { 0, 0, 0, 0 }, .gpiomute = 0x000003, .pll = PLL_28, @@ -2189,7 +2194,7 @@ struct tvcard bttv_tvcards[] = { .video_inputs = 4, /* IN1,IN2,IN3,IN4 */ /* .audio_inputs= 0, */ .svhs = NO_SVHS, - .muxsel = { 2, 3, 1, 0 }, + .muxsel = MUXSEL(2, 3, 1, 0), .no_msp34xx = 1, .no_tda9875 = 1, .no_tda7432 = 1, @@ -2207,7 +2212,7 @@ struct tvcard bttv_tvcards[] = { .svhs = 2, .needs_tvaudio = 0, .gpiomask = 0x68, - .muxsel = { 2, 3, 1 }, + .muxsel = MUXSEL(2, 3, 1), .gpiomux = { 0x68, 0x68, 0x61, 0x61 }, .pll = PLL_28, }, @@ -2221,7 +2226,7 @@ struct tvcard bttv_tvcards[] = { /* .audio_inputs= 1, */ .svhs = 2, .gpiomask = 0x008007, - .muxsel = { 2, 3, 1, 1 }, + .muxsel = MUXSEL(2, 3, 1, 1), .gpiomux = { 0, 1, 2, 2 }, .gpiomute = 3, .needs_tvaudio = 0, @@ -2245,7 +2250,8 @@ struct tvcard bttv_tvcards[] = { .no_msp34xx = 1, .no_tda9875 = 1, .no_tda7432 = 1, - .muxsel = {2,2,2,2},/*878A input is always MUX0, see above.*/ + /*878A input is always MUX0, see above.*/ + .muxsel = MUXSEL(2, 2, 2, 2), .gpiomux = { 0, 0, 0, 0 }, /* card has no audio */ .pll = PLL_28, .needs_tvaudio = 0, @@ -2261,7 +2267,7 @@ struct tvcard bttv_tvcards[] = { /* .audio_inputs= 1, */ .svhs = 2, .gpiomask = 0x0000000f, - .muxsel = { 2, 1, 1 }, + .muxsel = MUXSEL(2, 1, 1), .gpiomux = { 0x02, 0x00, 0x00, 0x00 }, .tuner_type = TUNER_TEMIC_PAL, .tuner_addr = ADDR_UNSET, @@ -2275,7 +2281,7 @@ struct tvcard bttv_tvcards[] = { .svhs = 1, .tuner_type = TUNER_ABSENT, .tuner_addr = ADDR_UNSET, - .muxsel = { 3 , 3 }, + .muxsel = MUXSEL(3, 3), .no_msp34xx = 1, .no_tda9875 = 1, .no_tda7432 = 1, @@ -2291,7 +2297,7 @@ struct tvcard bttv_tvcards[] = { .name = "AverMedia AverTV DVB-T 761", .video_inputs = 2, .svhs = 1, - .muxsel = { 3, 1, 2, 0 }, /* Comp0, S-Video, ?, ? */ + .muxsel = MUXSEL(3, 1, 2, 0), /* Comp0, S-Video, ?, ? */ .no_msp34xx = 1, .no_tda9875 = 1, .no_tda7432 = 1, @@ -2309,8 +2315,7 @@ struct tvcard bttv_tvcards[] = { /* .audio_inputs= 0, */ .svhs = NO_SVHS, .gpiomask = 0x0, - .muxsel = { 2, 2, 2, 2, 2, 2, 2, 2, - 3, 3, 3, 3, 3, 3, 3, 3 }, + .muxsel = MUXSEL(2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3), .muxsel_hook = sigmaSQ_muxsel, .gpiomux = { 0 }, .no_msp34xx = 1, @@ -2325,7 +2330,7 @@ struct tvcard bttv_tvcards[] = { /* .audio_inputs= 0, */ .svhs = NO_SVHS, .gpiomask = 0x0, - .muxsel = { 2, 2, 2, 2 }, + .muxsel = MUXSEL(2, 2, 2, 2), .muxsel_hook = sigmaSLC_muxsel, .gpiomux = { 0 }, .no_msp34xx = 1, @@ -2342,7 +2347,7 @@ struct tvcard bttv_tvcards[] = { /* .audio_inputs= 1, */ .svhs = NO_SVHS, .gpiomask = 0xFF, - .muxsel = { 2, 3, 1, 1 }, + .muxsel = MUXSEL(2, 3, 1, 1), .gpiomux = { 2, 0, 0, 0 }, .gpiomute = 10, .needs_tvaudio = 0, @@ -2373,7 +2378,7 @@ struct tvcard bttv_tvcards[] = { /* .audio_inputs= 1, */ .svhs = 2, .gpiomask = 0x3f, - .muxsel = {2, 3, 1, 0 }, + .muxsel = MUXSEL(2, 3, 1, 0), .gpiomux = {0x31, 0x31, 0x31, 0x31 }, .gpiomute = 0x31, .no_msp34xx = 1, @@ -2388,7 +2393,7 @@ struct tvcard bttv_tvcards[] = { .video_inputs = 4, /* .audio_inputs= 1, */ .svhs = 2, - .muxsel = { 2, 3, 1, 0 }, + .muxsel = MUXSEL(2, 3, 1, 0), .tuner_type = TUNER_PHILIPS_NTSC, .tuner_addr = ADDR_UNSET, .gpiomask = 0x008007, @@ -2402,7 +2407,7 @@ struct tvcard bttv_tvcards[] = { .video_inputs = 16, /* .audio_inputs= 0, */ .svhs = NO_SVHS, - .muxsel = { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 }, + .muxsel = MUXSEL(2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2), .pll = PLL_28, .no_msp34xx = 1, .no_tda9875 = 1, @@ -2439,7 +2444,7 @@ struct tvcard bttv_tvcards[] = { */ .gpiomask = 0x0003ff, .no_gpioirq = 1, - .muxsel = { 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 }, + .muxsel = MUXSEL(3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3), .pll = PLL_28, .no_msp34xx = 1, .no_tda7432 = 1, @@ -2461,7 +2466,7 @@ struct tvcard bttv_tvcards[] = { .svhs = NO_SVHS, .gpiomask = 0x010000, .no_gpioirq = 1, - .muxsel = { 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 }, + .muxsel = MUXSEL(3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3), .pll = PLL_28, .no_msp34xx = 1, .no_tda7432 = 1, @@ -2476,7 +2481,7 @@ struct tvcard bttv_tvcards[] = { .video_inputs = 4, /* .audio_inputs= 1, */ .svhs = 2, - .muxsel = { 2, 3, 1, 0 }, + .muxsel = MUXSEL(2, 3, 1, 0), .tuner_type = UNSET, .tuner_addr = ADDR_UNSET, .pll = PLL_28, @@ -2490,7 +2495,7 @@ struct tvcard bttv_tvcards[] = { .video_inputs = 3, /* .audio_inputs= 1, */ .svhs = 2, - .muxsel = { 2, 3, 1 }, + .muxsel = MUXSEL(2, 3, 1), .gpiomask = 0x00e00007, .gpiomux = { 0x00400005, 0, 0x00000001, 0 }, .gpiomute = 0x00c00007, @@ -2507,7 +2512,7 @@ struct tvcard bttv_tvcards[] = { /* .audio_inputs= 1, */ .svhs = 2, .gpiomask = 0x01fe00, - .muxsel = { 2, 3, 1, 1 }, + .muxsel = MUXSEL(2, 3, 1, 1), .gpiomux = { 0x001e00, 0, 0x018000, 0x014000 }, .gpiomute = 0x002000, .needs_tvaudio = 1, @@ -2523,7 +2528,7 @@ struct tvcard bttv_tvcards[] = { /* .audio_inputs= 1, */ .svhs = 2, .gpiomask = 0x001c0007, - .muxsel = { 2, 3, 1, 1 }, + .muxsel = MUXSEL(2, 3, 1, 1), .gpiomux = { 0, 1, 2, 2 }, .gpiomute = 3, .needs_tvaudio = 0, @@ -2541,7 +2546,7 @@ struct tvcard bttv_tvcards[] = { .svhs = 3, .has_dig_in = 1, .gpiomask = 0x01fe00, - .muxsel = { 2, 3, 1, 1, 0 }, /* in 4 is digital */ + .muxsel = MUXSEL(2, 3, 1, 1, 0), /* in 4 is digital */ /* .digital_mode= DIGITAL_MODE_CAMERA, */ .gpiomux = { 0x00400, 0x10400, 0x04400, 0x80000 }, .gpiomute = 0x12400, @@ -2559,7 +2564,7 @@ struct tvcard bttv_tvcards[] = { /* .audio_inputs= 1, */ .svhs = 2, .gpiomask = 0x3f, - .muxsel = { 2, 3, 1, 1 }, + .muxsel = MUXSEL(2, 3, 1, 1), .gpiomux = { 0x21, 0x20, 0x24, 0x2c }, .gpiomute = 0x29, .no_msp34xx = 1, @@ -2587,7 +2592,7 @@ struct tvcard bttv_tvcards[] = { .video_inputs = 4, /* .audio_inputs= 2, */ .svhs = NO_SVHS, - .muxsel = { 2, 3, 0, 1 }, /* 3,0,1 are guesses */ + .muxsel = MUXSEL(2, 3, 0, 1), /* 3,0,1 are guesses */ .gpiomask = 0x303, .gpiomute = 0x000, /* int + 32kHz */ .gpiomux = { 0, 0, 0x000, 0x100}, @@ -2605,7 +2610,7 @@ struct tvcard bttv_tvcards[] = { /* .audio_inputs= 1, */ .svhs = 2, .gpiomask = 15, - .muxsel = { 2, 3, 1, 1 }, + .muxsel = MUXSEL(2, 3, 1, 1), .gpiomux = { 2, 0, 0, 0 }, .gpiomute = 1, .needs_tvaudio = 1, @@ -2620,7 +2625,7 @@ struct tvcard bttv_tvcards[] = { /* .audio_inputs= 1, */ .svhs = 2, .gpiomask = 0x108007, - .muxsel = { 2, 3, 1, 1 }, + .muxsel = MUXSEL(2, 3, 1, 1), .gpiomux = { 100000, 100002, 100002, 100000 }, .no_msp34xx = 1, .no_tda9875 = 1, @@ -2637,7 +2642,7 @@ struct tvcard bttv_tvcards[] = { /* .audio_inputs= 0, */ .svhs = NO_SVHS, .gpiomask = 0x0f, /* old: 7 */ - .muxsel = { 0, 1, 3, 2 }, /* Composite 0-3 */ + .muxsel = MUXSEL(0, 1, 3, 2), /* Composite 0-3 */ .no_msp34xx = 1, .no_tda9875 = 1, .no_tda7432 = 1, @@ -2657,7 +2662,7 @@ struct tvcard bttv_tvcards[] = { /* .audio_inputs= 1, */ .svhs = 2, .gpiomask = 7, - .muxsel = { 2, 3, 1, 1 }, + .muxsel = MUXSEL(2, 3, 1, 1), .gpiomux = { 0, 1, 2, 3 }, .gpiomute = 4, .tuner_type = TUNER_TEMIC_4009FR5_PAL, @@ -2671,7 +2676,7 @@ struct tvcard bttv_tvcards[] = { .video_inputs = 4, /* .audio_inputs= 0, */ .svhs = NO_SVHS, - .muxsel = { 0, 1, 2, 3 }, + .muxsel = MUXSEL(0, 1, 2, 3), .tuner_type = TUNER_ABSENT, .tuner_addr = ADDR_UNSET, }, @@ -2680,7 +2685,7 @@ struct tvcard bttv_tvcards[] = { .video_inputs = 2, /* .audio_inputs= 0, */ .svhs = 1, - .muxsel = { 2, 0, 1, 3 }, + .muxsel = MUXSEL(2, 0, 1, 3), .tuner_type = TUNER_ABSENT, .tuner_addr = ADDR_UNSET, }, @@ -2692,7 +2697,7 @@ struct tvcard bttv_tvcards[] = { .video_inputs = 3, /* .audio_inputs= 1, */ .svhs = 2, - .muxsel = { 2, 3, 1 }, + .muxsel = MUXSEL(2, 3, 1), .gpiomask = 0x00e00007, .gpiomux = { 0x00400005, 0, 0x00000001, 0 }, .gpiomute = 0x00c00007, @@ -2707,7 +2712,7 @@ struct tvcard bttv_tvcards[] = { /* .audio_inputs= 1, */ .svhs = 2, .gpiomask = 0x3014f, - .muxsel = { 2, 3, 1, 1 }, + .muxsel = MUXSEL(2, 3, 1, 1), .gpiomux = { 0x20001,0x10001, 0, 0 }, .gpiomute = 10, .needs_tvaudio = 1, @@ -2722,8 +2727,7 @@ struct tvcard bttv_tvcards[] = { /* .audio_inputs= 0, */ .svhs = NO_SVHS, .gpiomask = 0x0, - .muxsel = { 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2 }, + .muxsel = MUXSEL(2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2), .muxsel_hook = geovision_muxsel, .gpiomux = { 0 }, .no_msp34xx = 1, @@ -2740,7 +2744,7 @@ struct tvcard bttv_tvcards[] = { /* .audio_inputs= 1, */ .svhs = 2, .gpiomask = 0x008007, - .muxsel = { 2, 3, 1, 1 }, + .muxsel = MUXSEL(2, 3, 1, 1), .gpiomux = { 0, 1, 2, 2 }, /* CONTVFMi */ .gpiomute = 3, /* CONTVFMi */ .needs_tvaudio = 0, @@ -2764,7 +2768,7 @@ struct tvcard bttv_tvcards[] = { 11 -> internal audio input */ .gpiomask = 0x060040, - .muxsel = { 2, 3, 3 }, + .muxsel = MUXSEL(2, 3, 3), .gpiomux = { 0x60000, 0x60000, 0x20000, 0x20000 }, .gpiomute = 0, .tuner_type = TUNER_TCL_MF02GIP_5N, @@ -2780,7 +2784,7 @@ struct tvcard bttv_tvcards[] = { /* .audio_inputs= 0, */ .svhs = NO_SVHS, .gpiomask = 0x00, - .muxsel = { 0, 2, 3, 1 }, + .muxsel = MUXSEL(0, 2, 3, 1), .gpiomux = { 0, 0, 0, 0 }, /* card has no audio */ .needs_tvaudio = 0, .pll = PLL_28, @@ -2794,7 +2798,7 @@ struct tvcard bttv_tvcards[] = { /* .audio_inputs= 0, */ .svhs = 3, .gpiomask = 0x00, - .muxsel = { 2, 3, 1 }, + .muxsel = MUXSEL(2, 3, 1), .gpiomux = { 0, 0, 0, 0 }, /* card has no audio */ .needs_tvaudio = 0, .pll = PLL_28, @@ -2808,7 +2812,7 @@ struct tvcard bttv_tvcards[] = { /* .audio_inputs= 0, */ .svhs = 3, .gpiomask = 0x00, - .muxsel = { 3, 2, 1 }, + .muxsel = MUXSEL(3, 2, 1), .gpiomux = { 0, 0, 0, 0 }, /* card has no audio */ .needs_tvaudio = 0, .pll = PLL_28, diff --git a/drivers/media/video/bt8xx/bttv-driver.c b/drivers/media/video/bt8xx/bttv-driver.c index 8d9756b9587e..ccf6aa6a975b 100644 --- a/drivers/media/video/bt8xx/bttv-driver.c +++ b/drivers/media/video/bt8xx/bttv-driver.c @@ -1142,7 +1142,7 @@ video_mux(struct bttv *btv, unsigned int input) btand(~BT848_CONTROL_COMP, BT848_E_CONTROL); btand(~BT848_CONTROL_COMP, BT848_O_CONTROL); } - mux = bttv_tvcards[btv->c.type].muxsel[input] & 3; + mux = bttv_muxsel(btv, input); btaor(mux<<5, ~(3<<5), BT848_IFORM); dprintk(KERN_DEBUG "bttv%d: video mux: input=%d mux=%d\n", btv->c.nr,input,mux); diff --git a/drivers/media/video/bt8xx/bttv.h b/drivers/media/video/bt8xx/bttv.h index e377e2887a53..ead6e749372a 100644 --- a/drivers/media/video/bt8xx/bttv.h +++ b/drivers/media/video/bt8xx/bttv.h @@ -206,15 +206,16 @@ struct bttv_core { struct bttv; - struct tvcard { char *name; void (*volume_gpio)(struct bttv *btv, __u16 volume); void (*audio_mode_gpio)(struct bttv *btv, struct v4l2_tuner *tuner, int set); void (*muxsel_hook)(struct bttv *btv, unsigned int input); + /* MUX bits for each input, two bits per input starting with the LSB */ + u32 muxsel; /* Use MUXSEL() to set */ + u32 gpiomask; - u32 muxsel[16]; u32 gpiomux[4]; /* Tuner, Radio, external, internal */ u32 gpiomute; /* GPIO mute setting */ u32 gpiomask2; /* GPIO MUX mask */ @@ -246,6 +247,31 @@ struct tvcard { extern struct tvcard bttv_tvcards[]; +/* + * This bit of cpp voodoo is used to create a macro with a variable number of + * arguments (1 to 16). It will pack each argument into a word two bits at a + * time. It can't be a function because it needs to be compile time constant to + * initialize structures. Since each argument must fit in two bits, it's ok + * that they are changed to octal. One should not use hex number, macros, or + * anything else with this macro. Just use plain integers from 0 to 3. + */ +#define _MUXSELf(a) 0##a << 30 +#define _MUXSELe(a, b...) 0##a << 28 | _MUXSELf(b) +#define _MUXSELd(a, b...) 0##a << 26 | _MUXSELe(b) +#define _MUXSELc(a, b...) 0##a << 24 | _MUXSELd(b) +#define _MUXSELb(a, b...) 0##a << 22 | _MUXSELc(b) +#define _MUXSELa(a, b...) 0##a << 20 | _MUXSELb(b) +#define _MUXSEL9(a, b...) 0##a << 18 | _MUXSELa(b) +#define _MUXSEL8(a, b...) 0##a << 16 | _MUXSEL9(b) +#define _MUXSEL7(a, b...) 0##a << 14 | _MUXSEL8(b) +#define _MUXSEL6(a, b...) 0##a << 12 | _MUXSEL7(b) +#define _MUXSEL5(a, b...) 0##a << 10 | _MUXSEL6(b) +#define _MUXSEL4(a, b...) 0##a << 8 | _MUXSEL5(b) +#define _MUXSEL3(a, b...) 0##a << 6 | _MUXSEL4(b) +#define _MUXSEL2(a, b...) 0##a << 4 | _MUXSEL3(b) +#define _MUXSEL1(a, b...) 0##a << 2 | _MUXSEL2(b) +#define MUXSEL(a, b...) (a | _MUXSEL1(b)) + /* identification / initialization of the card */ extern void bttv_idcard(struct bttv *btv); extern void bttv_init_card1(struct bttv *btv); diff --git a/drivers/media/video/bt8xx/bttvp.h b/drivers/media/video/bt8xx/bttvp.h index 23ab1c9527e4..497c8dcb4ae8 100644 --- a/drivers/media/video/bt8xx/bttvp.h +++ b/drivers/media/video/bt8xx/bttvp.h @@ -464,6 +464,12 @@ struct bttv { extern unsigned int bttv_num; extern struct bttv bttvs[BTTV_MAX]; +static inline unsigned int bttv_muxsel(const struct bttv *btv, + unsigned int input) +{ + return (bttv_tvcards[btv->c.type].muxsel >> (input * 2)) & 3; +} + #endif #define btwrite(dat,adr) writel((dat), btv->bt848_mmio+(adr)) -- cgit v1.2.3 From 4b10d3b626922ffa2387905a230b12450281a12d Mon Sep 17 00:00:00 2001 From: Trent Piepho Date: Wed, 28 Jan 2009 21:32:59 -0300 Subject: V4L/DVB (10568): bttv: dynamically allocate device data The bttv driver had static array of structures for up to 16 possible bttv devices, even though few users have more than one or two. The structures were quite large and this resulted in a huge BSS segment. Change the driver to allocate the bttv device data dynamically, which changes "struct bttv bttvs[BTTV_MAX]" to "struct bttv *bttvs[BTTV_MAX]". It would be nice to get ride of "bttvs" entirely but there are some complications with gpio access from the audio & mpeg drivers. To help bttvs removal along anyway, I changed the open() methods use the video device's drvdata to get the driver data instead of looking it up in the bttvs array. This is also more efficient. Some WARN_ON()s are added in cases the device node exists by the bttv device doesn't, which I don't think should be possible. The gpio access functions need to check if bttvs[card] is NULL now. Though calling them on a non-existent card in the first place is wrong, but hard to solve given the fundamental problems in how the gpio access code works. This patch reduces the bss size by 66560 bytes on ia32. Overall change is a reduction of 66398 bytes, as the WARN_ON()s add some 198 bytes. Signed-off-by: Trent Piepho Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/bt8xx/bttv-driver.c | 45 ++++++++++++--------------------- drivers/media/video/bt8xx/bttv-if.c | 18 ++++++++++--- drivers/media/video/bt8xx/bttvp.h | 2 +- 3 files changed, 31 insertions(+), 34 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/bt8xx/bttv-driver.c b/drivers/media/video/bt8xx/bttv-driver.c index ccf6aa6a975b..826ca60b42e6 100644 --- a/drivers/media/video/bt8xx/bttv-driver.c +++ b/drivers/media/video/bt8xx/bttv-driver.c @@ -58,7 +58,7 @@ unsigned int bttv_num; /* number of Bt848s in use */ -struct bttv bttvs[BTTV_MAX]; +struct bttv *bttvs[BTTV_MAX]; unsigned int bttv_debug; unsigned int bttv_verbose = 1; @@ -3217,29 +3217,19 @@ err: static int bttv_open(struct file *file) { int minor = video_devdata(file)->minor; - struct bttv *btv = NULL; + struct bttv *btv = video_drvdata(file); struct bttv_fh *fh; enum v4l2_buf_type type = 0; - unsigned int i; dprintk(KERN_DEBUG "bttv: open minor=%d\n",minor); lock_kernel(); - for (i = 0; i < bttv_num; i++) { - if (bttvs[i].video_dev && - bttvs[i].video_dev->minor == minor) { - btv = &bttvs[i]; - type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - break; - } - if (bttvs[i].vbi_dev && - bttvs[i].vbi_dev->minor == minor) { - btv = &bttvs[i]; - type = V4L2_BUF_TYPE_VBI_CAPTURE; - break; - } - } - if (NULL == btv) { + if (btv->video_dev->minor == minor) { + type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + } else if (btv->vbi_dev->minor == minor) { + type = V4L2_BUF_TYPE_VBI_CAPTURE; + } else { + WARN_ON(1); unlock_kernel(); return -ENODEV; } @@ -3429,20 +3419,14 @@ static struct video_device bttv_video_template = { static int radio_open(struct file *file) { int minor = video_devdata(file)->minor; - struct bttv *btv = NULL; + struct bttv *btv = video_drvdata(file); struct bttv_fh *fh; - unsigned int i; dprintk("bttv: open minor=%d\n",minor); lock_kernel(); - for (i = 0; i < bttv_num; i++) { - if (bttvs[i].radio_dev && bttvs[i].radio_dev->minor == minor) { - btv = &bttvs[i]; - break; - } - } - if (NULL == btv) { + WARN_ON(btv->radio_dev && btv->radio_dev->minor != minor); + if (!btv->radio_dev || btv->radio_dev->minor != minor) { unlock_kernel(); return -ENODEV; } @@ -4203,6 +4187,7 @@ static struct video_device *vdev_init(struct bttv *btv, vfd->parent = &btv->c.pci->dev; vfd->release = video_device_release; vfd->debug = bttv_debug; + video_set_drvdata(vfd, btv); snprintf(vfd->name, sizeof(vfd->name), "BT%d%s %s (%s)", btv->id, (btv->id==848 && btv->revision==0x12) ? "A" : "", type_name, bttv_tvcards[btv->c.type].name); @@ -4312,8 +4297,7 @@ static int __devinit bttv_probe(struct pci_dev *dev, if (bttv_num == BTTV_MAX) return -ENOMEM; printk(KERN_INFO "bttv: Bt8xx card found (%d).\n", bttv_num); - btv=&bttvs[bttv_num]; - memset(btv,0,sizeof(*btv)); + bttvs[bttv_num] = btv = kzalloc(sizeof(*btv), GFP_KERNEL); btv->c.nr = bttv_num; sprintf(btv->c.name,"bttv%d",btv->c.nr); @@ -4517,6 +4501,9 @@ static void __devexit bttv_remove(struct pci_dev *pci_dev) pci_resource_len(btv->c.pci,0)); pci_set_drvdata(pci_dev, NULL); + bttvs[btv->c.nr] = NULL; + kfree(btv); + return; } diff --git a/drivers/media/video/bt8xx/bttv-if.c b/drivers/media/video/bt8xx/bttv-if.c index ecf07988cd33..a6a540dc9e4b 100644 --- a/drivers/media/video/bt8xx/bttv-if.c +++ b/drivers/media/video/bt8xx/bttv-if.c @@ -47,7 +47,10 @@ struct pci_dev* bttv_get_pcidev(unsigned int card) { if (card >= bttv_num) return NULL; - return bttvs[card].c.pci; + if (!bttvs[card]) + return NULL; + + return bttvs[card]->c.pci; } @@ -59,7 +62,10 @@ int bttv_gpio_enable(unsigned int card, unsigned long mask, unsigned long data) return -EINVAL; } - btv = &bttvs[card]; + btv = bttvs[card]; + if (!btv) + return -ENODEV; + gpio_inout(mask,data); if (bttv_gpio) bttv_gpio_tracking(btv,"extern enable"); @@ -74,7 +80,9 @@ int bttv_read_gpio(unsigned int card, unsigned long *data) return -EINVAL; } - btv = &bttvs[card]; + btv = bttvs[card]; + if (!btv) + return -ENODEV; if(btv->shutdown) { return -ENODEV; @@ -94,7 +102,9 @@ int bttv_write_gpio(unsigned int card, unsigned long mask, unsigned long data) return -EINVAL; } - btv = &bttvs[card]; + btv = bttvs[card]; + if (!btv) + return -ENODEV; /* prior setting BT848_GPIO_REG_INP is (probably) not needed because direct input is set on init */ diff --git a/drivers/media/video/bt8xx/bttvp.h b/drivers/media/video/bt8xx/bttvp.h index 497c8dcb4ae8..b8274d233fd0 100644 --- a/drivers/media/video/bt8xx/bttvp.h +++ b/drivers/media/video/bt8xx/bttvp.h @@ -462,7 +462,7 @@ struct bttv { /* our devices */ #define BTTV_MAX 32 extern unsigned int bttv_num; -extern struct bttv bttvs[BTTV_MAX]; +extern struct bttv *bttvs[BTTV_MAX]; static inline unsigned int bttv_muxsel(const struct bttv *btv, unsigned int input) -- cgit v1.2.3 From 314893605e07547c372ebc6187e28c784ce0b1ed Mon Sep 17 00:00:00 2001 From: Tim Farrington Date: Thu, 15 Jan 2009 09:58:55 -0300 Subject: V4L/DVB (10574): saa7134: fix Avermedia E506R composite input Make correction to composite input plus svideo input to Avermedia E506R Signed-off-by: Tim Farrington Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/saa7134/saa7134-cards.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/saa7134/saa7134-cards.c b/drivers/media/video/saa7134/saa7134-cards.c index 3192ccb5fcfe..107f6d30d007 100644 --- a/drivers/media/video/saa7134/saa7134-cards.c +++ b/drivers/media/video/saa7134/saa7134-cards.c @@ -4323,13 +4323,13 @@ struct saa7134_board saa7134_boards[] = { .amux = TV, .tv = 1, }, { - .name = name_comp, - .vmux = 0, + .name = name_comp1, + .vmux = 3, .amux = LINE1, }, { .name = name_svideo, .vmux = 8, - .amux = LINE1, + .amux = LINE2, } }, .radio = { .name = name_radio, -- cgit v1.2.3 From ac829d62eeb5440899f0f034a9f756c2296105a5 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Tue, 27 Jan 2009 03:02:41 -0300 Subject: V4L/DVB (10616): tw9910: color format check is added on set_fmt Signed-off-by: Kuninori Morimoto Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/tw9910.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'drivers/media/video') diff --git a/drivers/media/video/tw9910.c b/drivers/media/video/tw9910.c index 52c0357faa5d..8dc3ec79a06f 100644 --- a/drivers/media/video/tw9910.c +++ b/drivers/media/video/tw9910.c @@ -645,6 +645,19 @@ static int tw9910_set_fmt(struct soc_camera_device *icd, __u32 pixfmt, struct tw9910_priv *priv = container_of(icd, struct tw9910_priv, icd); int ret = -EINVAL; u8 val; + int i; + + /* + * check color format + */ + for (i = 0 ; i < ARRAY_SIZE(tw9910_color_fmt) ; i++) { + if (pixfmt == tw9910_color_fmt[i].fourcc) { + ret = 0; + break; + } + } + if (ret < 0) + goto tw9910_set_fmt_error; /* * select suitable norm -- cgit v1.2.3 From 5899c75f0252552f3683e9bba2f2680ea69f76b3 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Mon, 2 Feb 2009 07:43:50 -0300 Subject: V4L/DVB (10617): gspca - vc032x: Remove the vc0321 reset. Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/vc032x.c | 10 ---------- 1 file changed, 10 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/gspca/vc032x.c b/drivers/media/video/gspca/vc032x.c index f8d535ce9081..9f3d9f104e6e 100644 --- a/drivers/media/video/gspca/vc032x.c +++ b/drivers/media/video/gspca/vc032x.c @@ -2072,14 +2072,6 @@ static void usb_exchange(struct gspca_dev *gspca_dev, /*not reached*/ } -static void vc0321_reset(struct gspca_dev *gspca_dev) -{ - reg_w(gspca_dev->dev, 0xa0, 0x00, 0xb04d); - reg_w(gspca_dev->dev, 0xa0, 0x01, 0xb301); - msleep(100); - reg_w(gspca_dev->dev, 0xa0, 0x01, 0xb003); - msleep(100); -} /* this function is called at probe time */ static int sd_config(struct gspca_dev *gspca_dev, @@ -2092,8 +2084,6 @@ static int sd_config(struct gspca_dev *gspca_dev, cam = &gspca_dev->cam; sd->bridge = id->driver_info; - - vc0321_reset(gspca_dev); sensor = vc032x_probe_sensor(gspca_dev); switch (sensor) { case -1: -- cgit v1.2.3 From 92e8c91bd2a0db4b129baf332344f564bdfca941 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Mon, 2 Feb 2009 16:25:38 -0300 Subject: V4L/DVB (10618): gspca - some drivers: Fix compilation warnings. Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/mr97310a.c | 2 +- drivers/media/video/gspca/sonixj.c | 2 +- drivers/media/video/gspca/spca505.c | 8 ++++---- 3 files changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/gspca/mr97310a.c b/drivers/media/video/gspca/mr97310a.c index 3a5ddff8f7a6..5ec5ce6e3ed9 100644 --- a/drivers/media/video/gspca/mr97310a.c +++ b/drivers/media/video/gspca/mr97310a.c @@ -73,7 +73,7 @@ static int reg_w(struct gspca_dev *gspca_dev, int len) rc = usb_bulk_msg(gspca_dev->dev, usb_sndbulkpipe(gspca_dev->dev, 4), - gspca_dev->usb_buf, len, 0, 500); + gspca_dev->usb_buf, len, NULL, 500); if (rc < 0) PDEBUG(D_ERR, "reg write [%02x] error %d", gspca_dev->usb_buf[0], rc); diff --git a/drivers/media/video/gspca/sonixj.c b/drivers/media/video/gspca/sonixj.c index 970c74f9fe8b..882d5e9b436a 100644 --- a/drivers/media/video/gspca/sonixj.c +++ b/drivers/media/video/gspca/sonixj.c @@ -1023,7 +1023,7 @@ static void mi0360_probe(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; int i, j; - u16 val; + u16 val = 0; static const u8 probe_tb[][4][8] = { { /* mi0360 */ {0xb0, 0x5d, 0x07, 0x00, 0x02, 0x00, 0x00, 0x10}, diff --git a/drivers/media/video/gspca/spca505.c b/drivers/media/video/gspca/spca505.c index 4fc54d8b84aa..2acec58b1b97 100644 --- a/drivers/media/video/gspca/spca505.c +++ b/drivers/media/video/gspca/spca505.c @@ -426,8 +426,8 @@ static const u8 spca505b_open_data_ccd[][3] = { {0x05, 0x00, 0x11}, {0x05, 0x00, 0x12}, {0x05, 0x6f, 0x00}, - {0x05, (u8) (initial_brightness >> 6), 0x00}, - {0x05, (u8) (initial_brightness << 2), 0x01}, + {0x05, initial_brightness >> 6, 0x00}, + {0x05, (initial_brightness << 2) & 0xff, 0x01}, {0x05, 0x00, 0x02}, {0x05, 0x01, 0x03}, {0x05, 0x00, 0x04}, @@ -560,8 +560,8 @@ static const u8 spca505b_open_data_ccd[][3] = { {0x06, 0x5f, 0x1f}, {0x06, 0x32, 0x20}, - {0x05, (u8) (initial_brightness >> 6), 0x00}, - {0x05, (u8) (initial_brightness << 2), 0x01}, + {0x05, initial_brightness >> 6, 0x00}, + {0x05, (initial_brightness << 2) & 0xff, 0x01}, {0x05, 0x06, 0xc1}, {0x05, 0x58, 0xc2}, {0x05, 0x00, 0xca}, -- cgit v1.2.3 From e23b290716ad9355d9f17b569c8c9e659ff68aa7 Mon Sep 17 00:00:00 2001 From: Tobias Klauser Date: Mon, 9 Feb 2009 18:06:49 -0300 Subject: V4L/DVB (10628): V4L: Storage class should be before const qualifier The C99 specification states in section 6.11.5: The placement of a storage-class specifier other than at the beginning of the declaration specifiers in a declaration is an obsolescent feature. Cc: Jean-Francois Moine Cc: Sakari Ailus Signed-off-by: Tobias Klauser Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/t613.c | 2 +- drivers/media/video/tcm825x.c | 22 +++++++++++----------- drivers/media/video/tcm825x.h | 2 +- 3 files changed, 13 insertions(+), 13 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/gspca/t613.c b/drivers/media/video/gspca/t613.c index 0a1f4efdc6ed..95c120a506d3 100644 --- a/drivers/media/video/gspca/t613.c +++ b/drivers/media/video/gspca/t613.c @@ -272,7 +272,7 @@ struct additional_sensor_data { const u8 stream[4]; }; -const static struct additional_sensor_data sensor_data[] = { +static const struct additional_sensor_data sensor_data[] = { { /* OM6802 */ .data1 = {0xc2, 0x28, 0x0f, 0x22, 0xcd, 0x27, 0x2c, 0x06, diff --git a/drivers/media/video/tcm825x.c b/drivers/media/video/tcm825x.c index 29991d1cf13e..b30c49248217 100644 --- a/drivers/media/video/tcm825x.c +++ b/drivers/media/video/tcm825x.c @@ -50,7 +50,7 @@ struct tcm825x_sensor { }; /* list of image formats supported by TCM825X sensor */ -const static struct v4l2_fmtdesc tcm825x_formats[] = { +static const struct v4l2_fmtdesc tcm825x_formats[] = { { .description = "YUYV (YUV 4:2:2), packed", .pixelformat = V4L2_PIX_FMT_UYVY, @@ -76,15 +76,15 @@ const static struct v4l2_fmtdesc tcm825x_formats[] = { * TCM825X register configuration for all combinations of pixel format and * image size */ -const static struct tcm825x_reg subqcif = { 0x20, TCM825X_PICSIZ }; -const static struct tcm825x_reg qcif = { 0x18, TCM825X_PICSIZ }; -const static struct tcm825x_reg cif = { 0x14, TCM825X_PICSIZ }; -const static struct tcm825x_reg qqvga = { 0x0c, TCM825X_PICSIZ }; -const static struct tcm825x_reg qvga = { 0x04, TCM825X_PICSIZ }; -const static struct tcm825x_reg vga = { 0x00, TCM825X_PICSIZ }; +static const struct tcm825x_reg subqcif = { 0x20, TCM825X_PICSIZ }; +static const struct tcm825x_reg qcif = { 0x18, TCM825X_PICSIZ }; +static const struct tcm825x_reg cif = { 0x14, TCM825X_PICSIZ }; +static const struct tcm825x_reg qqvga = { 0x0c, TCM825X_PICSIZ }; +static const struct tcm825x_reg qvga = { 0x04, TCM825X_PICSIZ }; +static const struct tcm825x_reg vga = { 0x00, TCM825X_PICSIZ }; -const static struct tcm825x_reg yuv422 = { 0x00, TCM825X_PICFMT }; -const static struct tcm825x_reg rgb565 = { 0x02, TCM825X_PICFMT }; +static const struct tcm825x_reg yuv422 = { 0x00, TCM825X_PICFMT }; +static const struct tcm825x_reg rgb565 = { 0x02, TCM825X_PICFMT }; /* Our own specific controls */ #define V4L2_CID_ALC V4L2_CID_PRIVATE_BASE @@ -248,10 +248,10 @@ static struct vcontrol { }; -const static struct tcm825x_reg *tcm825x_siz_reg[NUM_IMAGE_SIZES] = +static const struct tcm825x_reg *tcm825x_siz_reg[NUM_IMAGE_SIZES] = { &subqcif, &qqvga, &qcif, &qvga, &cif, &vga }; -const static struct tcm825x_reg *tcm825x_fmt_reg[NUM_PIXEL_FORMATS] = +static const struct tcm825x_reg *tcm825x_fmt_reg[NUM_PIXEL_FORMATS] = { &yuv422, &rgb565 }; /* diff --git a/drivers/media/video/tcm825x.h b/drivers/media/video/tcm825x.h index 770ebacfa344..5b7e69682368 100644 --- a/drivers/media/video/tcm825x.h +++ b/drivers/media/video/tcm825x.h @@ -188,7 +188,7 @@ struct tcm825x_platform_data { /* Array of image sizes supported by TCM825X. These must be ordered from * smallest image size to largest. */ -const static struct capture_size tcm825x_sizes[] = { +static const struct capture_size tcm825x_sizes[] = { { 128, 96 }, /* subQCIF */ { 160, 120 }, /* QQVGA */ { 176, 144 }, /* QCIF */ -- cgit v1.2.3 From 320a46485c83e70e374afa8bdfe8cd39a801cd5d Mon Sep 17 00:00:00 2001 From: Roel Kluin Date: Mon, 9 Feb 2009 18:57:06 -0300 Subject: V4L/DVB (10629): tvp514x: try_count reaches 0, not -1 with while (try_count-- > 0) { ... } try_count reaches 0, not -1. Cc: Vaibhav Hiremath Signed-off-by: Roel Kluin Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/tvp514x.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/tvp514x.c b/drivers/media/video/tvp514x.c index 8e23aa53c29a..5f4cbc2b23c1 100644 --- a/drivers/media/video/tvp514x.c +++ b/drivers/media/video/tvp514x.c @@ -686,7 +686,7 @@ static int ioctl_s_routing(struct v4l2_int_device *s, break; /* Input detected */ } - if ((current_std == STD_INVALID) || (try_count < 0)) + if ((current_std == STD_INVALID) || (try_count <= 0)) return -EINVAL; decoder->current_std = current_std; -- cgit v1.2.3 From 995a65285bde47bbb2a0c3dadc0b8822d47d78f4 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Thu, 12 Feb 2009 15:19:24 -0300 Subject: V4L/DVB (10631): zoran: fix printk format Fix printk format warning: drivers/media/video/zoran/zoran_driver.c:345: warning: format '%lx' expects type 'long unsigned int', but argument 5 has type 'phys_addr_t' Signed-off-by: Randy Dunlap Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/zoran/zoran_driver.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/zoran/zoran_driver.c b/drivers/media/video/zoran/zoran_driver.c index 120ef235e63d..b81e20912fa7 100644 --- a/drivers/media/video/zoran/zoran_driver.c +++ b/drivers/media/video/zoran/zoran_driver.c @@ -344,9 +344,9 @@ v4l_fbuffer_alloc (struct file *file) SetPageReserved(MAP_NR(mem + off)); dprintk(4, KERN_INFO - "%s: v4l_fbuffer_alloc() - V4L frame %d mem 0x%lx (bus: 0x%lx)\n", + "%s: v4l_fbuffer_alloc() - V4L frame %d mem 0x%lx (bus: 0x%llx)\n", ZR_DEVNAME(zr), i, (unsigned long) mem, - virt_to_bus(mem)); + (unsigned long long)virt_to_bus(mem)); } else { /* Use high memory which has been left at boot time */ -- cgit v1.2.3 From cb3bf504f7c875070d56e84ce1e28aff8c3b6790 Mon Sep 17 00:00:00 2001 From: Oldřich Jedlička Date: Thu, 12 Feb 2009 03:43:11 -0300 Subject: V4L/DVB (10632): Added support for AVerMedia Cardbus Hybrid remote control MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Added support for I2C device at address 0x40 and subaddress 0x0d/0x0b that provides remote control key reading support for AVerMedia Cardbus Hybrid card, possibly for other AVerMedia Cardbus cards. The I2C address 0x40 doesn't like the SAA7134's 0xfd quirk, so it was disabled. [mchehab@redhat.com: CodingStyle fixes] Signed-off-by: Oldřich Jedlička Signed-off-by: Mauro Carvalho Chehab --- drivers/media/common/ir-keymaps.c | 59 ++++++++++++++++++++++++++ drivers/media/video/ir-kbd-i2c.c | 64 +++++++++++++++++++++++++++++ drivers/media/video/saa7134/saa7134-cards.c | 5 +++ drivers/media/video/saa7134/saa7134-i2c.c | 2 +- include/media/ir-common.h | 1 + 5 files changed, 130 insertions(+), 1 deletion(-) (limited to 'drivers/media/video') diff --git a/drivers/media/common/ir-keymaps.c b/drivers/media/common/ir-keymaps.c index d7b205472e1c..97e78f71c60d 100644 --- a/drivers/media/common/ir-keymaps.c +++ b/drivers/media/common/ir-keymaps.c @@ -153,6 +153,65 @@ IR_KEYTAB_TYPE ir_codes_avermedia_m135a[IR_KEYTAB_SIZE] = { }; EXPORT_SYMBOL_GPL(ir_codes_avermedia_m135a); +/* Oldrich Jedlicka */ +IR_KEYTAB_TYPE ir_codes_avermedia_cardbus[IR_KEYTAB_SIZE] = { + [0x00] = KEY_POWER, + [0x01] = KEY_TUNER, /* TV/FM */ + [0x03] = KEY_TEXT, /* Teletext */ + [0x04] = KEY_EPG, + [0x05] = KEY_1, + [0x06] = KEY_2, + [0x07] = KEY_3, + [0x08] = KEY_AUDIO, + [0x09] = KEY_4, + [0x0a] = KEY_5, + [0x0b] = KEY_6, + [0x0c] = KEY_ZOOM, /* Full screen */ + [0x0d] = KEY_7, + [0x0e] = KEY_8, + [0x0f] = KEY_9, + [0x10] = KEY_PAGEUP, /* 16-CH PREV */ + [0x11] = KEY_0, + [0x12] = KEY_INFO, + [0x13] = KEY_AGAIN, /* CH RTN - channel return */ + [0x14] = KEY_MUTE, + [0x15] = KEY_EDIT, /* Autoscan */ + [0x17] = KEY_SAVE, /* Screenshot */ + [0x18] = KEY_PLAYPAUSE, + [0x19] = KEY_RECORD, + [0x1a] = KEY_PLAY, + [0x1b] = KEY_STOP, + [0x1c] = KEY_FASTFORWARD, + [0x1d] = KEY_REWIND, + [0x1e] = KEY_VOLUMEDOWN, + [0x1f] = KEY_VOLUMEUP, + [0x22] = KEY_SLEEP, /* Sleep */ + [0x23] = KEY_ZOOM, /* Aspect */ + [0x26] = KEY_SCREEN, /* Pos */ + [0x27] = KEY_ANGLE, /* Size */ + [0x28] = KEY_SELECT, /* Select */ + [0x29] = KEY_BLUE, /* Blue/Picture */ + [0x2a] = KEY_BACKSPACE, /* Back */ + [0x2b] = KEY_MEDIA, /* PIP (Picture-in-picture) */ + [0x2c] = KEY_DOWN, + [0x2e] = KEY_DOT, + [0x2f] = KEY_TV, /* Live TV */ + [0x32] = KEY_LEFT, + [0x33] = KEY_CLEAR, /* Clear */ + [0x35] = KEY_RED, /* Red/TV */ + [0x36] = KEY_UP, + [0x37] = KEY_HOME, /* Home */ + [0x39] = KEY_GREEN, /* Green/Video */ + [0x3d] = KEY_YELLOW, /* Yellow/Music */ + [0x3e] = KEY_OK, /* Ok */ + [0x3f] = KEY_RIGHT, + [0x40] = KEY_NEXT, /* Next */ + [0x41] = KEY_PREVIOUS, /* Previous */ + [0x42] = KEY_CHANNELDOWN, /* Channel down */ + [0x43] = KEY_CHANNELUP /* Channel up */ +}; +EXPORT_SYMBOL_GPL(ir_codes_avermedia_cardbus); + /* Attila Kondoros */ IR_KEYTAB_TYPE ir_codes_apac_viewcomp[IR_KEYTAB_SIZE] = { diff --git a/drivers/media/video/ir-kbd-i2c.c b/drivers/media/video/ir-kbd-i2c.c index d4658c56eddc..2ee49b7ddcf0 100644 --- a/drivers/media/video/ir-kbd-i2c.c +++ b/drivers/media/video/ir-kbd-i2c.c @@ -16,6 +16,8 @@ * Henry Wong * Mark Schultz * Brian Rogers + * modified for AVerMedia Cardbus by + * Oldrich Jedlicka * * 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 @@ -216,6 +218,46 @@ static int get_key_knc1(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw) return 1; } +static int get_key_avermedia_cardbus(struct IR_i2c *ir, + u32 *ir_key, u32 *ir_raw) +{ + unsigned char subaddr, key, keygroup; + struct i2c_msg msg[] = { { .addr = ir->c.addr, .flags = 0, + .buf = &subaddr, .len = 1}, + { .addr = ir->c.addr, .flags = I2C_M_RD, + .buf = &key, .len = 1} }; + subaddr = 0x0d; + if (2 != i2c_transfer(ir->c.adapter, msg, 2)) { + dprintk(1, "read error\n"); + return -EIO; + } + + if (key == 0xff) + return 0; + + subaddr = 0x0b; + msg[1].buf = &keygroup; + if (2 != i2c_transfer(ir->c.adapter, msg, 2)) { + dprintk(1, "read error\n"); + return -EIO; + } + + if (keygroup == 0xff) + return 0; + + dprintk(1, "read key 0x%02x/0x%02x\n", key, keygroup); + if (keygroup < 2 || keygroup > 3) { + /* Only a warning */ + dprintk(1, "warning: invalid key group 0x%02x for key 0x%02x\n", + keygroup, key); + } + key |= (keygroup & 1) << 6; + + *ir_key = key; + *ir_raw = key; + return 1; +} + /* ----------------------------------------------------------------------- */ static void ir_key_poll(struct IR_i2c *ir) @@ -360,6 +402,12 @@ static int ir_attach(struct i2c_adapter *adap, int addr, ir_type = IR_TYPE_OTHER; } break; + case 0x40: + name = "AVerMedia Cardbus remote"; + ir->get_key = get_key_avermedia_cardbus; + ir_type = IR_TYPE_OTHER; + ir_codes = ir_codes_avermedia_cardbus; + break; default: /* shouldn't happen */ printk(DEVNAME ": Huh? unknown i2c address (0x%02x)?\n", addr); @@ -524,6 +572,22 @@ static int ir_probe(struct i2c_adapter *adap) ir_attach(adap, msg.addr, 0, 0); } + /* Special case for AVerMedia Cardbus remote */ + if (adap->id == I2C_HW_SAA7134) { + unsigned char subaddr, data; + struct i2c_msg msg[] = { { .addr = 0x40, .flags = 0, + .buf = &subaddr, .len = 1}, + { .addr = 0x40, .flags = I2C_M_RD, + .buf = &data, .len = 1} }; + subaddr = 0x0d; + rc = i2c_transfer(adap, msg, 2); + dprintk(1, "probe 0x%02x/0x%02x @ %s: %s\n", + msg[0].addr, subaddr, adap->name, + (2 == rc) ? "yes" : "no"); + if (2 == rc) + ir_attach(adap, msg[0].addr, 0, 0); + } + return 0; } diff --git a/drivers/media/video/saa7134/saa7134-cards.c b/drivers/media/video/saa7134/saa7134-cards.c index 107f6d30d007..67c223cc867f 100644 --- a/drivers/media/video/saa7134/saa7134-cards.c +++ b/drivers/media/video/saa7134/saa7134-cards.c @@ -6019,6 +6019,11 @@ int saa7134_board_init1(struct saa7134_dev *dev) msleep(10); break; case SAA7134_BOARD_AVERMEDIA_CARDBUS_506: + saa7134_set_gpio(dev, 23, 0); + msleep(10); + saa7134_set_gpio(dev, 23, 1); + dev->has_remote = SAA7134_REMOTE_I2C; + break; case SAA7134_BOARD_AVERMEDIA_M103: saa7134_set_gpio(dev, 23, 0); msleep(10); diff --git a/drivers/media/video/saa7134/saa7134-i2c.c b/drivers/media/video/saa7134/saa7134-i2c.c index 2e15f43d26ec..f3e285aa2fb4 100644 --- a/drivers/media/video/saa7134/saa7134-i2c.c +++ b/drivers/media/video/saa7134/saa7134-i2c.c @@ -255,7 +255,7 @@ static int saa7134_i2c_xfer(struct i2c_adapter *i2c_adap, addr = msgs[i].addr << 1; if (msgs[i].flags & I2C_M_RD) addr |= 1; - if (i > 0 && msgs[i].flags & I2C_M_RD) { + if (i > 0 && msgs[i].flags & I2C_M_RD && msgs[i].addr != 0x40) { /* workaround for a saa7134 i2c bug * needed to talk to the mt352 demux * thanks to pinnacle for the hint */ diff --git a/include/media/ir-common.h b/include/media/ir-common.h index 31e62abb59ad..135e02270c9b 100644 --- a/include/media/ir-common.h +++ b/include/media/ir-common.h @@ -111,6 +111,7 @@ extern IR_KEYTAB_TYPE ir_codes_empty[IR_KEYTAB_SIZE]; extern IR_KEYTAB_TYPE ir_codes_avermedia[IR_KEYTAB_SIZE]; extern IR_KEYTAB_TYPE ir_codes_avermedia_dvbt[IR_KEYTAB_SIZE]; extern IR_KEYTAB_TYPE ir_codes_avermedia_m135a[IR_KEYTAB_SIZE]; +extern IR_KEYTAB_TYPE ir_codes_avermedia_cardbus[IR_KEYTAB_SIZE]; extern IR_KEYTAB_TYPE ir_codes_apac_viewcomp[IR_KEYTAB_SIZE]; extern IR_KEYTAB_TYPE ir_codes_pixelview[IR_KEYTAB_SIZE]; extern IR_KEYTAB_TYPE ir_codes_pixelview_new[IR_KEYTAB_SIZE]; -- cgit v1.2.3 From 090264e508c20baa0c3eea5a7d8eea4db84a29cc Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Thu, 12 Feb 2009 08:05:45 -0300 Subject: V4L/DVB (10620): gspca - main: More checks of the device disconnection. - prevent application oops when the device is disconnected - wake up the application at disconnection time - check the disconnection in ioctl dqbuf and poll Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/gspca.c | 105 +++++++++++++++++++++++++++----------- 1 file changed, 74 insertions(+), 31 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/gspca/gspca.c b/drivers/media/video/gspca/gspca.c index eac7aec44254..8aac7a1e8f33 100644 --- a/drivers/media/video/gspca/gspca.c +++ b/drivers/media/video/gspca/gspca.c @@ -132,11 +132,13 @@ static void fill_frame(struct gspca_dev *gspca_dev, cam_pkt_op pkt_scan; if (urb->status != 0) { + if (urb->status == -ESHUTDOWN) + return; /* disconnection */ #ifdef CONFIG_PM if (!gspca_dev->frozen) #endif PDEBUG(D_ERR|D_PACK, "urb status: %d", urb->status); - return; /* disconnection ? */ + return; } pkt_scan = gspca_dev->sd_desc->pkt_scan; for (i = 0; i < urb->number_of_packets; i++) { @@ -208,6 +210,8 @@ static void bulk_irq(struct urb *urb) switch (urb->status) { case 0: break; + case -ESHUTDOWN: + return; /* disconnection */ case -ECONNRESET: urb->status = 0; break; @@ -216,7 +220,7 @@ static void bulk_irq(struct urb *urb) if (!gspca_dev->frozen) #endif PDEBUG(D_ERR|D_PACK, "urb status: %d", urb->status); - return; /* disconnection ? */ + return; } /* check the availability of the frame buffer */ @@ -422,10 +426,8 @@ static void destroy_urbs(struct gspca_dev *gspca_dev) if (urb == NULL) break; - BUG_ON(!gspca_dev->dev); gspca_dev->urb[i] = NULL; - if (!gspca_dev->present) - usb_kill_urb(urb); + usb_kill_urb(urb); if (urb->transfer_buffer != NULL) usb_buffer_free(gspca_dev->dev, urb->transfer_buffer_length, @@ -593,6 +595,11 @@ static int gspca_init_transfer(struct gspca_dev *gspca_dev) if (mutex_lock_interruptible(&gspca_dev->usb_lock)) return -ERESTARTSYS; + if (!gspca_dev->present) { + ret = -ENODEV; + goto out; + } + /* set the higher alternate setting and * loop until urb submit succeeds */ gspca_dev->alt = gspca_dev->nbalt; @@ -662,12 +669,14 @@ static int gspca_set_alt0(struct gspca_dev *gspca_dev) static void gspca_stream_off(struct gspca_dev *gspca_dev) { gspca_dev->streaming = 0; - if (gspca_dev->present - && gspca_dev->sd_desc->stopN) - gspca_dev->sd_desc->stopN(gspca_dev); - destroy_urbs(gspca_dev); - if (gspca_dev->present) + if (gspca_dev->present) { + if (gspca_dev->sd_desc->stopN) + gspca_dev->sd_desc->stopN(gspca_dev); + destroy_urbs(gspca_dev); gspca_set_alt0(gspca_dev); + } + + /* always call stop0 to free the subdriver's resources */ if (gspca_dev->sd_desc->stop0) gspca_dev->sd_desc->stop0(gspca_dev); PDEBUG(D_STREAM, "stream off OK"); @@ -949,8 +958,17 @@ static int vidioc_querycap(struct file *file, void *priv, struct v4l2_capability *cap) { struct gspca_dev *gspca_dev = priv; + int ret; memset(cap, 0, sizeof *cap); + + /* protect the access to the usb device */ + if (mutex_lock_interruptible(&gspca_dev->usb_lock)) + return -ERESTARTSYS; + if (!gspca_dev->present) { + ret = -ENODEV; + goto out; + } strncpy(cap->driver, gspca_dev->sd_desc->name, sizeof cap->driver); if (gspca_dev->dev->product != NULL) { strncpy(cap->card, gspca_dev->dev->product, @@ -966,7 +984,10 @@ static int vidioc_querycap(struct file *file, void *priv, cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING | V4L2_CAP_READWRITE; - return 0; + ret = 0; +out: + mutex_unlock(&gspca_dev->usb_lock); + return ret; } static int vidioc_queryctrl(struct file *file, void *priv, @@ -1029,7 +1050,10 @@ static int vidioc_s_ctrl(struct file *file, void *priv, PDEBUG(D_CONF, "set ctrl [%08x] = %d", ctrl->id, ctrl->value); if (mutex_lock_interruptible(&gspca_dev->usb_lock)) return -ERESTARTSYS; - ret = ctrls->set(gspca_dev, ctrl->value); + if (gspca_dev->present) + ret = ctrls->set(gspca_dev, ctrl->value); + else + ret = -ENODEV; mutex_unlock(&gspca_dev->usb_lock); return ret; } @@ -1053,7 +1077,10 @@ static int vidioc_g_ctrl(struct file *file, void *priv, return -EINVAL; if (mutex_lock_interruptible(&gspca_dev->usb_lock)) return -ERESTARTSYS; - ret = ctrls->get(gspca_dev, &ctrl->value); + if (gspca_dev->present) + ret = ctrls->get(gspca_dev, &ctrl->value); + else + ret = -ENODEV; mutex_unlock(&gspca_dev->usb_lock); return ret; } @@ -1215,10 +1242,7 @@ static int vidioc_streamon(struct file *file, void *priv, return -EINVAL; if (mutex_lock_interruptible(&gspca_dev->queue_lock)) return -ERESTARTSYS; - if (!gspca_dev->present) { - ret = -ENODEV; - goto out; - } + if (gspca_dev->nframes == 0 || !(gspca_dev->frame[0].v4l2_buf.flags & V4L2_BUF_FLAG_QUEUED)) { ret = -EINVAL; @@ -1286,7 +1310,10 @@ static int vidioc_g_jpegcomp(struct file *file, void *priv, return -EINVAL; if (mutex_lock_interruptible(&gspca_dev->usb_lock)) return -ERESTARTSYS; - ret = gspca_dev->sd_desc->get_jcomp(gspca_dev, jpegcomp); + if (gspca_dev->present) + ret = gspca_dev->sd_desc->get_jcomp(gspca_dev, jpegcomp); + else + ret = -ENODEV; mutex_unlock(&gspca_dev->usb_lock); return ret; } @@ -1301,7 +1328,10 @@ static int vidioc_s_jpegcomp(struct file *file, void *priv, return -EINVAL; if (mutex_lock_interruptible(&gspca_dev->usb_lock)) return -ERESTARTSYS; - ret = gspca_dev->sd_desc->set_jcomp(gspca_dev, jpegcomp); + if (gspca_dev->present) + ret = gspca_dev->sd_desc->set_jcomp(gspca_dev, jpegcomp); + else + ret = -ENODEV; mutex_unlock(&gspca_dev->usb_lock); return ret; } @@ -1320,7 +1350,11 @@ static int vidioc_g_parm(struct file *filp, void *priv, if (mutex_lock_interruptible(&gspca_dev->usb_lock)) return -ERESTARTSYS; - ret = gspca_dev->sd_desc->get_streamparm(gspca_dev, parm); + if (gspca_dev->present) + ret = gspca_dev->sd_desc->get_streamparm(gspca_dev, + parm); + else + ret = -ENODEV; mutex_unlock(&gspca_dev->usb_lock); return ret; } @@ -1345,7 +1379,11 @@ static int vidioc_s_parm(struct file *filp, void *priv, if (mutex_lock_interruptible(&gspca_dev->usb_lock)) return -ERESTARTSYS; - ret = gspca_dev->sd_desc->set_streamparm(gspca_dev, parm); + if (gspca_dev->present) + ret = gspca_dev->sd_desc->set_streamparm(gspca_dev, + parm); + else + ret = -ENODEV; mutex_unlock(&gspca_dev->usb_lock); return ret; } @@ -1519,7 +1557,8 @@ static int frame_wait(struct gspca_dev *gspca_dev, if (gspca_dev->sd_desc->dq_callback) { mutex_lock(&gspca_dev->usb_lock); - gspca_dev->sd_desc->dq_callback(gspca_dev); + if (gspca_dev->present) + gspca_dev->sd_desc->dq_callback(gspca_dev); mutex_unlock(&gspca_dev->usb_lock); } return j; @@ -1541,6 +1580,9 @@ static int vidioc_dqbuf(struct file *file, void *priv, if (v4l2_buf->memory != gspca_dev->memory) return -EINVAL; + if (!gspca_dev->present) + return -ENODEV; + /* if not streaming, be sure the application will not loop forever */ if (!(file->f_flags & O_NONBLOCK) && !gspca_dev->streaming && gspca_dev->users == 1) @@ -1691,8 +1733,6 @@ static unsigned int dev_poll(struct file *file, poll_table *wait) PDEBUG(D_FRAM, "poll"); poll_wait(file, &gspca_dev->wq, wait); - if (!gspca_dev->present) - return POLLERR; /* if reqbufs is not done, the user would use read() */ if (gspca_dev->nframes == 0) { @@ -1705,10 +1745,6 @@ static unsigned int dev_poll(struct file *file, poll_table *wait) if (mutex_lock_interruptible(&gspca_dev->queue_lock) != 0) return POLLERR; - if (!gspca_dev->present) { - ret = POLLERR; - goto out; - } /* check the next incoming buffer */ i = gspca_dev->fr_o; @@ -1717,8 +1753,9 @@ static unsigned int dev_poll(struct file *file, poll_table *wait) ret = POLLIN | POLLRDNORM; /* something to read */ else ret = 0; -out: mutex_unlock(&gspca_dev->queue_lock); + if (!gspca_dev->present) + return POLLHUP; return ret; } @@ -1944,10 +1981,16 @@ void gspca_disconnect(struct usb_interface *intf) mutex_lock(&gspca_dev->usb_lock); gspca_dev->present = 0; - mutex_unlock(&gspca_dev->usb_lock); - destroy_urbs(gspca_dev); + if (gspca_dev->streaming) { + destroy_urbs(gspca_dev); + wake_up_interruptible(&gspca_dev->wq); + } + + /* the device is freed at exit of this function */ gspca_dev->dev = NULL; + mutex_unlock(&gspca_dev->usb_lock); + usb_set_intfdata(intf, NULL); /* release the device */ -- cgit v1.2.3 From c33c02ed07d678625d7ca2e26238c8e925710138 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Thu, 5 Feb 2009 15:04:33 -0300 Subject: V4L/DVB (10635): gspca - sonixj: No vertical flip control for mt9v111. Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/sonixj.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/gspca/sonixj.c b/drivers/media/video/gspca/sonixj.c index 882d5e9b436a..7b28bc7cec77 100644 --- a/drivers/media/video/gspca/sonixj.c +++ b/drivers/media/video/gspca/sonixj.c @@ -234,7 +234,7 @@ static __u32 ctrl_dis[] = { /* SENSOR_MI0360 1 */ (1 << INFRARED_IDX) | (1 << VFLIP_IDX), /* SENSOR_MO4000 2 */ - 0, + (1 << VFLIP_IDX), /* SENSOR_MT9V111 3 */ (1 << INFRARED_IDX) | (1 << VFLIP_IDX), /* SENSOR_OM6802 4 */ -- cgit v1.2.3 From 2797ba2a1727df07a4c74d494a43296cbf5179b9 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Thu, 5 Feb 2009 15:12:24 -0300 Subject: V4L/DVB (10636): gspca - sonixj: Add autogain for ov7630/48 and vflip for ov7648. Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/sonixj.c | 43 +++++++++++++++++++++++++++++++------- 1 file changed, 35 insertions(+), 8 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/gspca/sonixj.c b/drivers/media/video/gspca/sonixj.c index 7b28bc7cec77..444d2dc4544a 100644 --- a/drivers/media/video/gspca/sonixj.c +++ b/drivers/media/video/gspca/sonixj.c @@ -45,7 +45,7 @@ struct sd { u8 blue; u8 red; u8 gamma; - u8 vflip; /* ov7630 only */ + u8 vflip; /* ov7630/ov7648 only */ u8 infrared; /* mt9v111 only */ s8 ag_cnt; @@ -192,7 +192,7 @@ static struct ctrl sd_ctrls[] = { .set = sd_setautogain, .get = sd_getautogain, }, -/* ov7630 only */ +/* ov7630/ov7648 only */ #define VFLIP_IDX 6 { { @@ -202,7 +202,7 @@ static struct ctrl sd_ctrls[] = { .minimum = 0, .maximum = 1, .step = 1, -#define VFLIP_DEF 1 +#define VFLIP_DEF 0 /* vflip def = 1 for ov7630 */ .default_value = VFLIP_DEF, }, .set = sd_setvflip, @@ -240,7 +240,7 @@ static __u32 ctrl_dis[] = { /* SENSOR_OM6802 4 */ (1 << AUTOGAIN_IDX) | (1 << INFRARED_IDX), /* SENSOR_OV7630 5 */ - (1 << AUTOGAIN_IDX) | (1 << INFRARED_IDX) | (1 << VFLIP_IDX), + (1 << INFRARED_IDX), /* SENSOR_OV7648 6 */ (1 << AUTOGAIN_IDX) | (1 << INFRARED_IDX) | (1 << VFLIP_IDX), /* SENSOR_OV7660 7 */ @@ -669,7 +669,8 @@ static const u8 ov7648_sensor_init[][8] = { {0xb1, 0x21, 0x2d, 0x85, 0x00, 0x00, 0x00, 0x10}, /*...*/ /* {0xa1, 0x21, 0x12, 0x08, 0x00, 0x00, 0x00, 0x10}, jfm done */ -/* {0xa1, 0x21, 0x75, 0x06, 0x00, 0x00, 0x00, 0x10}, jfm done */ +/* {0xa1, 0x21, 0x75, 0x06, 0x00, 0x00, 0x00, 0x10}, * COMN + * set by setvflip */ {0xa1, 0x21, 0x19, 0x02, 0x00, 0x00, 0x00, 0x10}, {0xa1, 0x21, 0x10, 0x32, 0x00, 0x00, 0x00, 0x10}, /* {0xa1, 0x21, 0x16, 0x00, 0x00, 0x00, 0x00, 0x10}, jfm done */ @@ -1303,7 +1304,10 @@ static int sd_config(struct gspca_dev *gspca_dev, sd->gamma = GAMMA_DEF; sd->autogain = AUTOGAIN_DEF; sd->ag_cnt = -1; - sd->vflip = VFLIP_DEF; + if (sd->sensor != SENSOR_OV7630) + sd->vflip = 0; + else + sd->vflip = 1; sd->infrared = INFRARED_DEF; gspca_dev->ctrl_dis = ctrl_dis[sd->sensor]; @@ -1563,16 +1567,39 @@ static void setautogain(struct gspca_dev *gspca_dev) if (gspca_dev->ctrl_dis & (1 << AUTOGAIN_IDX)) return; + switch (sd->sensor) { + case SENSOR_OV7630: + case SENSOR_OV7648: { + u8 comb; + + if (sd->sensor == SENSOR_OV7630) + comb = 0xc0; + else + comb = 0xa0; + if (sd->autogain) + comb |= 0x02; + i2c_w1(&sd->gspca_dev, 0x13, comb); + return; + } + } if (sd->autogain) sd->ag_cnt = AG_CNT_START; else sd->ag_cnt = -1; } +/* ov7630/ov7648 only */ static void setvflip(struct sd *sd) { - i2c_w1(&sd->gspca_dev, 0x75, /* COMN */ - sd->vflip ? 0x82 : 0x02); + u8 comn; + + if (sd->sensor == SENSOR_OV7630) + comn = 0x02; + else + comn = 0x06; + if (sd->vflip) + comn |= 0x80; + i2c_w1(&sd->gspca_dev, 0x75, comn); } static void setinfrared(struct sd *sd) -- cgit v1.2.3 From c35d066e852256fa6492bb68315cf564494c8823 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Fri, 6 Feb 2009 13:45:23 -0300 Subject: V4L/DVB (10637): gspca - t613: Bad sensor name in kernel trace when 'other' sensor. Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/t613.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/gspca/t613.c b/drivers/media/video/gspca/t613.c index 95c120a506d3..24174ccb62fa 100644 --- a/drivers/media/video/gspca/t613.c +++ b/drivers/media/video/gspca/t613.c @@ -685,7 +685,7 @@ static int sd_init(struct gspca_dev *gspca_dev) sd->sensor = SENSOR_TAS5130A; break; case 0x0803: - PDEBUG(D_CONF, "sensor om6802"); + PDEBUG(D_CONF, "sensor 'other'"); sd->sensor = SENSOR_OTHER; break; case 0x0807: -- cgit v1.2.3 From 748c01488923fa1b0c94046d731116125dc16a60 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Fri, 6 Feb 2009 14:11:58 -0300 Subject: V4L/DVB (10638): gspca - t613: Bad debug level when displaying the sensor type. Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/t613.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/gspca/t613.c b/drivers/media/video/gspca/t613.c index 24174ccb62fa..353931023ac8 100644 --- a/drivers/media/video/gspca/t613.c +++ b/drivers/media/video/gspca/t613.c @@ -681,19 +681,19 @@ static int sd_init(struct gspca_dev *gspca_dev) | reg_r(gspca_dev, 0x07); switch (sensor_id) { case 0x0801: - PDEBUG(D_CONF, "sensor tas5130a"); + PDEBUG(D_PROBE, "sensor tas5130a"); sd->sensor = SENSOR_TAS5130A; break; case 0x0803: - PDEBUG(D_CONF, "sensor 'other'"); + PDEBUG(D_PROBE, "sensor 'other'"); sd->sensor = SENSOR_OTHER; break; case 0x0807: - PDEBUG(D_CONF, "sensor om6802"); + PDEBUG(D_PROBE, "sensor om6802"); sd->sensor = SENSOR_OM6802; break; default: - PDEBUG(D_CONF, "unknown sensor %04x", sensor_id); + PDEBUG(D_ERR|D_PROBE, "unknown sensor %04x", sensor_id); return -EINVAL; } -- cgit v1.2.3 From 27d35fc3fb06284edec8a3c9f6872a1ce7405a48 Mon Sep 17 00:00:00 2001 From: Adam Baker Date: Fri, 6 Feb 2009 15:12:46 -0300 Subject: V4L/DVB (10639): gspca - sq905: New subdriver. Add initial support for cameras based on the SQ Technologies SQ-905 chipset (USB ID 2770:9120) to V4L2 using the gspca infrastructure. Currently only supports one resolution and doesn't attempt to inform libv4l what image flipping options are needed. Signed-off-by: Adam Baker Signed-off-by: Theodore Kilgore Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/Kconfig | 9 + drivers/media/video/gspca/Makefile | 2 + drivers/media/video/gspca/sq905.c | 438 +++++++++++++++++++++++++++++++++++++ 3 files changed, 449 insertions(+) create mode 100644 drivers/media/video/gspca/sq905.c (limited to 'drivers/media/video') diff --git a/drivers/media/video/gspca/Kconfig b/drivers/media/video/gspca/Kconfig index 11c5d2fc20de..a0f05ef5ca70 100644 --- a/drivers/media/video/gspca/Kconfig +++ b/drivers/media/video/gspca/Kconfig @@ -176,6 +176,15 @@ config USB_GSPCA_SPCA561 To compile this driver as a module, choose M here: the module will be called gspca_spca561. +config USB_GSPCA_SQ905 + tristate "SQ Technologies SQ905 based USB Camera Driver" + depends on VIDEO_V4L2 && USB_GSPCA + help + Say Y here if you want support for cameras based on the SQ905 chip. + + To compile this driver as a module, choose M here: the + module will be called gspca_sq905. + config USB_GSPCA_STK014 tristate "Syntek DV4000 (STK014) USB Camera Driver" depends on VIDEO_V4L2 && USB_GSPCA diff --git a/drivers/media/video/gspca/Makefile b/drivers/media/video/gspca/Makefile index b3cbcc1764f4..b6ec61185736 100644 --- a/drivers/media/video/gspca/Makefile +++ b/drivers/media/video/gspca/Makefile @@ -16,6 +16,7 @@ obj-$(CONFIG_USB_GSPCA_SPCA505) += gspca_spca505.o obj-$(CONFIG_USB_GSPCA_SPCA506) += gspca_spca506.o obj-$(CONFIG_USB_GSPCA_SPCA508) += gspca_spca508.o obj-$(CONFIG_USB_GSPCA_SPCA561) += gspca_spca561.o +obj-$(CONFIG_USB_GSPCA_SQ905) += gspca_sq905.o obj-$(CONFIG_USB_GSPCA_SUNPLUS) += gspca_sunplus.o obj-$(CONFIG_USB_GSPCA_STK014) += gspca_stk014.o obj-$(CONFIG_USB_GSPCA_T613) += gspca_t613.o @@ -41,6 +42,7 @@ gspca_spca505-objs := spca505.o gspca_spca506-objs := spca506.o gspca_spca508-objs := spca508.o gspca_spca561-objs := spca561.o +gspca_sq905-objs := sq905.o gspca_stk014-objs := stk014.o gspca_sunplus-objs := sunplus.o gspca_t613-objs := t613.o diff --git a/drivers/media/video/gspca/sq905.c b/drivers/media/video/gspca/sq905.c new file mode 100644 index 000000000000..dafaed69e9d0 --- /dev/null +++ b/drivers/media/video/gspca/sq905.c @@ -0,0 +1,438 @@ +/* + * SQ905 subdriver + * + * Copyright (C) 2008, 2009 Adam Baker and Theodore Kilgore + * + * 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 + * 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 + */ + +/* + * History and Acknowledgments + * + * The original Linux driver for SQ905 based cameras was written by + * Marcell Lengyel and furter developed by many other contributers + * and is available from http://sourceforge.net/projects/sqcam/ + * + * This driver takes advantage of the reverse engineering work done for + * that driver and for libgphoto2 but shares no code with them. + * + * This driver has used as a base the finepix driver and other gspca + * based drivers and may still contain code fragments taken from those + * drivers. + */ + +#define MODULE_NAME "sq905" + +#include +#include "gspca.h" + +MODULE_AUTHOR("Adam Baker , " + "Theodore Kilgore "); +MODULE_DESCRIPTION("GSPCA/SQ905 USB Camera Driver"); +MODULE_LICENSE("GPL"); + +/* Default timeouts, in ms */ +#define SQ905_CMD_TIMEOUT 500 +#define SQ905_DATA_TIMEOUT 1000 + +/* Maximum transfer size to use. */ +#define SQ905_MAX_TRANSFER 0x8000 +#define FRAME_HEADER_LEN 64 + +/* The known modes, or registers. These go in the "value" slot. */ + +/* 00 is "none" obviously */ + +#define SQ905_BULK_READ 0x03 /* precedes any bulk read */ +#define SQ905_COMMAND 0x06 /* precedes the command codes below */ +#define SQ905_PING 0x07 /* when reading an "idling" command */ +#define SQ905_READ_DONE 0xc0 /* ack bulk read completed */ + +/* Some command codes. These go in the "index" slot. */ + +#define SQ905_ID 0xf0 /* asks for model string */ +#define SQ905_CONFIG 0x20 /* gets photo alloc. table, not used here */ +#define SQ905_DATA 0x30 /* accesses photo data, not used here */ +#define SQ905_CLEAR 0xa0 /* clear everything */ +#define SQ905_CAPTURE_LOW 0x60 /* Starts capture at 160x120 */ +#define SQ905_CAPTURE_MED 0x61 /* Starts capture at 320x240 */ +/* note that the capture command also controls the output dimensions */ +/* 0x60 -> 160x120, 0x61 -> 320x240 0x62 -> 640x480 depends on camera */ +/* 0x62 is not correct, at least for some cams. Should be 0x63 ? */ + +/* Structure to hold all of our device specific stuff */ +struct sd { + struct gspca_dev gspca_dev; /* !! must be the first item */ + + u8 cam_type; + + /* + * Driver stuff + */ + struct work_struct work_struct; + struct workqueue_struct *work_thread; +}; + +/* The driver only supports 320x240 so far. */ +static struct v4l2_pix_format sq905_mode[1] = { + { 320, 240, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE, + .bytesperline = 320, + .sizeimage = 320 * 240, + .colorspace = V4L2_COLORSPACE_SRGB, + .priv = 0} +}; + +struct cam_type { + u32 ident_word; + char *name; + struct v4l2_pix_format *min_mode; + u8 num_modes; + u8 sensor_flags; +}; + +#define SQ905_FLIP_HORIZ (1 << 0) +#define SQ905_FLIP_VERT (1 << 1) + +/* Last entry is default if nothing else matches */ +static struct cam_type cam_types[] = { + { 0x19010509, "PocketCam", &sq905_mode[0], 1, SQ905_FLIP_HORIZ }, + { 0x32010509, "Magpix", &sq905_mode[0], 1, SQ905_FLIP_HORIZ }, + { 0, "Default", &sq905_mode[0], 1, SQ905_FLIP_HORIZ | SQ905_FLIP_VERT } +}; + +/* + * Send a command to the camera. + */ +static int sq905_command(struct gspca_dev *gspca_dev, u16 index) +{ + int ret; + + gspca_dev->usb_buf[0] = '\0'; + ret = usb_control_msg(gspca_dev->dev, + usb_sndctrlpipe(gspca_dev->dev, 0), + USB_REQ_SYNCH_FRAME, /* request */ + USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, + SQ905_COMMAND, index, gspca_dev->usb_buf, 1, + SQ905_CMD_TIMEOUT); + if (ret < 0) { + PDEBUG(D_ERR, "%s: usb_control_msg failed (%d)", + __func__, ret); + return ret; + } + + ret = usb_control_msg(gspca_dev->dev, + usb_sndctrlpipe(gspca_dev->dev, 0), + USB_REQ_SYNCH_FRAME, /* request */ + USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, + SQ905_PING, 0, gspca_dev->usb_buf, 1, + SQ905_CMD_TIMEOUT); + if (ret < 0) { + PDEBUG(D_ERR, "%s: usb_control_msg failed 2 (%d)", + __func__, ret); + return ret; + } + + return 0; +} + +/* + * Acknowledge the end of a frame - see warning on sq905_command. + */ +static int sq905_ack_frame(struct gspca_dev *gspca_dev) +{ + int ret; + + gspca_dev->usb_buf[0] = '\0'; + ret = usb_control_msg(gspca_dev->dev, + usb_sndctrlpipe(gspca_dev->dev, 0), + USB_REQ_SYNCH_FRAME, /* request */ + USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, + SQ905_READ_DONE, 0, gspca_dev->usb_buf, 1, + SQ905_CMD_TIMEOUT); + if (ret < 0) { + PDEBUG(D_ERR, "%s: usb_control_msg failed (%d)", __func__, ret); + return ret; + } + + return 0; +} + +/* + * request and read a block of data - see warning on sq905_command. + */ +static int +sq905_read_data(struct gspca_dev *gspca_dev, u8 *data, int size) +{ + int ret; + int act_len; + + gspca_dev->usb_buf[0] = '\0'; + ret = usb_control_msg(gspca_dev->dev, + usb_sndctrlpipe(gspca_dev->dev, 0), + USB_REQ_SYNCH_FRAME, /* request */ + USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, + SQ905_BULK_READ, size, gspca_dev->usb_buf, + 1, SQ905_CMD_TIMEOUT); + if (ret < 0) { + PDEBUG(D_ERR, "%s: usb_control_msg failed (%d)", __func__, ret); + return ret; + } + ret = usb_bulk_msg(gspca_dev->dev, + usb_rcvbulkpipe(gspca_dev->dev, 0x81), + data, size, &act_len, SQ905_DATA_TIMEOUT); + + /* successful, it returns 0, otherwise negative */ + if (ret < 0 || act_len != size) { + PDEBUG(D_ERR, "bulk read fail (%d) len %d/%d", + ret, act_len, size); + return -EIO; + } + return 0; +} + +/* This function is called as a workqueue function and runs whenever the camera + * is streaming data. Because it is a workqueue function it is allowed to sleep + * so we can use synchronous USB calls. To avoid possible collisions with other + * threads attempting to use the camera's USB interface we take the gspca + * usb_lock when performing USB operations. In practice the only thing we need + * to protect against is the usb_set_interface call that gspca makes during + * stream_off as the camera doesn't provide any controls that the user could try + * to change. + */ +static void sq905_dostream(struct work_struct *work) +{ + struct sd *dev = container_of(work, struct sd, work_struct); + struct gspca_dev *gspca_dev = &dev->gspca_dev; + struct gspca_frame *frame; + int bytes_left; /* bytes remaining in current frame. */ + int data_len; /* size to use for the next read. */ + int header_read; /* true if we have already read the frame header. */ + int discarding; /* true if we failed to get space for frame. */ + int packet_type; + int ret; + u8 *data; + u8 *buffer; + + buffer = kmalloc(SQ905_MAX_TRANSFER, GFP_KERNEL | GFP_DMA); + mutex_lock(&gspca_dev->usb_lock); + if (!buffer) { + PDEBUG(D_ERR, "Couldn't allocate USB buffer"); + goto quit_stream; + } + + while (gspca_dev->present && gspca_dev->streaming) { + /* Need a short delay to ensure streaming flag was set by + * gspca and to make sure gspca can grab the mutex. */ + mutex_unlock(&gspca_dev->usb_lock); + msleep(1); + + /* request some data and then read it until we have + * a complete frame. */ + bytes_left = sq905_mode[0].sizeimage + FRAME_HEADER_LEN; + header_read = 0; + discarding = 0; + + while (bytes_left > 0) { + data_len = bytes_left > SQ905_MAX_TRANSFER ? + SQ905_MAX_TRANSFER : bytes_left; + mutex_lock(&gspca_dev->usb_lock); + if (!gspca_dev->present) + goto quit_stream; + ret = sq905_read_data(gspca_dev, buffer, data_len); + if (ret < 0) + goto quit_stream; + mutex_unlock(&gspca_dev->usb_lock); + PDEBUG(D_STREAM, + "Got %d bytes out of %d for frame", + data_len, bytes_left); + bytes_left -= data_len; + data = buffer; + if (!header_read) { + packet_type = FIRST_PACKET; + /* The first 64 bytes of each frame are + * a header full of FF 00 bytes */ + data += FRAME_HEADER_LEN; + data_len -= FRAME_HEADER_LEN; + header_read = 1; + } else if (bytes_left == 0) { + packet_type = LAST_PACKET; + } else { + packet_type = INTER_PACKET; + } + frame = gspca_get_i_frame(gspca_dev); + if (frame && !discarding) + gspca_frame_add(gspca_dev, packet_type, + frame, data, data_len); + else + discarding = 1; + } + /* acknowledge the frame */ + mutex_lock(&gspca_dev->usb_lock); + if (!gspca_dev->present) + goto quit_stream; + ret = sq905_ack_frame(gspca_dev); + if (ret < 0) + goto quit_stream; + } +quit_stream: + /* the usb_lock is already acquired */ + if (gspca_dev->present) + sq905_command(gspca_dev, SQ905_CLEAR); + mutex_unlock(&gspca_dev->usb_lock); + kfree(buffer); +} + +/* This function is called at probe time just before sd_init */ +static int sd_config(struct gspca_dev *gspca_dev, + const struct usb_device_id *id) +{ + struct cam *cam = &gspca_dev->cam; + struct sd *dev = (struct sd *) gspca_dev; + + cam->cam_mode = sq905_mode; + cam->nmodes = 1; + /* We don't use the buffer gspca allocates so make it small. */ + cam->bulk_size = 64; + + INIT_WORK(&dev->work_struct, sq905_dostream); + + return 0; +} + +/* called on streamoff with alt==0 and on disconnect */ +/* the usb_lock is held at entry - restore on exit */ +static void sd_stop0(struct gspca_dev *gspca_dev) +{ + struct sd *dev = (struct sd *) gspca_dev; + + /* wait for the work queue to terminate */ + mutex_unlock(&gspca_dev->usb_lock); + /* This waits for sq905_dostream to finish */ + destroy_workqueue(dev->work_thread); + dev->work_thread = NULL; + mutex_lock(&gspca_dev->usb_lock); +} + +/* this function is called at probe and resume time */ +static int sd_init(struct gspca_dev *gspca_dev) +{ + struct sd *dev = (struct sd *) gspca_dev; + u32 ident; + int ret; + + /* connect to the camera and read + * the model ID and process that and put it away. + */ + ret = sq905_command(gspca_dev, SQ905_CLEAR); + if (ret < 0) + return ret; + ret = sq905_command(gspca_dev, SQ905_ID); + if (ret < 0) + return ret; + ret = sq905_read_data(gspca_dev, gspca_dev->usb_buf, 4); + if (ret < 0) + return ret; + /* usb_buf is allocated with kmalloc so is aligned. */ + ident = le32_to_cpup((u32 *)gspca_dev->usb_buf); + ret = sq905_command(gspca_dev, SQ905_CLEAR); + if (ret < 0) + return ret; + dev->cam_type = 0; + while (dev->cam_type < ARRAY_SIZE(cam_types) - 1 && + ident != cam_types[dev->cam_type].ident_word) + dev->cam_type++; + PDEBUG(D_CONF, "SQ905 camera %s, ID %08x detected", + cam_types[dev->cam_type].name, ident); + return 0; +} + +/* Set up for getting frames. */ +static int sd_start(struct gspca_dev *gspca_dev) +{ + struct sd *dev = (struct sd *) gspca_dev; + int ret; + + /* "Open the shutter" and set size, to start capture */ + ret = sq905_command(&dev->gspca_dev, SQ905_CAPTURE_MED); + if (ret < 0) { + PDEBUG(D_ERR, "Start streaming command failed"); + return ret; + } + + /* Start the workqueue function to do the streaming */ + dev->work_thread = create_singlethread_workqueue(MODULE_NAME); + queue_work(dev->work_thread, &dev->work_struct); + + return 0; +} + +/* Table of supported USB devices */ +static const __devinitdata struct usb_device_id device_table[] = { + {USB_DEVICE(0x2770, 0x9120)}, + {} +}; + +MODULE_DEVICE_TABLE(usb, device_table); + +/* sub-driver description */ +static const struct sd_desc sd_desc = { + .name = MODULE_NAME, + .config = sd_config, + .init = sd_init, + .start = sd_start, + .stop0 = sd_stop0, +}; + +/* -- device connect -- */ +static int sd_probe(struct usb_interface *intf, + const struct usb_device_id *id) +{ + return gspca_dev_probe(intf, id, + &sd_desc, + sizeof(struct sd), + THIS_MODULE); +} + +static struct usb_driver sd_driver = { + .name = MODULE_NAME, + .id_table = device_table, + .probe = sd_probe, + .disconnect = gspca_disconnect, +#ifdef CONFIG_PM + .suspend = gspca_suspend, + .resume = gspca_resume, +#endif +}; + +/* -- module insert / remove -- */ +static int __init sd_mod_init(void) +{ + int ret; + + ret = usb_register(&sd_driver); + if (ret < 0) + return ret; + PDEBUG(D_PROBE, "registered"); + return 0; +} + +static void __exit sd_mod_exit(void) +{ + usb_deregister(&sd_driver); + PDEBUG(D_PROBE, "deregistered"); +} + +module_init(sd_mod_init); +module_exit(sd_mod_exit); -- cgit v1.2.3 From 775a05dd547747cdcc079e03f4e89c7475caa735 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sat, 14 Feb 2009 11:31:01 -0300 Subject: V4L/DVB (10641): v4l2-dev: remove limit of 32 devices per driver in get_index() get_index() had a limitation of 32 devices per driver. This was unnecessarily strict and has been replaced with the maximum number of devices. That should really satisfy anyone! Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/v4l2-dev.c | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/v4l2-dev.c b/drivers/media/video/v4l2-dev.c index 13f87c22e78d..922b39e79b8e 100644 --- a/drivers/media/video/v4l2-dev.c +++ b/drivers/media/video/v4l2-dev.c @@ -288,37 +288,38 @@ static const struct file_operations v4l2_fops = { */ static int get_index(struct video_device *vdev, int num) { - u32 used = 0; - const int max_index = sizeof(used) * 8 - 1; + /* This can be static since this function is called with the global + videodev_lock held. */ + static DECLARE_BITMAP(used, VIDEO_NUM_DEVICES); int i; - /* Currently a single v4l driver instance cannot create more than - 32 devices. - Increase to u64 or an array of u32 if more are needed. */ - if (num > max_index) { + if (num >= VIDEO_NUM_DEVICES) { printk(KERN_ERR "videodev: %s num is too large\n", __func__); return -EINVAL; } - /* Some drivers do not set the parent. In that case always return 0. */ + /* Some drivers do not set the parent. In that case always return + num or 0. */ if (vdev->parent == NULL) - return 0; + return num >= 0 ? num : 0; + + bitmap_zero(used, VIDEO_NUM_DEVICES); for (i = 0; i < VIDEO_NUM_DEVICES; i++) { if (video_device[i] != NULL && video_device[i]->parent == vdev->parent) { - used |= 1 << video_device[i]->index; + set_bit(video_device[i]->index, used); } } if (num >= 0) { - if (used & (1 << num)) + if (test_bit(num, used)) return -ENFILE; return num; } - i = ffz(used); - return i > max_index ? -ENFILE : i; + i = find_first_zero_bit(used, VIDEO_NUM_DEVICES); + return i == VIDEO_NUM_DEVICES ? -ENFILE : i; } int video_register_device(struct video_device *vdev, int type, int nr) -- cgit v1.2.3 From 62cfdacc9431cad7f9093e91b17ea68d684188ae Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sat, 14 Feb 2009 11:37:17 -0300 Subject: V4L/DVB (10642): vivi: update comment to reflect that vivi can now create more than 32 devs. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/vivi.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/vivi.c b/drivers/media/video/vivi.c index 13e7bd06a80c..0f25d686ca20 100644 --- a/drivers/media/video/vivi.c +++ b/drivers/media/video/vivi.c @@ -1345,10 +1345,7 @@ static struct video_device vivi_template = { The real maximum number of virtual drivers will depend on how many drivers will succeed. This is limited to the maximum number of devices that - videodev supports. Since there are 64 minors for video grabbers, this is - currently the theoretical maximum limit. However, a further limit does - exist at videodev that forbids any driver to register more than 32 video - grabbers. + videodev supports, which is equal to VIDEO_NUM_DEVICES. */ static int __init vivi_init(void) { -- cgit v1.2.3 From 3a63e4492fbc7aa7f99d4368822da1382ec6fe03 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sat, 14 Feb 2009 11:54:23 -0300 Subject: V4L/DVB (10643): v4l2-device: allow a NULL parent device when registering. Some drivers (e.g. for ISA devices) have no parent device because there is no associated bus driver. Allow the parent device to be NULL in those cases when registering v4l2_device. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- Documentation/video4linux/v4l2-framework.txt | 10 +++++--- drivers/media/video/v4l2-device.c | 37 ++++++++++++++++++---------- include/media/v4l2-device.h | 31 +++++++++++++---------- 3 files changed, 48 insertions(+), 30 deletions(-) (limited to 'drivers/media/video') diff --git a/Documentation/video4linux/v4l2-framework.txt b/Documentation/video4linux/v4l2-framework.txt index 48cdf86248cb..e1620e2a38ff 100644 --- a/Documentation/video4linux/v4l2-framework.txt +++ b/Documentation/video4linux/v4l2-framework.txt @@ -84,12 +84,14 @@ You must register the device instance: v4l2_device_register(struct device *dev, struct v4l2_device *v4l2_dev); Registration will initialize the v4l2_device struct and link dev->driver_data -to v4l2_dev. Registration will also set v4l2_dev->name to a value derived from -dev (driver name followed by the bus_id, to be precise). You may change the -name after registration if you want. +to v4l2_dev. If v4l2_dev->name is empty then it will be set to a value derived +from dev (driver name followed by the bus_id, to be precise). If you set it +up before calling v4l2_device_register then it will be untouched. If dev is +NULL, then you *must* setup v4l2_dev->name before calling v4l2_device_register. The first 'dev' argument is normally the struct device pointer of a pci_dev, -usb_device or platform_device. +usb_device or platform_device. It is rare for dev to be NULL, but it happens +with ISA devices, for example. You unregister with: diff --git a/drivers/media/video/v4l2-device.c b/drivers/media/video/v4l2-device.c index 8a4b74f3129f..3330ffb7d010 100644 --- a/drivers/media/video/v4l2-device.c +++ b/drivers/media/video/v4l2-device.c @@ -26,15 +26,24 @@ int v4l2_device_register(struct device *dev, struct v4l2_device *v4l2_dev) { - if (dev == NULL || v4l2_dev == NULL) + if (v4l2_dev == NULL) return -EINVAL; - /* Warn if we apparently re-register a device */ - WARN_ON(dev_get_drvdata(dev) != NULL); + INIT_LIST_HEAD(&v4l2_dev->subdevs); spin_lock_init(&v4l2_dev->lock); v4l2_dev->dev = dev; - snprintf(v4l2_dev->name, sizeof(v4l2_dev->name), "%s %s", + if (dev == NULL) { + /* If dev == NULL, then name must be filled in by the caller */ + WARN_ON(!v4l2_dev->name[0]); + return 0; + } + + /* Set name to driver name + device name if it is empty. */ + if (!v4l2_dev->name[0]) + snprintf(v4l2_dev->name, sizeof(v4l2_dev->name), "%s %s", dev->driver->name, dev_name(dev)); + if (dev_get_drvdata(dev)) + v4l2_warn(v4l2_dev, "Non-NULL drvdata on register\n"); dev_set_drvdata(dev, v4l2_dev); return 0; } @@ -44,10 +53,11 @@ void v4l2_device_unregister(struct v4l2_device *v4l2_dev) { struct v4l2_subdev *sd, *next; - if (v4l2_dev == NULL || v4l2_dev->dev == NULL) + if (v4l2_dev == NULL) return; - dev_set_drvdata(v4l2_dev->dev, NULL); - /* unregister subdevs */ + if (v4l2_dev->dev) + dev_set_drvdata(v4l2_dev->dev, NULL); + /* Unregister subdevs */ list_for_each_entry_safe(sd, next, &v4l2_dev->subdevs, list) v4l2_device_unregister_subdev(sd); @@ -55,19 +65,20 @@ void v4l2_device_unregister(struct v4l2_device *v4l2_dev) } EXPORT_SYMBOL_GPL(v4l2_device_unregister); -int v4l2_device_register_subdev(struct v4l2_device *dev, struct v4l2_subdev *sd) +int v4l2_device_register_subdev(struct v4l2_device *v4l2_dev, + struct v4l2_subdev *sd) { /* Check for valid input */ - if (dev == NULL || sd == NULL || !sd->name[0]) + if (v4l2_dev == NULL || sd == NULL || !sd->name[0]) return -EINVAL; /* Warn if we apparently re-register a subdev */ WARN_ON(sd->dev != NULL); if (!try_module_get(sd->owner)) return -ENODEV; - sd->dev = dev; - spin_lock(&dev->lock); - list_add_tail(&sd->list, &dev->subdevs); - spin_unlock(&dev->lock); + sd->dev = v4l2_dev; + spin_lock(&v4l2_dev->lock); + list_add_tail(&sd->list, &v4l2_dev->subdevs); + spin_unlock(&v4l2_dev->lock); return 0; } EXPORT_SYMBOL_GPL(v4l2_device_register_subdev); diff --git a/include/media/v4l2-device.h b/include/media/v4l2-device.h index 55e41afd95ef..5d7146dc2913 100644 --- a/include/media/v4l2-device.h +++ b/include/media/v4l2-device.h @@ -33,7 +33,9 @@ #define V4L2_DEVICE_NAME_SIZE (BUS_ID_SIZE + 16) struct v4l2_device { - /* dev->driver_data points to this struct */ + /* dev->driver_data points to this struct. + Note: dev might be NULL if there is no parent device + as is the case with e.g. ISA devices. */ struct device *dev; /* used to keep track of the registered subdevs */ struct list_head subdevs; @@ -44,7 +46,9 @@ struct v4l2_device { char name[V4L2_DEVICE_NAME_SIZE]; }; -/* Initialize v4l2_dev and make dev->driver_data point to v4l2_dev */ +/* Initialize v4l2_dev and make dev->driver_data point to v4l2_dev. + dev may be NULL in rare cases (ISA devices). In that case you + must fill in the v4l2_dev->name field before calling this function. */ int __must_check v4l2_device_register(struct device *dev, struct v4l2_device *v4l2_dev); /* Set v4l2_dev->dev->driver_data to NULL and unregister all sub-devices */ void v4l2_device_unregister(struct v4l2_device *v4l2_dev); @@ -52,23 +56,24 @@ void v4l2_device_unregister(struct v4l2_device *v4l2_dev); /* Register a subdev with a v4l2 device. While registered the subdev module is marked as in-use. An error is returned if the module is no longer loaded when you attempt to register it. */ -int __must_check v4l2_device_register_subdev(struct v4l2_device *dev, struct v4l2_subdev *sd); +int __must_check v4l2_device_register_subdev(struct v4l2_device *v4l2_dev, + struct v4l2_subdev *sd); /* Unregister a subdev with a v4l2 device. Can also be called if the subdev wasn't registered. In that case it will do nothing. */ void v4l2_device_unregister_subdev(struct v4l2_subdev *sd); /* Iterate over all subdevs. */ -#define v4l2_device_for_each_subdev(sd, dev) \ - list_for_each_entry(sd, &(dev)->subdevs, list) +#define v4l2_device_for_each_subdev(sd, v4l2_dev) \ + list_for_each_entry(sd, &(v4l2_dev)->subdevs, list) /* Call the specified callback for all subdevs matching the condition. Ignore any errors. Note that you cannot add or delete a subdev while walking the subdevs list. */ -#define __v4l2_device_call_subdevs(dev, cond, o, f, args...) \ +#define __v4l2_device_call_subdevs(v4l2_dev, cond, o, f, args...) \ do { \ struct v4l2_subdev *sd; \ \ - list_for_each_entry(sd, &(dev)->subdevs, list) \ + list_for_each_entry(sd, &(v4l2_dev)->subdevs, list) \ if ((cond) && sd->ops->o && sd->ops->o->f) \ sd->ops->o->f(sd , ##args); \ } while (0) @@ -77,12 +82,12 @@ void v4l2_device_unregister_subdev(struct v4l2_subdev *sd); If the callback returns an error other than 0 or -ENOIOCTLCMD, then return with that error code. Note that you cannot add or delete a subdev while walking the subdevs list. */ -#define __v4l2_device_call_subdevs_until_err(dev, cond, o, f, args...) \ +#define __v4l2_device_call_subdevs_until_err(v4l2_dev, cond, o, f, args...) \ ({ \ struct v4l2_subdev *sd; \ long err = 0; \ \ - list_for_each_entry(sd, &(dev)->subdevs, list) { \ + list_for_each_entry(sd, &(v4l2_dev)->subdevs, list) { \ if ((cond) && sd->ops->o && sd->ops->o->f) \ err = sd->ops->o->f(sd , ##args); \ if (err && err != -ENOIOCTLCMD) \ @@ -94,16 +99,16 @@ void v4l2_device_unregister_subdev(struct v4l2_subdev *sd); /* Call the specified callback for all subdevs matching grp_id (if 0, then match them all). Ignore any errors. Note that you cannot add or delete a subdev while walking the subdevs list. */ -#define v4l2_device_call_all(dev, grpid, o, f, args...) \ - __v4l2_device_call_subdevs(dev, \ +#define v4l2_device_call_all(v4l2_dev, grpid, o, f, args...) \ + __v4l2_device_call_subdevs(v4l2_dev, \ !(grpid) || sd->grp_id == (grpid), o, f , ##args) /* Call the specified callback for all subdevs matching grp_id (if 0, then match them all). If the callback returns an error other than 0 or -ENOIOCTLCMD, then return with that error code. Note that you cannot add or delete a subdev while walking the subdevs list. */ -#define v4l2_device_call_until_err(dev, grpid, o, f, args...) \ - __v4l2_device_call_subdevs_until_err(dev, \ +#define v4l2_device_call_until_err(v4l2_dev, grpid, o, f, args...) \ + __v4l2_device_call_subdevs_until_err(v4l2_dev, \ !(grpid) || sd->grp_id == (grpid), o, f , ##args) #endif -- cgit v1.2.3 From b01676005446ad51a32bb00577647c7aae7d2624 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sat, 14 Feb 2009 12:00:53 -0300 Subject: V4L/DVB (10644): v4l2-subdev: rename dev field to v4l2_dev Remain consistent in the naming: fields pointing to v4l2_device should be called v4l2_dev. There are too many device-like entities without adding to the confusion by mixing naming conventions. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- Documentation/video4linux/v4l2-framework.txt | 2 +- drivers/media/video/v4l2-device.c | 12 ++++++------ include/media/v4l2-subdev.h | 4 ++-- 3 files changed, 9 insertions(+), 9 deletions(-) (limited to 'drivers/media/video') diff --git a/Documentation/video4linux/v4l2-framework.txt b/Documentation/video4linux/v4l2-framework.txt index e1620e2a38ff..accc376e93cc 100644 --- a/Documentation/video4linux/v4l2-framework.txt +++ b/Documentation/video4linux/v4l2-framework.txt @@ -268,7 +268,7 @@ errors (except -ENOIOCTLCMD) occured, then 0 is returned. The second argument to both calls is a group ID. If 0, then all subdevs are called. If non-zero, then only those whose group ID match that value will -be called. Before a bridge driver registers a subdev it can set subdev->grp_id +be called. Before a bridge driver registers a subdev it can set sd->grp_id to whatever value it wants (it's 0 by default). This value is owned by the bridge driver and the sub-device driver will never modify or use it. diff --git a/drivers/media/video/v4l2-device.c b/drivers/media/video/v4l2-device.c index 3330ffb7d010..b3dcb8454379 100644 --- a/drivers/media/video/v4l2-device.c +++ b/drivers/media/video/v4l2-device.c @@ -72,10 +72,10 @@ int v4l2_device_register_subdev(struct v4l2_device *v4l2_dev, if (v4l2_dev == NULL || sd == NULL || !sd->name[0]) return -EINVAL; /* Warn if we apparently re-register a subdev */ - WARN_ON(sd->dev != NULL); + WARN_ON(sd->v4l2_dev != NULL); if (!try_module_get(sd->owner)) return -ENODEV; - sd->dev = v4l2_dev; + sd->v4l2_dev = v4l2_dev; spin_lock(&v4l2_dev->lock); list_add_tail(&sd->list, &v4l2_dev->subdevs); spin_unlock(&v4l2_dev->lock); @@ -86,12 +86,12 @@ EXPORT_SYMBOL_GPL(v4l2_device_register_subdev); void v4l2_device_unregister_subdev(struct v4l2_subdev *sd) { /* return if it isn't registered */ - if (sd == NULL || sd->dev == NULL) + if (sd == NULL || sd->v4l2_dev == NULL) return; - spin_lock(&sd->dev->lock); + spin_lock(&sd->v4l2_dev->lock); list_del(&sd->list); - spin_unlock(&sd->dev->lock); - sd->dev = NULL; + spin_unlock(&sd->v4l2_dev->lock); + sd->v4l2_dev = NULL; module_put(sd->owner); } EXPORT_SYMBOL_GPL(v4l2_device_unregister_subdev); diff --git a/include/media/v4l2-subdev.h b/include/media/v4l2-subdev.h index cd640c6f039b..05b69652e6c4 100644 --- a/include/media/v4l2-subdev.h +++ b/include/media/v4l2-subdev.h @@ -137,7 +137,7 @@ struct v4l2_subdev_ops { struct v4l2_subdev { struct list_head list; struct module *owner; - struct v4l2_device *dev; + struct v4l2_device *v4l2_dev; const struct v4l2_subdev_ops *ops; /* name must be unique */ char name[V4L2_SUBDEV_NAME_SIZE]; @@ -176,7 +176,7 @@ static inline void v4l2_subdev_init(struct v4l2_subdev *sd, /* ops->core MUST be set */ BUG_ON(!ops || !ops->core); sd->ops = ops; - sd->dev = NULL; + sd->v4l2_dev = NULL; sd->name[0] = '\0'; sd->grp_id = 0; sd->priv = NULL; -- cgit v1.2.3 From 5ab6c9af375e27c48bd2e86f4d9f6d68c9ab98fd Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sat, 14 Feb 2009 13:23:12 -0300 Subject: V4L/DVB (10645): vivi: introduce v4l2_device and do several cleanups - add v4l2_device - remove BKL - make the debug parameter settable on the fly - set bus_info in querycap Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/vivi.c | 258 +++++++++++++++++++++++---------------------- 1 file changed, 130 insertions(+), 128 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/vivi.c b/drivers/media/video/vivi.c index 0f25d686ca20..625e9662c7ad 100644 --- a/drivers/media/video/vivi.c +++ b/drivers/media/video/vivi.c @@ -33,12 +33,13 @@ #include #endif #include -#include -#include -#include #include #include #include +#include +#include +#include +#include "font.h" #define VIVI_MODULE_NAME "vivi" @@ -47,18 +48,32 @@ #define WAKE_DENOMINATOR 1001 #define BUFFER_TIMEOUT msecs_to_jiffies(500) /* 0.5 seconds */ -#include "font.h" - #define VIVI_MAJOR_VERSION 0 -#define VIVI_MINOR_VERSION 5 +#define VIVI_MINOR_VERSION 6 #define VIVI_RELEASE 0 #define VIVI_VERSION \ KERNEL_VERSION(VIVI_MAJOR_VERSION, VIVI_MINOR_VERSION, VIVI_RELEASE) -/* Declare static vars that will be used as parameters */ -static unsigned int vid_limit = 16; /* Video memory limit, in Mb */ -static int video_nr = -1; /* /dev/videoN, -1 for autodetect */ -static int n_devs = 1; /* Number of virtual devices */ +MODULE_DESCRIPTION("Video Technology Magazine Virtual Video Capture Board"); +MODULE_AUTHOR("Mauro Carvalho Chehab, Ted Walther and John Sokol"); +MODULE_LICENSE("Dual BSD/GPL"); + +static unsigned video_nr = -1; +module_param(video_nr, uint, 0644); +MODULE_PARM_DESC(video_nr, "videoX start number, -1 is autodetect"); + +static unsigned n_devs = 1; +module_param(n_devs, uint, 0644); +MODULE_PARM_DESC(n_devs, "number of video devices to create"); + +static unsigned debug; +module_param(debug, uint, 0644); +MODULE_PARM_DESC(debug, "activates debug info"); + +static unsigned int vid_limit = 16; +module_param(vid_limit, uint, 0644); +MODULE_PARM_DESC(vid_limit, "capture memory limit in megabytes"); + /* supported controls */ static struct v4l2_queryctrl vivi_qctrl[] = { @@ -112,11 +127,8 @@ static struct v4l2_queryctrl vivi_qctrl[] = { static int qctl_regs[ARRAY_SIZE(vivi_qctrl)]; -#define dprintk(dev, level, fmt, arg...) \ - do { \ - if (dev->vfd->debug >= (level)) \ - printk(KERN_DEBUG "vivi: " fmt , ## arg); \ - } while (0) +#define dprintk(dev, level, fmt, arg...) \ + v4l2_dbg(level, debug, &dev->v4l2_dev, fmt, ## arg) /* ------------------------------------------------------------------ Basic structures @@ -206,6 +218,7 @@ static LIST_HEAD(vivi_devlist); struct vivi_dev { struct list_head vivi_devlist; + struct v4l2_device v4l2_dev; spinlock_t slock; struct mutex mutex; @@ -656,7 +669,7 @@ static int vivi_start_thread(struct vivi_fh *fh) dma_q->kthread = kthread_run(vivi_thread, fh, "vivi"); if (IS_ERR(dma_q->kthread)) { - printk(KERN_ERR "vivi: kernel_thread() failed\n"); + v4l2_err(&dev->v4l2_dev, "kernel_thread() failed\n"); return PTR_ERR(dma_q->kthread); } /* Wakes thread */ @@ -799,8 +812,12 @@ static struct videobuf_queue_ops vivi_video_qops = { static int vidioc_querycap(struct file *file, void *priv, struct v4l2_capability *cap) { + struct vivi_fh *fh = priv; + struct vivi_dev *dev = fh->dev; + strcpy(cap->driver, "vivi"); strcpy(cap->card, "vivi"); + strlcpy(cap->bus_info, dev->v4l2_dev.name, sizeof(cap->bus_info)); cap->version = VIVI_VERSION; cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING | @@ -1124,32 +1141,21 @@ static int vidioc_s_ctrl(struct file *file, void *priv, static int vivi_open(struct file *file) { - int minor = video_devdata(file)->minor; - struct vivi_dev *dev; + struct vivi_dev *dev = video_drvdata(file); struct vivi_fh *fh = NULL; int i; int retval = 0; - printk(KERN_DEBUG "vivi: open called (minor=%d)\n", minor); - - lock_kernel(); - list_for_each_entry(dev, &vivi_devlist, vivi_devlist) - if (dev->vfd->minor == minor) - goto found; - unlock_kernel(); - return -ENODEV; - -found: mutex_lock(&dev->mutex); dev->users++; if (dev->users > 1) { dev->users--; - retval = -EBUSY; - goto unlock; + mutex_unlock(&dev->mutex); + return -EBUSY; } - dprintk(dev, 1, "open minor=%d type=%s users=%d\n", minor, + dprintk(dev, 1, "open /dev/video%d type=%s users=%d\n", dev->vfd->num, v4l2_type_names[V4L2_BUF_TYPE_VIDEO_CAPTURE], dev->users); /* allocate + initialize per filehandle data */ @@ -1157,14 +1163,11 @@ found: if (NULL == fh) { dev->users--; retval = -ENOMEM; - goto unlock; } -unlock: mutex_unlock(&dev->mutex); - if (retval) { - unlock_kernel(); + + if (retval) return retval; - } file->private_data = fh; fh->dev = dev; @@ -1193,7 +1196,6 @@ unlock: sizeof(struct vivi_buffer), fh); vivi_start_thread(fh); - unlock_kernel(); return 0; } @@ -1249,32 +1251,6 @@ static int vivi_close(struct file *file) return 0; } -static int vivi_release(void) -{ - struct vivi_dev *dev; - struct list_head *list; - - while (!list_empty(&vivi_devlist)) { - list = vivi_devlist.next; - list_del(list); - dev = list_entry(list, struct vivi_dev, vivi_devlist); - - if (-1 != dev->vfd->minor) { - printk(KERN_INFO "%s: unregistering /dev/video%d\n", - VIVI_MODULE_NAME, dev->vfd->num); - video_unregister_device(dev->vfd); - } else { - printk(KERN_INFO "%s: releasing /dev/video%d\n", - VIVI_MODULE_NAME, dev->vfd->num); - video_device_release(dev->vfd); - } - - kfree(dev); - } - - return 0; -} - static int vivi_mmap(struct file *file, struct vm_area_struct *vma) { struct vivi_fh *fh = file->private_data; @@ -1337,84 +1313,126 @@ static struct video_device vivi_template = { .tvnorms = V4L2_STD_525_60, .current_norm = V4L2_STD_NTSC_M, }; + /* ----------------------------------------------------------------- Initialization and module stuff ------------------------------------------------------------------*/ -/* This routine allocates from 1 to n_devs virtual drivers. +static int vivi_release(void) +{ + struct vivi_dev *dev; + struct list_head *list; - The real maximum number of virtual drivers will depend on how many drivers - will succeed. This is limited to the maximum number of devices that - videodev supports, which is equal to VIDEO_NUM_DEVICES. - */ -static int __init vivi_init(void) + while (!list_empty(&vivi_devlist)) { + list = vivi_devlist.next; + list_del(list); + dev = list_entry(list, struct vivi_dev, vivi_devlist); + + v4l2_info(&dev->v4l2_dev, "unregistering /dev/video%d\n", + dev->vfd->num); + video_unregister_device(dev->vfd); + v4l2_device_unregister(&dev->v4l2_dev); + kfree(dev); + } + + return 0; +} + +static int __init vivi_create_instance(int i) { - int ret = -ENOMEM, i; struct vivi_dev *dev; struct video_device *vfd; + int ret; - if (n_devs <= 0) - n_devs = 1; + dev = kzalloc(sizeof(*dev), GFP_KERNEL); + if (!dev) + return -ENOMEM; - for (i = 0; i < n_devs; i++) { - dev = kzalloc(sizeof(*dev), GFP_KERNEL); - if (!dev) - break; + snprintf(dev->v4l2_dev.name, sizeof(dev->v4l2_dev.name), + "%s-%03d", VIVI_MODULE_NAME, i); + ret = v4l2_device_register(NULL, &dev->v4l2_dev); + if (ret) + goto free_dev; - /* init video dma queues */ - INIT_LIST_HEAD(&dev->vidq.active); - init_waitqueue_head(&dev->vidq.wq); + /* init video dma queues */ + INIT_LIST_HEAD(&dev->vidq.active); + init_waitqueue_head(&dev->vidq.wq); - /* initialize locks */ - spin_lock_init(&dev->slock); - mutex_init(&dev->mutex); + /* initialize locks */ + spin_lock_init(&dev->slock); + mutex_init(&dev->mutex); - vfd = video_device_alloc(); - if (!vfd) { - kfree(dev); - break; - } + ret = -ENOMEM; + vfd = video_device_alloc(); + if (!vfd) + goto unreg_dev; - *vfd = vivi_template; + *vfd = vivi_template; - ret = video_register_device(vfd, VFL_TYPE_GRABBER, video_nr); - if (ret < 0) { - video_device_release(vfd); - kfree(dev); + ret = video_register_device(vfd, VFL_TYPE_GRABBER, video_nr); + if (ret < 0) + goto rel_vdev; - /* If some registers succeeded, keep driver */ - if (i) - ret = 0; + video_set_drvdata(vfd, dev); - break; - } + /* Now that everything is fine, let's add it to device list */ + list_add_tail(&dev->vivi_devlist, &vivi_devlist); - /* Now that everything is fine, let's add it to device list */ - list_add_tail(&dev->vivi_devlist, &vivi_devlist); + snprintf(vfd->name, sizeof(vfd->name), "%s (%i)", + vivi_template.name, vfd->num); - snprintf(vfd->name, sizeof(vfd->name), "%s (%i)", - vivi_template.name, vfd->minor); + if (video_nr >= 0) + video_nr++; - if (video_nr >= 0) - video_nr++; + dev->vfd = vfd; + v4l2_info(&dev->v4l2_dev, "V4L2 device registered as /dev/video%d\n", + vfd->num); + return 0; + +rel_vdev: + video_device_release(vfd); +unreg_dev: + v4l2_device_unregister(&dev->v4l2_dev); +free_dev: + kfree(dev); + return ret; +} - dev->vfd = vfd; - printk(KERN_INFO "%s: V4L2 device registered as /dev/video%d\n", - VIVI_MODULE_NAME, vfd->num); +/* This routine allocates from 1 to n_devs virtual drivers. + + The real maximum number of virtual drivers will depend on how many drivers + will succeed. This is limited to the maximum number of devices that + videodev supports, which is equal to VIDEO_NUM_DEVICES. + */ +static int __init vivi_init(void) +{ + int ret, i; + + if (n_devs <= 0) + n_devs = 1; + + for (i = 0; i < n_devs; i++) { + ret = vivi_create_instance(i); + if (ret) { + /* If some instantiations succeeded, keep driver */ + if (i) + ret = 0; + break; + } } if (ret < 0) { - vivi_release(); printk(KERN_INFO "Error %d while loading vivi driver\n", ret); - } else { - printk(KERN_INFO "Video Technology Magazine Virtual Video " + return ret; + } + + printk(KERN_INFO "Video Technology Magazine Virtual Video " "Capture Board ver %u.%u.%u successfully loaded.\n", (VIVI_VERSION >> 16) & 0xFF, (VIVI_VERSION >> 8) & 0xFF, VIVI_VERSION & 0xFF); - /* n_devs will reflect the actual number of allocated devices */ - n_devs = i; - } + /* n_devs will reflect the actual number of allocated devices */ + n_devs = i; return ret; } @@ -1426,19 +1444,3 @@ static void __exit vivi_exit(void) module_init(vivi_init); module_exit(vivi_exit); - -MODULE_DESCRIPTION("Video Technology Magazine Virtual Video Capture Board"); -MODULE_AUTHOR("Mauro Carvalho Chehab, Ted Walther and John Sokol"); -MODULE_LICENSE("Dual BSD/GPL"); - -module_param(video_nr, uint, 0444); -MODULE_PARM_DESC(video_nr, "video iminor start number"); - -module_param(n_devs, uint, 0444); -MODULE_PARM_DESC(n_devs, "number of video devices to create"); - -module_param_named(debug, vivi_template.debug, int, 0444); -MODULE_PARM_DESC(debug, "activates debug info"); - -module_param(vid_limit, int, 0644); -MODULE_PARM_DESC(vid_limit, "capture memory limit in megabytes"); -- cgit v1.2.3 From c41ee24bc44d5ce813da1fcf8a0f018a825cfa84 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sat, 14 Feb 2009 13:43:44 -0300 Subject: V4L/DVB (10646): vivi: controls are per-device, not global. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/vivi.c | 40 ++++++++++++++++++++++------------------ 1 file changed, 22 insertions(+), 18 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/vivi.c b/drivers/media/video/vivi.c index 625e9662c7ad..5b4786b07ad0 100644 --- a/drivers/media/video/vivi.c +++ b/drivers/media/video/vivi.c @@ -125,8 +125,6 @@ static struct v4l2_queryctrl vivi_qctrl[] = { } }; -static int qctl_regs[ARRAY_SIZE(vivi_qctrl)]; - #define dprintk(dev, level, fmt, arg...) \ v4l2_dbg(level, debug, &dev->v4l2_dev, fmt, ## arg) @@ -239,6 +237,9 @@ struct vivi_dev { /* Input Number */ int input; + + /* Control 'registers' */ + int qctl_regs[ARRAY_SIZE(vivi_qctrl)]; }; struct vivi_fh { @@ -1108,12 +1109,14 @@ static int vidioc_queryctrl(struct file *file, void *priv, static int vidioc_g_ctrl(struct file *file, void *priv, struct v4l2_control *ctrl) { + struct vivi_fh *fh = priv; + struct vivi_dev *dev = fh->dev; int i; for (i = 0; i < ARRAY_SIZE(vivi_qctrl); i++) if (ctrl->id == vivi_qctrl[i].id) { - ctrl->value = qctl_regs[i]; - return (0); + ctrl->value = dev->qctl_regs[i]; + return 0; } return -EINVAL; @@ -1121,16 +1124,18 @@ static int vidioc_g_ctrl(struct file *file, void *priv, static int vidioc_s_ctrl(struct file *file, void *priv, struct v4l2_control *ctrl) { + struct vivi_fh *fh = priv; + struct vivi_dev *dev = fh->dev; int i; for (i = 0; i < ARRAY_SIZE(vivi_qctrl); i++) if (ctrl->id == vivi_qctrl[i].id) { - if (ctrl->value < vivi_qctrl[i].minimum - || ctrl->value > vivi_qctrl[i].maximum) { - return (-ERANGE); - } - qctl_regs[i] = ctrl->value; - return (0); + if (ctrl->value < vivi_qctrl[i].minimum || + ctrl->value > vivi_qctrl[i].maximum) { + return -ERANGE; + } + dev->qctl_regs[i] = ctrl->value; + return 0; } return -EINVAL; } @@ -1143,7 +1148,6 @@ static int vivi_open(struct file *file) { struct vivi_dev *dev = video_drvdata(file); struct vivi_fh *fh = NULL; - int i; int retval = 0; mutex_lock(&dev->mutex); @@ -1177,10 +1181,6 @@ static int vivi_open(struct file *file) fh->width = 640; fh->height = 480; - /* Put all controls at a sane state */ - for (i = 0; i < ARRAY_SIZE(vivi_qctrl); i++) - qctl_regs[i] = vivi_qctrl[i].default_value; - /* Resets frame counters */ dev->h = 0; dev->m = 0; @@ -1338,18 +1338,18 @@ static int vivi_release(void) return 0; } -static int __init vivi_create_instance(int i) +static int __init vivi_create_instance(int inst) { struct vivi_dev *dev; struct video_device *vfd; - int ret; + int ret, i; dev = kzalloc(sizeof(*dev), GFP_KERNEL); if (!dev) return -ENOMEM; snprintf(dev->v4l2_dev.name, sizeof(dev->v4l2_dev.name), - "%s-%03d", VIVI_MODULE_NAME, i); + "%s-%03d", VIVI_MODULE_NAME, inst); ret = v4l2_device_register(NULL, &dev->v4l2_dev); if (ret) goto free_dev; @@ -1375,6 +1375,10 @@ static int __init vivi_create_instance(int i) video_set_drvdata(vfd, dev); + /* Set all controls to their default value. */ + for (i = 0; i < ARRAY_SIZE(vivi_qctrl); i++) + dev->qctl_regs[i] = vivi_qctrl[i].default_value; + /* Now that everything is fine, let's add it to device list */ list_add_tail(&dev->vivi_devlist, &vivi_devlist); -- cgit v1.2.3 From 4a5aa62bd5e27d90ceb11bc256de659d5c99e0dc Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sat, 14 Feb 2009 13:50:19 -0300 Subject: V4L/DVB (10647): vivi: add slider flag to controls. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/vivi.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/vivi.c b/drivers/media/video/vivi.c index 5b4786b07ad0..616eb1a8dbee 100644 --- a/drivers/media/video/vivi.c +++ b/drivers/media/video/vivi.c @@ -84,7 +84,7 @@ static struct v4l2_queryctrl vivi_qctrl[] = { .maximum = 65535, .step = 65535/100, .default_value = 65535, - .flags = 0, + .flags = V4L2_CTRL_FLAG_SLIDER, .type = V4L2_CTRL_TYPE_INTEGER, }, { .id = V4L2_CID_BRIGHTNESS, @@ -94,7 +94,7 @@ static struct v4l2_queryctrl vivi_qctrl[] = { .maximum = 255, .step = 1, .default_value = 127, - .flags = 0, + .flags = V4L2_CTRL_FLAG_SLIDER, }, { .id = V4L2_CID_CONTRAST, .type = V4L2_CTRL_TYPE_INTEGER, @@ -103,7 +103,7 @@ static struct v4l2_queryctrl vivi_qctrl[] = { .maximum = 255, .step = 0x1, .default_value = 0x10, - .flags = 0, + .flags = V4L2_CTRL_FLAG_SLIDER, }, { .id = V4L2_CID_SATURATION, .type = V4L2_CTRL_TYPE_INTEGER, @@ -112,7 +112,7 @@ static struct v4l2_queryctrl vivi_qctrl[] = { .maximum = 255, .step = 0x1, .default_value = 127, - .flags = 0, + .flags = V4L2_CTRL_FLAG_SLIDER, }, { .id = V4L2_CID_HUE, .type = V4L2_CTRL_TYPE_INTEGER, @@ -121,7 +121,7 @@ static struct v4l2_queryctrl vivi_qctrl[] = { .maximum = 127, .step = 0x1, .default_value = 0, - .flags = 0, + .flags = V4L2_CTRL_FLAG_SLIDER, } }; -- cgit v1.2.3 From 72362422f3a9cb66e26fa9f0d90d3ef5241e78ba Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Sat, 14 Feb 2009 19:26:56 -0300 Subject: V4L/DVB (10650): uvcvideo: Initialize streaming parameters with the probe control value The UVC specification requires SET_CUR requests on the streaming commit control to use values retrieved from a successful GET_CUR request on the probe control. Initialize streaming parameters with the probe control current value to make sure the driver always complies. Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/uvc/uvc_video.c | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/uvc/uvc_video.c b/drivers/media/video/uvc/uvc_video.c index 7ebb89539c36..9139086f940a 100644 --- a/drivers/media/video/uvc/uvc_video.c +++ b/drivers/media/video/uvc/uvc_video.c @@ -1026,11 +1026,20 @@ int uvc_video_init(struct uvc_video_device *video) */ usb_set_interface(video->dev->udev, video->streaming->intfnum, 0); - /* Some webcams don't suport GET_DEF requests on the probe control. We - * fall back to GET_CUR if GET_DEF fails. + /* Set the streaming probe control with default streaming parameters + * retrieved from the device. Webcams that don't suport GET_DEF + * requests on the probe control will just keep their current streaming + * parameters. */ - if ((ret = uvc_get_video_ctrl(video, probe, 1, GET_DEF)) < 0 && - (ret = uvc_get_video_ctrl(video, probe, 1, GET_CUR)) < 0) + if (uvc_get_video_ctrl(video, probe, 1, GET_DEF) == 0) + uvc_set_video_ctrl(video, probe, 1); + + /* Initialize the streaming parameters with the probe control current + * value. This makes sure SET_CUR requests on the streaming commit + * control will always use values retrieved from a successful GET_CUR + * request on the probe control, as required by the UVC specification. + */ + if ((ret = uvc_get_video_ctrl(video, probe, 1, GET_CUR)) < 0) return ret; /* Check if the default format descriptor exists. Use the first -- cgit v1.2.3 From c90e777976f6237a0cdb644c6a9406907939b174 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Sat, 14 Feb 2009 19:39:08 -0300 Subject: V4L/DVB (10651): uvcvideo: Ignore empty bulk URBs Devices may send a zero-length packet to signal the end of a bulk payload. If the payload size is a multiple of the URB size the zero-length packet will be received by the URB completion handler. Handle this by ignoring all empty URBs. Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/uvc/uvc_video.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers/media/video') diff --git a/drivers/media/video/uvc/uvc_video.c b/drivers/media/video/uvc/uvc_video.c index 9139086f940a..0789ba381fc1 100644 --- a/drivers/media/video/uvc/uvc_video.c +++ b/drivers/media/video/uvc/uvc_video.c @@ -540,6 +540,9 @@ static void uvc_video_decode_bulk(struct urb *urb, u8 *mem; int len, ret; + if (urb->actual_length == 0) + return; + mem = urb->transfer_buffer; len = urb->actual_length; video->bulk.payload_size += len; -- cgit v1.2.3 From 50144aeeb702ea105697ae5249f059ea3990b838 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Mon, 16 Feb 2009 17:41:52 -0300 Subject: V4L/DVB (10652): uvcvideo: Add quirk to override wrong bandwidth value for Vimicro devices At least 3 Vimicro cameras (0x332d, 0x3410 and 0x3420) fail to return correct bandwidth information. The first model rounds the value provided by the host to the nearest supported packet size, while the other two always request the maximum bandwidth. Introduce a device quirk to override the value returned by the device with an estimated bandwidth computed by the driver from the frame size and frame rate, and enable it for all Vimicro cameras. Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/uvc/uvc_driver.c | 9 +++++++++ drivers/media/video/uvc/uvc_video.c | 34 ++++++++++++++++++++++++++++++---- drivers/media/video/uvc/uvcvideo.h | 1 + 3 files changed, 40 insertions(+), 4 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/uvc/uvc_driver.c b/drivers/media/video/uvc/uvc_driver.c index ebcd5bf0edb7..22e2783ac555 100644 --- a/drivers/media/video/uvc/uvc_driver.c +++ b/drivers/media/video/uvc/uvc_driver.c @@ -1861,6 +1861,15 @@ static struct usb_device_id uvc_ids[] = { .bInterfaceSubClass = 1, .bInterfaceProtocol = 0, .driver_info = UVC_QUIRK_STREAM_NO_FID }, + /* ViMicro */ + { .match_flags = USB_DEVICE_ID_MATCH_VENDOR + | USB_DEVICE_ID_MATCH_INT_INFO, + .idVendor = 0x0ac8, + .idProduct = 0x0000, + .bInterfaceClass = USB_CLASS_VIDEO, + .bInterfaceSubClass = 1, + .bInterfaceProtocol = 0, + .driver_info = UVC_QUIRK_FIX_BANDWIDTH }, /* MT6227 */ { .match_flags = USB_DEVICE_ID_MATCH_DEVICE | USB_DEVICE_ID_MATCH_INT_INFO, diff --git a/drivers/media/video/uvc/uvc_video.c b/drivers/media/video/uvc/uvc_video.c index 0789ba381fc1..a95e17329c5b 100644 --- a/drivers/media/video/uvc/uvc_video.c +++ b/drivers/media/video/uvc/uvc_video.c @@ -61,7 +61,7 @@ int uvc_query_ctrl(struct uvc_device *dev, __u8 query, __u8 unit, return 0; } -static void uvc_fixup_buffer_size(struct uvc_video_device *video, +static void uvc_fixup_video_ctrl(struct uvc_video_device *video, struct uvc_streaming_control *ctrl) { struct uvc_format *format; @@ -84,6 +84,31 @@ static void uvc_fixup_buffer_size(struct uvc_video_device *video, video->dev->uvc_version < 0x0110)) ctrl->dwMaxVideoFrameSize = frame->dwMaxVideoFrameBufferSize; + + if (video->dev->quirks & UVC_QUIRK_FIX_BANDWIDTH && + video->streaming->intf->num_altsetting > 1) { + u32 interval; + u32 bandwidth; + + interval = (ctrl->dwFrameInterval > 100000) + ? ctrl->dwFrameInterval + : frame->dwFrameInterval[0]; + + /* Compute a bandwidth estimation by multiplying the frame + * size by the number of video frames per second, divide the + * result by the number of USB frames (or micro-frames for + * high-speed devices) per second and add the UVC header size + * (assumed to be 12 bytes long). + */ + bandwidth = frame->wWidth * frame->wHeight / 8 * format->bpp; + bandwidth *= 10000000 / interval + 1; + bandwidth /= 1000; + if (video->dev->udev->speed == USB_SPEED_HIGH) + bandwidth /= 8; + bandwidth += 12; + + ctrl->dwMaxPayloadTransferSize = bandwidth; + } } static int uvc_get_video_ctrl(struct uvc_video_device *video, @@ -158,10 +183,11 @@ static int uvc_get_video_ctrl(struct uvc_video_device *video, ctrl->bMaxVersion = 0; } - /* Some broken devices return a null or wrong dwMaxVideoFrameSize. - * Try to get the value from the format and frame descriptors. + /* Some broken devices return null or wrong dwMaxVideoFrameSize and + * dwMaxPayloadTransferSize fields. Try to get the value from the + * format and frame descriptors. */ - uvc_fixup_buffer_size(video, ctrl); + uvc_fixup_video_ctrl(video, ctrl); ret = 0; out: diff --git a/drivers/media/video/uvc/uvcvideo.h b/drivers/media/video/uvc/uvcvideo.h index 6f55c4d49cf4..e5014e668f99 100644 --- a/drivers/media/video/uvc/uvcvideo.h +++ b/drivers/media/video/uvc/uvcvideo.h @@ -314,6 +314,7 @@ struct uvc_xu_control { #define UVC_QUIRK_STREAM_NO_FID 0x00000010 #define UVC_QUIRK_IGNORE_SELECTOR_UNIT 0x00000020 #define UVC_QUIRK_PRUNE_CONTROLS 0x00000040 +#define UVC_QUIRK_FIX_BANDWIDTH 0x00000080 /* Format flags */ #define UVC_FMT_FLAG_COMPRESSED 0x00000001 -- cgit v1.2.3 From df7fa09cca9d80f746c29f95b09a7223f6c2f4e7 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 25 Feb 2009 09:06:13 -0300 Subject: V4L/DVB (10654): em28xx: VideoMate For You USB TV box requires tvaudio As reported by Vitaly Wool : > about half a year ago I posted the patch that basically enabled Compro > VideoMate For You USB TV box support. > The main problem is I couldn't get the sound working. > So I kind of decomposed the box and found out the audio decoder chip > used there was Philips TDA9874A. As far as I can see, it's not supported > within the em28xx suite although it is for other TV tuner drivers. A tvaudio modprobing confirms that tda9874a chip is accessible via i2c: tvaudio: TV audio decoder + audio/video mux driver tvaudio: known chips: tda9840, tda9873h, tda9874h/a, tda9850, tda9855, tea6300, tea6320, tea6420, tda8425, pic16c54 (PV951), ta8874z tvaudio' 1-0058: chip found @ 0xb0 tvaudio' 1-0058: tvaudio': chip_read2: reg254=0x11 tvaudio' 1-0058: tvaudio': chip_read2: reg255=0x2 tvaudio' 1-0058: tda9874a_checkit(): DIC=0x11, SIC=0x2. tvaudio' 1-0058: found tda9874a. tvaudio' 1-0058: tda9874h/a found @ 0xb0 (em28xx #0) tvaudio' 1-0058: tda9874h/a: chip_write: reg0=0x0 tvaudio' 1-0058: tda9874h/a: chip_write: reg1=0xc0 tvaudio' 1-0058: tda9874h/a: chip_write: reg2=0x2 tvaudio' 1-0058: tda9874h/a: chip_write: reg11=0x80 tvaudio' 1-0058: tda9874h/a: chip_write: reg12=0x0 tvaudio' 1-0058: tda9874h/a: chip_write: reg13=0x0 tvaudio' 1-0058: tda9874h/a: chip_write: reg14=0x1 tvaudio' 1-0058: tda9874h/a: chip_write: reg15=0x0 tvaudio' 1-0058: tda9874h/a: chip_write: reg16=0x14 tvaudio' 1-0058: tda9874h/a: chip_write: reg17=0x50 tvaudio' 1-0058: tda9874h/a: chip_write: reg18=0xf9 tvaudio' 1-0058: tda9874h/a: chip_write: reg19=0x80 tvaudio' 1-0058: tda9874h/a: chip_write: reg20=0x80 tvaudio' 1-0058: tda9874h/a: chip_write: reg24=0x80 tvaudio' 1-0058: tda9874h/a: chip_write: reg255=0x0 tvaudio' 1-0058: tda9874a_setup(): A2, B/G [0x00]. tvaudio' 1-0058: tda9874h/a: thread started] This patch automatically loads tvaudio when needed (currently, only with this board). Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/em28xx/em28xx-cards.c | 3 +++ drivers/media/video/em28xx/em28xx.h | 6 ++++++ 2 files changed, 9 insertions(+) (limited to 'drivers/media/video') diff --git a/drivers/media/video/em28xx/em28xx-cards.c b/drivers/media/video/em28xx/em28xx-cards.c index 615cf362e79c..2b27460dae35 100644 --- a/drivers/media/video/em28xx/em28xx-cards.c +++ b/drivers/media/video/em28xx/em28xx-cards.c @@ -1244,6 +1244,7 @@ struct em28xx_board em28xx_boards[] = { .tuner_type = TUNER_LG_PAL_NEW_TAPC, .tda9887_conf = TDA9887_PRESENT, .decoder = EM28XX_TVP5150, + .adecoder = EM28XX_TVAUDIO, .input = { { .type = EM28XX_VMUX_TELEVISION, .vmux = TVP5150_COMPOSITE0, @@ -1917,6 +1918,8 @@ void em28xx_card_setup(struct em28xx *dev) request_module("tvp5150"); if (dev->board.tuner_type != TUNER_ABSENT) request_module("tuner"); + if (dev->board.adecoder == EM28XX_TVAUDIO) + request_module("tvaudio"); #endif em28xx_config_tuner(dev); diff --git a/drivers/media/video/em28xx/em28xx.h b/drivers/media/video/em28xx/em28xx.h index 3e82d818c0cd..89a793cb8ca4 100644 --- a/drivers/media/video/em28xx/em28xx.h +++ b/drivers/media/video/em28xx/em28xx.h @@ -357,6 +357,11 @@ enum em28xx_decoder { EM28XX_SAA711X, }; +enum em28xx_adecoder { + EM28XX_NOADECODER = 0, + EM28XX_TVAUDIO, +}; + struct em28xx_board { char *name; int vchannels; @@ -382,6 +387,7 @@ struct em28xx_board { unsigned char xclk, i2c_speed; enum em28xx_decoder decoder; + enum em28xx_adecoder adecoder; struct em28xx_input input[MAX_EM28XX_INPUT]; struct em28xx_input radio; -- cgit v1.2.3 From 6722e0ef1f72d86169b2b0f96ad34afd225cd080 Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Mon, 12 Jan 2009 06:17:43 -0300 Subject: V4L/DVB (10655): tvp514x: make the module aware of rich people because they might design two of those chips on a single board. You never know. Signed-off-by: Sebastian Andrzej Siewior Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/tvp514x.c | 106 ++++++++++++++++++++++++------------------ 1 file changed, 60 insertions(+), 46 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/tvp514x.c b/drivers/media/video/tvp514x.c index 5f4cbc2b23c1..f0b2b8ed2fe4 100644 --- a/drivers/media/video/tvp514x.c +++ b/drivers/media/video/tvp514x.c @@ -86,9 +86,12 @@ struct tvp514x_std_info { struct v4l2_standard standard; }; +static struct tvp514x_reg tvp514x_reg_list_default[0x40]; /** - * struct tvp514x_decoded - TVP5146/47 decoder object + * struct tvp514x_decoder - TVP5146/47 decoder object * @v4l2_int_device: Slave handle + * @tvp514x_slave: Slave pointer which is used by @v4l2_int_device + * @tvp514x_regs: copy of hw's regs with preset values. * @pdata: Board specific * @client: I2C client data * @id: Entry from I2C table @@ -103,7 +106,9 @@ struct tvp514x_std_info { * @route: input and output routing at chip level */ struct tvp514x_decoder { - struct v4l2_int_device *v4l2_int_device; + struct v4l2_int_device v4l2_int_device; + struct v4l2_int_slave tvp514x_slave; + struct tvp514x_reg tvp514x_regs[ARRAY_SIZE(tvp514x_reg_list_default)]; const struct tvp514x_platform_data *pdata; struct i2c_client *client; @@ -124,7 +129,7 @@ struct tvp514x_decoder { }; /* TVP514x default register values */ -static struct tvp514x_reg tvp514x_reg_list[] = { +static struct tvp514x_reg tvp514x_reg_list_default[] = { {TOK_WRITE, REG_INPUT_SEL, 0x05}, /* Composite selected */ {TOK_WRITE, REG_AFE_GAIN_CTRL, 0x0F}, {TOK_WRITE, REG_VIDEO_STD, 0x00}, /* Auto mode */ @@ -422,7 +427,7 @@ static int tvp514x_configure(struct tvp514x_decoder *decoder) /* common register initialization */ err = - tvp514x_write_regs(decoder->client, tvp514x_reg_list); + tvp514x_write_regs(decoder->client, decoder->tvp514x_regs); if (err) return err; @@ -580,7 +585,8 @@ static int ioctl_s_std(struct v4l2_int_device *s, v4l2_std_id *std_id) return err; decoder->current_std = i; - tvp514x_reg_list[REG_VIDEO_STD].val = decoder->std_list[i].video_std; + decoder->tvp514x_regs[REG_VIDEO_STD].val = + decoder->std_list[i].video_std; v4l_dbg(1, debug, decoder->client, "Standard set to: %s", decoder->std_list[i].standard.name); @@ -625,8 +631,8 @@ static int ioctl_s_routing(struct v4l2_int_device *s, if (err) return err; - tvp514x_reg_list[REG_INPUT_SEL].val = input_sel; - tvp514x_reg_list[REG_OUTPUT_FORMATTER1].val = output_sel; + decoder->tvp514x_regs[REG_INPUT_SEL].val = input_sel; + decoder->tvp514x_regs[REG_OUTPUT_FORMATTER1].val = output_sel; /* Clear status */ msleep(LOCK_RETRY_DELAY); @@ -779,16 +785,16 @@ ioctl_g_ctrl(struct v4l2_int_device *s, struct v4l2_control *ctrl) switch (ctrl->id) { case V4L2_CID_BRIGHTNESS: - ctrl->value = tvp514x_reg_list[REG_BRIGHTNESS].val; + ctrl->value = decoder->tvp514x_regs[REG_BRIGHTNESS].val; break; case V4L2_CID_CONTRAST: - ctrl->value = tvp514x_reg_list[REG_CONTRAST].val; + ctrl->value = decoder->tvp514x_regs[REG_CONTRAST].val; break; case V4L2_CID_SATURATION: - ctrl->value = tvp514x_reg_list[REG_SATURATION].val; + ctrl->value = decoder->tvp514x_regs[REG_SATURATION].val; break; case V4L2_CID_HUE: - ctrl->value = tvp514x_reg_list[REG_HUE].val; + ctrl->value = decoder->tvp514x_regs[REG_HUE].val; if (ctrl->value == 0x7F) ctrl->value = 180; else if (ctrl->value == 0x80) @@ -798,7 +804,7 @@ ioctl_g_ctrl(struct v4l2_int_device *s, struct v4l2_control *ctrl) break; case V4L2_CID_AUTOGAIN: - ctrl->value = tvp514x_reg_list[REG_AFE_GAIN_CTRL].val; + ctrl->value = decoder->tvp514x_regs[REG_AFE_GAIN_CTRL].val; if ((ctrl->value & 0x3) == 3) ctrl->value = 1; else @@ -848,7 +854,7 @@ ioctl_s_ctrl(struct v4l2_int_device *s, struct v4l2_control *ctrl) value); if (err) return err; - tvp514x_reg_list[REG_BRIGHTNESS].val = value; + decoder->tvp514x_regs[REG_BRIGHTNESS].val = value; break; case V4L2_CID_CONTRAST: if (ctrl->value < 0 || ctrl->value > 255) { @@ -861,7 +867,7 @@ ioctl_s_ctrl(struct v4l2_int_device *s, struct v4l2_control *ctrl) value); if (err) return err; - tvp514x_reg_list[REG_CONTRAST].val = value; + decoder->tvp514x_regs[REG_CONTRAST].val = value; break; case V4L2_CID_SATURATION: if (ctrl->value < 0 || ctrl->value > 255) { @@ -874,7 +880,7 @@ ioctl_s_ctrl(struct v4l2_int_device *s, struct v4l2_control *ctrl) value); if (err) return err; - tvp514x_reg_list[REG_SATURATION].val = value; + decoder->tvp514x_regs[REG_SATURATION].val = value; break; case V4L2_CID_HUE: if (value == 180) @@ -893,7 +899,7 @@ ioctl_s_ctrl(struct v4l2_int_device *s, struct v4l2_control *ctrl) value); if (err) return err; - tvp514x_reg_list[REG_HUE].val = value; + decoder->tvp514x_regs[REG_HUE].val = value; break; case V4L2_CID_AUTOGAIN: if (value == 1) @@ -910,7 +916,7 @@ ioctl_s_ctrl(struct v4l2_int_device *s, struct v4l2_control *ctrl) value); if (err) return err; - tvp514x_reg_list[REG_AFE_GAIN_CTRL].val = value; + decoder->tvp514x_regs[REG_AFE_GAIN_CTRL].val = value; break; default: v4l_err(decoder->client, @@ -1275,7 +1281,7 @@ static int ioctl_init(struct v4l2_int_device *s) struct tvp514x_decoder *decoder = s->priv; /* Set default standard to auto */ - tvp514x_reg_list[REG_VIDEO_STD].val = + decoder->tvp514x_regs[REG_VIDEO_STD].val = VIDEO_STD_AUTO_SWITCH_BIT; return tvp514x_configure(decoder); @@ -1344,11 +1350,6 @@ static struct v4l2_int_ioctl_desc tvp514x_ioctl_desc[] = { (v4l2_int_ioctl_func *) ioctl_s_routing}, }; -static struct v4l2_int_slave tvp514x_slave = { - .ioctls = tvp514x_ioctl_desc, - .num_ioctls = ARRAY_SIZE(tvp514x_ioctl_desc), -}; - static struct tvp514x_decoder tvp514x_dev = { .state = STATE_NOT_DETECTED, @@ -1369,17 +1370,15 @@ static struct tvp514x_decoder tvp514x_dev = { .current_std = STD_NTSC_MJ, .std_list = tvp514x_std_list, .num_stds = ARRAY_SIZE(tvp514x_std_list), - -}; - -static struct v4l2_int_device tvp514x_int_device = { - .module = THIS_MODULE, - .name = TVP514X_MODULE_NAME, - .priv = &tvp514x_dev, - .type = v4l2_int_type_slave, - .u = { - .slave = &tvp514x_slave, - }, + .v4l2_int_device = { + .module = THIS_MODULE, + .name = TVP514X_MODULE_NAME, + .type = v4l2_int_type_slave, + }, + .tvp514x_slave = { + .ioctls = tvp514x_ioctl_desc, + .num_ioctls = ARRAY_SIZE(tvp514x_ioctl_desc), + }, }; /** @@ -1392,26 +1391,37 @@ static struct v4l2_int_device tvp514x_int_device = { static int tvp514x_probe(struct i2c_client *client, const struct i2c_device_id *id) { - struct tvp514x_decoder *decoder = &tvp514x_dev; + struct tvp514x_decoder *decoder; int err; /* Check if the adapter supports the needed features */ if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) return -EIO; - decoder->pdata = client->dev.platform_data; - if (!decoder->pdata) { + decoder = kzalloc(sizeof(*decoder), GFP_KERNEL); + if (!decoder) + return -ENOMEM; + + if (!client->dev.platform_data) { v4l_err(client, "No platform data!!\n"); - return -ENODEV; + err = -ENODEV; + goto out_free; } + + *decoder = tvp514x_dev; + decoder->v4l2_int_device.priv = decoder; + decoder->pdata = client->dev.platform_data; + decoder->v4l2_int_device.u.slave = &decoder->tvp514x_slave; + memcpy(decoder->tvp514x_regs, tvp514x_reg_list_default, + sizeof(tvp514x_reg_list_default)); /* * Fetch platform specific data, and configure the * tvp514x_reg_list[] accordingly. Since this is one * time configuration, no need to preserve. */ - tvp514x_reg_list[REG_OUTPUT_FORMATTER2].val |= + decoder->tvp514x_regs[REG_OUTPUT_FORMATTER2].val |= (decoder->pdata->clk_polarity << 1); - tvp514x_reg_list[REG_SYNC_CONTROL].val |= + decoder->tvp514x_regs[REG_SYNC_CONTROL].val |= ((decoder->pdata->hs_polarity << 2) | (decoder->pdata->vs_polarity << 3)); /* @@ -1419,23 +1429,27 @@ tvp514x_probe(struct i2c_client *client, const struct i2c_device_id *id) */ decoder->id = (struct i2c_device_id *)id; /* Attach to Master */ - strcpy(tvp514x_int_device.u.slave->attach_to, decoder->pdata->master); - decoder->v4l2_int_device = &tvp514x_int_device; + strcpy(decoder->v4l2_int_device.u.slave->attach_to, + decoder->pdata->master); decoder->client = client; i2c_set_clientdata(client, decoder); /* Register with V4L2 layer as slave device */ - err = v4l2_int_device_register(decoder->v4l2_int_device); + err = v4l2_int_device_register(&decoder->v4l2_int_device); if (err) { i2c_set_clientdata(client, NULL); v4l_err(client, "Unable to register to v4l2. Err[%d]\n", err); + goto out_free; } else v4l_info(client, "Registered to v4l2 master %s!!\n", decoder->pdata->master); - return 0; + +out_free: + kfree(decoder); + return err; } /** @@ -1452,9 +1466,9 @@ static int __exit tvp514x_remove(struct i2c_client *client) if (!client->adapter) return -ENODEV; /* our client isn't attached */ - v4l2_int_device_unregister(decoder->v4l2_int_device); + v4l2_int_device_unregister(&decoder->v4l2_int_device); i2c_set_clientdata(client, NULL); - + kfree(decoder); return 0; } /* -- cgit v1.2.3 From 2d9329f3a551b50350a15d19edd9ab3df6c6bad0 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Mon, 23 Feb 2009 12:12:58 -0300 Subject: V4L/DVB (10665): soc-camera: add data signal polarity flags to drivers All soc-camera camera and host drivers must specify supported data signal polarity, after all drivers are fixed, we'll add a suitable test to soc_camera_bus_param_compatible(). Signed-off-by: Guennadi Liakhovetski Signed-off-by: Mauro Carvalho Chehab --- arch/sh/boards/board-ap325rxa.c | 3 ++- arch/sh/boards/mach-migor/setup.c | 5 +++-- drivers/media/video/mt9m001.c | 2 +- drivers/media/video/mt9m111.c | 2 +- drivers/media/video/mt9v022.c | 2 +- drivers/media/video/ov772x.c | 2 +- drivers/media/video/pxa_camera.c | 1 + 7 files changed, 10 insertions(+), 7 deletions(-) (limited to 'drivers/media/video') diff --git a/arch/sh/boards/board-ap325rxa.c b/arch/sh/boards/board-ap325rxa.c index a64e38841c49..e27655b8a98d 100644 --- a/arch/sh/boards/board-ap325rxa.c +++ b/arch/sh/boards/board-ap325rxa.c @@ -310,7 +310,8 @@ static struct platform_device camera_device = { static struct sh_mobile_ceu_info sh_mobile_ceu_info = { .flags = SOCAM_PCLK_SAMPLE_RISING | SOCAM_HSYNC_ACTIVE_HIGH | - SOCAM_VSYNC_ACTIVE_HIGH | SOCAM_MASTER | SOCAM_DATAWIDTH_8, + SOCAM_VSYNC_ACTIVE_HIGH | SOCAM_DATA_ACTIVE_HIGH | SOCAM_MASTER | + SOCAM_DATAWIDTH_8, }; static struct resource ceu_resources[] = { diff --git a/arch/sh/boards/mach-migor/setup.c b/arch/sh/boards/mach-migor/setup.c index bc35b4cae6b3..4fd6a727873c 100644 --- a/arch/sh/boards/mach-migor/setup.c +++ b/arch/sh/boards/mach-migor/setup.c @@ -352,8 +352,9 @@ static int tw9910_power(struct device *dev, int mode) } static struct sh_mobile_ceu_info sh_mobile_ceu_info = { - .flags = SOCAM_MASTER | SOCAM_DATAWIDTH_8 | SOCAM_PCLK_SAMPLE_RISING \ - | SOCAM_HSYNC_ACTIVE_HIGH | SOCAM_VSYNC_ACTIVE_HIGH, + .flags = SOCAM_MASTER | SOCAM_DATAWIDTH_8 | SOCAM_PCLK_SAMPLE_RISING + | SOCAM_HSYNC_ACTIVE_HIGH | SOCAM_VSYNC_ACTIVE_HIGH + | SOCAM_DATA_ACTIVE_HIGH, }; static struct resource migor_ceu_resources[] = { diff --git a/drivers/media/video/mt9m001.c b/drivers/media/video/mt9m001.c index c1bf75ef2741..2d1034dad495 100644 --- a/drivers/media/video/mt9m001.c +++ b/drivers/media/video/mt9m001.c @@ -276,7 +276,7 @@ static unsigned long mt9m001_query_bus_param(struct soc_camera_device *icd) /* MT9M001 has all capture_format parameters fixed */ unsigned long flags = SOCAM_DATAWIDTH_10 | SOCAM_PCLK_SAMPLE_RISING | SOCAM_HSYNC_ACTIVE_HIGH | SOCAM_VSYNC_ACTIVE_HIGH | - SOCAM_MASTER; + SOCAM_DATA_ACTIVE_HIGH | SOCAM_MASTER; if (bus_switch_possible(mt9m001)) flags |= SOCAM_DATAWIDTH_8; diff --git a/drivers/media/video/mt9m111.c b/drivers/media/video/mt9m111.c index 5b8e20979cce..6c363af165b7 100644 --- a/drivers/media/video/mt9m111.c +++ b/drivers/media/video/mt9m111.c @@ -420,7 +420,7 @@ static unsigned long mt9m111_query_bus_param(struct soc_camera_device *icd) struct soc_camera_link *icl = mt9m111->client->dev.platform_data; unsigned long flags = SOCAM_MASTER | SOCAM_PCLK_SAMPLE_RISING | SOCAM_HSYNC_ACTIVE_HIGH | SOCAM_VSYNC_ACTIVE_HIGH | - SOCAM_DATAWIDTH_8; + SOCAM_DATA_ACTIVE_HIGH | SOCAM_DATAWIDTH_8; return soc_camera_apply_sensor_flags(icl, flags); } diff --git a/drivers/media/video/mt9v022.c b/drivers/media/video/mt9v022.c index b04c8cb1644d..6eb4b3a818d7 100644 --- a/drivers/media/video/mt9v022.c +++ b/drivers/media/video/mt9v022.c @@ -336,7 +336,7 @@ static unsigned long mt9v022_query_bus_param(struct soc_camera_device *icd) return SOCAM_PCLK_SAMPLE_RISING | SOCAM_PCLK_SAMPLE_FALLING | SOCAM_HSYNC_ACTIVE_HIGH | SOCAM_HSYNC_ACTIVE_LOW | SOCAM_VSYNC_ACTIVE_HIGH | SOCAM_VSYNC_ACTIVE_LOW | - SOCAM_MASTER | SOCAM_SLAVE | + SOCAM_DATA_ACTIVE_HIGH | SOCAM_MASTER | SOCAM_SLAVE | width_flag; } diff --git a/drivers/media/video/ov772x.c b/drivers/media/video/ov772x.c index 3c9e0ba974e9..4d8ac6fd89fb 100644 --- a/drivers/media/video/ov772x.c +++ b/drivers/media/video/ov772x.c @@ -718,7 +718,7 @@ static unsigned long ov772x_query_bus_param(struct soc_camera_device *icd) struct soc_camera_link *icl = priv->client->dev.platform_data; unsigned long flags = SOCAM_PCLK_SAMPLE_RISING | SOCAM_MASTER | SOCAM_VSYNC_ACTIVE_HIGH | SOCAM_HSYNC_ACTIVE_HIGH | - priv->info->buswidth; + SOCAM_DATA_ACTIVE_HIGH | priv->info->buswidth; return soc_camera_apply_sensor_flags(icl, flags); } diff --git a/drivers/media/video/pxa_camera.c b/drivers/media/video/pxa_camera.c index 0c4ce58c53d5..2cc203cfbe6c 100644 --- a/drivers/media/video/pxa_camera.c +++ b/drivers/media/video/pxa_camera.c @@ -878,6 +878,7 @@ static int test_platform_param(struct pxa_camera_dev *pcdev, SOCAM_HSYNC_ACTIVE_LOW | SOCAM_VSYNC_ACTIVE_HIGH | SOCAM_VSYNC_ACTIVE_LOW | + SOCAM_DATA_ACTIVE_HIGH | SOCAM_PCLK_SAMPLE_RISING | SOCAM_PCLK_SAMPLE_FALLING; -- cgit v1.2.3 From 2941e81f64c2c3f99d03be09790f610dd6fedf64 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 23 Feb 2009 12:12:58 -0300 Subject: V4L/DVB (10666): ov772x: move configuration from start_capture() to set_fmt() soc_camera framework requires, that camera configuration is performed in set_fmt, and start_capture and stop_capture only turn the camera on/off. This patch modifies ov772x to comply to this requirement. Signed-off-by: Kuninori Morimoto Signed-off-by: Guennadi Liakhovetski Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/ov772x.c | 125 +++++++++++++++++++++---------------------- 1 file changed, 62 insertions(+), 63 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/ov772x.c b/drivers/media/video/ov772x.c index 4d8ac6fd89fb..4d54e1899571 100644 --- a/drivers/media/video/ov772x.c +++ b/drivers/media/video/ov772x.c @@ -500,9 +500,8 @@ static const struct soc_camera_data_format ov772x_fmt_lists[] = { /* * color format list */ -#define T_YUYV 0 static const struct ov772x_color_format ov772x_cfmts[] = { - [T_YUYV] = { + { SETFOURCC(YUYV), .regs = ov772x_YYUV_regs, }, @@ -635,74 +634,20 @@ static int ov772x_release(struct soc_camera_device *icd) static int ov772x_start_capture(struct soc_camera_device *icd) { struct ov772x_priv *priv = container_of(icd, struct ov772x_priv, icd); - int ret; - - if (!priv->win) - priv->win = &ov772x_win_vga; - if (!priv->fmt) - priv->fmt = &ov772x_cfmts[T_YUYV]; - - /* - * reset hardware - */ - ov772x_reset(priv->client); - - /* - * set color format - */ - ret = ov772x_write_array(priv->client, priv->fmt->regs); - if (ret < 0) - goto start_end; - - /* - * set size format - */ - ret = ov772x_write_array(priv->client, priv->win->regs); - if (ret < 0) - goto start_end; - - /* - * set COM7 bit ( QVGA or VGA ) - */ - ret = ov772x_mask_set(priv->client, - COM7, SLCT_MASK, priv->win->com7_bit); - if (ret < 0) - goto start_end; - /* - * set UV setting - */ - if (priv->fmt->option & OP_UV) { - ret = ov772x_mask_set(priv->client, - DSP_CTRL3, UV_MASK, UV_ON); - if (ret < 0) - goto start_end; - } - - /* - * set SWAP setting - */ - if (priv->fmt->option & OP_SWAP_RGB) { - ret = ov772x_mask_set(priv->client, - COM3, SWAP_MASK, SWAP_RGB); - if (ret < 0) - goto start_end; + if (!priv->win || !priv->fmt) { + dev_err(&icd->dev, "norm or win select error\n"); + return -EPERM; } dev_dbg(&icd->dev, "format %s, win %s\n", priv->fmt->name, priv->win->name); -start_end: - priv->fmt = NULL; - priv->win = NULL; - - return ret; + return 0; } static int ov772x_stop_capture(struct soc_camera_device *icd) { - struct ov772x_priv *priv = container_of(icd, struct ov772x_priv, icd); - ov772x_reset(priv->client); return 0; } @@ -787,7 +732,6 @@ ov772x_select_win(u32 width, u32 height) return win; } - static int ov772x_set_fmt(struct soc_camera_device *icd, __u32 pixfmt, struct v4l2_rect *rect) @@ -803,16 +747,72 @@ static int ov772x_set_fmt(struct soc_camera_device *icd, for (i = 0; i < ARRAY_SIZE(ov772x_cfmts); i++) { if (pixfmt == ov772x_cfmts[i].fourcc) { priv->fmt = ov772x_cfmts + i; - ret = 0; break; } } + if (!priv->fmt) + goto ov772x_set_fmt_error; /* * select win */ priv->win = ov772x_select_win(rect->width, rect->height); + /* + * reset hardware + */ + ov772x_reset(priv->client); + + /* + * set color format + */ + ret = ov772x_write_array(priv->client, priv->fmt->regs); + if (ret < 0) + goto ov772x_set_fmt_error; + + /* + * set size format + */ + ret = ov772x_write_array(priv->client, priv->win->regs); + if (ret < 0) + goto ov772x_set_fmt_error; + + /* + * set COM7 bit ( QVGA or VGA ) + */ + ret = ov772x_mask_set(priv->client, + COM7, SLCT_MASK, priv->win->com7_bit); + if (ret < 0) + goto ov772x_set_fmt_error; + + /* + * set UV setting + */ + if (priv->fmt->option & OP_UV) { + ret = ov772x_mask_set(priv->client, + DSP_CTRL3, UV_MASK, UV_ON); + if (ret < 0) + goto ov772x_set_fmt_error; + } + + /* + * set SWAP setting + */ + if (priv->fmt->option & OP_SWAP_RGB) { + ret = ov772x_mask_set(priv->client, + COM3, SWAP_MASK, SWAP_RGB); + if (ret < 0) + goto ov772x_set_fmt_error; + } + + return ret; + +ov772x_set_fmt_error: + + ov772x_reset(priv->client); + priv->win = NULL; + priv->fmt = NULL; + return ret; } @@ -889,7 +889,6 @@ static int ov772x_video_probe(struct soc_camera_device *icd) i2c_smbus_read_byte_data(priv->client, MIDH), i2c_smbus_read_byte_data(priv->client, MIDL)); - return soc_camera_video_start(icd); } -- cgit v1.2.3 From cdce7c0be2b3377cc389dc03cc855f3d2e452df3 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 23 Feb 2009 12:12:58 -0300 Subject: V4L/DVB (10667): ov772x: setting method to register is changed. Color format regs array had been used, but it was not easy to understand what to want to do, and additional bit became complex. This patch modify this problem. Signed-off-by: Kuninori Morimoto Signed-off-by: Guennadi Liakhovetski Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/ov772x.c | 121 +++++++++++++++++-------------------------- 1 file changed, 48 insertions(+), 73 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/ov772x.c b/drivers/media/video/ov772x.c index 4d54e1899571..702e61a9c02b 100644 --- a/drivers/media/video/ov772x.c +++ b/drivers/media/video/ov772x.c @@ -271,11 +271,13 @@ #define SLCT_QVGA 0x40 /* 1 : QVGA */ #define ITU656_ON_OFF 0x20 /* ITU656 protocol ON/OFF selection */ /* RGB output format control */ +#define FMT_MASK 0x0c /* Mask of color format */ #define FMT_GBR422 0x00 /* 00 : GBR 4:2:2 */ #define FMT_RGB565 0x04 /* 01 : RGB 565 */ #define FMT_RGB555 0x08 /* 10 : RGB 555 */ #define FMT_RGB444 0x0c /* 11 : RGB 444 */ /* Output format control */ +#define OFMT_MASK 0x03 /* Mask of output format */ #define OFMT_YUV 0x00 /* 00 : YUV */ #define OFMT_P_BRAW 0x01 /* 01 : Processed Bayer RAW */ #define OFMT_RGB 0x02 /* 10 : RGB */ @@ -299,7 +301,7 @@ #define GAIN_2x 0x00 /* 000 : 2x */ #define GAIN_4x 0x10 /* 001 : 4x */ #define GAIN_8x 0x20 /* 010 : 8x */ -#define GAIN_16x 0x30 /* 011 : 16x */ +#define GAIN_16x 0x30 /* 011 : 16x */ #define GAIN_32x 0x40 /* 100 : 32x */ #define GAIN_64x 0x50 /* 101 : 64x */ #define GAIN_128x 0x60 /* 110 : 128x */ @@ -355,13 +357,6 @@ #define VOSZ_VGA 0xF0 #define VOSZ_QVGA 0x78 -/* - * bit configure (32 bit) - * this is used in struct ov772x_color_format :: option - */ -#define OP_UV 0x00000001 -#define OP_SWAP_RGB 0x00000002 - /* * ID */ @@ -380,8 +375,9 @@ struct regval_list { struct ov772x_color_format { char *name; __u32 fourcc; - const struct regval_list *regs; - unsigned int option; + u8 dsp3; + u8 com3; + u8 com7; }; struct ov772x_win_size { @@ -403,34 +399,6 @@ struct ov772x_priv { #define ENDMARKER { 0xff, 0xff } -/* - * register setting for color format - */ -static const struct regval_list ov772x_RGB555_regs[] = { - { COM3, 0x00 }, - { COM7, FMT_RGB555 | OFMT_RGB }, - ENDMARKER, -}; - -static const struct regval_list ov772x_RGB565_regs[] = { - { COM3, 0x00 }, - { COM7, FMT_RGB565 | OFMT_RGB }, - ENDMARKER, -}; - -static const struct regval_list ov772x_YYUV_regs[] = { - { COM3, SWAP_YUV }, - { COM7, OFMT_YUV }, - ENDMARKER, -}; - -static const struct regval_list ov772x_UVYY_regs[] = { - { COM3, 0x00 }, - { COM7, OFMT_YUV }, - ENDMARKER, -}; - - /* * register setting for window size */ @@ -503,34 +471,45 @@ static const struct soc_camera_data_format ov772x_fmt_lists[] = { static const struct ov772x_color_format ov772x_cfmts[] = { { SETFOURCC(YUYV), - .regs = ov772x_YYUV_regs, + .dsp3 = 0x0, + .com3 = SWAP_YUV, + .com7 = OFMT_YUV, }, { SETFOURCC(YVYU), - .regs = ov772x_YYUV_regs, - .option = OP_UV, + .dsp3 = UV_ON, + .com3 = SWAP_YUV, + .com7 = OFMT_YUV, }, { SETFOURCC(UYVY), - .regs = ov772x_UVYY_regs, + .dsp3 = 0x0, + .com3 = 0x0, + .com7 = OFMT_YUV, }, { SETFOURCC(RGB555), - .regs = ov772x_RGB555_regs, - .option = OP_SWAP_RGB, + .dsp3 = 0x0, + .com3 = SWAP_RGB, + .com7 = FMT_RGB555 | OFMT_RGB, }, { SETFOURCC(RGB555X), - .regs = ov772x_RGB555_regs, + .dsp3 = 0x0, + .com3 = 0x0, + .com7 = FMT_RGB555 | OFMT_RGB, }, { SETFOURCC(RGB565), - .regs = ov772x_RGB565_regs, - .option = OP_SWAP_RGB, + .dsp3 = 0x0, + .com3 = SWAP_RGB, + .com7 = FMT_RGB565 | OFMT_RGB, }, { SETFOURCC(RGB565X), - .regs = ov772x_RGB565_regs, + .dsp3 = 0x0, + .com3 = 0x0, + .com7 = FMT_RGB565 | OFMT_RGB, }, }; @@ -738,6 +717,7 @@ static int ov772x_set_fmt(struct soc_camera_device *icd, { struct ov772x_priv *priv = container_of(icd, struct ov772x_priv, icd); int ret = -EINVAL; + u8 val; int i; /* @@ -763,13 +743,6 @@ static int ov772x_set_fmt(struct soc_camera_device *icd, */ ov772x_reset(priv->client); - /* - * set color format - */ - ret = ov772x_write_array(priv->client, priv->fmt->regs); - if (ret < 0) - goto ov772x_set_fmt_error; - /* * set size format */ @@ -778,32 +751,34 @@ static int ov772x_set_fmt(struct soc_camera_device *icd, goto ov772x_set_fmt_error; /* - * set COM7 bit ( QVGA or VGA ) + * set DSP_CTRL3 */ - ret = ov772x_mask_set(priv->client, - COM7, SLCT_MASK, priv->win->com7_bit); - if (ret < 0) - goto ov772x_set_fmt_error; - - /* - * set UV setting - */ - if (priv->fmt->option & OP_UV) { + val = priv->fmt->dsp3; + if (val) { ret = ov772x_mask_set(priv->client, - DSP_CTRL3, UV_MASK, UV_ON); + DSP_CTRL3, UV_MASK, val); if (ret < 0) goto ov772x_set_fmt_error; } /* - * set SWAP setting + * set COM3 */ - if (priv->fmt->option & OP_SWAP_RGB) { - ret = ov772x_mask_set(priv->client, - COM3, SWAP_MASK, SWAP_RGB); - if (ret < 0) - goto ov772x_set_fmt_error; - } + val = priv->fmt->com3; + ret = ov772x_mask_set(priv->client, + COM3, SWAP_MASK, val); + if (ret < 0) + goto ov772x_set_fmt_error; + + /* + * set COM7 + */ + val = priv->win->com7_bit | priv->fmt->com7; + ret = ov772x_mask_set(priv->client, + COM7, (SLCT_MASK | FMT_MASK | OFMT_MASK), + val); + if (ret < 0) + goto ov772x_set_fmt_error; return ret; -- cgit v1.2.3 From 66b46e68a52114e7065f0bfd0016276ae5925e70 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 23 Feb 2009 12:12:58 -0300 Subject: V4L/DVB (10668): ov772x: bit mask operation fix on ov772x_mask_set. Signed-off-by: Kuninori Morimoto Signed-off-by: Guennadi Liakhovetski Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/ov772x.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/ov772x.c b/drivers/media/video/ov772x.c index 702e61a9c02b..6b18da7c3c0a 100644 --- a/drivers/media/video/ov772x.c +++ b/drivers/media/video/ov772x.c @@ -565,8 +565,11 @@ static int ov772x_mask_set(struct i2c_client *client, u8 set) { s32 val = i2c_smbus_read_byte_data(client, command); + if (val < 0) + return val; + val &= ~mask; - val |= set; + val |= set & mask; return i2c_smbus_write_byte_data(client, command, val); } -- cgit v1.2.3 From 051489119affd527f2834e9f8ba3e2a71bf1ca23 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 23 Feb 2009 12:12:58 -0300 Subject: V4L/DVB (10669): ov772x: Add image flip support o ov772x_camera_info :: flags supports default image flip. o V4L2_CID_VFLIP/HFLIP supports image flip for user side. Thank Magnus for advice. Signed-off-by: Kuninori Morimoto Signed-off-by: Guennadi Liakhovetski Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/ov772x.c | 88 ++++++++++++++++++++++++++++++++++++++++++-- include/media/ov772x.h | 5 +++ 2 files changed, 89 insertions(+), 4 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/ov772x.c b/drivers/media/video/ov772x.c index 6b18da7c3c0a..880e51f0e9fd 100644 --- a/drivers/media/video/ov772x.c +++ b/drivers/media/video/ov772x.c @@ -217,10 +217,11 @@ #define OCAP_4x 0x03 /* 4x */ /* COM3 */ -#define SWAP_MASK 0x38 +#define SWAP_MASK (SWAP_RGB | SWAP_YUV | SWAP_ML) +#define IMG_MASK (VFLIP_IMG | HFLIP_IMG) -#define VFIMG_ON_OFF 0x80 /* Vertical flip image ON/OFF selection */ -#define HMIMG_ON_OFF 0x40 /* Horizontal mirror image ON/OFF selection */ +#define VFLIP_IMG 0x80 /* Vertical flip image ON/OFF selection */ +#define HFLIP_IMG 0x40 /* Horizontal mirror image ON/OFF selection */ #define SWAP_RGB 0x20 /* Swap B/R output sequence in RGB mode */ #define SWAP_YUV 0x10 /* Swap Y/UV output sequence in YUV mode */ #define SWAP_ML 0x08 /* Swap output MSB/LSB */ @@ -395,6 +396,8 @@ struct ov772x_priv { const struct ov772x_color_format *fmt; const struct ov772x_win_size *win; int model; + unsigned int flag_vflip:1; + unsigned int flag_hflip:1; }; #define ENDMARKER { 0xff, 0xff } @@ -540,6 +543,27 @@ static const struct ov772x_win_size ov772x_win_qvga = { .regs = ov772x_qvga_regs, }; +static const struct v4l2_queryctrl ov772x_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, + }, +}; + /* * general function @@ -650,6 +674,49 @@ static unsigned long ov772x_query_bus_param(struct soc_camera_device *icd) return soc_camera_apply_sensor_flags(icl, flags); } +static int ov772x_get_control(struct soc_camera_device *icd, + struct v4l2_control *ctrl) +{ + struct ov772x_priv *priv = container_of(icd, struct ov772x_priv, icd); + + switch (ctrl->id) { + case V4L2_CID_VFLIP: + ctrl->value = priv->flag_vflip; + break; + case V4L2_CID_HFLIP: + ctrl->value = priv->flag_hflip; + break; + } + return 0; +} + +static int ov772x_set_control(struct soc_camera_device *icd, + struct v4l2_control *ctrl) +{ + struct ov772x_priv *priv = container_of(icd, struct ov772x_priv, icd); + int ret = 0; + u8 val; + + switch (ctrl->id) { + case V4L2_CID_VFLIP: + val = ctrl->value ? VFLIP_IMG : 0x00; + priv->flag_vflip = ctrl->value; + if (priv->info->flags & OV772X_FLAG_VFLIP) + val ^= VFLIP_IMG; + ret = ov772x_mask_set(priv->client, COM3, VFLIP_IMG, val); + break; + case V4L2_CID_HFLIP: + val = ctrl->value ? HFLIP_IMG : 0x00; + priv->flag_hflip = ctrl->value; + if (priv->info->flags & OV772X_FLAG_HFLIP) + val ^= HFLIP_IMG; + ret = ov772x_mask_set(priv->client, COM3, HFLIP_IMG, val); + break; + } + + return ret; +} + static int ov772x_get_chip_id(struct soc_camera_device *icd, struct v4l2_dbg_chip_ident *id) { @@ -768,8 +835,17 @@ static int ov772x_set_fmt(struct soc_camera_device *icd, * set COM3 */ val = priv->fmt->com3; + if (priv->info->flags & OV772X_FLAG_VFLIP) + val |= VFLIP_IMG; + if (priv->info->flags & OV772X_FLAG_HFLIP) + val |= HFLIP_IMG; + if (priv->flag_vflip) + val ^= VFLIP_IMG; + if (priv->flag_hflip) + val ^= HFLIP_IMG; + ret = ov772x_mask_set(priv->client, - COM3, SWAP_MASK, val); + COM3, SWAP_MASK | IMG_MASK, val); if (ret < 0) goto ov772x_set_fmt_error; @@ -887,6 +963,10 @@ static struct soc_camera_ops ov772x_ops = { .try_fmt = ov772x_try_fmt, .set_bus_param = ov772x_set_bus_param, .query_bus_param = ov772x_query_bus_param, + .controls = ov772x_controls, + .num_controls = ARRAY_SIZE(ov772x_controls), + .get_control = ov772x_get_control, + .set_control = ov772x_set_control, .get_chip_id = ov772x_get_chip_id, #ifdef CONFIG_VIDEO_ADV_DEBUG .get_register = ov772x_get_register, diff --git a/include/media/ov772x.h b/include/media/ov772x.h index e391d55edb95..57db48dd85b8 100644 --- a/include/media/ov772x.h +++ b/include/media/ov772x.h @@ -13,8 +13,13 @@ #include +/* for flags */ +#define OV772X_FLAG_VFLIP 0x00000001 /* Vertical flip image */ +#define OV772X_FLAG_HFLIP 0x00000002 /* Horizontal flip image */ + struct ov772x_camera_info { unsigned long buswidth; + unsigned long flags; struct soc_camera_link link; }; -- cgit v1.2.3 From 1af1b7a2def2f0936fc95edb5dcb3871934b7852 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 23 Feb 2009 12:12:58 -0300 Subject: V4L/DVB (10670): tw9910: bit mask operation fix on tw9910_mask_set. Signed-off-by: Kuninori Morimoto Signed-off-by: Guennadi Liakhovetski Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/tw9910.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/tw9910.c b/drivers/media/video/tw9910.c index 8dc3ec79a06f..0558b22fd3fb 100644 --- a/drivers/media/video/tw9910.c +++ b/drivers/media/video/tw9910.c @@ -460,9 +460,11 @@ static int tw9910_mask_set(struct i2c_client *client, u8 command, u8 mask, u8 set) { s32 val = i2c_smbus_read_byte_data(client, command); + if (val < 0) + return val; val &= ~mask; - val |= set; + val |= set & mask; return i2c_smbus_write_byte_data(client, command, val); } -- cgit v1.2.3 From c354b400c0eac1cc0009958754797538857ce640 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 23 Feb 2009 12:12:58 -0300 Subject: V4L/DVB (10671): sh_mobile_ceu: SOCAM flags are not platform dependent sh_mobile_ceu_camera.c support for signal polarity flags isn't platform dependent, provide them locally. Only the bus width is implementation specific. Signed-off-by: Kuninori Morimoto Acked-by: Magnus Damm Signed-off-by: Guennadi Liakhovetski Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/sh_mobile_ceu_camera.c | 28 ++++++++++++++++++++++++++-- include/media/sh_mobile_ceu.h | 5 +++-- 2 files changed, 29 insertions(+), 4 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/sh_mobile_ceu_camera.c b/drivers/media/video/sh_mobile_ceu_camera.c index ddcb81d0b81a..8a1badba70f7 100644 --- a/drivers/media/video/sh_mobile_ceu_camera.c +++ b/drivers/media/video/sh_mobile_ceu_camera.c @@ -101,6 +101,30 @@ struct sh_mobile_ceu_dev { const struct soc_camera_data_format *camera_fmt; }; +static unsigned long make_bus_param(struct sh_mobile_ceu_dev *pcdev) +{ + unsigned long flags; + + flags = SOCAM_MASTER | + SOCAM_PCLK_SAMPLE_RISING | + SOCAM_HSYNC_ACTIVE_HIGH | + SOCAM_HSYNC_ACTIVE_LOW | + SOCAM_VSYNC_ACTIVE_HIGH | + SOCAM_VSYNC_ACTIVE_LOW | + SOCAM_DATA_ACTIVE_HIGH; + + if (pcdev->pdata->flags & SH_CEU_FLAG_USE_8BIT_BUS) + flags |= SOCAM_DATAWIDTH_8; + + if (pcdev->pdata->flags & SH_CEU_FLAG_USE_16BIT_BUS) + flags |= SOCAM_DATAWIDTH_16; + + if (flags & SOCAM_DATAWIDTH_MASK) + return flags; + + return 0; +} + static void ceu_write(struct sh_mobile_ceu_dev *priv, unsigned long reg_offs, u32 data) { @@ -396,7 +420,7 @@ static int sh_mobile_ceu_set_bus_param(struct soc_camera_device *icd, camera_flags = icd->ops->query_bus_param(icd); common_flags = soc_camera_bus_param_compatible(camera_flags, - pcdev->pdata->flags); + make_bus_param(pcdev)); if (!common_flags) return -EINVAL; @@ -517,7 +541,7 @@ static int sh_mobile_ceu_try_bus_param(struct soc_camera_device *icd) camera_flags = icd->ops->query_bus_param(icd); common_flags = soc_camera_bus_param_compatible(camera_flags, - pcdev->pdata->flags); + make_bus_param(pcdev)); if (!common_flags) return -EINVAL; diff --git a/include/media/sh_mobile_ceu.h b/include/media/sh_mobile_ceu.h index b5dbefea3740..0f3524cff435 100644 --- a/include/media/sh_mobile_ceu.h +++ b/include/media/sh_mobile_ceu.h @@ -1,10 +1,11 @@ #ifndef __ASM_SH_MOBILE_CEU_H__ #define __ASM_SH_MOBILE_CEU_H__ -#include +#define SH_CEU_FLAG_USE_8BIT_BUS (1 << 0) /* use 8bit bus width */ +#define SH_CEU_FLAG_USE_16BIT_BUS (1 << 1) /* use 16bit bus width */ struct sh_mobile_ceu_info { - unsigned long flags; /* SOCAM_... */ + unsigned long flags; }; #endif /* __ASM_SH_MOBILE_CEU_H__ */ -- cgit v1.2.3 From c8329accf7e75a8a8fbe4ad0a15a3eacf221f380 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Mon, 23 Feb 2009 12:12:58 -0300 Subject: V4L/DVB (10672): sh_mobile_ceu_camera: include NV* formats into the format list only once. Currently, if an soc-camera device, connected to the sh_mobile_ceu_camera camera host driver, supports several formats from the UYVY, VYUY, YUYV, YVYU set, the driver would add four NV* formats for each of them. This patch fixes this misbehaviour. Reported-by: Kuninori Morimoto Signed-off-by: Guennadi Liakhovetski Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/sh_mobile_ceu_camera.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) (limited to 'drivers/media/video') diff --git a/drivers/media/video/sh_mobile_ceu_camera.c b/drivers/media/video/sh_mobile_ceu_camera.c index 8a1badba70f7..ed3bfc4cf9f9 100644 --- a/drivers/media/video/sh_mobile_ceu_camera.c +++ b/drivers/media/video/sh_mobile_ceu_camera.c @@ -586,11 +586,29 @@ static int sh_mobile_ceu_get_formats(struct soc_camera_device *icd, int idx, if (ret < 0) return 0; + /* Beginning of a pass */ + if (!idx) + icd->host_priv = NULL; + switch (icd->formats[idx].fourcc) { case V4L2_PIX_FMT_UYVY: case V4L2_PIX_FMT_VYUY: case V4L2_PIX_FMT_YUYV: case V4L2_PIX_FMT_YVYU: + if (icd->host_priv) + goto add_single_format; + + /* + * Our case is simple so far: for any of the above four camera + * formats we add all our four synthesized NV* formats, so, + * just marking the device with a single flag suffices. If + * the format generation rules are more complex, you would have + * to actually hang your already added / counted formats onto + * the host_priv pointer and check whether the format you're + * going to add now is already there. + */ + icd->host_priv = (void *)sh_mobile_ceu_formats; + n = ARRAY_SIZE(sh_mobile_ceu_formats); formats += n; for (k = 0; xlate && k < n; k++) { @@ -603,6 +621,7 @@ static int sh_mobile_ceu_get_formats(struct soc_camera_device *icd, int idx, icd->formats[idx].name); } default: +add_single_format: /* Generic pass-through */ formats++; if (xlate) { -- cgit v1.2.3 From 70e1d353e5d70551c5f69d464c4d194afae62f63 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Mon, 23 Feb 2009 12:13:23 -0300 Subject: V4L/DVB (10673): mt9t031: fix gain and hflip controls, register update, and scaling Multiple fixes: 1. allow register update by setting the Output Control register to 2 and not 3 2. fix scaling factor calculations 3. recover lost HFLIP control 4. fix Global Gain calculation Signed-off-by: Guennadi Liakhovetski Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/mt9t031.c | 127 ++++++++++++++++++++++++++++-------------- 1 file changed, 84 insertions(+), 43 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/mt9t031.c b/drivers/media/video/mt9t031.c index 349d8e365530..acc1fa9db67d 100644 --- a/drivers/media/video/mt9t031.c +++ b/drivers/media/video/mt9t031.c @@ -150,7 +150,7 @@ static int mt9t031_init(struct soc_camera_device *icd) if (ret >= 0) ret = reg_write(icd, MT9T031_RESET, 0); if (ret >= 0) - ret = reg_clear(icd, MT9T031_OUTPUT_CONTROL, 3); + ret = reg_clear(icd, MT9T031_OUTPUT_CONTROL, 2); return ret >= 0 ? 0 : -EIO; } @@ -158,14 +158,14 @@ static int mt9t031_init(struct soc_camera_device *icd) static int mt9t031_release(struct soc_camera_device *icd) { /* Disable the chip */ - reg_clear(icd, MT9T031_OUTPUT_CONTROL, 3); + reg_clear(icd, MT9T031_OUTPUT_CONTROL, 2); return 0; } static int mt9t031_start_capture(struct soc_camera_device *icd) { /* Switch to master "normal" mode */ - if (reg_set(icd, MT9T031_OUTPUT_CONTROL, 3) < 0) + if (reg_set(icd, MT9T031_OUTPUT_CONTROL, 2) < 0) return -EIO; return 0; } @@ -173,7 +173,7 @@ static int mt9t031_start_capture(struct soc_camera_device *icd) static int mt9t031_stop_capture(struct soc_camera_device *icd) { /* Stop sensor readout */ - if (reg_clear(icd, MT9T031_OUTPUT_CONTROL, 3) < 0) + if (reg_clear(icd, MT9T031_OUTPUT_CONTROL, 2) < 0) return -EIO; return 0; } @@ -201,6 +201,18 @@ static unsigned long mt9t031_query_bus_param(struct soc_camera_device *icd) return soc_camera_apply_sensor_flags(icl, MT9T031_BUS_PARAM); } +/* Round up minima and round down maxima */ +static void recalculate_limits(struct soc_camera_device *icd, + u16 xskip, u16 yskip) +{ + icd->x_min = (MT9T031_COLUMN_SKIP + xskip - 1) / xskip; + icd->y_min = (MT9T031_ROW_SKIP + yskip - 1) / yskip; + icd->width_min = (MT9T031_MIN_WIDTH + xskip - 1) / xskip; + icd->height_min = (MT9T031_MIN_HEIGHT + yskip - 1) / yskip; + icd->width_max = MT9T031_MAX_WIDTH / xskip; + icd->height_max = MT9T031_MAX_HEIGHT / yskip; +} + static int mt9t031_set_fmt(struct soc_camera_device *icd, __u32 pixfmt, struct v4l2_rect *rect) { @@ -208,54 +220,70 @@ static int mt9t031_set_fmt(struct soc_camera_device *icd, int ret; const u16 hblank = MT9T031_HORIZONTAL_BLANK, vblank = MT9T031_VERTICAL_BLANK; - u16 xbin, xskip = mt9t031->xskip, ybin, yskip = mt9t031->yskip, - width = rect->width * xskip, height = rect->height * yskip; + u16 xbin, xskip, ybin, yskip, width, height, left, top; if (pixfmt) { - /* S_FMT - use binning and skipping for scaling, recalculate */ + /* + * try_fmt has put rectangle within limits. + * S_FMT - use binning and skipping for scaling, recalculate + * limits, used for cropping + */ /* Is this more optimal than just a division? */ for (xskip = 8; xskip > 1; xskip--) - if (rect->width * xskip <= icd->width_max) + if (rect->width * xskip <= MT9T031_MAX_WIDTH) break; for (yskip = 8; yskip > 1; yskip--) - if (rect->height * yskip <= icd->height_max) + if (rect->height * yskip <= MT9T031_MAX_HEIGHT) break; - width = rect->width * xskip; - height = rect->height * yskip; - - dev_dbg(&icd->dev, "xskip %u, width %u, yskip %u, height %u\n", - xskip, width, yskip, height); + recalculate_limits(icd, xskip, yskip); + } else { + /* CROP - no change in scaling, or in limits */ + xskip = mt9t031->xskip; + yskip = mt9t031->yskip; } + /* Make sure we don't exceed sensor limits */ + if (rect->left + rect->width > icd->width_max) + rect->left = (icd->width_max - rect->width) / 2 + icd->x_min; + + if (rect->top + rect->height > icd->height_max) + rect->top = (icd->height_max - rect->height) / 2 + icd->y_min; + + width = rect->width * xskip; + height = rect->height * yskip; + left = rect->left * xskip; + top = rect->top * yskip; + xbin = min(xskip, (u16)3); ybin = min(yskip, (u16)3); - /* Make sure we don't exceed frame limits */ - if (rect->left + width > icd->width_max) - rect->left = (icd->width_max - width) / 2; + dev_dbg(&icd->dev, "xskip %u, width %u/%u, yskip %u, height %u/%u\n", + xskip, width, rect->width, yskip, height, rect->height); - if (rect->top + height > icd->height_max) - rect->top = (icd->height_max - height) / 2; - - /* Could just do roundup(rect->left, [xy]bin); but this is cheaper */ + /* Could just do roundup(rect->left, [xy]bin * 2); but this is cheaper */ switch (xbin) { case 2: - rect->left = (rect->left + 1) & ~1; + left = (left + 3) & ~3; break; case 3: - rect->left = roundup(rect->left, 3); + left = roundup(left, 6); } switch (ybin) { case 2: - rect->top = (rect->top + 1) & ~1; + top = (top + 3) & ~3; break; case 3: - rect->top = roundup(rect->top, 3); + top = roundup(top, 6); } + /* Disable register update, reconfigure atomically */ + ret = reg_set(icd, MT9T031_OUTPUT_CONTROL, 1); + if (ret < 0) + return ret; + /* Blanking and start values - default... */ ret = reg_write(icd, MT9T031_HORIZONTAL_BLANKING, hblank); if (ret >= 0) @@ -270,14 +298,14 @@ static int mt9t031_set_fmt(struct soc_camera_device *icd, ret = reg_write(icd, MT9T031_ROW_ADDRESS_MODE, ((ybin - 1) << 4) | (yskip - 1)); } - dev_dbg(&icd->dev, "new left %u, top %u\n", rect->left, rect->top); + dev_dbg(&icd->dev, "new physical left %u, top %u\n", left, top); /* The caller provides a supported format, as guaranteed by * icd->try_fmt_cap(), soc_camera_s_crop() and soc_camera_cropcap() */ if (ret >= 0) - ret = reg_write(icd, MT9T031_COLUMN_START, rect->left); + ret = reg_write(icd, MT9T031_COLUMN_START, left); if (ret >= 0) - ret = reg_write(icd, MT9T031_ROW_START, rect->top); + ret = reg_write(icd, MT9T031_ROW_START, top); if (ret >= 0) ret = reg_write(icd, MT9T031_WINDOW_WIDTH, width - 1); if (ret >= 0) @@ -302,6 +330,9 @@ static int mt9t031_set_fmt(struct soc_camera_device *icd, mt9t031->yskip = yskip; } + /* Re-enable register update, commit all changes */ + reg_clear(icd, MT9T031_OUTPUT_CONTROL, 1); + return ret < 0 ? ret : 0; } @@ -310,14 +341,14 @@ static int mt9t031_try_fmt(struct soc_camera_device *icd, { struct v4l2_pix_format *pix = &f->fmt.pix; - if (pix->height < icd->height_min) - pix->height = icd->height_min; - if (pix->height > icd->height_max) - pix->height = icd->height_max; - if (pix->width < icd->width_min) - pix->width = icd->width_min; - if (pix->width > icd->width_max) - pix->width = icd->width_max; + if (pix->height < MT9T031_MIN_HEIGHT) + pix->height = MT9T031_MIN_HEIGHT; + if (pix->height > MT9T031_MAX_HEIGHT) + pix->height = MT9T031_MAX_HEIGHT; + if (pix->width < MT9T031_MIN_WIDTH) + pix->width = MT9T031_MIN_WIDTH; + if (pix->width > MT9T031_MAX_WIDTH) + pix->width = MT9T031_MAX_WIDTH; pix->width &= ~0x01; /* has to be even */ pix->height &= ~0x01; /* has to be even */ @@ -389,6 +420,14 @@ static const struct v4l2_queryctrl mt9t031_controls[] = { .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, @@ -513,21 +552,23 @@ static int mt9t031_set_control(struct soc_camera_device *icd, struct v4l2_contro if (data < 0) return -EIO; } else { - /* Pack it into 1.125..15 variable step, register values 9..67 */ + /* Pack it into 1.125..128 variable step, register values 9..0x7860 */ /* We assume qctrl->maximum - qctrl->default_value - 1 > 0 */ unsigned long range = qctrl->maximum - qctrl->default_value - 1; + /* calculated gain: map 65..127 to 9..1024 step 0.125 */ unsigned long gain = ((ctrl->value - qctrl->default_value - 1) * - 111 + range / 2) / range + 9; + 1015 + range / 2) / range + 9; - if (gain <= 32) + if (gain <= 32) /* calculated gain 9..32 -> 9..32 */ data = gain; - else if (gain <= 64) + else if (gain <= 64) /* calculated gain 33..64 -> 0x51..0x60 */ data = ((gain - 32) * 16 + 16) / 32 + 80; else - data = ((gain - 64) * 7 + 28) / 56 + 96; + /* calculated gain 65..1024 -> (1..120) << 8 + 0x60 */ + data = (((gain - 64 + 7) * 32) & 0xff00) | 0x60; - dev_dbg(&icd->dev, "Setting gain from %d to %d\n", - reg_read(icd, MT9T031_GLOBAL_GAIN), data); + dev_dbg(&icd->dev, "Setting gain from 0x%x to 0x%x\n", + reg_read(icd, MT9T031_GLOBAL_GAIN), data); data = reg_write(icd, MT9T031_GLOBAL_GAIN, data); if (data < 0) return -EIO; -- cgit v1.2.3 From 4f67130ad35d6760c27984cf94b13a8cb85e4034 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Mon, 23 Feb 2009 12:13:24 -0300 Subject: V4L/DVB (10674): soc-camera: camera host driver for i.MX3x SoCs Tested with 8 bit Bayer and 8 bit monochrome video. create mode 100644 arch/arm/plat-mxc/include/mach/mx3_camera.h create mode 100644 drivers/media/video/mx3_camera.c Signed-off-by: Guennadi Liakhovetski Signed-off-by: Mauro Carvalho Chehab --- arch/arm/plat-mxc/include/mach/mx3_camera.h | 52 ++ drivers/media/video/Kconfig | 7 + drivers/media/video/Makefile | 5 +- drivers/media/video/mx3_camera.c | 1183 +++++++++++++++++++++++++++ 4 files changed, 1245 insertions(+), 2 deletions(-) create mode 100644 arch/arm/plat-mxc/include/mach/mx3_camera.h create mode 100644 drivers/media/video/mx3_camera.c (limited to 'drivers/media/video') diff --git a/arch/arm/plat-mxc/include/mach/mx3_camera.h b/arch/arm/plat-mxc/include/mach/mx3_camera.h new file mode 100644 index 000000000000..36d7ff27b5e2 --- /dev/null +++ b/arch/arm/plat-mxc/include/mach/mx3_camera.h @@ -0,0 +1,52 @@ +/* + * mx3_camera.h - i.MX3x camera driver header file + * + * Copyright (C) 2008, Guennadi Liakhovetski, DENX Software Engineering, + * + * 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 _MX3_CAMERA_H_ +#define _MX3_CAMERA_H_ + +#include + +#define MX3_CAMERA_CLK_SRC 1 +#define MX3_CAMERA_EXT_VSYNC 2 +#define MX3_CAMERA_DP 4 +#define MX3_CAMERA_PCP 8 +#define MX3_CAMERA_HSP 0x10 +#define MX3_CAMERA_VSP 0x20 +#define MX3_CAMERA_DATAWIDTH_4 0x40 +#define MX3_CAMERA_DATAWIDTH_8 0x80 +#define MX3_CAMERA_DATAWIDTH_10 0x100 +#define MX3_CAMERA_DATAWIDTH_15 0x200 + +#define MX3_CAMERA_DATAWIDTH_MASK (MX3_CAMERA_DATAWIDTH_4 | MX3_CAMERA_DATAWIDTH_8 | \ + MX3_CAMERA_DATAWIDTH_10 | MX3_CAMERA_DATAWIDTH_15) + +/** + * struct mx3_camera_pdata - i.MX3x camera platform data + * @flags: MX3_CAMERA_* flags + * @mclk_10khz: master clock frequency in 10kHz units + * @dma_dev: IPU DMA device to match against in channel allocation + */ +struct mx3_camera_pdata { + unsigned long flags; + unsigned long mclk_10khz; + struct device *dma_dev; +}; + +#endif diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig index 19cf3b8f67c4..3e4ce4aade3e 100644 --- a/drivers/media/video/Kconfig +++ b/drivers/media/video/Kconfig @@ -779,6 +779,13 @@ config SOC_CAMERA_OV772X help This is a ov772x camera driver +config VIDEO_MX3 + tristate "i.MX3x Camera Sensor Interface driver" + depends on VIDEO_DEV && MX3_IPU && SOC_CAMERA + select VIDEOBUF_DMA_CONTIG + ---help--- + This is a v4l2 driver for the i.MX3x Camera Sensor Interface + config VIDEO_PXA27x tristate "PXA27x Quick Capture Interface driver" depends on VIDEO_DEV && PXA27x && SOC_CAMERA diff --git a/drivers/media/video/Makefile b/drivers/media/video/Makefile index 72f6d03d2d8f..6e2c69569f97 100644 --- a/drivers/media/video/Makefile +++ b/drivers/media/video/Makefile @@ -134,10 +134,11 @@ obj-$(CONFIG_VIDEO_CX18) += cx18/ obj-$(CONFIG_VIDEO_VIVI) += vivi.o obj-$(CONFIG_VIDEO_CX23885) += cx23885/ -obj-$(CONFIG_VIDEO_PXA27x) += pxa_camera.o +obj-$(CONFIG_VIDEO_MX3) += mx3_camera.o +obj-$(CONFIG_VIDEO_PXA27x) += pxa_camera.o obj-$(CONFIG_VIDEO_SH_MOBILE_CEU) += sh_mobile_ceu_camera.o obj-$(CONFIG_VIDEO_OMAP2) += omap2cam.o -obj-$(CONFIG_SOC_CAMERA) += soc_camera.o +obj-$(CONFIG_SOC_CAMERA) += soc_camera.o obj-$(CONFIG_SOC_CAMERA_MT9M001) += mt9m001.o obj-$(CONFIG_SOC_CAMERA_MT9M111) += mt9m111.o obj-$(CONFIG_SOC_CAMERA_MT9T031) += mt9t031.o diff --git a/drivers/media/video/mx3_camera.c b/drivers/media/video/mx3_camera.c new file mode 100644 index 000000000000..f525dc48f6ca --- /dev/null +++ b/drivers/media/video/mx3_camera.c @@ -0,0 +1,1183 @@ +/* + * V4L2 Driver for i.MX3x camera host + * + * Copyright (C) 2008 + * Guennadi Liakhovetski, DENX Software Engineering, + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include + +#define MX3_CAM_DRV_NAME "mx3-camera" + +/* CMOS Sensor Interface Registers */ +#define CSI_REG_START 0x60 + +#define CSI_SENS_CONF (0x60 - CSI_REG_START) +#define CSI_SENS_FRM_SIZE (0x64 - CSI_REG_START) +#define CSI_ACT_FRM_SIZE (0x68 - CSI_REG_START) +#define CSI_OUT_FRM_CTRL (0x6C - CSI_REG_START) +#define CSI_TST_CTRL (0x70 - CSI_REG_START) +#define CSI_CCIR_CODE_1 (0x74 - CSI_REG_START) +#define CSI_CCIR_CODE_2 (0x78 - CSI_REG_START) +#define CSI_CCIR_CODE_3 (0x7C - CSI_REG_START) +#define CSI_FLASH_STROBE_1 (0x80 - CSI_REG_START) +#define CSI_FLASH_STROBE_2 (0x84 - CSI_REG_START) + +#define CSI_SENS_CONF_VSYNC_POL_SHIFT 0 +#define CSI_SENS_CONF_HSYNC_POL_SHIFT 1 +#define CSI_SENS_CONF_DATA_POL_SHIFT 2 +#define CSI_SENS_CONF_PIX_CLK_POL_SHIFT 3 +#define CSI_SENS_CONF_SENS_PRTCL_SHIFT 4 +#define CSI_SENS_CONF_SENS_CLKSRC_SHIFT 7 +#define CSI_SENS_CONF_DATA_FMT_SHIFT 8 +#define CSI_SENS_CONF_DATA_WIDTH_SHIFT 10 +#define CSI_SENS_CONF_EXT_VSYNC_SHIFT 15 +#define CSI_SENS_CONF_DIVRATIO_SHIFT 16 + +#define CSI_SENS_CONF_DATA_FMT_RGB_YUV444 (0UL << CSI_SENS_CONF_DATA_FMT_SHIFT) +#define CSI_SENS_CONF_DATA_FMT_YUV422 (2UL << CSI_SENS_CONF_DATA_FMT_SHIFT) +#define CSI_SENS_CONF_DATA_FMT_BAYER (3UL << CSI_SENS_CONF_DATA_FMT_SHIFT) + +#define MAX_VIDEO_MEM 16 + +struct mx3_camera_buffer { + /* common v4l buffer stuff -- must be first */ + struct videobuf_buffer vb; + const struct soc_camera_data_format *fmt; + + /* One descriptot per scatterlist (per frame) */ + struct dma_async_tx_descriptor *txd; + + /* We have to "build" a scatterlist ourselves - one element per frame */ + struct scatterlist sg; +}; + +/** + * struct mx3_camera_dev - i.MX3x camera (CSI) object + * @dev: camera device, to which the coherent buffer is attached + * @icd: currently attached camera sensor + * @clk: pointer to clock + * @base: remapped register base address + * @pdata: platform data + * @platform_flags: platform flags + * @mclk: master clock frequency in Hz + * @capture: list of capture videobuffers + * @lock: protects video buffer lists + * @active: active video buffer + * @idmac_channel: array of pointers to IPU DMAC DMA channels + * @soc_host: embedded soc_host object + */ +struct mx3_camera_dev { + struct device *dev; + /* + * i.MX3x is only supposed to handle one camera on its Camera Sensor + * Interface. If anyone ever builds hardware to enable more than one + * camera _simultaneously_, they will have to modify this driver too + */ + struct soc_camera_device *icd; + struct clk *clk; + + void __iomem *base; + + struct mx3_camera_pdata *pdata; + + unsigned long platform_flags; + unsigned long mclk; + + struct list_head capture; + spinlock_t lock; /* Protects video buffer lists */ + struct mx3_camera_buffer *active; + + /* IDMAC / dmaengine interface */ + struct idmac_channel *idmac_channel[1]; /* We need one channel */ + + struct soc_camera_host soc_host; +}; + +struct dma_chan_request { + struct mx3_camera_dev *mx3_cam; + enum ipu_channel id; +}; + +static int mx3_camera_set_bus_param(struct soc_camera_device *icd, __u32 pixfmt); + +static u32 csi_reg_read(struct mx3_camera_dev *mx3, off_t reg) +{ + return __raw_readl(mx3->base + reg); +} + +static void csi_reg_write(struct mx3_camera_dev *mx3, u32 value, off_t reg) +{ + __raw_writel(value, mx3->base + reg); +} + +/* Called from the IPU IDMAC ISR */ +static void mx3_cam_dma_done(void *arg) +{ + struct idmac_tx_desc *desc = to_tx_desc(arg); + struct dma_chan *chan = desc->txd.chan; + struct idmac_channel *ichannel = to_idmac_chan(chan); + struct mx3_camera_dev *mx3_cam = ichannel->client; + struct videobuf_buffer *vb; + + dev_dbg(chan->device->dev, "callback cookie %d, active DMA 0x%08x\n", + desc->txd.cookie, mx3_cam->active ? sg_dma_address(&mx3_cam->active->sg) : 0); + + spin_lock(&mx3_cam->lock); + if (mx3_cam->active) { + vb = &mx3_cam->active->vb; + + list_del_init(&vb->queue); + vb->state = VIDEOBUF_DONE; + do_gettimeofday(&vb->ts); + vb->field_count++; + wake_up(&vb->done); + } + + if (list_empty(&mx3_cam->capture)) { + mx3_cam->active = NULL; + spin_unlock(&mx3_cam->lock); + + /* + * stop capture - without further buffers IPU_CHA_BUF0_RDY will + * not get updated + */ + return; + } + + mx3_cam->active = list_entry(mx3_cam->capture.next, + struct mx3_camera_buffer, vb.queue); + mx3_cam->active->vb.state = VIDEOBUF_ACTIVE; + spin_unlock(&mx3_cam->lock); +} + +static void free_buffer(struct videobuf_queue *vq, struct mx3_camera_buffer *buf) +{ + struct soc_camera_device *icd = vq->priv_data; + struct videobuf_buffer *vb = &buf->vb; + struct dma_async_tx_descriptor *txd = buf->txd; + struct idmac_channel *ichan; + + BUG_ON(in_interrupt()); + + dev_dbg(&icd->dev, "%s (vb=0x%p) 0x%08lx %d\n", __func__, + vb, vb->baddr, 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(vb, 0, 0); + if (txd) { + ichan = to_idmac_chan(txd->chan); + async_tx_ack(txd); + } + videobuf_dma_contig_free(vq, vb); + buf->txd = NULL; + + vb->state = VIDEOBUF_NEEDS_INIT; +} + +/* + * Videobuf operations + */ + +/* + * Calculate the __buffer__ (not data) size and number of buffers. + * Called with .vb_lock held + */ +static int mx3_videobuf_setup(struct videobuf_queue *vq, unsigned int *count, + unsigned int *size) +{ + struct soc_camera_device *icd = vq->priv_data; + struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); + struct mx3_camera_dev *mx3_cam = ici->priv; + /* + * bits-per-pixel (depth) as specified in camera's pixel format does + * not necessarily match what the camera interface writes to RAM, but + * it should be good enough for now. + */ + unsigned int bpp = DIV_ROUND_UP(icd->current_fmt->depth, 8); + + if (!mx3_cam->idmac_channel[0]) + return -EINVAL; + + *size = icd->width * icd->height * bpp; + + if (!*count) + *count = 32; + + if (*size * *count > MAX_VIDEO_MEM * 1024 * 1024) + *count = MAX_VIDEO_MEM * 1024 * 1024 / *size; + + return 0; +} + +/* Called with .vb_lock held */ +static int mx3_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 mx3_camera_dev *mx3_cam = ici->priv; + struct mx3_camera_buffer *buf = + container_of(vb, struct mx3_camera_buffer, vb); + /* current_fmt _must_ always be set */ + size_t new_size = icd->width * icd->height * + ((icd->current_fmt->depth + 7) >> 3); + int ret; + + /* + * I think, in buf_prepare you only have to protect global data, + * the actual buffer is yours + */ + + 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; + if (vb->state != VIDEOBUF_NEEDS_INIT) + free_buffer(vq, buf); + } + + if (vb->baddr && vb->bsize < new_size) { + /* User provided buffer, but it is too small */ + ret = -ENOMEM; + goto out; + } + + if (vb->state == VIDEOBUF_NEEDS_INIT) { + struct idmac_channel *ichan = mx3_cam->idmac_channel[0]; + struct scatterlist *sg = &buf->sg; + + /* + * The total size of video-buffers that will be allocated / mapped. + * *size that we calculated in videobuf_setup gets assigned to + * vb->bsize, and now we use the same calculation to get vb->size. + */ + vb->size = new_size; + + /* This actually (allocates and) maps buffers */ + ret = videobuf_iolock(vq, vb, NULL); + if (ret) + goto fail; + + /* + * We will have to configure the IDMAC channel. It has two slots + * for DMA buffers, we shall enter the first two buffers there, + * and then submit new buffers in DMA-ready interrupts + */ + sg_init_table(sg, 1); + sg_dma_address(sg) = videobuf_to_dma_contig(vb); + sg_dma_len(sg) = vb->size; + + buf->txd = ichan->dma_chan.device->device_prep_slave_sg( + &ichan->dma_chan, sg, 1, DMA_FROM_DEVICE, + DMA_PREP_INTERRUPT); + if (!buf->txd) { + ret = -EIO; + goto fail; + } + + buf->txd->callback_param = buf->txd; + buf->txd->callback = mx3_cam_dma_done; + + vb->state = VIDEOBUF_PREPARED; + } + + return 0; + +fail: + free_buffer(vq, buf); +out: + return ret; +} + +static enum pixel_fmt fourcc_to_ipu_pix(__u32 fourcc) +{ + /* Add more formats as need arises and test possibilities appear... */ + switch (fourcc) { + case V4L2_PIX_FMT_RGB565: + return IPU_PIX_FMT_RGB565; + case V4L2_PIX_FMT_RGB24: + return IPU_PIX_FMT_RGB24; + case V4L2_PIX_FMT_RGB332: + return IPU_PIX_FMT_RGB332; + case V4L2_PIX_FMT_YUV422P: + return IPU_PIX_FMT_YVU422P; + default: + return IPU_PIX_FMT_GENERIC; + } +} + +/* Called with .vb_lock held */ +static void mx3_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 mx3_camera_dev *mx3_cam = ici->priv; + struct mx3_camera_buffer *buf = + container_of(vb, struct mx3_camera_buffer, vb); + struct dma_async_tx_descriptor *txd = buf->txd; + struct idmac_channel *ichan = to_idmac_chan(txd->chan); + struct idmac_video_param *video = &ichan->params.video; + const struct soc_camera_data_format *data_fmt = icd->current_fmt; + dma_cookie_t cookie; + unsigned long flags; + + /* This is the configuration of one sg-element */ + video->out_pixel_fmt = fourcc_to_ipu_pix(data_fmt->fourcc); + video->out_width = icd->width; + video->out_height = icd->height; + video->out_stride = icd->width; + +#ifdef DEBUG + /* helps to see what DMA actually has written */ + memset((void *)vb->baddr, 0xaa, vb->bsize); +#endif + + spin_lock_irqsave(&mx3_cam->lock, flags); + + list_add_tail(&vb->queue, &mx3_cam->capture); + + if (!mx3_cam->active) { + mx3_cam->active = buf; + vb->state = VIDEOBUF_ACTIVE; + } else { + vb->state = VIDEOBUF_QUEUED; + } + + spin_unlock_irqrestore(&mx3_cam->lock, flags); + + cookie = txd->tx_submit(txd); + dev_dbg(&icd->dev, "Submitted cookie %d DMA 0x%08x\n", cookie, sg_dma_address(&buf->sg)); + if (cookie >= 0) + return; + + /* Submit error */ + vb->state = VIDEOBUF_PREPARED; + + spin_lock_irqsave(&mx3_cam->lock, flags); + + list_del_init(&vb->queue); + + if (mx3_cam->active == buf) + mx3_cam->active = NULL; + + spin_unlock_irqrestore(&mx3_cam->lock, flags); +} + +/* Called with .vb_lock held */ +static void mx3_videobuf_release(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 mx3_camera_dev *mx3_cam = ici->priv; + struct mx3_camera_buffer *buf = + container_of(vb, struct mx3_camera_buffer, vb); + unsigned long flags; + + dev_dbg(&icd->dev, "Release%s DMA 0x%08x (state %d), queue %sempty\n", + mx3_cam->active == buf ? " active" : "", sg_dma_address(&buf->sg), + vb->state, list_empty(&vb->queue) ? "" : "not "); + spin_lock_irqsave(&mx3_cam->lock, flags); + if ((vb->state == VIDEOBUF_ACTIVE || vb->state == VIDEOBUF_QUEUED) && + !list_empty(&vb->queue)) { + vb->state = VIDEOBUF_ERROR; + + list_del_init(&vb->queue); + if (mx3_cam->active == buf) + mx3_cam->active = NULL; + } + spin_unlock_irqrestore(&mx3_cam->lock, flags); + free_buffer(vq, buf); +} + +static struct videobuf_queue_ops mx3_videobuf_ops = { + .buf_setup = mx3_videobuf_setup, + .buf_prepare = mx3_videobuf_prepare, + .buf_queue = mx3_videobuf_queue, + .buf_release = mx3_videobuf_release, +}; + +static void mx3_camera_init_videobuf(struct videobuf_queue *q, + struct soc_camera_device *icd) +{ + struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); + struct mx3_camera_dev *mx3_cam = ici->priv; + + videobuf_queue_dma_contig_init(q, &mx3_videobuf_ops, mx3_cam->dev, + &mx3_cam->lock, + V4L2_BUF_TYPE_VIDEO_CAPTURE, + V4L2_FIELD_NONE, + sizeof(struct mx3_camera_buffer), icd); +} + +/* First part of ipu_csi_init_interface() */ +static void mx3_camera_activate(struct mx3_camera_dev *mx3_cam, + struct soc_camera_device *icd) +{ + u32 conf; + long rate; + + /* Set default size: ipu_csi_set_window_size() */ + csi_reg_write(mx3_cam, (640 - 1) | ((480 - 1) << 16), CSI_ACT_FRM_SIZE); + /* ...and position to 0:0: ipu_csi_set_window_pos() */ + conf = csi_reg_read(mx3_cam, CSI_OUT_FRM_CTRL) & 0xffff0000; + csi_reg_write(mx3_cam, conf, CSI_OUT_FRM_CTRL); + + /* We use only gated clock synchronisation mode so far */ + conf = 0 << CSI_SENS_CONF_SENS_PRTCL_SHIFT; + + /* Set generic data, platform-biggest bus-width */ + conf |= CSI_SENS_CONF_DATA_FMT_BAYER; + + if (mx3_cam->platform_flags & MX3_CAMERA_DATAWIDTH_15) + conf |= 3 << CSI_SENS_CONF_DATA_WIDTH_SHIFT; + else if (mx3_cam->platform_flags & MX3_CAMERA_DATAWIDTH_10) + conf |= 2 << CSI_SENS_CONF_DATA_WIDTH_SHIFT; + else if (mx3_cam->platform_flags & MX3_CAMERA_DATAWIDTH_8) + conf |= 1 << CSI_SENS_CONF_DATA_WIDTH_SHIFT; + else/* if (mx3_cam->platform_flags & MX3_CAMERA_DATAWIDTH_4)*/ + conf |= 0 << CSI_SENS_CONF_DATA_WIDTH_SHIFT; + + if (mx3_cam->platform_flags & MX3_CAMERA_CLK_SRC) + conf |= 1 << CSI_SENS_CONF_SENS_CLKSRC_SHIFT; + if (mx3_cam->platform_flags & MX3_CAMERA_EXT_VSYNC) + conf |= 1 << CSI_SENS_CONF_EXT_VSYNC_SHIFT; + if (mx3_cam->platform_flags & MX3_CAMERA_DP) + conf |= 1 << CSI_SENS_CONF_DATA_POL_SHIFT; + if (mx3_cam->platform_flags & MX3_CAMERA_PCP) + conf |= 1 << CSI_SENS_CONF_PIX_CLK_POL_SHIFT; + if (mx3_cam->platform_flags & MX3_CAMERA_HSP) + conf |= 1 << CSI_SENS_CONF_HSYNC_POL_SHIFT; + if (mx3_cam->platform_flags & MX3_CAMERA_VSP) + conf |= 1 << CSI_SENS_CONF_VSYNC_POL_SHIFT; + + /* ipu_csi_init_interface() */ + csi_reg_write(mx3_cam, conf, CSI_SENS_CONF); + + clk_enable(mx3_cam->clk); + rate = clk_round_rate(mx3_cam->clk, mx3_cam->mclk); + dev_dbg(&icd->dev, "Set SENS_CONF to %x, rate %ld\n", conf, rate); + if (rate) + clk_set_rate(mx3_cam->clk, rate); +} + +/* Called with .video_lock held */ +static int mx3_camera_add_device(struct soc_camera_device *icd) +{ + struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); + struct mx3_camera_dev *mx3_cam = ici->priv; + int ret; + + if (mx3_cam->icd) { + ret = -EBUSY; + goto ebusy; + } + + mx3_camera_activate(mx3_cam, icd); + ret = icd->ops->init(icd); + if (ret < 0) { + clk_disable(mx3_cam->clk); + goto einit; + } + + mx3_cam->icd = icd; + +einit: +ebusy: + if (!ret) + dev_info(&icd->dev, "MX3 Camera driver attached to camera %d\n", + icd->devnum); + + return ret; +} + +/* Called with .video_lock held */ +static void mx3_camera_remove_device(struct soc_camera_device *icd) +{ + struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); + struct mx3_camera_dev *mx3_cam = ici->priv; + struct idmac_channel **ichan = &mx3_cam->idmac_channel[0]; + + BUG_ON(icd != mx3_cam->icd); + + if (*ichan) { + dma_release_channel(&(*ichan)->dma_chan); + *ichan = NULL; + } + + icd->ops->release(icd); + + clk_disable(mx3_cam->clk); + + mx3_cam->icd = NULL; + + dev_info(&icd->dev, "MX3 Camera driver detached from camera %d\n", + icd->devnum); +} + +static bool channel_change_requested(struct soc_camera_device *icd, + const struct soc_camera_format_xlate *xlate, + __u32 pixfmt, struct v4l2_rect *rect) +{ + struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); + struct mx3_camera_dev *mx3_cam = ici->priv; + struct idmac_channel *ichan = mx3_cam->idmac_channel[0]; + + /* So far only one configuration is supported */ + return pixfmt || (ichan && rect->width * rect->height > + icd->width * icd->height); +} + +static int test_platform_param(struct mx3_camera_dev *mx3_cam, + unsigned char buswidth, unsigned long *flags) +{ + /* + * Platform specified synchronization and pixel clock polarities are + * only a recommendation and are only used during probing. MX3x + * camera interface only works in master mode, i.e., uses HSYNC and + * VSYNC signals from the sensor + */ + *flags = SOCAM_MASTER | + SOCAM_HSYNC_ACTIVE_HIGH | + SOCAM_HSYNC_ACTIVE_LOW | + SOCAM_VSYNC_ACTIVE_HIGH | + SOCAM_VSYNC_ACTIVE_LOW | + SOCAM_PCLK_SAMPLE_RISING | + SOCAM_PCLK_SAMPLE_FALLING | + SOCAM_DATA_ACTIVE_HIGH | + SOCAM_DATA_ACTIVE_LOW; + + /* If requested data width is supported by the platform, use it or any + * possible lower value - i.MX31 is smart enough to schift bits */ + switch (buswidth) { + case 15: + if (!(mx3_cam->platform_flags & MX3_CAMERA_DATAWIDTH_15)) + return -EINVAL; + *flags |= SOCAM_DATAWIDTH_15 | SOCAM_DATAWIDTH_10 | + SOCAM_DATAWIDTH_8 | SOCAM_DATAWIDTH_4; + break; + case 10: + if (!(mx3_cam->platform_flags & MX3_CAMERA_DATAWIDTH_10)) + return -EINVAL; + *flags |= SOCAM_DATAWIDTH_10 | SOCAM_DATAWIDTH_8 | + SOCAM_DATAWIDTH_4; + break; + case 8: + if (!(mx3_cam->platform_flags & MX3_CAMERA_DATAWIDTH_8)) + return -EINVAL; + *flags |= SOCAM_DATAWIDTH_8 | SOCAM_DATAWIDTH_4; + break; + case 4: + if (!(mx3_cam->platform_flags & MX3_CAMERA_DATAWIDTH_4)) + return -EINVAL; + *flags |= SOCAM_DATAWIDTH_4; + break; + default: + dev_info(mx3_cam->dev, "Unsupported bus width %d\n", buswidth); + return -EINVAL; + } + + return 0; +} + +static int mx3_camera_try_bus_param(struct soc_camera_device *icd, + const unsigned int depth) +{ + struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); + struct mx3_camera_dev *mx3_cam = ici->priv; + unsigned long bus_flags, camera_flags; + int ret = test_platform_param(mx3_cam, depth, &bus_flags); + + dev_dbg(&ici->dev, "requested bus width %d bit: %d\n", depth, ret); + + if (ret < 0) + return ret; + + camera_flags = icd->ops->query_bus_param(icd); + + ret = soc_camera_bus_param_compatible(camera_flags, bus_flags); + if (ret < 0) + dev_warn(&icd->dev, "Flags incompatible: camera %lx, host %lx\n", + camera_flags, bus_flags); + + return ret; +} + +static bool chan_filter(struct dma_chan *chan, void *arg) +{ + struct dma_chan_request *rq = arg; + struct mx3_camera_pdata *pdata; + + if (!rq) + return false; + + pdata = rq->mx3_cam->dev->platform_data; + + return rq->id == chan->chan_id && + pdata->dma_dev == chan->device->dev; +} + +static const struct soc_camera_data_format mx3_camera_formats[] = { + { + .name = "Bayer (sRGB) 8 bit", + .depth = 8, + .fourcc = V4L2_PIX_FMT_SBGGR8, + .colorspace = V4L2_COLORSPACE_SRGB, + }, { + .name = "Monochrome 8 bit", + .depth = 8, + .fourcc = V4L2_PIX_FMT_GREY, + .colorspace = V4L2_COLORSPACE_JPEG, + }, +}; + +static bool buswidth_supported(struct soc_camera_host *ici, int depth) +{ + struct mx3_camera_dev *mx3_cam = ici->priv; + + switch (depth) { + case 4: + return !!(mx3_cam->platform_flags & MX3_CAMERA_DATAWIDTH_4); + case 8: + return !!(mx3_cam->platform_flags & MX3_CAMERA_DATAWIDTH_8); + case 10: + return !!(mx3_cam->platform_flags & MX3_CAMERA_DATAWIDTH_10); + case 15: + return !!(mx3_cam->platform_flags & MX3_CAMERA_DATAWIDTH_15); + } + return false; +} + +static int mx3_camera_get_formats(struct soc_camera_device *icd, int idx, + struct soc_camera_format_xlate *xlate) +{ + struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); + int formats = 0, buswidth, ret; + + buswidth = icd->formats[idx].depth; + + if (!buswidth_supported(ici, buswidth)) + return 0; + + ret = mx3_camera_try_bus_param(icd, buswidth); + if (ret < 0) + return 0; + + switch (icd->formats[idx].fourcc) { + case V4L2_PIX_FMT_SGRBG10: + formats++; + if (xlate) { + xlate->host_fmt = &mx3_camera_formats[0]; + xlate->cam_fmt = icd->formats + idx; + xlate->buswidth = buswidth; + xlate++; + dev_dbg(&ici->dev, "Providing format %s using %s\n", + mx3_camera_formats[0].name, + icd->formats[idx].name); + } + goto passthrough; + case V4L2_PIX_FMT_Y16: + formats++; + if (xlate) { + xlate->host_fmt = &mx3_camera_formats[1]; + xlate->cam_fmt = icd->formats + idx; + xlate->buswidth = buswidth; + xlate++; + dev_dbg(&ici->dev, "Providing format %s using %s\n", + mx3_camera_formats[0].name, + icd->formats[idx].name); + } + default: +passthrough: + /* Generic pass-through */ + formats++; + if (xlate) { + xlate->host_fmt = icd->formats + idx; + xlate->cam_fmt = icd->formats + idx; + xlate->buswidth = buswidth; + xlate++; + dev_dbg(&ici->dev, + "Providing format %s in pass-through mode\n", + icd->formats[idx].name); + } + } + + return formats; +} + +static int mx3_camera_set_fmt(struct soc_camera_device *icd, + __u32 pixfmt, struct v4l2_rect *rect) +{ + struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); + struct mx3_camera_dev *mx3_cam = ici->priv; + const struct soc_camera_format_xlate *xlate; + u32 ctrl, width_field, height_field; + int ret; + + xlate = soc_camera_xlate_by_fourcc(icd, pixfmt); + if (pixfmt && !xlate) { + dev_warn(&ici->dev, "Format %x not found\n", pixfmt); + return -EINVAL; + } + + /* + * We now know pixel formats and can decide upon DMA-channel(s) + * So far only direct camera-to-memory is supported + */ + if (channel_change_requested(icd, xlate, pixfmt, rect)) { + dma_cap_mask_t mask; + struct dma_chan *chan; + struct idmac_channel **ichan = &mx3_cam->idmac_channel[0]; + /* We have to use IDMAC_IC_7 for Bayer / generic data */ + struct dma_chan_request rq = {.mx3_cam = mx3_cam, + .id = IDMAC_IC_7}; + + if (*ichan) { + struct videobuf_buffer *vb, *_vb; + dma_release_channel(&(*ichan)->dma_chan); + *ichan = NULL; + mx3_cam->active = NULL; + list_for_each_entry_safe(vb, _vb, &mx3_cam->capture, queue) { + list_del_init(&vb->queue); + vb->state = VIDEOBUF_ERROR; + wake_up(&vb->done); + } + } + + dma_cap_zero(mask); + dma_cap_set(DMA_SLAVE, mask); + dma_cap_set(DMA_PRIVATE, mask); + chan = dma_request_channel(mask, chan_filter, &rq); + if (!chan) + return -EBUSY; + + *ichan = to_idmac_chan(chan); + (*ichan)->client = mx3_cam; + } + + /* + * Might have to perform a complete interface initialisation like in + * ipu_csi_init_interface() in mxc_v4l2_s_param(). Also consider + * mxc_v4l2_s_fmt() + */ + + /* Setup frame size - this cannot be changed on-the-fly... */ + width_field = rect->width - 1; + height_field = rect->height - 1; + csi_reg_write(mx3_cam, width_field | (height_field << 16), CSI_SENS_FRM_SIZE); + + csi_reg_write(mx3_cam, width_field << 16, CSI_FLASH_STROBE_1); + csi_reg_write(mx3_cam, (height_field << 16) | 0x22, CSI_FLASH_STROBE_2); + + csi_reg_write(mx3_cam, width_field | (height_field << 16), CSI_ACT_FRM_SIZE); + + /* ...and position */ + ctrl = csi_reg_read(mx3_cam, CSI_OUT_FRM_CTRL) & 0xffff0000; + /* Sensor does the cropping */ + csi_reg_write(mx3_cam, ctrl | 0 | (0 << 8), CSI_OUT_FRM_CTRL); + + /* + * No need to free resources here if we fail, we'll see if we need to + * do this next time we are called + */ + + ret = icd->ops->set_fmt(icd, pixfmt ? xlate->cam_fmt->fourcc : 0, rect); + if (pixfmt && !ret) { + icd->buswidth = xlate->buswidth; + icd->current_fmt = xlate->host_fmt; + } + + return ret; +} + +static int mx3_camera_try_fmt(struct soc_camera_device *icd, + struct v4l2_format *f) +{ + struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); + const struct soc_camera_format_xlate *xlate; + struct v4l2_pix_format *pix = &f->fmt.pix; + __u32 pixfmt = pix->pixelformat; + enum v4l2_field field; + int ret; + + xlate = soc_camera_xlate_by_fourcc(icd, pixfmt); + if (pixfmt && !xlate) { + dev_warn(&ici->dev, "Format %x not found\n", pixfmt); + return -EINVAL; + } + + /* limit to MX3 hardware capabilities */ + if (pix->height > 4096) + pix->height = 4096; + if (pix->width > 4096) + pix->width = 4096; + + pix->bytesperline = pix->width * + DIV_ROUND_UP(xlate->host_fmt->depth, 8); + pix->sizeimage = pix->height * pix->bytesperline; + + /* camera has to see its format, but the user the original one */ + pix->pixelformat = xlate->cam_fmt->fourcc; + /* limit to sensor capabilities */ + ret = icd->ops->try_fmt(icd, f); + pix->pixelformat = xlate->host_fmt->fourcc; + + field = pix->field; + + if (field == V4L2_FIELD_ANY) { + pix->field = V4L2_FIELD_NONE; + } else if (field != V4L2_FIELD_NONE) { + dev_err(&icd->dev, "Field type %d unsupported.\n", field); + return -EINVAL; + } + + return ret; +} + +static int mx3_camera_reqbufs(struct soc_camera_file *icf, + struct v4l2_requestbuffers *p) +{ + return 0; +} + +static unsigned int mx3_camera_poll(struct file *file, poll_table *pt) +{ + struct soc_camera_file *icf = file->private_data; + + return videobuf_poll_stream(file, &icf->vb_vidq, pt); +} + +static int mx3_camera_querycap(struct soc_camera_host *ici, + struct v4l2_capability *cap) +{ + /* cap->name is set by the firendly caller:-> */ + strlcpy(cap->card, "i.MX3x Camera", sizeof(cap->card)); + cap->version = KERNEL_VERSION(0, 2, 2); + cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING; + + return 0; +} + +static int mx3_camera_set_bus_param(struct soc_camera_device *icd, __u32 pixfmt) +{ + struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); + struct mx3_camera_dev *mx3_cam = ici->priv; + unsigned long bus_flags, camera_flags, common_flags; + u32 dw, sens_conf; + int ret = test_platform_param(mx3_cam, icd->buswidth, &bus_flags); + const struct soc_camera_format_xlate *xlate; + + xlate = soc_camera_xlate_by_fourcc(icd, pixfmt); + if (!xlate) { + dev_warn(&ici->dev, "Format %x not found\n", pixfmt); + return -EINVAL; + } + + dev_dbg(&ici->dev, "requested bus width %d bit: %d\n", + icd->buswidth, ret); + + if (ret < 0) + return ret; + + camera_flags = icd->ops->query_bus_param(icd); + + common_flags = soc_camera_bus_param_compatible(camera_flags, bus_flags); + if (!common_flags) { + dev_dbg(&ici->dev, "no common flags: camera %lx, host %lx\n", + camera_flags, bus_flags); + return -EINVAL; + } + + /* Make choices, based on platform preferences */ + if ((common_flags & SOCAM_HSYNC_ACTIVE_HIGH) && + (common_flags & SOCAM_HSYNC_ACTIVE_LOW)) { + if (mx3_cam->platform_flags & MX3_CAMERA_HSP) + common_flags &= ~SOCAM_HSYNC_ACTIVE_HIGH; + else + common_flags &= ~SOCAM_HSYNC_ACTIVE_LOW; + } + + if ((common_flags & SOCAM_VSYNC_ACTIVE_HIGH) && + (common_flags & SOCAM_VSYNC_ACTIVE_LOW)) { + if (mx3_cam->platform_flags & MX3_CAMERA_VSP) + common_flags &= ~SOCAM_VSYNC_ACTIVE_HIGH; + else + common_flags &= ~SOCAM_VSYNC_ACTIVE_LOW; + } + + if ((common_flags & SOCAM_DATA_ACTIVE_HIGH) && + (common_flags & SOCAM_DATA_ACTIVE_LOW)) { + if (mx3_cam->platform_flags & MX3_CAMERA_DP) + common_flags &= ~SOCAM_DATA_ACTIVE_HIGH; + else + common_flags &= ~SOCAM_DATA_ACTIVE_LOW; + } + + if ((common_flags & SOCAM_PCLK_SAMPLE_RISING) && + (common_flags & SOCAM_PCLK_SAMPLE_FALLING)) { + if (mx3_cam->platform_flags & MX3_CAMERA_PCP) + common_flags &= ~SOCAM_PCLK_SAMPLE_RISING; + else + common_flags &= ~SOCAM_PCLK_SAMPLE_FALLING; + } + + /* Make the camera work in widest common mode, we'll take care of + * the rest */ + if (common_flags & SOCAM_DATAWIDTH_15) + common_flags = (common_flags & ~SOCAM_DATAWIDTH_MASK) | + SOCAM_DATAWIDTH_15; + else if (common_flags & SOCAM_DATAWIDTH_10) + common_flags = (common_flags & ~SOCAM_DATAWIDTH_MASK) | + SOCAM_DATAWIDTH_10; + else if (common_flags & SOCAM_DATAWIDTH_8) + common_flags = (common_flags & ~SOCAM_DATAWIDTH_MASK) | + SOCAM_DATAWIDTH_8; + else + common_flags = (common_flags & ~SOCAM_DATAWIDTH_MASK) | + SOCAM_DATAWIDTH_4; + + ret = icd->ops->set_bus_param(icd, common_flags); + if (ret < 0) + return ret; + + /* + * So far only gated clock mode is supported. Add a line + * (3 << CSI_SENS_CONF_SENS_PRTCL_SHIFT) | + * below and select the required mode when supporting other + * synchronisation protocols. + */ + sens_conf = csi_reg_read(mx3_cam, CSI_SENS_CONF) & + ~((1 << CSI_SENS_CONF_VSYNC_POL_SHIFT) | + (1 << CSI_SENS_CONF_HSYNC_POL_SHIFT) | + (1 << CSI_SENS_CONF_DATA_POL_SHIFT) | + (1 << CSI_SENS_CONF_PIX_CLK_POL_SHIFT) | + (3 << CSI_SENS_CONF_DATA_FMT_SHIFT) | + (3 << CSI_SENS_CONF_DATA_WIDTH_SHIFT)); + + /* TODO: Support RGB and YUV formats */ + + /* This has been set in mx3_camera_activate(), but we clear it above */ + sens_conf |= CSI_SENS_CONF_DATA_FMT_BAYER; + + if (common_flags & SOCAM_PCLK_SAMPLE_FALLING) + sens_conf |= 1 << CSI_SENS_CONF_PIX_CLK_POL_SHIFT; + if (common_flags & SOCAM_HSYNC_ACTIVE_LOW) + sens_conf |= 1 << CSI_SENS_CONF_HSYNC_POL_SHIFT; + if (common_flags & SOCAM_VSYNC_ACTIVE_LOW) + sens_conf |= 1 << CSI_SENS_CONF_VSYNC_POL_SHIFT; + if (common_flags & SOCAM_DATA_ACTIVE_LOW) + sens_conf |= 1 << CSI_SENS_CONF_DATA_POL_SHIFT; + + /* Just do what we're asked to do */ + switch (xlate->host_fmt->depth) { + case 4: + dw = 0 << CSI_SENS_CONF_DATA_WIDTH_SHIFT; + break; + case 8: + dw = 1 << CSI_SENS_CONF_DATA_WIDTH_SHIFT; + break; + case 10: + dw = 2 << CSI_SENS_CONF_DATA_WIDTH_SHIFT; + break; + default: + /* + * Actually it can only be 15 now, default is just to silence + * compiler warnings + */ + case 15: + dw = 3 << CSI_SENS_CONF_DATA_WIDTH_SHIFT; + } + + csi_reg_write(mx3_cam, sens_conf | dw, CSI_SENS_CONF); + + dev_dbg(&ici->dev, "Set SENS_CONF to %x\n", sens_conf | dw); + + return 0; +} + +static struct soc_camera_host_ops mx3_soc_camera_host_ops = { + .owner = THIS_MODULE, + .add = mx3_camera_add_device, + .remove = mx3_camera_remove_device, +#ifdef CONFIG_PM + .suspend = mx3_camera_suspend, + .resume = mx3_camera_resume, +#endif + .set_fmt = mx3_camera_set_fmt, + .try_fmt = mx3_camera_try_fmt, + .get_formats = mx3_camera_get_formats, + .init_videobuf = mx3_camera_init_videobuf, + .reqbufs = mx3_camera_reqbufs, + .poll = mx3_camera_poll, + .querycap = mx3_camera_querycap, + .set_bus_param = mx3_camera_set_bus_param, +}; + +static int mx3_camera_probe(struct platform_device *pdev) +{ + struct mx3_camera_dev *mx3_cam; + struct resource *res; + void __iomem *base; + int err = 0; + struct soc_camera_host *soc_host; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) { + err = -ENODEV; + goto egetres; + } + + mx3_cam = vmalloc(sizeof(*mx3_cam)); + if (!mx3_cam) { + dev_err(&pdev->dev, "Could not allocate mx3 camera object\n"); + err = -ENOMEM; + goto ealloc; + } + memset(mx3_cam, 0, sizeof(*mx3_cam)); + + mx3_cam->clk = clk_get(&pdev->dev, "csi_clk"); + if (IS_ERR(mx3_cam->clk)) { + err = PTR_ERR(mx3_cam->clk); + goto eclkget; + } + + dev_set_drvdata(&pdev->dev, mx3_cam); + + mx3_cam->pdata = pdev->dev.platform_data; + mx3_cam->platform_flags = mx3_cam->pdata->flags; + if (!(mx3_cam->platform_flags & (MX3_CAMERA_DATAWIDTH_4 | + MX3_CAMERA_DATAWIDTH_8 | MX3_CAMERA_DATAWIDTH_10 | + MX3_CAMERA_DATAWIDTH_15))) { + /* 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 8 bit\n"); + mx3_cam->platform_flags |= MX3_CAMERA_DATAWIDTH_8; + } + + mx3_cam->mclk = mx3_cam->pdata->mclk_10khz * 10000; + if (!mx3_cam->mclk) { + dev_warn(&pdev->dev, + "mclk_10khz == 0! Please, fix your platform data. " + "Using default 20MHz\n"); + mx3_cam->mclk = 20000000; + } + + /* list of video-buffers */ + INIT_LIST_HEAD(&mx3_cam->capture); + spin_lock_init(&mx3_cam->lock); + + base = ioremap(res->start, res->end - res->start + 1); + if (!base) { + err = -ENOMEM; + goto eioremap; + } + + mx3_cam->base = base; + mx3_cam->dev = &pdev->dev; + + soc_host = &mx3_cam->soc_host; + soc_host->drv_name = MX3_CAM_DRV_NAME; + soc_host->ops = &mx3_soc_camera_host_ops; + soc_host->priv = mx3_cam; + soc_host->dev.parent = &pdev->dev; + soc_host->nr = pdev->id; + err = soc_camera_host_register(soc_host); + if (err) + goto ecamhostreg; + + /* IDMAC interface */ + dmaengine_get(); + + return 0; + +ecamhostreg: + iounmap(base); +eioremap: + clk_put(mx3_cam->clk); +eclkget: + vfree(mx3_cam); +ealloc: +egetres: + return err; +} + +static int __devexit mx3_camera_remove(struct platform_device *pdev) +{ + struct mx3_camera_dev *mx3_cam = platform_get_drvdata(pdev); + + clk_put(mx3_cam->clk); + + soc_camera_host_unregister(&mx3_cam->soc_host); + + iounmap(mx3_cam->base); + + /* + * The channel has either not been allocated, + * or should have been released + */ + if (WARN_ON(mx3_cam->idmac_channel[0])) + dma_release_channel(&mx3_cam->idmac_channel[0]->dma_chan); + + vfree(mx3_cam); + + dmaengine_put(); + + dev_info(&pdev->dev, "i.MX3x Camera driver unloaded\n"); + + return 0; +} + +static struct platform_driver mx3_camera_driver = { + .driver = { + .name = MX3_CAM_DRV_NAME, + }, + .probe = mx3_camera_probe, + .remove = __exit_p(mx3_camera_remove), +}; + + +static int __devinit mx3_camera_init(void) +{ + return platform_driver_register(&mx3_camera_driver); +} + +static void __exit mx3_camera_exit(void) +{ + platform_driver_unregister(&mx3_camera_driver); +} + +module_init(mx3_camera_init); +module_exit(mx3_camera_exit); + +MODULE_DESCRIPTION("i.MX3x SoC Camera Host driver"); +MODULE_AUTHOR("Guennadi Liakhovetski "); +MODULE_LICENSE("GPL v2"); -- cgit v1.2.3 From afb13683e988707bb6120435926243954e283b3e Mon Sep 17 00:00:00 2001 From: Antonio Ospite Date: Mon, 23 Feb 2009 12:13:24 -0300 Subject: V4L/DVB (10676): mt9m111: Call icl->reset() on mt9m111_reset(). Call icl->reset() on mt9m111_reset(). Signed-off-by: Antonio Ospite Acked-by: Robert Jarzmik Signed-off-by: Guennadi Liakhovetski Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/mt9m111.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers/media/video') diff --git a/drivers/media/video/mt9m111.c b/drivers/media/video/mt9m111.c index 6c363af165b7..7e6be36f0855 100644 --- a/drivers/media/video/mt9m111.c +++ b/drivers/media/video/mt9m111.c @@ -393,6 +393,8 @@ static int mt9m111_disable(struct soc_camera_device *icd) static int mt9m111_reset(struct soc_camera_device *icd) { + struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd); + struct soc_camera_link *icl = mt9m111->client->dev.platform_data; int ret; ret = reg_set(RESET, MT9M111_RESET_RESET_MODE); @@ -401,6 +403,10 @@ static int mt9m111_reset(struct soc_camera_device *icd) if (!ret) ret = reg_clear(RESET, MT9M111_RESET_RESET_MODE | MT9M111_RESET_RESET_SOC); + + if (icl->reset) + icl->reset(&mt9m111->client->dev); + return ret; } -- cgit v1.2.3 From 8d97770a687b282184e85027628b030f8a5c53d2 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Thu, 19 Feb 2009 15:34:48 -0300 Subject: V4L/DVB (10679): gspca - sonixj: Handle the webcam 0c45:613c instead of sn9c102. Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/sonixj.c | 2 +- drivers/media/video/sn9c102/sn9c102_devtable.h | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/gspca/sonixj.c b/drivers/media/video/gspca/sonixj.c index 444d2dc4544a..edc26d8ad2ad 100644 --- a/drivers/media/video/gspca/sonixj.c +++ b/drivers/media/video/gspca/sonixj.c @@ -2160,9 +2160,9 @@ static const __devinitdata struct usb_device_id device_table[] = { {USB_DEVICE(0x0c45, 0x613a), BSI(SN9C120, OV7648, 0x21)}, #if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE {USB_DEVICE(0x0c45, 0x613b), BSI(SN9C120, OV7660, 0x21)}, +#endif {USB_DEVICE(0x0c45, 0x613c), BSI(SN9C120, HV7131R, 0x11)}, /* {USB_DEVICE(0x0c45, 0x613e), BSI(SN9C120, OV7630, 0x??)}, */ -#endif {USB_DEVICE(0x0c45, 0x6143), BSI(SN9C120, SP80708, 0x18)}, {} }; diff --git a/drivers/media/video/sn9c102/sn9c102_devtable.h b/drivers/media/video/sn9c102/sn9c102_devtable.h index 8cb3457e778d..41dfb60f4fb5 100644 --- a/drivers/media/video/sn9c102/sn9c102_devtable.h +++ b/drivers/media/video/sn9c102/sn9c102_devtable.h @@ -123,7 +123,9 @@ static const struct usb_device_id sn9c102_id_table[] = { { SN9C102_USB_DEVICE(0x0c45, 0x613a, BRIDGE_SN9C120), }, #endif { SN9C102_USB_DEVICE(0x0c45, 0x613b, BRIDGE_SN9C120), }, +#if !defined CONFIG_USB_GSPCA && !defined CONFIG_USB_GSPCA_MODULE { SN9C102_USB_DEVICE(0x0c45, 0x613c, BRIDGE_SN9C120), }, +#endif { SN9C102_USB_DEVICE(0x0c45, 0x613e, BRIDGE_SN9C120), }, { } }; -- cgit v1.2.3 From 603538a085e42c02b9b3184b6104d73e22a7e5d1 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Thu, 19 Feb 2009 15:38:31 -0300 Subject: V4L/DVB (10680): gspca - zc3xx: Bad probe of the ov7xxx sensors. This patch fixes one bug of the kernel bug report 12737. Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/zc3xx.c | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/gspca/zc3xx.c b/drivers/media/video/gspca/zc3xx.c index e6a6cb946a21..fb9b122ac61d 100644 --- a/drivers/media/video/gspca/zc3xx.c +++ b/drivers/media/video/gspca/zc3xx.c @@ -6987,7 +6987,7 @@ static int vga_3wr_probe(struct gspca_dev *gspca_dev) static int zcxx_probeSensor(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; - int sensor, sensor2; + int sensor; switch (sd->sensor) { case SENSOR_MC501CB: @@ -7002,16 +7002,9 @@ static int zcxx_probeSensor(struct gspca_dev *gspca_dev) break; } sensor = vga_2wr_probe(gspca_dev); - if (sensor >= 0) { - if (sensor < 0x7600) - return sensor; - /* next probe is needed for OmniVision ? */ - } - sensor2 = vga_3wr_probe(gspca_dev); - if (sensor2 >= 0 - && sensor >= 0) + if (sensor >= 0) return sensor; - return sensor2; + return vga_3wr_probe(gspca_dev); } /* this function is called at probe time */ -- cgit v1.2.3 From e2d750fcef6dd15afdf327c56156d85085eb4978 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Thu, 19 Feb 2009 15:41:28 -0300 Subject: V4L/DVB (10681): gspca - zc3xx: Bad probe of the ov7630c sensor. This patch fixes an other bug of the kernel bug report 12737. Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/zc3xx.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers/media/video') diff --git a/drivers/media/video/gspca/zc3xx.c b/drivers/media/video/gspca/zc3xx.c index fb9b122ac61d..4f459a746037 100644 --- a/drivers/media/video/gspca/zc3xx.c +++ b/drivers/media/video/gspca/zc3xx.c @@ -7141,6 +7141,10 @@ static int sd_config(struct gspca_dev *gspca_dev, PDEBUG(D_PROBE, "Find Sensor OV7620"); sd->sensor = SENSOR_OV7620; break; + case 0x7631: + PDEBUG(D_PROBE, "Find Sensor OV7630C"); + sd->sensor = SENSOR_OV7630C; + break; case 0x7648: PDEBUG(D_PROBE, "Find Sensor OV7648"); sd->sensor = SENSOR_OV7620; /* same sensor (?) */ -- cgit v1.2.3 From 11c469e6160f2f829819787bc86f177e7c5a3623 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 20 Feb 2009 05:50:52 -0300 Subject: V4L/DVB (10685): v4l2: add colorfx support to v4l2-common.c, and add to 'Changes' in spec. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/v4l2-common.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'drivers/media/video') diff --git a/drivers/media/video/v4l2-common.c b/drivers/media/video/v4l2-common.c index 7086f9f3c785..cc5f67801bd1 100644 --- a/drivers/media/video/v4l2-common.c +++ b/drivers/media/video/v4l2-common.c @@ -334,6 +334,12 @@ const char **v4l2_ctrl_get_menu(u32 id) "Aperture Priority Mode", NULL }; + static const char *colorfx[] = { + "None", + "Black & White", + "Sepia", + NULL + }; switch (id) { case V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ: @@ -370,6 +376,8 @@ const char **v4l2_ctrl_get_menu(u32 id) return camera_power_line_frequency; case V4L2_CID_EXPOSURE_AUTO: return camera_exposure_auto; + case V4L2_CID_COLORFX: + return colorfx; default: return NULL; } @@ -412,6 +420,7 @@ const char *v4l2_ctrl_get_name(u32 id) case V4L2_CID_BACKLIGHT_COMPENSATION: return "Backlight Compensation"; case V4L2_CID_CHROMA_AGC: return "Chroma AGC"; case V4L2_CID_COLOR_KILLER: return "Color Killer"; + case V4L2_CID_COLORFX: return "Color Effects"; /* MPEG controls */ case V4L2_CID_MPEG_CLASS: return "MPEG Encoder Controls"; @@ -517,6 +526,7 @@ int v4l2_ctrl_query_fill(struct v4l2_queryctrl *qctrl, s32 min, s32 max, s32 ste case V4L2_CID_MPEG_STREAM_TYPE: case V4L2_CID_MPEG_STREAM_VBI_FMT: case V4L2_CID_EXPOSURE_AUTO: + case V4L2_CID_COLORFX: qctrl->type = V4L2_CTRL_TYPE_MENU; step = 1; break; @@ -585,6 +595,8 @@ int v4l2_ctrl_query_fill_std(struct v4l2_queryctrl *qctrl) return v4l2_ctrl_query_fill(qctrl, 0, 127, 1, 64); case V4L2_CID_HUE: return v4l2_ctrl_query_fill(qctrl, -128, 127, 1, 0); + case V4L2_CID_COLORFX: + return v4l2_ctrl_query_fill(qctrl, 0, 1, 1, 0); /* MPEG controls */ case V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ: -- cgit v1.2.3 From 81dde91f640d6dea89229bb00c4ff38739fc1867 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 20 Feb 2009 06:30:12 -0300 Subject: V4L/DVB (10687): v4l2-common/v4l2-spec: support/document write-only and button controls The controls V4L2_CID_PAN_RESET and V4L2_CID_TILT_RESET changed their type to button controls (these are unused at the moment, so this is a safe change). The controls V4L2_CID_PAN_RELATIVE, V4L2_CID_TILT_RELATIVE, V4L2_CID_FOCUS_RELATIVE and V4L2_CID_ZOOM_RELATIVE are marked as write-only controls. Cc: Laurent Pinchart Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/v4l2-common.c | 29 ++++++++++++++++++++++++----- 1 file changed, 24 insertions(+), 5 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/v4l2-common.c b/drivers/media/video/v4l2-common.c index cc5f67801bd1..bca4daf87a12 100644 --- a/drivers/media/video/v4l2-common.c +++ b/drivers/media/video/v4l2-common.c @@ -390,16 +390,16 @@ const char *v4l2_ctrl_get_name(u32 id) switch (id) { /* USER controls */ case V4L2_CID_USER_CLASS: return "User Controls"; + case V4L2_CID_BRIGHTNESS: return "Brightness"; + case V4L2_CID_CONTRAST: return "Contrast"; + case V4L2_CID_SATURATION: return "Saturation"; + case V4L2_CID_HUE: return "Hue"; case V4L2_CID_AUDIO_VOLUME: return "Volume"; - case V4L2_CID_AUDIO_MUTE: return "Mute"; case V4L2_CID_AUDIO_BALANCE: return "Balance"; case V4L2_CID_AUDIO_BASS: return "Bass"; case V4L2_CID_AUDIO_TREBLE: return "Treble"; + case V4L2_CID_AUDIO_MUTE: return "Mute"; case V4L2_CID_AUDIO_LOUDNESS: return "Loudness"; - case V4L2_CID_BRIGHTNESS: return "Brightness"; - case V4L2_CID_CONTRAST: return "Contrast"; - case V4L2_CID_SATURATION: return "Saturation"; - case V4L2_CID_HUE: return "Hue"; case V4L2_CID_BLACK_LEVEL: return "Black Level"; case V4L2_CID_AUTO_WHITE_BALANCE: return "White Balance, Automatic"; case V4L2_CID_DO_WHITE_BALANCE: return "Do White Balance"; @@ -499,16 +499,25 @@ int v4l2_ctrl_query_fill(struct v4l2_queryctrl *qctrl, s32 min, s32 max, s32 ste case V4L2_CID_HFLIP: case V4L2_CID_VFLIP: case V4L2_CID_HUE_AUTO: + case V4L2_CID_CHROMA_AGC: + case V4L2_CID_COLOR_KILLER: case V4L2_CID_MPEG_AUDIO_MUTE: case V4L2_CID_MPEG_VIDEO_MUTE: case V4L2_CID_MPEG_VIDEO_GOP_CLOSURE: case V4L2_CID_MPEG_VIDEO_PULLDOWN: case V4L2_CID_EXPOSURE_AUTO_PRIORITY: + case V4L2_CID_FOCUS_AUTO: case V4L2_CID_PRIVACY: qctrl->type = V4L2_CTRL_TYPE_BOOLEAN; min = 0; max = step = 1; break; + case V4L2_CID_PAN_RESET: + case V4L2_CID_TILT_RESET: + qctrl->type = V4L2_CTRL_TYPE_BUTTON; + qctrl->flags |= V4L2_CTRL_FLAG_WRITE_ONLY; + min = max = step = def = 0; + break; case V4L2_CID_POWER_LINE_FREQUENCY: case V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ: case V4L2_CID_MPEG_AUDIO_ENCODING: @@ -557,8 +566,17 @@ int v4l2_ctrl_query_fill(struct v4l2_queryctrl *qctrl, s32 min, s32 max, s32 ste case V4L2_CID_CONTRAST: case V4L2_CID_SATURATION: case V4L2_CID_HUE: + case V4L2_CID_RED_BALANCE: + case V4L2_CID_BLUE_BALANCE: + case V4L2_CID_GAMMA: qctrl->flags |= V4L2_CTRL_FLAG_SLIDER; break; + case V4L2_CID_PAN_RELATIVE: + case V4L2_CID_TILT_RELATIVE: + case V4L2_CID_FOCUS_RELATIVE: + case V4L2_CID_ZOOM_RELATIVE: + qctrl->flags |= V4L2_CTRL_FLAG_WRITE_ONLY; + break; } qctrl->minimum = min; qctrl->maximum = max; @@ -578,6 +596,7 @@ int v4l2_ctrl_query_fill_std(struct v4l2_queryctrl *qctrl) /* USER controls */ case V4L2_CID_USER_CLASS: case V4L2_CID_MPEG_CLASS: + case V4L2_CID_CAMERA_CLASS: return v4l2_ctrl_query_fill(qctrl, 0, 0, 0, 0); case V4L2_CID_AUDIO_VOLUME: return v4l2_ctrl_query_fill(qctrl, 0, 65535, 65535 / 100, 58880); -- cgit v1.2.3 From ab373190813a2e89f9ab7338c6b106804611f2b7 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sat, 21 Feb 2009 18:08:41 -0300 Subject: V4L/DVB (10691): v4l2-common: add v4l2_i2c_subdev_addr() Add small function to retrieve the i2c address from a v4l2_subdev pointer. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/v4l2-common.c | 9 +++++++++ include/media/v4l2-common.h | 2 ++ 2 files changed, 11 insertions(+) (limited to 'drivers/media/video') diff --git a/drivers/media/video/v4l2-common.c b/drivers/media/video/v4l2-common.c index bca4daf87a12..caa7ba0705a5 100644 --- a/drivers/media/video/v4l2-common.c +++ b/drivers/media/video/v4l2-common.c @@ -1022,6 +1022,15 @@ struct v4l2_subdev *v4l2_i2c_new_probed_subdev(struct i2c_adapter *adapter, } EXPORT_SYMBOL_GPL(v4l2_i2c_new_probed_subdev); +/* Return i2c client address of v4l2_subdev. */ +unsigned short v4l2_i2c_subdev_addr(struct v4l2_subdev *sd) +{ + struct i2c_client *client = v4l2_get_subdevdata(sd); + + return client ? client->addr : I2C_CLIENT_END; +} +EXPORT_SYMBOL_GPL(v4l2_i2c_subdev_addr); + /* Return a list of I2C tuner addresses to probe. Use only if the tuner addresses are unknown. */ const unsigned short *v4l2_i2c_tuner_addrs(enum v4l2_i2c_tuner_type type) diff --git a/include/media/v4l2-common.h b/include/media/v4l2-common.h index de785da4564c..7779d9c93ec8 100644 --- a/include/media/v4l2-common.h +++ b/include/media/v4l2-common.h @@ -154,6 +154,8 @@ struct v4l2_subdev *v4l2_i2c_new_probed_subdev(struct i2c_adapter *adapter, /* Initialize an v4l2_subdev with data from an i2c_client struct */ void v4l2_i2c_subdev_init(struct v4l2_subdev *sd, struct i2c_client *client, const struct v4l2_subdev_ops *ops); +/* Return i2c client address of v4l2_subdev. */ +unsigned short v4l2_i2c_subdev_addr(struct v4l2_subdev *sd); enum v4l2_i2c_tuner_type { ADDRS_RADIO, /* Radio tuner addresses */ -- cgit v1.2.3 From 1df795370c1392a026c63816368108187aec2ec1 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sat, 21 Feb 2009 18:11:31 -0300 Subject: V4L/DVB (10692): usbvision: convert to v4l2_device/v4l2_subdev. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/usbvision/usbvision-core.c | 2 +- drivers/media/video/usbvision/usbvision-i2c.c | 147 +++++++----------------- drivers/media/video/usbvision/usbvision-video.c | 63 +++++----- drivers/media/video/usbvision/usbvision.h | 8 +- 4 files changed, 75 insertions(+), 145 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/usbvision/usbvision-core.c b/drivers/media/video/usbvision/usbvision-core.c index 4444e7e3cdf8..eadebb91b092 100644 --- a/drivers/media/video/usbvision/usbvision-core.c +++ b/drivers/media/video/usbvision/usbvision-core.c @@ -2633,7 +2633,7 @@ int usbvision_muxsel(struct usb_usbvision *usbvision, int channel) } route.input = mode[channel]; route.output = 0; - call_i2c_clients(usbvision, VIDIOC_INT_S_VIDEO_ROUTING,&route); + call_all(usbvision, video, s_routing, &route); usbvision_set_audio(usbvision, audio[channel]); return 0; } diff --git a/drivers/media/video/usbvision/usbvision-i2c.c b/drivers/media/video/usbvision/usbvision-i2c.c index 6057098282ca..dd2f8f27c73b 100644 --- a/drivers/media/video/usbvision/usbvision-i2c.c +++ b/drivers/media/video/usbvision/usbvision-i2c.c @@ -202,72 +202,78 @@ static struct i2c_algorithm usbvision_algo = { }; -/* - * registering functions to load algorithms at runtime - */ -static int usbvision_i2c_usb_add_bus(struct i2c_adapter *adap) -{ - PDEBUG(DBG_I2C, "I2C debugging is enabled [i2c]"); - PDEBUG(DBG_I2C, "ALGO debugging is enabled [i2c]"); - - /* register new adapter to i2c module... */ - - adap->algo = &usbvision_algo; - - adap->timeout = 100; /* default values, should */ - adap->retries = 3; /* be replaced by defines */ - - i2c_add_adapter(adap); - - PDEBUG(DBG_I2C,"i2c bus for %s registered", adap->name); - - return 0; -} - /* ----------------------------------------------------------------------- */ /* usbvision specific I2C functions */ /* ----------------------------------------------------------------------- */ static struct i2c_adapter i2c_adap_template; -static struct i2c_client i2c_client_template; int usbvision_i2c_register(struct usb_usbvision *usbvision) { + static unsigned short saa711x_addrs[] = { + 0x4a >> 1, 0x48 >> 1, /* SAA7111, SAA7111A and SAA7113 */ + 0x42 >> 1, 0x40 >> 1, /* SAA7114, SAA7115 and SAA7118 */ + I2C_CLIENT_END }; + memcpy(&usbvision->i2c_adap, &i2c_adap_template, sizeof(struct i2c_adapter)); - memcpy(&usbvision->i2c_client, &i2c_client_template, - sizeof(struct i2c_client)); sprintf(usbvision->i2c_adap.name + strlen(usbvision->i2c_adap.name), " #%d", usbvision->vdev->num); PDEBUG(DBG_I2C,"Adaptername: %s", usbvision->i2c_adap.name); usbvision->i2c_adap.dev.parent = &usbvision->dev->dev; - i2c_set_adapdata(&usbvision->i2c_adap, usbvision); - i2c_set_clientdata(&usbvision->i2c_client, usbvision); - - usbvision->i2c_client.adapter = &usbvision->i2c_adap; + i2c_set_adapdata(&usbvision->i2c_adap, &usbvision->v4l2_dev); if (usbvision_write_reg(usbvision, USBVISION_SER_MODE, USBVISION_IIC_LRNACK) < 0) { printk(KERN_ERR "usbvision_register: can't write reg\n"); return -EBUSY; } -#ifdef CONFIG_MODULES + PDEBUG(DBG_I2C, "I2C debugging is enabled [i2c]"); + PDEBUG(DBG_I2C, "ALGO debugging is enabled [i2c]"); + + /* register new adapter to i2c module... */ + + usbvision->i2c_adap.algo = &usbvision_algo; + + usbvision->i2c_adap.timeout = 100; /* default values, should */ + usbvision->i2c_adap.retries = 3; /* be replaced by defines */ + + i2c_add_adapter(&usbvision->i2c_adap); + + PDEBUG(DBG_I2C, "i2c bus for %s registered", usbvision->i2c_adap.name); + /* Request the load of the i2c modules we need */ switch (usbvision_device_data[usbvision->DevModel].Codec) { case CODEC_SAA7113: - request_module("saa7115"); - break; case CODEC_SAA7111: - request_module("saa7115"); + v4l2_i2c_new_probed_subdev(&usbvision->i2c_adap, "saa7115", + "saa7115_auto", saa711x_addrs); break; } if (usbvision_device_data[usbvision->DevModel].Tuner == 1) { - request_module("tuner"); + struct v4l2_subdev *sd; + enum v4l2_i2c_tuner_type type; + struct tuner_setup tun_setup; + + sd = v4l2_i2c_new_probed_subdev(&usbvision->i2c_adap, "tuner", + "tuner", v4l2_i2c_tuner_addrs(ADDRS_DEMOD)); + /* depending on whether we found a demod or not, select + the tuner type. */ + type = sd ? ADDRS_TV_WITH_DEMOD : ADDRS_TV; + + sd = v4l2_i2c_new_probed_subdev(&usbvision->i2c_adap, "tuner", + "tuner", v4l2_i2c_tuner_addrs(type)); + + if (usbvision->tuner_type != -1) { + tun_setup.mode_mask = T_ANALOG_TV | T_RADIO; + tun_setup.type = usbvision->tuner_type; + tun_setup.addr = v4l2_i2c_subdev_addr(sd); + call_all(usbvision, tuner, s_type_addr, &tun_setup); + } } -#endif - return usbvision_i2c_usb_add_bus(&usbvision->i2c_adap); + return 0; } int usbvision_i2c_unregister(struct usb_usbvision *usbvision) @@ -280,67 +286,6 @@ int usbvision_i2c_unregister(struct usb_usbvision *usbvision) return 0; } -void call_i2c_clients(struct usb_usbvision *usbvision, unsigned int cmd, - void *arg) -{ - i2c_clients_command(&usbvision->i2c_adap, cmd, arg); -} - -static int attach_inform(struct i2c_client *client) -{ - struct usb_usbvision *usbvision; - - usbvision = (struct usb_usbvision *)i2c_get_adapdata(client->adapter); - - switch (client->addr << 1) { - case 0x42 << 1: - case 0x43 << 1: - case 0x4a << 1: - case 0x4b << 1: - PDEBUG(DBG_I2C,"attach_inform: tda9887 detected."); - break; - case 0x42: - PDEBUG(DBG_I2C,"attach_inform: saa7114 detected."); - break; - case 0x4a: - PDEBUG(DBG_I2C,"attach_inform: saa7113 detected."); - break; - case 0x48: - PDEBUG(DBG_I2C,"attach_inform: saa7111 detected."); - break; - case 0xa0: - PDEBUG(DBG_I2C,"attach_inform: eeprom detected."); - break; - - default: - { - struct tuner_setup tun_setup; - - PDEBUG(DBG_I2C,"attach inform: detected I2C address %x", client->addr << 1); - usbvision->tuner_addr = client->addr; - - if ((usbvision->have_tuner) && (usbvision->tuner_type != -1)) { - tun_setup.mode_mask = T_ANALOG_TV | T_RADIO; - tun_setup.type = usbvision->tuner_type; - tun_setup.addr = usbvision->tuner_addr; - call_i2c_clients(usbvision, TUNER_SET_TYPE_ADDR, &tun_setup); - } - } - break; - } - return 0; -} - -static int detach_inform(struct i2c_client *client) -{ - struct usb_usbvision *usbvision; - - usbvision = (struct usb_usbvision *)i2c_get_adapdata(client->adapter); - - PDEBUG(DBG_I2C,"usbvision[%d] detaches %s", usbvision->nr, client->name); - return 0; -} - static int usbvision_i2c_read_max4(struct usb_usbvision *usbvision, unsigned char addr, char *buf, short len) @@ -513,14 +458,6 @@ static int usbvision_i2c_read(struct usb_usbvision *usbvision, unsigned char add static struct i2c_adapter i2c_adap_template = { .owner = THIS_MODULE, .name = "usbvision", - .id = I2C_HW_B_BT848, /* FIXME */ - .client_register = attach_inform, - .client_unregister = detach_inform, - .class = I2C_CLASS_TV_ANALOG, -}; - -static struct i2c_client i2c_client_template = { - .name = "usbvision internal", }; /* diff --git a/drivers/media/video/usbvision/usbvision-video.c b/drivers/media/video/usbvision/usbvision-video.c index 334c77d9116f..cfa184d63c65 100644 --- a/drivers/media/video/usbvision/usbvision-video.c +++ b/drivers/media/video/usbvision/usbvision-video.c @@ -212,7 +212,7 @@ static ssize_t show_hue(struct device *cd, ctrl.id = V4L2_CID_HUE; ctrl.value = 0; if(usbvision->user) - call_i2c_clients(usbvision, VIDIOC_G_CTRL, &ctrl); + call_all(usbvision, core, g_ctrl, &ctrl); return sprintf(buf, "%d\n", ctrl.value); } static DEVICE_ATTR(hue, S_IRUGO, show_hue, NULL); @@ -227,7 +227,7 @@ static ssize_t show_contrast(struct device *cd, ctrl.id = V4L2_CID_CONTRAST; ctrl.value = 0; if(usbvision->user) - call_i2c_clients(usbvision, VIDIOC_G_CTRL, &ctrl); + call_all(usbvision, core, g_ctrl, &ctrl); return sprintf(buf, "%d\n", ctrl.value); } static DEVICE_ATTR(contrast, S_IRUGO, show_contrast, NULL); @@ -242,7 +242,7 @@ static ssize_t show_brightness(struct device *cd, ctrl.id = V4L2_CID_BRIGHTNESS; ctrl.value = 0; if(usbvision->user) - call_i2c_clients(usbvision, VIDIOC_G_CTRL, &ctrl); + call_all(usbvision, core, g_ctrl, &ctrl); return sprintf(buf, "%d\n", ctrl.value); } static DEVICE_ATTR(brightness, S_IRUGO, show_brightness, NULL); @@ -257,7 +257,7 @@ static ssize_t show_saturation(struct device *cd, ctrl.id = V4L2_CID_SATURATION; ctrl.value = 0; if(usbvision->user) - call_i2c_clients(usbvision, VIDIOC_G_CTRL, &ctrl); + call_all(usbvision, core, g_ctrl, &ctrl); return sprintf(buf, "%d\n", ctrl.value); } static DEVICE_ATTR(saturation, S_IRUGO, show_saturation, NULL); @@ -622,8 +622,7 @@ static int vidioc_s_std (struct file *file, void *priv, v4l2_std_id *id) usbvision->tvnormId=*id; mutex_lock(&usbvision->lock); - call_i2c_clients(usbvision, VIDIOC_S_STD, - &usbvision->tvnormId); + call_all(usbvision, tuner, s_std, usbvision->tvnormId); mutex_unlock(&usbvision->lock); /* propagate the change to the decoder */ usbvision_muxsel(usbvision, usbvision->ctl_input); @@ -645,7 +644,7 @@ static int vidioc_g_tuner (struct file *file, void *priv, strcpy(vt->name, "Television"); } /* Let clients fill in the remainder of this struct */ - call_i2c_clients(usbvision,VIDIOC_G_TUNER,vt); + call_all(usbvision, tuner, g_tuner, vt); return 0; } @@ -659,7 +658,7 @@ static int vidioc_s_tuner (struct file *file, void *priv, if (!usbvision->have_tuner || vt->index) return -EINVAL; /* let clients handle this */ - call_i2c_clients(usbvision,VIDIOC_S_TUNER,vt); + call_all(usbvision, tuner, s_tuner, vt); return 0; } @@ -690,7 +689,7 @@ static int vidioc_s_frequency (struct file *file, void *priv, return -EINVAL; usbvision->freq = freq->frequency; - call_i2c_clients(usbvision, VIDIOC_S_FREQUENCY, freq); + call_all(usbvision, tuner, s_frequency, freq); return 0; } @@ -728,7 +727,7 @@ static int vidioc_queryctrl (struct file *file, void *priv, memset(ctrl,0,sizeof(*ctrl)); ctrl->id=id; - call_i2c_clients(usbvision, VIDIOC_QUERYCTRL, ctrl); + call_all(usbvision, core, queryctrl, ctrl); if (!ctrl->type) return -EINVAL; @@ -740,7 +739,7 @@ static int vidioc_g_ctrl (struct file *file, void *priv, struct v4l2_control *ctrl) { struct usb_usbvision *usbvision = video_drvdata(file); - call_i2c_clients(usbvision, VIDIOC_G_CTRL, ctrl); + call_all(usbvision, core, g_ctrl, ctrl); return 0; } @@ -749,7 +748,7 @@ static int vidioc_s_ctrl (struct file *file, void *priv, struct v4l2_control *ctrl) { struct usb_usbvision *usbvision = video_drvdata(file); - call_i2c_clients(usbvision, VIDIOC_S_CTRL, ctrl); + call_all(usbvision, core, s_ctrl, ctrl); return 0; } @@ -900,10 +899,9 @@ static int vidioc_dqbuf (struct file *file, void *priv, struct v4l2_buffer *vb) static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i) { struct usb_usbvision *usbvision = video_drvdata(file); - int b=V4L2_BUF_TYPE_VIDEO_CAPTURE; usbvision->streaming = Stream_On; - call_i2c_clients(usbvision,VIDIOC_STREAMON , &b); + call_all(usbvision, video, s_stream, 1); return 0; } @@ -912,7 +910,6 @@ static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type type) { struct usb_usbvision *usbvision = video_drvdata(file); - int b=V4L2_BUF_TYPE_VIDEO_CAPTURE; if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE) return -EINVAL; @@ -920,7 +917,7 @@ static int vidioc_streamoff(struct file *file, if(usbvision->streaming == Stream_On) { usbvision_stream_interrupt(usbvision); /* Stop all video streamings */ - call_i2c_clients(usbvision,VIDIOC_STREAMOFF , &b); + call_all(usbvision, video, s_stream, 0); } usbvision_empty_framequeues(usbvision); @@ -1043,7 +1040,7 @@ static ssize_t usbvision_v4l2_read(struct file *file, char __user *buf, if(usbvision->streaming != Stream_On) { /* no stream is running, make it running ! */ usbvision->streaming = Stream_On; - call_i2c_clients(usbvision,VIDIOC_STREAMON , NULL); + call_all(usbvision, video, s_stream, 1); } /* Then, enqueue as many frames as possible @@ -1214,7 +1211,7 @@ static int usbvision_radio_open(struct file *file) // If so far no errors then we shall start the radio usbvision->radio = 1; - call_i2c_clients(usbvision,AUDC_SET_RADIO,&usbvision->tuner_type); + call_all(usbvision, tuner, s_radio); usbvision_set_audio(usbvision, USBVISION_AUDIO_RADIO); usbvision->user++; } @@ -1427,7 +1424,7 @@ static struct video_device *usbvision_vdev_init(struct usb_usbvision *usbvision, } *vdev = *vdev_template; // vdev->minor = -1; - vdev->parent = &usb_dev->dev; + vdev->v4l2_dev = &usbvision->v4l2_dev; snprintf(vdev->name, sizeof(vdev->name), "%s", name); video_set_drvdata(vdev, usbvision); return vdev; @@ -1548,33 +1545,30 @@ static struct usb_usbvision *usbvision_alloc(struct usb_device *dev) { struct usb_usbvision *usbvision; - if ((usbvision = kzalloc(sizeof(struct usb_usbvision), GFP_KERNEL)) == - NULL) { - goto err_exit; - } + usbvision = kzalloc(sizeof(struct usb_usbvision), GFP_KERNEL); + if (usbvision == NULL) + return NULL; usbvision->dev = dev; + if (v4l2_device_register(&dev->dev, &usbvision->v4l2_dev)) + goto err_free; mutex_init(&usbvision->lock); /* available */ // prepare control urb for control messages during interrupts usbvision->ctrlUrb = usb_alloc_urb(USBVISION_URB_FRAMES, GFP_KERNEL); - if (usbvision->ctrlUrb == NULL) { - goto err_exit; - } + if (usbvision->ctrlUrb == NULL) + goto err_unreg; init_waitqueue_head(&usbvision->ctrlUrb_wq); usbvision_init_powerOffTimer(usbvision); return usbvision; -err_exit: - if (usbvision && usbvision->ctrlUrb) { - usb_free_urb(usbvision->ctrlUrb); - } - if (usbvision) { - kfree(usbvision); - } +err_unreg: + v4l2_device_unregister(&usbvision->v4l2_dev); +err_free: + kfree(usbvision); return NULL; } @@ -1604,6 +1598,7 @@ static void usbvision_release(struct usb_usbvision *usbvision) usb_free_urb(usbvision->ctrlUrb); } + v4l2_device_unregister(&usbvision->v4l2_dev); kfree(usbvision); PDEBUG(DBG_PROBE, "success"); @@ -1739,8 +1734,6 @@ static int __devinit usbvision_probe(struct usb_interface *intf, usbvision->tuner_type = usbvision_device_data[model].TunerType; } - usbvision->tuner_addr = ADDR_UNSET; - usbvision->DevModel = model; usbvision->remove_pending = 0; usbvision->iface = ifnum; diff --git a/drivers/media/video/usbvision/usbvision.h b/drivers/media/video/usbvision/usbvision.h index 20d7ec624999..06fe43655957 100644 --- a/drivers/media/video/usbvision/usbvision.h +++ b/drivers/media/video/usbvision/usbvision.h @@ -35,7 +35,7 @@ #include #include #include -#include +#include #include #include @@ -357,13 +357,13 @@ extern struct usbvision_device_data_st usbvision_device_data[]; extern struct usb_device_id usbvision_table[]; struct usb_usbvision { + struct v4l2_device v4l2_dev; struct video_device *vdev; /* Video Device */ struct video_device *rdev; /* Radio Device */ struct video_device *vbi; /* VBI Device */ /* i2c Declaration Section*/ struct i2c_adapter i2c_adap; - struct i2c_client i2c_client; struct urb *ctrlUrb; unsigned char ctrlUrbBuffer[8]; @@ -374,7 +374,6 @@ struct usb_usbvision { /* configuration part */ int have_tuner; int tuner_type; - int tuner_addr; int bridgeType; // NT1003, NT1004, NT1005 int radio; int video_inputs; // # of inputs @@ -464,6 +463,8 @@ struct usb_usbvision { int ComprBlockTypes[4]; }; +#define call_all(usbvision, o, f, args...) \ + v4l2_device_call_all(&usbvision->v4l2_dev, 0, o, f, ##args) /* --------------------------------------------------------------- */ /* defined in usbvision-i2c.c */ @@ -475,7 +476,6 @@ struct usb_usbvision { /* ----------------------------------------------------------------------- */ int usbvision_i2c_register(struct usb_usbvision *usbvision); int usbvision_i2c_unregister(struct usb_usbvision *usbvision); -void call_i2c_clients(struct usb_usbvision *usbvision, unsigned int cmd,void *arg); /* defined in usbvision-core.c */ int usbvision_read_reg(struct usb_usbvision *usbvision, unsigned char reg); -- cgit v1.2.3 From 10afbef15e7bba5e1008f583852077743d28c395 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sat, 21 Feb 2009 18:47:24 -0300 Subject: V4L/DVB (10698): v4l2-common: remove v4l2_ctrl_query_fill_std The v4l2_ctrl_query_fill_std() function wasn't one the best idea I ever had. It doesn't add anything valuable that cannot be expressed equally well with v4l2_ctrl_query_fill and only adds overhead. Replace it with v4l2_ctrl_query_fill() everywhere it is used and remove it from v4l2_common.c. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx18/cx18-av-core.c | 7 +- drivers/media/video/cx2341x.c | 108 +++++++++++++++---- drivers/media/video/cx25840/cx25840-core.c | 7 +- drivers/media/video/msp3400-driver.c | 26 ++--- drivers/media/video/saa7115.c | 4 +- drivers/media/video/saa7134/saa6752hs.c | 12 ++- drivers/media/video/saa7134/saa7134-empress.c | 2 +- drivers/media/video/tda7432.c | 6 +- drivers/media/video/tda9875.c | 3 +- drivers/media/video/tvaudio.c | 17 +-- drivers/media/video/tvp514x.c | 5 +- drivers/media/video/v4l2-common.c | 145 -------------------------- include/media/v4l2-common.h | 1 - 13 files changed, 141 insertions(+), 202 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/cx18/cx18-av-core.c b/drivers/media/video/cx18/cx18-av-core.c index a3bd2c95f582..fc576cf1a8b5 100644 --- a/drivers/media/video/cx18/cx18-av-core.c +++ b/drivers/media/video/cx18/cx18-av-core.c @@ -788,10 +788,12 @@ int cx18_av_cmd(struct cx18 *cx, unsigned int cmd, void *arg) switch (qc->id) { case V4L2_CID_BRIGHTNESS: + return v4l2_ctrl_query_fill(qc, 0, 255, 1, 128); case V4L2_CID_CONTRAST: case V4L2_CID_SATURATION: + return v4l2_ctrl_query_fill(qc, 0, 127, 1, 64); case V4L2_CID_HUE: - return v4l2_ctrl_query_fill_std(qc); + return v4l2_ctrl_query_fill(qc, -128, 127, 1, 0); default: break; } @@ -801,10 +803,11 @@ int cx18_av_cmd(struct cx18 *cx, unsigned int cmd, void *arg) return v4l2_ctrl_query_fill(qc, 0, 65535, 65535 / 100, state->default_volume); case V4L2_CID_AUDIO_MUTE: + return v4l2_ctrl_query_fill(qc, 0, 1, 1, 0); case V4L2_CID_AUDIO_BALANCE: case V4L2_CID_AUDIO_BASS: case V4L2_CID_AUDIO_TREBLE: - return v4l2_ctrl_query_fill_std(qc); + return v4l2_ctrl_query_fill(qc, 0, 65535, 65535 / 100, 32768); default: return -EINVAL; } diff --git a/drivers/media/video/cx2341x.c b/drivers/media/video/cx2341x.c index b36f522d2c55..8ded52946334 100644 --- a/drivers/media/video/cx2341x.c +++ b/drivers/media/video/cx2341x.c @@ -500,6 +500,29 @@ int cx2341x_ctrl_query(const struct cx2341x_mpeg_params *params, int err; switch (qctrl->id) { + case V4L2_CID_MPEG_STREAM_TYPE: + return v4l2_ctrl_query_fill(qctrl, + V4L2_MPEG_STREAM_TYPE_MPEG2_PS, + V4L2_MPEG_STREAM_TYPE_MPEG2_SVCD, 1, + V4L2_MPEG_STREAM_TYPE_MPEG2_PS); + + case V4L2_CID_MPEG_STREAM_VBI_FMT: + if (params->capabilities & CX2341X_CAP_HAS_SLICED_VBI) + return v4l2_ctrl_query_fill(qctrl, + V4L2_MPEG_STREAM_VBI_FMT_NONE, + V4L2_MPEG_STREAM_VBI_FMT_IVTV, 1, + V4L2_MPEG_STREAM_VBI_FMT_NONE); + return cx2341x_ctrl_query_fill(qctrl, + V4L2_MPEG_STREAM_VBI_FMT_NONE, + V4L2_MPEG_STREAM_VBI_FMT_NONE, 1, + default_params.stream_vbi_fmt); + + case V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ: + return v4l2_ctrl_query_fill(qctrl, + V4L2_MPEG_AUDIO_SAMPLING_FREQ_44100, + V4L2_MPEG_AUDIO_SAMPLING_FREQ_32000, 1, + V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000); + case V4L2_CID_MPEG_AUDIO_ENCODING: if (params->capabilities & CX2341X_CAP_HAS_AC3) { /* @@ -531,9 +554,36 @@ int cx2341x_ctrl_query(const struct cx2341x_mpeg_params *params, qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE; return 0; - case V4L2_CID_MPEG_AUDIO_L1_BITRATE: - case V4L2_CID_MPEG_AUDIO_L3_BITRATE: - return -EINVAL; + case V4L2_CID_MPEG_AUDIO_MODE: + return v4l2_ctrl_query_fill(qctrl, + V4L2_MPEG_AUDIO_MODE_STEREO, + V4L2_MPEG_AUDIO_MODE_MONO, 1, + V4L2_MPEG_AUDIO_MODE_STEREO); + + case V4L2_CID_MPEG_AUDIO_MODE_EXTENSION: + err = v4l2_ctrl_query_fill(qctrl, + V4L2_MPEG_AUDIO_MODE_EXTENSION_BOUND_4, + V4L2_MPEG_AUDIO_MODE_EXTENSION_BOUND_16, 1, + V4L2_MPEG_AUDIO_MODE_EXTENSION_BOUND_4); + if (err == 0 && + params->audio_mode != V4L2_MPEG_AUDIO_MODE_JOINT_STEREO) + qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE; + return err; + + case V4L2_CID_MPEG_AUDIO_EMPHASIS: + return v4l2_ctrl_query_fill(qctrl, + V4L2_MPEG_AUDIO_EMPHASIS_NONE, + V4L2_MPEG_AUDIO_EMPHASIS_CCITT_J17, 1, + V4L2_MPEG_AUDIO_EMPHASIS_NONE); + + case V4L2_CID_MPEG_AUDIO_CRC: + return v4l2_ctrl_query_fill(qctrl, + V4L2_MPEG_AUDIO_CRC_NONE, + V4L2_MPEG_AUDIO_CRC_CRC16, 1, + V4L2_MPEG_AUDIO_CRC_NONE); + + case V4L2_CID_MPEG_AUDIO_MUTE: + return v4l2_ctrl_query_fill(qctrl, 0, 1, 1, 0); case V4L2_CID_MPEG_AUDIO_AC3_BITRATE: err = v4l2_ctrl_query_fill(qctrl, @@ -550,13 +600,6 @@ int cx2341x_ctrl_query(const struct cx2341x_mpeg_params *params, qctrl->flags |= V4L2_CTRL_FLAG_DISABLED; return 0; - case V4L2_CID_MPEG_AUDIO_MODE_EXTENSION: - err = v4l2_ctrl_query_fill_std(qctrl); - if (err == 0 && - params->audio_mode != V4L2_MPEG_AUDIO_MODE_JOINT_STEREO) - qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE; - return err; - case V4L2_CID_MPEG_VIDEO_ENCODING: /* this setting is read-only for the cx2341x since the V4L2_CID_MPEG_STREAM_TYPE really determines the @@ -569,32 +612,51 @@ int cx2341x_ctrl_query(const struct cx2341x_mpeg_params *params, qctrl->flags |= V4L2_CTRL_FLAG_READ_ONLY; return err; + case V4L2_CID_MPEG_VIDEO_ASPECT: + return v4l2_ctrl_query_fill(qctrl, + V4L2_MPEG_VIDEO_ASPECT_1x1, + V4L2_MPEG_VIDEO_ASPECT_221x100, 1, + V4L2_MPEG_VIDEO_ASPECT_4x3); + + case V4L2_CID_MPEG_VIDEO_B_FRAMES: + return v4l2_ctrl_query_fill(qctrl, 0, 33, 1, 2); + + case V4L2_CID_MPEG_VIDEO_GOP_SIZE: + return v4l2_ctrl_query_fill(qctrl, 1, 34, 1, + params->is_50hz ? 12 : 15); + + case V4L2_CID_MPEG_VIDEO_GOP_CLOSURE: + return v4l2_ctrl_query_fill(qctrl, 0, 1, 1, 1); + case V4L2_CID_MPEG_VIDEO_BITRATE_MODE: - err = v4l2_ctrl_query_fill_std(qctrl); + err = v4l2_ctrl_query_fill(qctrl, + V4L2_MPEG_VIDEO_BITRATE_MODE_VBR, + V4L2_MPEG_VIDEO_BITRATE_MODE_CBR, 1, + V4L2_MPEG_VIDEO_BITRATE_MODE_VBR); if (err == 0 && params->video_encoding == V4L2_MPEG_VIDEO_ENCODING_MPEG_1) qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE; return err; + case V4L2_CID_MPEG_VIDEO_BITRATE: + return v4l2_ctrl_query_fill(qctrl, 0, 27000000, 1, 6000000); + case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK: - err = v4l2_ctrl_query_fill_std(qctrl); + err = v4l2_ctrl_query_fill(qctrl, 0, 27000000, 1, 8000000); if (err == 0 && params->video_bitrate_mode == V4L2_MPEG_VIDEO_BITRATE_MODE_CBR) qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE; return err; - case V4L2_CID_MPEG_STREAM_VBI_FMT: - if (params->capabilities & CX2341X_CAP_HAS_SLICED_VBI) - return v4l2_ctrl_query_fill_std(qctrl); - return cx2341x_ctrl_query_fill(qctrl, - V4L2_MPEG_STREAM_VBI_FMT_NONE, - V4L2_MPEG_STREAM_VBI_FMT_NONE, 1, - default_params.stream_vbi_fmt); + case V4L2_CID_MPEG_VIDEO_TEMPORAL_DECIMATION: + return v4l2_ctrl_query_fill(qctrl, 0, 255, 1, 0); - case V4L2_CID_MPEG_VIDEO_GOP_SIZE: - return v4l2_ctrl_query_fill(qctrl, 1, 34, 1, - params->is_50hz ? 12 : 15); + case V4L2_CID_MPEG_VIDEO_MUTE: + return v4l2_ctrl_query_fill(qctrl, 0, 1, 1, 0); + + case V4L2_CID_MPEG_VIDEO_MUTE_YUV: /* Init YUV (really YCbCr) to black */ + return v4l2_ctrl_query_fill(qctrl, 0, 0xffffff, 1, 0x008080); /* CX23415/6 specific */ case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE: @@ -696,7 +758,7 @@ int cx2341x_ctrl_query(const struct cx2341x_mpeg_params *params, default_params.stream_insert_nav_packets); default: - return v4l2_ctrl_query_fill_std(qctrl); + return -EINVAL; } } diff --git a/drivers/media/video/cx25840/cx25840-core.c b/drivers/media/video/cx25840/cx25840-core.c index d4059ecaa58e..4a5d5ef9dfc7 100644 --- a/drivers/media/video/cx25840/cx25840-core.c +++ b/drivers/media/video/cx25840/cx25840-core.c @@ -1205,10 +1205,12 @@ static int cx25840_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qc) switch (qc->id) { case V4L2_CID_BRIGHTNESS: + return v4l2_ctrl_query_fill(qc, 0, 255, 1, 128); case V4L2_CID_CONTRAST: case V4L2_CID_SATURATION: + return v4l2_ctrl_query_fill(qc, 0, 127, 1, 64); case V4L2_CID_HUE: - return v4l2_ctrl_query_fill_std(qc); + return v4l2_ctrl_query_fill(qc, -128, 127, 1, 0); default: break; } @@ -1220,10 +1222,11 @@ static int cx25840_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qc) return v4l2_ctrl_query_fill(qc, 0, 65535, 65535 / 100, state->default_volume); case V4L2_CID_AUDIO_MUTE: + return v4l2_ctrl_query_fill(qc, 0, 1, 1, 0); case V4L2_CID_AUDIO_BALANCE: case V4L2_CID_AUDIO_BASS: case V4L2_CID_AUDIO_TREBLE: - return v4l2_ctrl_query_fill_std(qc); + return v4l2_ctrl_query_fill(qc, 0, 65535, 65535 / 100, 32768); default: return -EINVAL; } diff --git a/drivers/media/video/msp3400-driver.c b/drivers/media/video/msp3400-driver.c index 4d7a91852117..d972828d1cbe 100644 --- a/drivers/media/video/msp3400-driver.c +++ b/drivers/media/video/msp3400-driver.c @@ -713,22 +713,24 @@ static int msp_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qc) struct msp_state *state = to_state(sd); switch (qc->id) { - case V4L2_CID_AUDIO_VOLUME: - case V4L2_CID_AUDIO_MUTE: - return v4l2_ctrl_query_fill_std(qc); - default: - break; + case V4L2_CID_AUDIO_VOLUME: + return v4l2_ctrl_query_fill(qc, 0, 65535, 65535 / 100, 58880); + case V4L2_CID_AUDIO_MUTE: + return v4l2_ctrl_query_fill(qc, 0, 1, 1, 0); + default: + break; } if (!state->has_sound_processing) return -EINVAL; switch (qc->id) { - case V4L2_CID_AUDIO_LOUDNESS: - case V4L2_CID_AUDIO_BALANCE: - case V4L2_CID_AUDIO_BASS: - case V4L2_CID_AUDIO_TREBLE: - return v4l2_ctrl_query_fill_std(qc); - default: - return -EINVAL; + case V4L2_CID_AUDIO_LOUDNESS: + return v4l2_ctrl_query_fill(qc, 0, 1, 1, 0); + case V4L2_CID_AUDIO_BALANCE: + case V4L2_CID_AUDIO_BASS: + case V4L2_CID_AUDIO_TREBLE: + return v4l2_ctrl_query_fill(qc, 0, 65535, 65535 / 100, 32768); + default: + return -EINVAL; } return 0; } diff --git a/drivers/media/video/saa7115.c b/drivers/media/video/saa7115.c index dd1943987ce6..a845582ca5d4 100644 --- a/drivers/media/video/saa7115.c +++ b/drivers/media/video/saa7115.c @@ -1206,10 +1206,12 @@ static int saa711x_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qc) { switch (qc->id) { case V4L2_CID_BRIGHTNESS: + return v4l2_ctrl_query_fill(qc, 0, 255, 1, 128); case V4L2_CID_CONTRAST: case V4L2_CID_SATURATION: + return v4l2_ctrl_query_fill(qc, 0, 127, 1, 64); case V4L2_CID_HUE: - return v4l2_ctrl_query_fill_std(qc); + return v4l2_ctrl_query_fill(qc, -128, 127, 1, 0); default: return -EINVAL; } diff --git a/drivers/media/video/saa7134/saa6752hs.c b/drivers/media/video/saa7134/saa6752hs.c index 2d292ad776e9..dc2213e2f86e 100644 --- a/drivers/media/video/saa7134/saa6752hs.c +++ b/drivers/media/video/saa7134/saa6752hs.c @@ -592,7 +592,7 @@ static int saa6752hs_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qc V4L2_MPEG_VIDEO_ASPECT_4x3); case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK: - err = v4l2_ctrl_query_fill_std(qctrl); + err = v4l2_ctrl_query_fill(qctrl, 0, 27000000, 1, 8000000); if (err == 0 && params->vi_bitrate_mode == V4L2_MPEG_VIDEO_BITRATE_MODE_CBR) @@ -606,12 +606,20 @@ static int saa6752hs_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qc V4L2_MPEG_STREAM_TYPE_MPEG2_TS); case V4L2_CID_MPEG_VIDEO_BITRATE_MODE: + return v4l2_ctrl_query_fill(qctrl, + V4L2_MPEG_VIDEO_BITRATE_MODE_VBR, + V4L2_MPEG_VIDEO_BITRATE_MODE_CBR, 1, + V4L2_MPEG_VIDEO_BITRATE_MODE_VBR); case V4L2_CID_MPEG_VIDEO_BITRATE: + return v4l2_ctrl_query_fill(qctrl, 0, 27000000, 1, 6000000); case V4L2_CID_MPEG_STREAM_PID_PMT: + return v4l2_ctrl_query_fill(qctrl, 0, (1 << 14) - 1, 1, 16); case V4L2_CID_MPEG_STREAM_PID_AUDIO: + return v4l2_ctrl_query_fill(qctrl, 0, (1 << 14) - 1, 1, 260); case V4L2_CID_MPEG_STREAM_PID_VIDEO: + return v4l2_ctrl_query_fill(qctrl, 0, (1 << 14) - 1, 1, 256); case V4L2_CID_MPEG_STREAM_PID_PCR: - return v4l2_ctrl_query_fill_std(qctrl); + return v4l2_ctrl_query_fill(qctrl, 0, (1 << 14) - 1, 1, 259); default: break; diff --git a/drivers/media/video/saa7134/saa7134-empress.c b/drivers/media/video/saa7134/saa7134-empress.c index 2e15bb7c3f0a..c6cfe0fe7e3d 100644 --- a/drivers/media/video/saa7134/saa7134-empress.c +++ b/drivers/media/video/saa7134/saa7134-empress.c @@ -390,7 +390,7 @@ static int empress_queryctrl(struct file *file, void *priv, if (c->id == 0) return -EINVAL; if (c->id == V4L2_CID_USER_CLASS || c->id == V4L2_CID_MPEG_CLASS) - return v4l2_ctrl_query_fill_std(c); + return v4l2_ctrl_query_fill(c, 0, 0, 0, 0); if (V4L2_CTRL_ID2CLASS(c->id) != V4L2_CTRL_CLASS_MPEG) return saa7134_queryctrl(file, priv, c); return saa_call_empress(dev, core, queryctrl, c); diff --git a/drivers/media/video/tda7432.c b/drivers/media/video/tda7432.c index 2090e170bd9c..976ce207cfcb 100644 --- a/drivers/media/video/tda7432.c +++ b/drivers/media/video/tda7432.c @@ -421,12 +421,14 @@ static int tda7432_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) static int tda7432_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qc) { switch (qc->id) { - case V4L2_CID_AUDIO_MUTE: case V4L2_CID_AUDIO_VOLUME: + return v4l2_ctrl_query_fill(qc, 0, 65535, 65535 / 100, 58880); + case V4L2_CID_AUDIO_MUTE: + return v4l2_ctrl_query_fill(qc, 0, 1, 1, 0); case V4L2_CID_AUDIO_BALANCE: case V4L2_CID_AUDIO_BASS: case V4L2_CID_AUDIO_TREBLE: - return v4l2_ctrl_query_fill_std(qc); + return v4l2_ctrl_query_fill(qc, 0, 65535, 65535 / 100, 32768); } return -EINVAL; } diff --git a/drivers/media/video/tda9875.c b/drivers/media/video/tda9875.c index 19fbd18f4882..e71b2bd46612 100644 --- a/drivers/media/video/tda9875.c +++ b/drivers/media/video/tda9875.c @@ -313,9 +313,10 @@ static int tda9875_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qc) { switch (qc->id) { case V4L2_CID_AUDIO_VOLUME: + return v4l2_ctrl_query_fill(qc, 0, 65535, 65535 / 100, 58880); case V4L2_CID_AUDIO_BASS: case V4L2_CID_AUDIO_TREBLE: - return v4l2_ctrl_query_fill_std(qc); + return v4l2_ctrl_query_fill(qc, 0, 65535, 65535 / 100, 32768); } return -EINVAL; } diff --git a/drivers/media/video/tvaudio.c b/drivers/media/video/tvaudio.c index 076ed5bf48b1..0eb3b1694287 100644 --- a/drivers/media/video/tvaudio.c +++ b/drivers/media/video/tvaudio.c @@ -1636,21 +1636,24 @@ static int tvaudio_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qc) switch (qc->id) { case V4L2_CID_AUDIO_MUTE: - break; + return v4l2_ctrl_query_fill(qc, 0, 1, 1, 0); case V4L2_CID_AUDIO_VOLUME: + if (desc->flags & CHIP_HAS_VOLUME) + return v4l2_ctrl_query_fill(qc, 0, 65535, 65535 / 100, 58880); + break; case V4L2_CID_AUDIO_BALANCE: - if (!(desc->flags & CHIP_HAS_VOLUME)) - return -EINVAL; + if (desc->flags & CHIP_HAS_VOLUME) + return v4l2_ctrl_query_fill(qc, 0, 65535, 65535 / 100, 32768); break; case V4L2_CID_AUDIO_BASS: case V4L2_CID_AUDIO_TREBLE: - if (!(desc->flags & CHIP_HAS_BASSTREBLE)) - return -EINVAL; + if (desc->flags & CHIP_HAS_BASSTREBLE) + return v4l2_ctrl_query_fill(qc, 0, 65535, 65535 / 100, 32768); break; default: - return -EINVAL; + break; } - return v4l2_ctrl_query_fill_std(qc); + return -EINVAL; } static int tvaudio_s_routing(struct v4l2_subdev *sd, const struct v4l2_routing *rt) diff --git a/drivers/media/video/tvp514x.c b/drivers/media/video/tvp514x.c index f0b2b8ed2fe4..4262e60b8116 100644 --- a/drivers/media/video/tvp514x.c +++ b/drivers/media/video/tvp514x.c @@ -725,10 +725,9 @@ ioctl_queryctrl(struct v4l2_int_device *s, struct v4l2_queryctrl *qctrl) switch (qctrl->id) { case V4L2_CID_BRIGHTNESS: - /* Brightness supported is same as standard one (0-255), - * so make use of standard API provided. + /* Brightness supported is (0-255), */ - err = v4l2_ctrl_query_fill_std(qctrl); + err = v4l2_ctrl_query_fill(qctrl, 0, 255, 1, 128); break; case V4L2_CID_CONTRAST: case V4L2_CID_SATURATION: diff --git a/drivers/media/video/v4l2-common.c b/drivers/media/video/v4l2-common.c index caa7ba0705a5..dbced906aa06 100644 --- a/drivers/media/video/v4l2-common.c +++ b/drivers/media/video/v4l2-common.c @@ -588,151 +588,6 @@ int v4l2_ctrl_query_fill(struct v4l2_queryctrl *qctrl, s32 min, s32 max, s32 ste } EXPORT_SYMBOL(v4l2_ctrl_query_fill); -/* Fill in a struct v4l2_queryctrl with standard values based on - the control ID. */ -int v4l2_ctrl_query_fill_std(struct v4l2_queryctrl *qctrl) -{ - switch (qctrl->id) { - /* USER controls */ - case V4L2_CID_USER_CLASS: - case V4L2_CID_MPEG_CLASS: - case V4L2_CID_CAMERA_CLASS: - return v4l2_ctrl_query_fill(qctrl, 0, 0, 0, 0); - case V4L2_CID_AUDIO_VOLUME: - return v4l2_ctrl_query_fill(qctrl, 0, 65535, 65535 / 100, 58880); - case V4L2_CID_AUDIO_MUTE: - case V4L2_CID_AUDIO_LOUDNESS: - return v4l2_ctrl_query_fill(qctrl, 0, 1, 1, 0); - case V4L2_CID_AUDIO_BALANCE: - case V4L2_CID_AUDIO_BASS: - case V4L2_CID_AUDIO_TREBLE: - return v4l2_ctrl_query_fill(qctrl, 0, 65535, 65535 / 100, 32768); - case V4L2_CID_BRIGHTNESS: - return v4l2_ctrl_query_fill(qctrl, 0, 255, 1, 128); - case V4L2_CID_CONTRAST: - case V4L2_CID_SATURATION: - return v4l2_ctrl_query_fill(qctrl, 0, 127, 1, 64); - case V4L2_CID_HUE: - return v4l2_ctrl_query_fill(qctrl, -128, 127, 1, 0); - case V4L2_CID_COLORFX: - return v4l2_ctrl_query_fill(qctrl, 0, 1, 1, 0); - - /* MPEG controls */ - case V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ: - return v4l2_ctrl_query_fill(qctrl, - V4L2_MPEG_AUDIO_SAMPLING_FREQ_44100, - V4L2_MPEG_AUDIO_SAMPLING_FREQ_32000, 1, - V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000); - case V4L2_CID_MPEG_AUDIO_ENCODING: - return v4l2_ctrl_query_fill(qctrl, - V4L2_MPEG_AUDIO_ENCODING_LAYER_1, - V4L2_MPEG_AUDIO_ENCODING_AC3, 1, - V4L2_MPEG_AUDIO_ENCODING_LAYER_2); - case V4L2_CID_MPEG_AUDIO_L1_BITRATE: - return v4l2_ctrl_query_fill(qctrl, - V4L2_MPEG_AUDIO_L1_BITRATE_32K, - V4L2_MPEG_AUDIO_L1_BITRATE_448K, 1, - V4L2_MPEG_AUDIO_L1_BITRATE_256K); - case V4L2_CID_MPEG_AUDIO_L2_BITRATE: - return v4l2_ctrl_query_fill(qctrl, - V4L2_MPEG_AUDIO_L2_BITRATE_32K, - V4L2_MPEG_AUDIO_L2_BITRATE_384K, 1, - V4L2_MPEG_AUDIO_L2_BITRATE_224K); - case V4L2_CID_MPEG_AUDIO_L3_BITRATE: - return v4l2_ctrl_query_fill(qctrl, - V4L2_MPEG_AUDIO_L3_BITRATE_32K, - V4L2_MPEG_AUDIO_L3_BITRATE_320K, 1, - V4L2_MPEG_AUDIO_L3_BITRATE_192K); - case V4L2_CID_MPEG_AUDIO_AAC_BITRATE: - return v4l2_ctrl_query_fill(qctrl, 0, 6400, 1, 3200000); - case V4L2_CID_MPEG_AUDIO_AC3_BITRATE: - return v4l2_ctrl_query_fill(qctrl, - V4L2_MPEG_AUDIO_AC3_BITRATE_32K, - V4L2_MPEG_AUDIO_AC3_BITRATE_640K, 1, - V4L2_MPEG_AUDIO_AC3_BITRATE_384K); - case V4L2_CID_MPEG_AUDIO_MODE: - return v4l2_ctrl_query_fill(qctrl, - V4L2_MPEG_AUDIO_MODE_STEREO, - V4L2_MPEG_AUDIO_MODE_MONO, 1, - V4L2_MPEG_AUDIO_MODE_STEREO); - case V4L2_CID_MPEG_AUDIO_MODE_EXTENSION: - return v4l2_ctrl_query_fill(qctrl, - V4L2_MPEG_AUDIO_MODE_EXTENSION_BOUND_4, - V4L2_MPEG_AUDIO_MODE_EXTENSION_BOUND_16, 1, - V4L2_MPEG_AUDIO_MODE_EXTENSION_BOUND_4); - case V4L2_CID_MPEG_AUDIO_EMPHASIS: - return v4l2_ctrl_query_fill(qctrl, - V4L2_MPEG_AUDIO_EMPHASIS_NONE, - V4L2_MPEG_AUDIO_EMPHASIS_CCITT_J17, 1, - V4L2_MPEG_AUDIO_EMPHASIS_NONE); - case V4L2_CID_MPEG_AUDIO_CRC: - return v4l2_ctrl_query_fill(qctrl, - V4L2_MPEG_AUDIO_CRC_NONE, - V4L2_MPEG_AUDIO_CRC_CRC16, 1, - V4L2_MPEG_AUDIO_CRC_NONE); - case V4L2_CID_MPEG_AUDIO_MUTE: - return v4l2_ctrl_query_fill(qctrl, 0, 1, 1, 0); - case V4L2_CID_MPEG_VIDEO_ENCODING: - return v4l2_ctrl_query_fill(qctrl, - V4L2_MPEG_VIDEO_ENCODING_MPEG_1, - V4L2_MPEG_VIDEO_ENCODING_MPEG_4_AVC, 1, - V4L2_MPEG_VIDEO_ENCODING_MPEG_2); - case V4L2_CID_MPEG_VIDEO_ASPECT: - return v4l2_ctrl_query_fill(qctrl, - V4L2_MPEG_VIDEO_ASPECT_1x1, - V4L2_MPEG_VIDEO_ASPECT_221x100, 1, - V4L2_MPEG_VIDEO_ASPECT_4x3); - case V4L2_CID_MPEG_VIDEO_B_FRAMES: - return v4l2_ctrl_query_fill(qctrl, 0, 33, 1, 2); - case V4L2_CID_MPEG_VIDEO_GOP_SIZE: - return v4l2_ctrl_query_fill(qctrl, 1, 34, 1, 12); - case V4L2_CID_MPEG_VIDEO_GOP_CLOSURE: - return v4l2_ctrl_query_fill(qctrl, 0, 1, 1, 1); - case V4L2_CID_MPEG_VIDEO_PULLDOWN: - return v4l2_ctrl_query_fill(qctrl, 0, 1, 1, 0); - case V4L2_CID_MPEG_VIDEO_BITRATE_MODE: - return v4l2_ctrl_query_fill(qctrl, - V4L2_MPEG_VIDEO_BITRATE_MODE_VBR, - V4L2_MPEG_VIDEO_BITRATE_MODE_CBR, 1, - V4L2_MPEG_VIDEO_BITRATE_MODE_VBR); - case V4L2_CID_MPEG_VIDEO_BITRATE: - return v4l2_ctrl_query_fill(qctrl, 0, 27000000, 1, 6000000); - case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK: - return v4l2_ctrl_query_fill(qctrl, 0, 27000000, 1, 8000000); - case V4L2_CID_MPEG_VIDEO_TEMPORAL_DECIMATION: - return v4l2_ctrl_query_fill(qctrl, 0, 255, 1, 0); - case V4L2_CID_MPEG_VIDEO_MUTE: - return v4l2_ctrl_query_fill(qctrl, 0, 1, 1, 0); - case V4L2_CID_MPEG_VIDEO_MUTE_YUV: /* Init YUV (really YCbCr) to black */ - return v4l2_ctrl_query_fill(qctrl, 0, 0xffffff, 1, 0x008080); - case V4L2_CID_MPEG_STREAM_TYPE: - return v4l2_ctrl_query_fill(qctrl, - V4L2_MPEG_STREAM_TYPE_MPEG2_PS, - V4L2_MPEG_STREAM_TYPE_MPEG2_SVCD, 1, - V4L2_MPEG_STREAM_TYPE_MPEG2_PS); - case V4L2_CID_MPEG_STREAM_PID_PMT: - return v4l2_ctrl_query_fill(qctrl, 0, (1 << 14) - 1, 1, 16); - case V4L2_CID_MPEG_STREAM_PID_AUDIO: - return v4l2_ctrl_query_fill(qctrl, 0, (1 << 14) - 1, 1, 260); - case V4L2_CID_MPEG_STREAM_PID_VIDEO: - return v4l2_ctrl_query_fill(qctrl, 0, (1 << 14) - 1, 1, 256); - case V4L2_CID_MPEG_STREAM_PID_PCR: - return v4l2_ctrl_query_fill(qctrl, 0, (1 << 14) - 1, 1, 259); - case V4L2_CID_MPEG_STREAM_PES_ID_AUDIO: - return v4l2_ctrl_query_fill(qctrl, 0, 255, 1, 0); - case V4L2_CID_MPEG_STREAM_PES_ID_VIDEO: - return v4l2_ctrl_query_fill(qctrl, 0, 255, 1, 0); - case V4L2_CID_MPEG_STREAM_VBI_FMT: - return v4l2_ctrl_query_fill(qctrl, - V4L2_MPEG_STREAM_VBI_FMT_NONE, - V4L2_MPEG_STREAM_VBI_FMT_IVTV, 1, - V4L2_MPEG_STREAM_VBI_FMT_NONE); - default: - return -EINVAL; - } -} -EXPORT_SYMBOL(v4l2_ctrl_query_fill_std); - /* Fill in a struct v4l2_querymenu based on the struct v4l2_queryctrl and the menu. The qctrl pointer may be NULL, in which case it is ignored. If menu_items is NULL, then the menu items are retrieved using diff --git a/include/media/v4l2-common.h b/include/media/v4l2-common.h index 7779d9c93ec8..3a6905615d68 100644 --- a/include/media/v4l2-common.h +++ b/include/media/v4l2-common.h @@ -102,7 +102,6 @@ int v4l2_ctrl_check(struct v4l2_ext_control *ctrl, struct v4l2_queryctrl *qctrl, const char *v4l2_ctrl_get_name(u32 id); const char **v4l2_ctrl_get_menu(u32 id); int v4l2_ctrl_query_fill(struct v4l2_queryctrl *qctrl, s32 min, s32 max, s32 step, s32 def); -int v4l2_ctrl_query_fill_std(struct v4l2_queryctrl *qctrl); int v4l2_ctrl_query_menu(struct v4l2_querymenu *qmenu, struct v4l2_queryctrl *qctrl, const char **menu_items); #define V4L2_CTRL_MENU_IDS_END (0xffffffff) -- cgit v1.2.3 From 674a323218ab0b0be100b51c251a72787b5c9e3a Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 18 Feb 2009 12:22:16 -0300 Subject: V4L/DVB (10700): saa7115: don't access reg 0x87 if it is not present. Devices like the saa7111 do not have this register, so check for this before using it. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/saa7115.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/saa7115.c b/drivers/media/video/saa7115.c index a845582ca5d4..b1c5f63bb77a 100644 --- a/drivers/media/video/saa7115.c +++ b/drivers/media/video/saa7115.c @@ -1310,11 +1310,12 @@ static int saa711x_s_stream(struct v4l2_subdev *sd, int enable) v4l2_dbg(1, debug, sd, "%s output\n", enable ? "enable" : "disable"); - if (state->enable != enable) { - state->enable = enable; - saa711x_write(sd, R_87_I_PORT_I_O_ENA_OUT_CLK_AND_GATED, - state->enable); - } + if (state->enable == enable) + return 0; + state->enable = enable; + if (!saa711x_has_reg(state->ident, R_87_I_PORT_I_O_ENA_OUT_CLK_AND_GATED)) + return 0; + saa711x_write(sd, R_87_I_PORT_I_O_ENA_OUT_CLK_AND_GATED, state->enable); return 0; } -- cgit v1.2.3 From 9040320a899f41cc1978bdd4b6867b172da9b021 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 18 Feb 2009 12:23:38 -0300 Subject: V4L/DVB (10701): saa7185: add colorbar support. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/saa7185.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) (limited to 'drivers/media/video') diff --git a/drivers/media/video/saa7185.c b/drivers/media/video/saa7185.c index 6debb65152ee..8d06bb312c55 100644 --- a/drivers/media/video/saa7185.c +++ b/drivers/media/video/saa7185.c @@ -281,6 +281,8 @@ static int saa7185_command(struct i2c_client *client, unsigned cmd, void *arg) switch (*iarg) { case 0: + /* turn off colorbar */ + saa7185_write(client, 0x3a, 0x0f); /* Switch RTCE to 1 */ saa7185_write(client, 0x61, (encoder->reg[0x61] & 0xf7) | 0x08); @@ -288,6 +290,8 @@ static int saa7185_command(struct i2c_client *client, unsigned cmd, void *arg) break; case 1: + /* turn off colorbar */ + saa7185_write(client, 0x3a, 0x0f); /* Switch RTCE to 0 */ saa7185_write(client, 0x61, (encoder->reg[0x61] & 0xf7) | 0x00); @@ -295,6 +299,16 @@ static int saa7185_command(struct i2c_client *client, unsigned cmd, void *arg) saa7185_write(client, 0x6e, 0x00); break; + case 2: + /* turn on colorbar */ + saa7185_write(client, 0x3a, 0x8f); + /* Switch RTCE to 0 */ + saa7185_write(client, 0x61, + (encoder->reg[0x61] & 0xf7) | 0x08); + /* SW: a slight sync problem... */ + saa7185_write(client, 0x6e, 0x01); + break; + default: return -EINVAL; } -- cgit v1.2.3 From 17bdd9ddd14dc4d15277aacb277272f7a6c4eb2a Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 18 Feb 2009 12:35:33 -0300 Subject: V4L/DVB (10702): saa7115: add querystd and g_input_status support for zoran. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/saa7115.c | 43 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) (limited to 'drivers/media/video') diff --git a/drivers/media/video/saa7115.c b/drivers/media/video/saa7115.c index b1c5f63bb77a..591f7f98aa33 100644 --- a/drivers/media/video/saa7115.c +++ b/drivers/media/video/saa7115.c @@ -1373,6 +1373,47 @@ static int saa711x_g_vbi_data(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_dat } } +static int saa711x_querystd(struct v4l2_subdev *sd, v4l2_std_id *std) +{ + struct saa711x_state *state = to_state(sd); + int reg1e; + + *std = V4L2_STD_ALL; + if (state->ident != V4L2_IDENT_SAA7115) + return 0; + reg1e = saa711x_read(sd, R_1E_STATUS_BYTE_1_VD_DEC); + + switch (reg1e & 0x03) { + case 1: + *std = V4L2_STD_NTSC; + break; + case 2: + *std = V4L2_STD_PAL; + break; + case 3: + *std = V4L2_STD_SECAM; + break; + default: + break; + } + return 0; +} + +static int saa711x_g_input_status(struct v4l2_subdev *sd, u32 *status) +{ + struct saa711x_state *state = to_state(sd); + int reg1e = 0x80; + int reg1f; + + *status = V4L2_IN_ST_NO_SIGNAL; + if (state->ident == V4L2_IDENT_SAA7115) + reg1e = saa711x_read(sd, R_1E_STATUS_BYTE_1_VD_DEC); + reg1f = saa711x_read(sd, R_1F_STATUS_BYTE_2_VD_DEC); + if ((reg1f & 0xc1) == 0x81 && (reg1e & 0xc0) == 0x80) + *status = 0; + return 0; +} + #ifdef CONFIG_VIDEO_ADV_DEBUG static int saa711x_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg) { @@ -1496,6 +1537,8 @@ static const struct v4l2_subdev_video_ops saa711x_video_ops = { .g_vbi_data = saa711x_g_vbi_data, .decode_vbi_line = saa711x_decode_vbi_line, .s_stream = saa711x_s_stream, + .querystd = saa711x_querystd, + .g_input_status = saa711x_g_input_status, }; static const struct v4l2_subdev_ops saa711x_ops = { -- cgit v1.2.3 From 96b8e145f0a6f3c0470b5cdbe7ba9be314bb556f Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 18 Feb 2009 13:13:31 -0300 Subject: V4L/DVB (10703): zoran: convert to video_ioctl2 and remove 'ready_to_be_freed' hack. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/zoran/zoran.h | 2 - drivers/media/video/zoran/zoran_driver.c | 2557 +++++++++++++----------------- 2 files changed, 1114 insertions(+), 1445 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/zoran/zoran.h b/drivers/media/video/zoran/zoran.h index e873a916250f..1bf540cb546c 100644 --- a/drivers/media/video/zoran/zoran.h +++ b/drivers/media/video/zoran/zoran.h @@ -312,7 +312,6 @@ struct zoran_jpg_struct { struct zoran_jpg_buffer buffer[BUZ_MAX_FRAME]; /* buffers */ int num_buffers, buffer_size; u8 allocated; /* Flag if buffers are allocated */ - u8 ready_to_be_freed; /* hack - see zoran_driver.c */ u8 need_contiguous; /* Flag if contiguous buffers are needed */ }; @@ -321,7 +320,6 @@ struct zoran_v4l_struct { struct zoran_v4l_buffer buffer[VIDEO_MAX_FRAME]; /* buffers */ int num_buffers, buffer_size; u8 allocated; /* Flag if buffers are allocated */ - u8 ready_to_be_freed; /* hack - see zoran_driver.c */ }; struct zoran; diff --git a/drivers/media/video/zoran/zoran_driver.c b/drivers/media/video/zoran/zoran_driver.c index b81e20912fa7..dc6ba554597f 100644 --- a/drivers/media/video/zoran/zoran_driver.c +++ b/drivers/media/video/zoran/zoran_driver.c @@ -309,11 +309,6 @@ v4l_fbuffer_alloc (struct file *file) unsigned char *mem; unsigned long pmem = 0; - /* we might have old buffers lying around... */ - if (fh->v4l_buffers.ready_to_be_freed) { - v4l_fbuffer_free(file); - } - for (i = 0; i < fh->v4l_buffers.num_buffers; i++) { if (fh->v4l_buffers.buffer[i].fbuffer) dprintk(2, @@ -421,7 +416,6 @@ v4l_fbuffer_free (struct file *file) } fh->v4l_buffers.allocated = 0; - fh->v4l_buffers.ready_to_be_freed = 0; } /* @@ -466,11 +460,6 @@ jpg_fbuffer_alloc (struct file *file) int i, j, off; unsigned long mem; - /* we might have old buffers lying around */ - if (fh->jpg_buffers.ready_to_be_freed) { - jpg_fbuffer_free(file); - } - for (i = 0; i < fh->jpg_buffers.num_buffers; i++) { if (fh->jpg_buffers.buffer[i].frag_tab) dprintk(2, @@ -613,7 +602,6 @@ jpg_fbuffer_free (struct file *file) } fh->jpg_buffers.allocated = 0; - fh->jpg_buffers.ready_to_be_freed = 0; } /* @@ -657,7 +645,7 @@ zoran_v4l_set_format (struct file *file, if ((bpp == 2 && (width & 1)) || (bpp == 3 && (width & 3))) { dprintk(1, KERN_ERR - "%s: v4l_set_format() - wrong frame alingment\n", + "%s: v4l_set_format() - wrong frame alignment\n", ZR_DEVNAME(zr)); return -EINVAL; } @@ -1122,7 +1110,6 @@ zoran_open_init_session (struct file *file) fh->v4l_buffers.buffer[i].bs.frame = i; } fh->v4l_buffers.allocated = 0; - fh->v4l_buffers.ready_to_be_freed = 0; fh->v4l_buffers.active = ZORAN_FREE; fh->v4l_buffers.buffer_size = v4l_bufsize; fh->v4l_buffers.num_buffers = v4l_nbufs; @@ -1138,7 +1125,6 @@ zoran_open_init_session (struct file *file) } fh->jpg_buffers.need_contiguous = zr->jpg_buffers.need_contiguous; fh->jpg_buffers.allocated = 0; - fh->jpg_buffers.ready_to_be_freed = 0; fh->jpg_buffers.active = ZORAN_FREE; fh->jpg_buffers.buffer_size = jpg_bufsize; fh->jpg_buffers.num_buffers = jpg_nbufs; @@ -1172,10 +1158,8 @@ zoran_close_end_session (struct file *file) } /* v4l buffers */ - if (fh->v4l_buffers.allocated || - fh->v4l_buffers.ready_to_be_freed) { + if (fh->v4l_buffers.allocated) v4l_fbuffer_free(file); - } /* jpg capture */ if (fh->jpg_buffers.active != ZORAN_FREE) { @@ -1186,10 +1170,8 @@ zoran_close_end_session (struct file *file) } /* jpg buffers */ - if (fh->jpg_buffers.allocated || - fh->jpg_buffers.ready_to_be_freed) { + if (fh->jpg_buffers.allocated) jpg_fbuffer_free(file); - } } /* @@ -1903,38 +1885,13 @@ zoran_set_input (struct zoran *zr, * ioctl routine */ -static long zoran_do_ioctl(struct file *file, unsigned int cmd, void *arg) +static long zoran_default(struct file *file, void *__fh, int cmd, void *arg) { - struct zoran_fh *fh = file->private_data; + struct zoran_fh *fh = __fh; struct zoran *zr = fh->zr; - /* CAREFUL: used in multiple places here */ struct zoran_jpg_settings settings; - /* we might have older buffers lying around... We don't want - * to wait, but we do want to try cleaning them up ASAP. So - * we try to obtain the lock and free them. If that fails, we - * don't do anything and wait for the next turn. In the end, - * zoran_close() or a new allocation will still free them... - * This is just a 'the sooner the better' extra 'feature' - * - * We don't free the buffers right on munmap() because that - * causes oopses (kfree() inside munmap() oopses for no - * apparent reason - it's also not reproduceable in any way, - * but moving the free code outside the munmap() handler fixes - * all this... If someone knows why, please explain me (Ronald) - */ - if (mutex_trylock(&zr->resource_lock)) { - /* we obtained it! Let's try to free some things */ - if (fh->jpg_buffers.ready_to_be_freed) - jpg_fbuffer_free(file); - if (fh->v4l_buffers.ready_to_be_freed) - v4l_fbuffer_free(file); - - mutex_unlock(&zr->resource_lock); - } - switch (cmd) { - case VIDIOCGCAP: { struct video_capability *vcap = arg; @@ -1956,7 +1913,6 @@ static long zoran_do_ioctl(struct file *file, unsigned int cmd, void *arg) return 0; } - break; case VIDIOCGCHAN: { @@ -1987,7 +1943,6 @@ static long zoran_do_ioctl(struct file *file, unsigned int cmd, void *arg) return 0; } - break; /* RJ: the documentation at http://roadrunner.swansea.linux.org.uk/v4lapi.shtml says: * @@ -2017,11 +1972,10 @@ static long zoran_do_ioctl(struct file *file, unsigned int cmd, void *arg) /* Make sure the changes come into effect */ res = wait_grab_pending(zr); - schan_unlock_and_return: +schan_unlock_and_return: mutex_unlock(&zr->resource_lock); return res; } - break; case VIDIOCGPICT: { @@ -2045,7 +1999,6 @@ static long zoran_do_ioctl(struct file *file, unsigned int cmd, void *arg) return 0; } - break; case VIDIOCSPICT: { @@ -2091,7 +2044,6 @@ static long zoran_do_ioctl(struct file *file, unsigned int cmd, void *arg) return 0; } - break; case VIDIOCCAPTURE: { @@ -2106,7 +2058,6 @@ static long zoran_do_ioctl(struct file *file, unsigned int cmd, void *arg) return res; } - break; case VIDIOCGWIN: { @@ -2124,7 +2075,6 @@ static long zoran_do_ioctl(struct file *file, unsigned int cmd, void *arg) vwin->clipcount = 0; return 0; } - break; case VIDIOCSWIN: { @@ -2146,7 +2096,6 @@ static long zoran_do_ioctl(struct file *file, unsigned int cmd, void *arg) return res; } - break; case VIDIOCGFBUF: { @@ -2159,7 +2108,6 @@ static long zoran_do_ioctl(struct file *file, unsigned int cmd, void *arg) mutex_unlock(&zr->resource_lock); return 0; } - break; case VIDIOCSFBUF: { @@ -2192,7 +2140,6 @@ static long zoran_do_ioctl(struct file *file, unsigned int cmd, void *arg) return res; } - break; case VIDIOCSYNC: { @@ -2208,7 +2155,6 @@ static long zoran_do_ioctl(struct file *file, unsigned int cmd, void *arg) zr->v4l_sync_tail++; return res; } - break; case VIDIOCMCAPTURE: { @@ -2226,7 +2172,6 @@ static long zoran_do_ioctl(struct file *file, unsigned int cmd, void *arg) mutex_unlock(&zr->resource_lock); return res; } - break; case VIDIOCGMBUF: { @@ -2262,12 +2207,11 @@ static long zoran_do_ioctl(struct file *file, unsigned int cmd, void *arg) /* The next mmap will map the V4L buffers */ fh->map_mode = ZORAN_MAP_MODE_RAW; - v4l1reqbuf_unlock_and_return: +v4l1reqbuf_unlock_and_return: mutex_unlock(&zr->resource_lock); return res; } - break; case VIDIOCGUNIT: { @@ -2283,7 +2227,6 @@ static long zoran_do_ioctl(struct file *file, unsigned int cmd, void *arg) return 0; } - break; /* * RJ: In principal we could support subcaptures for V4L grabbing. @@ -2297,7 +2240,6 @@ static long zoran_do_ioctl(struct file *file, unsigned int cmd, void *arg) ZR_DEVNAME(zr)); return -EINVAL; } - break; case VIDIOCSCAPTURE: { @@ -2305,7 +2247,6 @@ static long zoran_do_ioctl(struct file *file, unsigned int cmd, void *arg) ZR_DEVNAME(zr)); return -EINVAL; } - break; case BUZIOC_G_PARAMS: { @@ -2352,7 +2293,6 @@ static long zoran_do_ioctl(struct file *file, unsigned int cmd, void *arg) return 0; } - break; case BUZIOC_S_PARAMS: { @@ -2401,12 +2341,11 @@ static long zoran_do_ioctl(struct file *file, unsigned int cmd, void *arg) } fh->jpg_settings = settings; - sparams_unlock_and_return: +sparams_unlock_and_return: mutex_unlock(&zr->resource_lock); return res; } - break; case BUZIOC_REQBUFS: { @@ -2456,12 +2395,11 @@ static long zoran_do_ioctl(struct file *file, unsigned int cmd, void *arg) /* The next mmap will map the MJPEG buffers - could * also be *_PLAY, but it doesn't matter here */ fh->map_mode = ZORAN_MAP_MODE_JPG_REC; - jpgreqbuf_unlock_and_return: +jpgreqbuf_unlock_and_return: mutex_unlock(&zr->resource_lock); return res; } - break; case BUZIOC_QBUF_CAPT: { @@ -2476,7 +2414,6 @@ static long zoran_do_ioctl(struct file *file, unsigned int cmd, void *arg) return res; } - break; case BUZIOC_QBUF_PLAY: { @@ -2491,7 +2428,6 @@ static long zoran_do_ioctl(struct file *file, unsigned int cmd, void *arg) return res; } - break; case BUZIOC_SYNC: { @@ -2506,7 +2442,6 @@ static long zoran_do_ioctl(struct file *file, unsigned int cmd, void *arg) return res; } - break; case BUZIOC_G_STATUS: { @@ -2550,7 +2485,7 @@ static long zoran_do_ioctl(struct file *file, unsigned int cmd, void *arg) input = zr->card.input[zr->input].muxsel; decoder_command(zr, DECODER_SET_INPUT, &input); decoder_command(zr, DECODER_SET_NORM, &zr->norm); - gstat_unlock_and_return: +gstat_unlock_and_return: mutex_unlock(&zr->resource_lock); if (!res) { @@ -2569,1599 +2504,1297 @@ static long zoran_do_ioctl(struct file *file, unsigned int cmd, void *arg) return res; } - break; - - /* The new video4linux2 capture interface - much nicer than video4linux1, since - * it allows for integrating the JPEG capturing calls inside standard v4l2 - */ - - case VIDIOC_QUERYCAP: - { - struct v4l2_capability *cap = arg; - - dprintk(3, KERN_DEBUG "%s: VIDIOC_QUERYCAP\n", ZR_DEVNAME(zr)); - memset(cap, 0, sizeof(*cap)); - strncpy(cap->card, ZR_DEVNAME(zr), sizeof(cap->card)-1); - strncpy(cap->driver, "zoran", sizeof(cap->driver)-1); - snprintf(cap->bus_info, sizeof(cap->bus_info), "PCI:%s", - pci_name(zr->pci_dev)); - cap->version = - KERNEL_VERSION(MAJOR_VERSION, MINOR_VERSION, - RELEASE_VERSION); - cap->capabilities = ZORAN_V4L2_VID_FLAGS; - - return 0; + default: + return -EINVAL; } - break; - - case VIDIOC_ENUM_FMT: - { - struct v4l2_fmtdesc *fmt = arg; - int index = fmt->index, num = -1, i, flag = 0, type = - fmt->type; +} - dprintk(3, KERN_DEBUG "%s: VIDIOC_ENUM_FMT - index=%d\n", - ZR_DEVNAME(zr), fmt->index); +static int zoran_querycap(struct file *file, void *__fh, struct v4l2_capability *cap) +{ + struct zoran_fh *fh = __fh; + struct zoran *zr = fh->zr; - switch (fmt->type) { - case V4L2_BUF_TYPE_VIDEO_CAPTURE: - flag = ZORAN_FORMAT_CAPTURE; - break; - case V4L2_BUF_TYPE_VIDEO_OUTPUT: - flag = ZORAN_FORMAT_PLAYBACK; - break; - case V4L2_BUF_TYPE_VIDEO_OVERLAY: - flag = ZORAN_FORMAT_OVERLAY; - break; - default: - dprintk(1, - KERN_ERR - "%s: VIDIOC_ENUM_FMT - unknown type %d\n", - ZR_DEVNAME(zr), fmt->type); - return -EINVAL; - } + memset(cap, 0, sizeof(*cap)); + strncpy(cap->card, ZR_DEVNAME(zr), sizeof(cap->card)-1); + strncpy(cap->driver, "zoran", sizeof(cap->driver)-1); + snprintf(cap->bus_info, sizeof(cap->bus_info), "PCI:%s", + pci_name(zr->pci_dev)); + cap->version = + KERNEL_VERSION(MAJOR_VERSION, MINOR_VERSION, + RELEASE_VERSION); + cap->capabilities = ZORAN_V4L2_VID_FLAGS; - for (i = 0; i < NUM_FORMATS; i++) { - if (zoran_formats[i].flags & flag) - num++; - if (num == fmt->index) - break; - } - if (fmt->index < 0 /* late, but not too late */ || - i == NUM_FORMATS) - return -EINVAL; + return 0; +} - memset(fmt, 0, sizeof(*fmt)); - fmt->index = index; - fmt->type = type; - strncpy(fmt->description, zoran_formats[i].name, sizeof(fmt->description)-1); - fmt->pixelformat = zoran_formats[i].fourcc; - if (zoran_formats[i].flags & ZORAN_FORMAT_COMPRESSED) - fmt->flags |= V4L2_FMT_FLAG_COMPRESSED; +static int zoran_enum_fmt(struct zoran *zr, struct v4l2_fmtdesc *fmt, int flag) +{ + int num = -1, i; - return 0; + for (i = 0; i < NUM_FORMATS; i++) { + if (zoran_formats[i].flags & flag) + num++; + if (num == fmt->index) + break; } - break; - - case VIDIOC_G_FMT: - { - struct v4l2_format *fmt = arg; - int type = fmt->type; + if (fmt->index < 0 /* late, but not too late */ || i == NUM_FORMATS) + return -EINVAL; - dprintk(5, KERN_DEBUG "%s: VIDIOC_G_FMT\n", ZR_DEVNAME(zr)); + strncpy(fmt->description, zoran_formats[i].name, sizeof(fmt->description)-1); + fmt->pixelformat = zoran_formats[i].fourcc; + if (zoran_formats[i].flags & ZORAN_FORMAT_COMPRESSED) + fmt->flags |= V4L2_FMT_FLAG_COMPRESSED; + return 0; +} - memset(fmt, 0, sizeof(*fmt)); - fmt->type = type; +static int zoran_enum_fmt_vid_cap(struct file *file, void *__fh, + struct v4l2_fmtdesc *f) +{ + struct zoran_fh *fh = __fh; + struct zoran *zr = fh->zr; - switch (fmt->type) { - case V4L2_BUF_TYPE_VIDEO_OVERLAY: + return zoran_enum_fmt(zr, f, ZORAN_FORMAT_CAPTURE); +} - mutex_lock(&zr->resource_lock); +static int zoran_enum_fmt_vid_out(struct file *file, void *__fh, + struct v4l2_fmtdesc *f) +{ + struct zoran_fh *fh = __fh; + struct zoran *zr = fh->zr; - fmt->fmt.win.w.left = fh->overlay_settings.x; - fmt->fmt.win.w.top = fh->overlay_settings.y; - fmt->fmt.win.w.width = fh->overlay_settings.width; - fmt->fmt.win.w.height = - fh->overlay_settings.height; - if (fh->overlay_settings.width * 2 > - BUZ_MAX_HEIGHT) - fmt->fmt.win.field = V4L2_FIELD_INTERLACED; - else - fmt->fmt.win.field = V4L2_FIELD_TOP; + return zoran_enum_fmt(zr, f, ZORAN_FORMAT_PLAYBACK); +} - mutex_unlock(&zr->resource_lock); +static int zoran_enum_fmt_vid_overlay(struct file *file, void *__fh, + struct v4l2_fmtdesc *f) +{ + struct zoran_fh *fh = __fh; + struct zoran *zr = fh->zr; - break; + return zoran_enum_fmt(zr, f, ZORAN_FORMAT_OVERLAY); +} - case V4L2_BUF_TYPE_VIDEO_CAPTURE: - case V4L2_BUF_TYPE_VIDEO_OUTPUT: - - mutex_lock(&zr->resource_lock); - - if (fmt->type == V4L2_BUF_TYPE_VIDEO_CAPTURE && - fh->map_mode == ZORAN_MAP_MODE_RAW) { - - fmt->fmt.pix.width = - fh->v4l_settings.width; - fmt->fmt.pix.height = - fh->v4l_settings.height; - fmt->fmt.pix.sizeimage = - fh->v4l_settings.bytesperline * - fh->v4l_settings.height; - fmt->fmt.pix.pixelformat = - fh->v4l_settings.format->fourcc; - fmt->fmt.pix.colorspace = - fh->v4l_settings.format->colorspace; - fmt->fmt.pix.bytesperline = - fh->v4l_settings.bytesperline; - if (BUZ_MAX_HEIGHT < - (fh->v4l_settings.height * 2)) - fmt->fmt.pix.field = - V4L2_FIELD_INTERLACED; - else - fmt->fmt.pix.field = - V4L2_FIELD_TOP; +static int zoran_g_fmt_vid_out(struct file *file, void *__fh, + struct v4l2_format *fmt) +{ + struct zoran_fh *fh = __fh; + struct zoran *zr = fh->zr; - } else { + mutex_lock(&zr->resource_lock); - fmt->fmt.pix.width = - fh->jpg_settings.img_width / - fh->jpg_settings.HorDcm; - fmt->fmt.pix.height = - fh->jpg_settings.img_height / - (fh->jpg_settings.VerDcm * - fh->jpg_settings.TmpDcm); - fmt->fmt.pix.sizeimage = - zoran_v4l2_calc_bufsize(&fh-> - jpg_settings); - fmt->fmt.pix.pixelformat = - V4L2_PIX_FMT_MJPEG; - if (fh->jpg_settings.TmpDcm == 1) - fmt->fmt.pix.field = - (fh->jpg_settings. - odd_even ? V4L2_FIELD_SEQ_BT : - V4L2_FIELD_SEQ_BT); - else - fmt->fmt.pix.field = - (fh->jpg_settings. - odd_even ? V4L2_FIELD_TOP : - V4L2_FIELD_BOTTOM); - - fmt->fmt.pix.bytesperline = 0; - fmt->fmt.pix.colorspace = - V4L2_COLORSPACE_SMPTE170M; - } + fmt->fmt.pix.width = fh->jpg_settings.img_width / fh->jpg_settings.HorDcm; + fmt->fmt.pix.height = fh->jpg_settings.img_height / + (fh->jpg_settings.VerDcm * fh->jpg_settings.TmpDcm); + fmt->fmt.pix.sizeimage = zoran_v4l2_calc_bufsize(&fh->jpg_settings); + fmt->fmt.pix.pixelformat = V4L2_PIX_FMT_MJPEG; + if (fh->jpg_settings.TmpDcm == 1) + fmt->fmt.pix.field = (fh->jpg_settings.odd_even ? + V4L2_FIELD_SEQ_BT : V4L2_FIELD_SEQ_BT); + else + fmt->fmt.pix.field = (fh->jpg_settings.odd_even ? + V4L2_FIELD_TOP : V4L2_FIELD_BOTTOM); + fmt->fmt.pix.bytesperline = 0; + fmt->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; - mutex_unlock(&zr->resource_lock); + mutex_unlock(&zr->resource_lock); + return 0; +} - break; +static int zoran_g_fmt_vid_cap(struct file *file, void *__fh, + struct v4l2_format *fmt) +{ + struct zoran_fh *fh = __fh; + struct zoran *zr = fh->zr; - default: - dprintk(1, - KERN_ERR - "%s: VIDIOC_G_FMT - unsupported type %d\n", - ZR_DEVNAME(zr), fmt->type); - return -EINVAL; - } - return 0; - } - break; + if (fh->map_mode != ZORAN_MAP_MODE_RAW) + return zoran_g_fmt_vid_out(file, fh, fmt); - case VIDIOC_S_FMT: - { - struct v4l2_format *fmt = arg; - int i, res = 0; - __le32 printformat; - - dprintk(3, KERN_DEBUG "%s: VIDIOC_S_FMT - type=%d, ", - ZR_DEVNAME(zr), fmt->type); - - switch (fmt->type) { - case V4L2_BUF_TYPE_VIDEO_OVERLAY: - - dprintk(3, "x=%d, y=%d, w=%d, h=%d, cnt=%d, map=0x%p\n", - fmt->fmt.win.w.left, fmt->fmt.win.w.top, - fmt->fmt.win.w.width, - fmt->fmt.win.w.height, - fmt->fmt.win.clipcount, - fmt->fmt.win.bitmap); - mutex_lock(&zr->resource_lock); - res = - setup_window(file, fmt->fmt.win.w.left, - fmt->fmt.win.w.top, - fmt->fmt.win.w.width, - fmt->fmt.win.w.height, - (struct video_clip __user *) - fmt->fmt.win.clips, - fmt->fmt.win.clipcount, - fmt->fmt.win.bitmap); - mutex_unlock(&zr->resource_lock); - return res; - break; + mutex_lock(&zr->resource_lock); + fmt->fmt.pix.width = fh->v4l_settings.width; + fmt->fmt.pix.height = fh->v4l_settings.height; + fmt->fmt.pix.sizeimage = fh->v4l_settings.bytesperline * + fh->v4l_settings.height; + fmt->fmt.pix.pixelformat = fh->v4l_settings.format->fourcc; + fmt->fmt.pix.colorspace = fh->v4l_settings.format->colorspace; + fmt->fmt.pix.bytesperline = fh->v4l_settings.bytesperline; + if (BUZ_MAX_HEIGHT < (fh->v4l_settings.height * 2)) + fmt->fmt.pix.field = V4L2_FIELD_INTERLACED; + else + fmt->fmt.pix.field = V4L2_FIELD_TOP; + mutex_unlock(&zr->resource_lock); + return 0; +} - case V4L2_BUF_TYPE_VIDEO_CAPTURE: - case V4L2_BUF_TYPE_VIDEO_OUTPUT: - - printformat = - __cpu_to_le32(fmt->fmt.pix.pixelformat); - dprintk(3, "size=%dx%d, fmt=0x%x (%4.4s)\n", - fmt->fmt.pix.width, fmt->fmt.pix.height, - fmt->fmt.pix.pixelformat, - (char *) &printformat); - - /* we can be requested to do JPEG/raw playback/capture */ - if (! - (fmt->type == V4L2_BUF_TYPE_VIDEO_CAPTURE || - (fmt->type == V4L2_BUF_TYPE_VIDEO_OUTPUT && - fmt->fmt.pix.pixelformat == - V4L2_PIX_FMT_MJPEG))) { - dprintk(1, - KERN_ERR - "%s: VIDIOC_S_FMT - unknown type %d/0x%x(%4.4s) combination\n", - ZR_DEVNAME(zr), fmt->type, - fmt->fmt.pix.pixelformat, - (char *) &printformat); - return -EINVAL; - } +static int zoran_g_fmt_vid_overlay(struct file *file, void *__fh, + struct v4l2_format *fmt) +{ + struct zoran_fh *fh = __fh; + struct zoran *zr = fh->zr; - if (fmt->fmt.pix.pixelformat == V4L2_PIX_FMT_MJPEG) { - mutex_lock(&zr->resource_lock); + mutex_lock(&zr->resource_lock); - settings = fh->jpg_settings; + fmt->fmt.win.w.left = fh->overlay_settings.x; + fmt->fmt.win.w.top = fh->overlay_settings.y; + fmt->fmt.win.w.width = fh->overlay_settings.width; + fmt->fmt.win.w.height = fh->overlay_settings.height; + if (fh->overlay_settings.width * 2 > BUZ_MAX_HEIGHT) + fmt->fmt.win.field = V4L2_FIELD_INTERLACED; + else + fmt->fmt.win.field = V4L2_FIELD_TOP; - if (fh->v4l_buffers.allocated || - fh->jpg_buffers.allocated) { - dprintk(1, - KERN_ERR - "%s: VIDIOC_S_FMT - cannot change capture mode\n", - ZR_DEVNAME(zr)); - res = -EBUSY; - goto sfmtjpg_unlock_and_return; - } + mutex_unlock(&zr->resource_lock); + return 0; +} - /* we actually need to set 'real' parameters now */ - if ((fmt->fmt.pix.height * 2) > - BUZ_MAX_HEIGHT) - settings.TmpDcm = 1; - else - settings.TmpDcm = 2; - settings.decimation = 0; - if (fmt->fmt.pix.height <= - fh->jpg_settings.img_height / 2) - settings.VerDcm = 2; - else - settings.VerDcm = 1; - if (fmt->fmt.pix.width <= - fh->jpg_settings.img_width / 4) - settings.HorDcm = 4; - else if (fmt->fmt.pix.width <= - fh->jpg_settings.img_width / 2) - settings.HorDcm = 2; - else - settings.HorDcm = 1; - if (settings.TmpDcm == 1) - settings.field_per_buff = 2; - else - settings.field_per_buff = 1; - - /* check */ - if ((res = - zoran_check_jpg_settings(zr, - &settings))) - goto sfmtjpg_unlock_and_return; - - /* it's ok, so set them */ - fh->jpg_settings = settings; - - /* tell the user what we actually did */ - fmt->fmt.pix.width = - settings.img_width / settings.HorDcm; - fmt->fmt.pix.height = - settings.img_height * 2 / - (settings.TmpDcm * settings.VerDcm); - if (settings.TmpDcm == 1) - fmt->fmt.pix.field = - (fh->jpg_settings. - odd_even ? V4L2_FIELD_SEQ_TB : - V4L2_FIELD_SEQ_BT); - else - fmt->fmt.pix.field = - (fh->jpg_settings. - odd_even ? V4L2_FIELD_TOP : - V4L2_FIELD_BOTTOM); - fh->jpg_buffers.buffer_size = - zoran_v4l2_calc_bufsize(&fh-> - jpg_settings); - fmt->fmt.pix.bytesperline = 0; - fmt->fmt.pix.sizeimage = - fh->jpg_buffers.buffer_size; - fmt->fmt.pix.colorspace = - V4L2_COLORSPACE_SMPTE170M; - - /* we hereby abuse this variable to show that - * we're gonna do mjpeg capture */ - fh->map_mode = - (fmt->type == - V4L2_BUF_TYPE_VIDEO_CAPTURE) ? - ZORAN_MAP_MODE_JPG_REC : - ZORAN_MAP_MODE_JPG_PLAY; - sfmtjpg_unlock_and_return: - mutex_unlock(&zr->resource_lock); - } else { - for (i = 0; i < NUM_FORMATS; i++) - if (fmt->fmt.pix.pixelformat == - zoran_formats[i].fourcc) - break; - if (i == NUM_FORMATS) { - dprintk(1, - KERN_ERR - "%s: VIDIOC_S_FMT - unknown/unsupported format 0x%x (%4.4s)\n", - ZR_DEVNAME(zr), - fmt->fmt.pix.pixelformat, - (char *) &printformat); - return -EINVAL; - } - mutex_lock(&zr->resource_lock); - if (fh->jpg_buffers.allocated || - (fh->v4l_buffers.allocated && - fh->v4l_buffers.active != - ZORAN_FREE)) { - dprintk(1, - KERN_ERR - "%s: VIDIOC_S_FMT - cannot change capture mode\n", - ZR_DEVNAME(zr)); - res = -EBUSY; - goto sfmtv4l_unlock_and_return; - } - if (fmt->fmt.pix.height > BUZ_MAX_HEIGHT) - fmt->fmt.pix.height = - BUZ_MAX_HEIGHT; - if (fmt->fmt.pix.width > BUZ_MAX_WIDTH) - fmt->fmt.pix.width = BUZ_MAX_WIDTH; - - if ((res = - zoran_v4l_set_format(file, - fmt->fmt.pix. - width, - fmt->fmt.pix. - height, - &zoran_formats - [i]))) - goto sfmtv4l_unlock_and_return; - - /* tell the user the - * results/missing stuff */ - fmt->fmt.pix.bytesperline = - fh->v4l_settings.bytesperline; - fmt->fmt.pix.sizeimage = - fh->v4l_settings.height * - fh->v4l_settings.bytesperline; - fmt->fmt.pix.colorspace = - fh->v4l_settings.format->colorspace; - if (BUZ_MAX_HEIGHT < - (fh->v4l_settings.height * 2)) - fmt->fmt.pix.field = - V4L2_FIELD_INTERLACED; - else - fmt->fmt.pix.field = - V4L2_FIELD_TOP; - - fh->map_mode = ZORAN_MAP_MODE_RAW; - sfmtv4l_unlock_and_return: - mutex_unlock(&zr->resource_lock); - } +static int zoran_try_fmt_vid_overlay(struct file *file, void *__fh, + struct v4l2_format *fmt) +{ + struct zoran_fh *fh = __fh; + struct zoran *zr = fh->zr; - break; + mutex_lock(&zr->resource_lock); - default: - dprintk(1, - KERN_ERR - "%s: VIDIOC_S_FMT - unsupported type %d\n", - ZR_DEVNAME(zr), fmt->type); - return -EINVAL; - } + if (fmt->fmt.win.w.width > BUZ_MAX_WIDTH) + fmt->fmt.win.w.width = BUZ_MAX_WIDTH; + if (fmt->fmt.win.w.width < BUZ_MIN_WIDTH) + fmt->fmt.win.w.width = BUZ_MIN_WIDTH; + if (fmt->fmt.win.w.height > BUZ_MAX_HEIGHT) + fmt->fmt.win.w.height = BUZ_MAX_HEIGHT; + if (fmt->fmt.win.w.height < BUZ_MIN_HEIGHT) + fmt->fmt.win.w.height = BUZ_MIN_HEIGHT; - return res; - } - break; + mutex_unlock(&zr->resource_lock); + return 0; +} - case VIDIOC_G_FBUF: - { - struct v4l2_framebuffer *fb = arg; +static int zoran_try_fmt_vid_out(struct file *file, void *__fh, + struct v4l2_format *fmt) +{ + struct zoran_fh *fh = __fh; + struct zoran *zr = fh->zr; + struct zoran_jpg_settings settings; + int res = 0; - dprintk(3, KERN_DEBUG "%s: VIDIOC_G_FBUF\n", ZR_DEVNAME(zr)); + if (fmt->fmt.pix.bytesperline > 0) + return -EINVAL; - memset(fb, 0, sizeof(*fb)); - mutex_lock(&zr->resource_lock); - fb->base = zr->buffer.base; - fb->fmt.width = zr->buffer.width; - fb->fmt.height = zr->buffer.height; - if (zr->overlay_settings.format) { - fb->fmt.pixelformat = - fh->overlay_settings.format->fourcc; - } - fb->fmt.bytesperline = zr->buffer.bytesperline; - mutex_unlock(&zr->resource_lock); - fb->fmt.colorspace = V4L2_COLORSPACE_SRGB; - fb->fmt.field = V4L2_FIELD_INTERLACED; - fb->flags = V4L2_FBUF_FLAG_OVERLAY; - fb->capability = V4L2_FBUF_CAP_LIST_CLIPPING; + if (fmt->fmt.pix.pixelformat != V4L2_PIX_FMT_MJPEG) + return -EINVAL; - return 0; - } - break; + mutex_lock(&zr->resource_lock); + settings = fh->jpg_settings; - case VIDIOC_S_FBUF: - { - int i, res = 0; - struct v4l2_framebuffer *fb = arg; - __le32 printformat = __cpu_to_le32(fb->fmt.pixelformat); + /* we actually need to set 'real' parameters now */ + if ((fmt->fmt.pix.height * 2) > BUZ_MAX_HEIGHT) + settings.TmpDcm = 1; + else + settings.TmpDcm = 2; + settings.decimation = 0; + if (fmt->fmt.pix.height <= fh->jpg_settings.img_height / 2) + settings.VerDcm = 2; + else + settings.VerDcm = 1; + if (fmt->fmt.pix.width <= fh->jpg_settings.img_width / 4) + settings.HorDcm = 4; + else if (fmt->fmt.pix.width <= fh->jpg_settings.img_width / 2) + settings.HorDcm = 2; + else + settings.HorDcm = 1; + if (settings.TmpDcm == 1) + settings.field_per_buff = 2; + else + settings.field_per_buff = 1; + + /* check */ + res = zoran_check_jpg_settings(zr, &settings); + if (res) + goto tryfmt_unlock_and_return; + + /* tell the user what we actually did */ + fmt->fmt.pix.width = settings.img_width / settings.HorDcm; + fmt->fmt.pix.height = settings.img_height * 2 / + (settings.TmpDcm * settings.VerDcm); + if (settings.TmpDcm == 1) + fmt->fmt.pix.field = (fh->jpg_settings.odd_even ? + V4L2_FIELD_SEQ_TB : V4L2_FIELD_SEQ_BT); + else + fmt->fmt.pix.field = (fh->jpg_settings.odd_even ? + V4L2_FIELD_TOP : V4L2_FIELD_BOTTOM); - dprintk(3, - KERN_DEBUG - "%s: VIDIOC_S_FBUF - base=0x%p, size=%dx%d, bpl=%d, fmt=0x%x (%4.4s)\n", - ZR_DEVNAME(zr), fb->base, fb->fmt.width, fb->fmt.height, - fb->fmt.bytesperline, fb->fmt.pixelformat, - (char *) &printformat); + fmt->fmt.pix.sizeimage = zoran_v4l2_calc_bufsize(&settings); +tryfmt_unlock_and_return: + mutex_unlock(&zr->resource_lock); + return res; +} - for (i = 0; i < NUM_FORMATS; i++) - if (zoran_formats[i].fourcc == fb->fmt.pixelformat) - break; - if (i == NUM_FORMATS) { - dprintk(1, - KERN_ERR - "%s: VIDIOC_S_FBUF - format=0x%x (%4.4s) not allowed\n", - ZR_DEVNAME(zr), fb->fmt.pixelformat, - (char *) &printformat); - return -EINVAL; - } +static int zoran_try_fmt_vid_cap(struct file *file, void *__fh, + struct v4l2_format *fmt) +{ + struct zoran_fh *fh = __fh; + struct zoran *zr = fh->zr; + int i; - mutex_lock(&zr->resource_lock); - res = - setup_fbuffer(file, fb->base, &zoran_formats[i], - fb->fmt.width, fb->fmt.height, - fb->fmt.bytesperline); - mutex_unlock(&zr->resource_lock); + if (fmt->fmt.pix.bytesperline > 0) + return -EINVAL; - return res; - } - break; + if (fmt->fmt.pix.pixelformat == V4L2_PIX_FMT_MJPEG) + return zoran_try_fmt_vid_out(file, fh, fmt); - case VIDIOC_OVERLAY: - { - int *on = arg, res; + mutex_lock(&zr->resource_lock); - dprintk(3, KERN_DEBUG "%s: VIDIOC_PREVIEW - on=%d\n", - ZR_DEVNAME(zr), *on); + for (i = 0; i < NUM_FORMATS; i++) + if (zoran_formats[i].fourcc == fmt->fmt.pix.pixelformat) + break; - mutex_lock(&zr->resource_lock); - res = setup_overlay(file, *on); + if (i == NUM_FORMATS) { mutex_unlock(&zr->resource_lock); - - return res; + return -EINVAL; } - break; - - case VIDIOC_REQBUFS: - { - struct v4l2_requestbuffers *req = arg; - int res = 0; - - dprintk(3, KERN_DEBUG "%s: VIDIOC_REQBUFS - type=%d\n", - ZR_DEVNAME(zr), req->type); - if (req->memory != V4L2_MEMORY_MMAP) { - dprintk(1, - KERN_ERR - "%s: only MEMORY_MMAP capture is supported, not %d\n", - ZR_DEVNAME(zr), req->memory); - return -EINVAL; - } + if (fmt->fmt.pix.width > BUZ_MAX_WIDTH) + fmt->fmt.pix.width = BUZ_MAX_WIDTH; + if (fmt->fmt.pix.width < BUZ_MIN_WIDTH) + fmt->fmt.pix.width = BUZ_MIN_WIDTH; + if (fmt->fmt.pix.height > BUZ_MAX_HEIGHT) + fmt->fmt.pix.height = BUZ_MAX_HEIGHT; + if (fmt->fmt.pix.height < BUZ_MIN_HEIGHT) + fmt->fmt.pix.height = BUZ_MIN_HEIGHT; + mutex_unlock(&zr->resource_lock); - mutex_lock(&zr->resource_lock); + return 0; +} - if (fh->v4l_buffers.allocated || fh->jpg_buffers.allocated) { - dprintk(1, - KERN_ERR - "%s: VIDIOC_REQBUFS - buffers allready allocated\n", - ZR_DEVNAME(zr)); - res = -EBUSY; - goto v4l2reqbuf_unlock_and_return; - } +static int zoran_s_fmt_vid_overlay(struct file *file, void *__fh, + struct v4l2_format *fmt) +{ + struct zoran_fh *fh = __fh; + struct zoran *zr = fh->zr; + int res; + + dprintk(3, "x=%d, y=%d, w=%d, h=%d, cnt=%d, map=0x%p\n", + fmt->fmt.win.w.left, fmt->fmt.win.w.top, + fmt->fmt.win.w.width, + fmt->fmt.win.w.height, + fmt->fmt.win.clipcount, + fmt->fmt.win.bitmap); + mutex_lock(&zr->resource_lock); + res = setup_window(file, fmt->fmt.win.w.left, + fmt->fmt.win.w.top, + fmt->fmt.win.w.width, + fmt->fmt.win.w.height, + (struct video_clip __user *) + fmt->fmt.win.clips, + fmt->fmt.win.clipcount, + fmt->fmt.win.bitmap); + mutex_unlock(&zr->resource_lock); + return res; +} - if (fh->map_mode == ZORAN_MAP_MODE_RAW && - req->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) { +static int zoran_s_fmt_vid_out(struct file *file, void *__fh, + struct v4l2_format *fmt) +{ + struct zoran_fh *fh = __fh; + struct zoran *zr = fh->zr; + __le32 printformat = __cpu_to_le32(fmt->fmt.pix.pixelformat); + struct zoran_jpg_settings settings; + int res = 0; - /* control user input */ - if (req->count < 2) - req->count = 2; - if (req->count > v4l_nbufs) - req->count = v4l_nbufs; - fh->v4l_buffers.num_buffers = req->count; + dprintk(3, "size=%dx%d, fmt=0x%x (%4.4s)\n", + fmt->fmt.pix.width, fmt->fmt.pix.height, + fmt->fmt.pix.pixelformat, + (char *) &printformat); + if (fmt->fmt.pix.pixelformat != V4L2_PIX_FMT_MJPEG) + return -EINVAL; - if (v4l_fbuffer_alloc(file)) { - res = -ENOMEM; - goto v4l2reqbuf_unlock_and_return; - } + mutex_lock(&zr->resource_lock); - /* The next mmap will map the V4L buffers */ - fh->map_mode = ZORAN_MAP_MODE_RAW; + settings = fh->jpg_settings; - } else if (fh->map_mode == ZORAN_MAP_MODE_JPG_REC || - fh->map_mode == ZORAN_MAP_MODE_JPG_PLAY) { + if (fh->v4l_buffers.allocated || fh->jpg_buffers.allocated) { + dprintk(1, KERN_ERR "%s: VIDIOC_S_FMT - cannot change capture mode\n", + ZR_DEVNAME(zr)); + res = -EBUSY; + goto sfmtjpg_unlock_and_return; + } - /* we need to calculate size ourselves now */ - if (req->count < 4) - req->count = 4; - if (req->count > jpg_nbufs) - req->count = jpg_nbufs; - fh->jpg_buffers.num_buffers = req->count; - fh->jpg_buffers.buffer_size = - zoran_v4l2_calc_bufsize(&fh->jpg_settings); - - if (jpg_fbuffer_alloc(file)) { - res = -ENOMEM; - goto v4l2reqbuf_unlock_and_return; - } - - /* The next mmap will map the MJPEG buffers */ - if (req->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) - fh->map_mode = ZORAN_MAP_MODE_JPG_REC; - else - fh->map_mode = ZORAN_MAP_MODE_JPG_PLAY; - - } else { - dprintk(1, - KERN_ERR - "%s: VIDIOC_REQBUFS - unknown type %d\n", - ZR_DEVNAME(zr), req->type); - res = -EINVAL; - goto v4l2reqbuf_unlock_and_return; - } - v4l2reqbuf_unlock_and_return: - mutex_unlock(&zr->resource_lock); - - return 0; - } - break; - - case VIDIOC_QUERYBUF: - { - struct v4l2_buffer *buf = arg; - __u32 type = buf->type; - int index = buf->index, res; - - dprintk(3, - KERN_DEBUG - "%s: VIDIOC_QUERYBUF - index=%d, type=%d\n", - ZR_DEVNAME(zr), buf->index, buf->type); + /* we actually need to set 'real' parameters now */ + if ((fmt->fmt.pix.height * 2) > BUZ_MAX_HEIGHT) + settings.TmpDcm = 1; + else + settings.TmpDcm = 2; + settings.decimation = 0; + if (fmt->fmt.pix.height <= fh->jpg_settings.img_height / 2) + settings.VerDcm = 2; + else + settings.VerDcm = 1; + if (fmt->fmt.pix.width <= fh->jpg_settings.img_width / 4) + settings.HorDcm = 4; + else if (fmt->fmt.pix.width <= fh->jpg_settings.img_width / 2) + settings.HorDcm = 2; + else + settings.HorDcm = 1; + if (settings.TmpDcm == 1) + settings.field_per_buff = 2; + else + settings.field_per_buff = 1; + + /* check */ + res = zoran_check_jpg_settings(zr, &settings); + if (res) + goto sfmtjpg_unlock_and_return; + + /* it's ok, so set them */ + fh->jpg_settings = settings; + + /* tell the user what we actually did */ + fmt->fmt.pix.width = settings.img_width / settings.HorDcm; + fmt->fmt.pix.height = settings.img_height * 2 / + (settings.TmpDcm * settings.VerDcm); + if (settings.TmpDcm == 1) + fmt->fmt.pix.field = (fh->jpg_settings.odd_even ? + V4L2_FIELD_SEQ_TB : V4L2_FIELD_SEQ_BT); + else + fmt->fmt.pix.field = (fh->jpg_settings.odd_even ? + V4L2_FIELD_TOP : V4L2_FIELD_BOTTOM); + fh->jpg_buffers.buffer_size = zoran_v4l2_calc_bufsize(&fh->jpg_settings); + fmt->fmt.pix.bytesperline = 0; + fmt->fmt.pix.sizeimage = fh->jpg_buffers.buffer_size; + fmt->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; + + /* we hereby abuse this variable to show that + * we're gonna do mjpeg capture */ + fh->map_mode = (fmt->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) ? + ZORAN_MAP_MODE_JPG_REC : ZORAN_MAP_MODE_JPG_PLAY; +sfmtjpg_unlock_and_return: + mutex_unlock(&zr->resource_lock); + return res; +} - memset(buf, 0, sizeof(*buf)); - buf->type = type; - buf->index = index; +static int zoran_s_fmt_vid_cap(struct file *file, void *__fh, + struct v4l2_format *fmt) +{ + struct zoran_fh *fh = __fh; + struct zoran *zr = fh->zr; + int i; + int res = 0; - mutex_lock(&zr->resource_lock); - res = zoran_v4l2_buffer_status(file, buf, buf->index); - mutex_unlock(&zr->resource_lock); + if (fmt->fmt.pix.pixelformat == V4L2_PIX_FMT_MJPEG) + return zoran_s_fmt_vid_out(file, fh, fmt); - return res; + for (i = 0; i < NUM_FORMATS; i++) + if (fmt->fmt.pix.pixelformat == zoran_formats[i].fourcc) + break; + if (i == NUM_FORMATS) { + dprintk(1, KERN_ERR "%s: VIDIOC_S_FMT - unknown/unsupported format 0x%x\n", + ZR_DEVNAME(zr), fmt->fmt.pix.pixelformat); + return -EINVAL; } - break; - - case VIDIOC_QBUF: - { - struct v4l2_buffer *buf = arg; - int res = 0, codec_mode, buf_type; - - dprintk(3, - KERN_DEBUG "%s: VIDIOC_QBUF - type=%d, index=%d\n", - ZR_DEVNAME(zr), buf->type, buf->index); + mutex_lock(&zr->resource_lock); + if (fh->jpg_buffers.allocated || + (fh->v4l_buffers.allocated && fh->v4l_buffers.active != ZORAN_FREE)) { + dprintk(1, KERN_ERR "%s: VIDIOC_S_FMT - cannot change capture mode\n", + ZR_DEVNAME(zr)); + res = -EBUSY; + goto sfmtv4l_unlock_and_return; + } + if (fmt->fmt.pix.height > BUZ_MAX_HEIGHT) + fmt->fmt.pix.height = BUZ_MAX_HEIGHT; + if (fmt->fmt.pix.width > BUZ_MAX_WIDTH) + fmt->fmt.pix.width = BUZ_MAX_WIDTH; + + res = zoran_v4l_set_format(file, fmt->fmt.pix.width, + fmt->fmt.pix.height, &zoran_formats[i]); + if (res) + goto sfmtv4l_unlock_and_return; + + /* tell the user the + * results/missing stuff */ + fmt->fmt.pix.bytesperline = fh->v4l_settings.bytesperline; + fmt->fmt.pix.sizeimage = fh->v4l_settings.height * fh->v4l_settings.bytesperline; + fmt->fmt.pix.colorspace = fh->v4l_settings.format->colorspace; + if (BUZ_MAX_HEIGHT < (fh->v4l_settings.height * 2)) + fmt->fmt.pix.field = V4L2_FIELD_INTERLACED; + else + fmt->fmt.pix.field = V4L2_FIELD_TOP; - mutex_lock(&zr->resource_lock); + fh->map_mode = ZORAN_MAP_MODE_RAW; +sfmtv4l_unlock_and_return: + mutex_unlock(&zr->resource_lock); + return res; +} - switch (fh->map_mode) { - case ZORAN_MAP_MODE_RAW: - if (buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) { - dprintk(1, - KERN_ERR - "%s: VIDIOC_QBUF - invalid buf->type=%d for map_mode=%d\n", - ZR_DEVNAME(zr), buf->type, fh->map_mode); - res = -EINVAL; - goto qbuf_unlock_and_return; - } +static int zoran_g_fbuf(struct file *file, void *__fh, + struct v4l2_framebuffer *fb) +{ + struct zoran_fh *fh = __fh; + struct zoran *zr = fh->zr; - res = zoran_v4l_queue_frame(file, buf->index); - if (res) - goto qbuf_unlock_and_return; - if (!zr->v4l_memgrab_active && - fh->v4l_buffers.active == ZORAN_LOCKED) - zr36057_set_memgrab(zr, 1); - break; + memset(fb, 0, sizeof(*fb)); + mutex_lock(&zr->resource_lock); + fb->base = zr->buffer.base; + fb->fmt.width = zr->buffer.width; + fb->fmt.height = zr->buffer.height; + if (zr->overlay_settings.format) + fb->fmt.pixelformat = fh->overlay_settings.format->fourcc; + fb->fmt.bytesperline = zr->buffer.bytesperline; + mutex_unlock(&zr->resource_lock); + fb->fmt.colorspace = V4L2_COLORSPACE_SRGB; + fb->fmt.field = V4L2_FIELD_INTERLACED; + fb->flags = V4L2_FBUF_FLAG_OVERLAY; + fb->capability = V4L2_FBUF_CAP_LIST_CLIPPING; - case ZORAN_MAP_MODE_JPG_REC: - case ZORAN_MAP_MODE_JPG_PLAY: - if (fh->map_mode == ZORAN_MAP_MODE_JPG_PLAY) { - buf_type = V4L2_BUF_TYPE_VIDEO_OUTPUT; - codec_mode = BUZ_MODE_MOTION_DECOMPRESS; - } else { - buf_type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - codec_mode = BUZ_MODE_MOTION_COMPRESS; - } + return 0; +} - if (buf->type != buf_type) { - dprintk(1, - KERN_ERR - "%s: VIDIOC_QBUF - invalid buf->type=%d for map_mode=%d\n", - ZR_DEVNAME(zr), buf->type, fh->map_mode); - res = -EINVAL; - goto qbuf_unlock_and_return; - } +static int zoran_s_fbuf(struct file *file, void *__fh, + struct v4l2_framebuffer *fb) +{ + struct zoran_fh *fh = __fh; + struct zoran *zr = fh->zr; + int i, res = 0; + __le32 printformat = __cpu_to_le32(fb->fmt.pixelformat); - res = - zoran_jpg_queue_frame(file, buf->index, - codec_mode); - if (res != 0) - goto qbuf_unlock_and_return; - if (zr->codec_mode == BUZ_MODE_IDLE && - fh->jpg_buffers.active == ZORAN_LOCKED) { - zr36057_enable_jpg(zr, codec_mode); - } + for (i = 0; i < NUM_FORMATS; i++) + if (zoran_formats[i].fourcc == fb->fmt.pixelformat) break; - - default: - dprintk(1, - KERN_ERR - "%s: VIDIOC_QBUF - unsupported type %d\n", - ZR_DEVNAME(zr), buf->type); - res = -EINVAL; - goto qbuf_unlock_and_return; - } - qbuf_unlock_and_return: - mutex_unlock(&zr->resource_lock); - - return res; + if (i == NUM_FORMATS) { + dprintk(1, KERN_ERR "%s: VIDIOC_S_FBUF - format=0x%x (%4.4s) not allowed\n", + ZR_DEVNAME(zr), fb->fmt.pixelformat, + (char *)&printformat); + return -EINVAL; } - break; - - case VIDIOC_DQBUF: - { - struct v4l2_buffer *buf = arg; - int res = 0, buf_type, num = -1; /* compiler borks here (?) */ - dprintk(3, KERN_DEBUG "%s: VIDIOC_DQBUF - type=%d\n", - ZR_DEVNAME(zr), buf->type); - - mutex_lock(&zr->resource_lock); + mutex_lock(&zr->resource_lock); + res = setup_fbuffer(file, fb->base, &zoran_formats[i], + fb->fmt.width, fb->fmt.height, + fb->fmt.bytesperline); + mutex_unlock(&zr->resource_lock); - switch (fh->map_mode) { - case ZORAN_MAP_MODE_RAW: - if (buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) { - dprintk(1, - KERN_ERR - "%s: VIDIOC_QBUF - invalid buf->type=%d for map_mode=%d\n", - ZR_DEVNAME(zr), buf->type, fh->map_mode); - res = -EINVAL; - goto dqbuf_unlock_and_return; - } + return res; +} - num = zr->v4l_pend[zr->v4l_sync_tail & V4L_MASK_FRAME]; - if (file->f_flags & O_NONBLOCK && - zr->v4l_buffers.buffer[num].state != - BUZ_STATE_DONE) { - res = -EAGAIN; - goto dqbuf_unlock_and_return; - } - res = v4l_sync(file, num); - if (res) - goto dqbuf_unlock_and_return; - else - zr->v4l_sync_tail++; - res = zoran_v4l2_buffer_status(file, buf, num); - break; +static int zoran_overlay(struct file *file, void *__fh, unsigned int on) +{ + struct zoran_fh *fh = __fh; + struct zoran *zr = fh->zr; + int res; - case ZORAN_MAP_MODE_JPG_REC: - case ZORAN_MAP_MODE_JPG_PLAY: - { - struct zoran_sync bs; + mutex_lock(&zr->resource_lock); + res = setup_overlay(file, on); + mutex_unlock(&zr->resource_lock); - if (fh->map_mode == ZORAN_MAP_MODE_JPG_PLAY) - buf_type = V4L2_BUF_TYPE_VIDEO_OUTPUT; - else - buf_type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + return res; +} - if (buf->type != buf_type) { - dprintk(1, - KERN_ERR - "%s: VIDIOC_QBUF - invalid buf->type=%d for map_mode=%d\n", - ZR_DEVNAME(zr), buf->type, fh->map_mode); - res = -EINVAL; - goto dqbuf_unlock_and_return; - } +static int zoran_reqbufs(struct file *file, void *__fh, struct v4l2_requestbuffers *req) +{ + struct zoran_fh *fh = __fh; + struct zoran *zr = fh->zr; + int res = 0; - num = - zr->jpg_pend[zr-> - jpg_que_tail & BUZ_MASK_FRAME]; + if (req->memory != V4L2_MEMORY_MMAP) { + dprintk(1, + KERN_ERR + "%s: only MEMORY_MMAP capture is supported, not %d\n", + ZR_DEVNAME(zr), req->memory); + return -EINVAL; + } - if (file->f_flags & O_NONBLOCK && - zr->jpg_buffers.buffer[num].state != - BUZ_STATE_DONE) { - res = -EAGAIN; - goto dqbuf_unlock_and_return; - } - res = jpg_sync(file, &bs); - if (res) - goto dqbuf_unlock_and_return; - res = - zoran_v4l2_buffer_status(file, buf, bs.frame); - break; - } + mutex_lock(&zr->resource_lock); - default: - dprintk(1, + if (fh->v4l_buffers.allocated || fh->jpg_buffers.allocated) { + dprintk(1, KERN_ERR - "%s: VIDIOC_DQBUF - unsupported type %d\n", - ZR_DEVNAME(zr), buf->type); - res = -EINVAL; - goto dqbuf_unlock_and_return; - } - dqbuf_unlock_and_return: - mutex_unlock(&zr->resource_lock); - - return res; + "%s: VIDIOC_REQBUFS - buffers allready allocated\n", + ZR_DEVNAME(zr)); + res = -EBUSY; + goto v4l2reqbuf_unlock_and_return; } - break; - - case VIDIOC_STREAMON: - { - int res = 0; - dprintk(3, KERN_DEBUG "%s: VIDIOC_STREAMON\n", ZR_DEVNAME(zr)); + if (fh->map_mode == ZORAN_MAP_MODE_RAW && + req->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) { - mutex_lock(&zr->resource_lock); + /* control user input */ + if (req->count < 2) + req->count = 2; + if (req->count > v4l_nbufs) + req->count = v4l_nbufs; + fh->v4l_buffers.num_buffers = req->count; - switch (fh->map_mode) { - case ZORAN_MAP_MODE_RAW: /* raw capture */ - if (zr->v4l_buffers.active != ZORAN_ACTIVE || - fh->v4l_buffers.active != ZORAN_ACTIVE) { - res = -EBUSY; - goto strmon_unlock_and_return; - } + if (v4l_fbuffer_alloc(file)) { + res = -ENOMEM; + goto v4l2reqbuf_unlock_and_return; + } - zr->v4l_buffers.active = fh->v4l_buffers.active = - ZORAN_LOCKED; - zr->v4l_settings = fh->v4l_settings; + /* The next mmap will map the V4L buffers */ + fh->map_mode = ZORAN_MAP_MODE_RAW; - zr->v4l_sync_tail = zr->v4l_pend_tail; - if (!zr->v4l_memgrab_active && - zr->v4l_pend_head != zr->v4l_pend_tail) { - zr36057_set_memgrab(zr, 1); - } - break; + } else if (fh->map_mode == ZORAN_MAP_MODE_JPG_REC || + fh->map_mode == ZORAN_MAP_MODE_JPG_PLAY) { - case ZORAN_MAP_MODE_JPG_REC: - case ZORAN_MAP_MODE_JPG_PLAY: - /* what is the codec mode right now? */ - if (zr->jpg_buffers.active != ZORAN_ACTIVE || - fh->jpg_buffers.active != ZORAN_ACTIVE) { - res = -EBUSY; - goto strmon_unlock_and_return; - } + /* we need to calculate size ourselves now */ + if (req->count < 4) + req->count = 4; + if (req->count > jpg_nbufs) + req->count = jpg_nbufs; + fh->jpg_buffers.num_buffers = req->count; + fh->jpg_buffers.buffer_size = + zoran_v4l2_calc_bufsize(&fh->jpg_settings); - zr->jpg_buffers.active = fh->jpg_buffers.active = - ZORAN_LOCKED; + if (jpg_fbuffer_alloc(file)) { + res = -ENOMEM; + goto v4l2reqbuf_unlock_and_return; + } - if (zr->jpg_que_head != zr->jpg_que_tail) { - /* Start the jpeg codec when the first frame is queued */ - jpeg_start(zr); - } + /* The next mmap will map the MJPEG buffers */ + if (req->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) + fh->map_mode = ZORAN_MAP_MODE_JPG_REC; + else + fh->map_mode = ZORAN_MAP_MODE_JPG_PLAY; - break; - default: - dprintk(1, + } else { + dprintk(1, KERN_ERR - "%s: VIDIOC_STREAMON - invalid map mode %d\n", - ZR_DEVNAME(zr), fh->map_mode); - res = -EINVAL; - goto strmon_unlock_and_return; - } - strmon_unlock_and_return: - mutex_unlock(&zr->resource_lock); - - return res; + "%s: VIDIOC_REQBUFS - unknown type %d\n", + ZR_DEVNAME(zr), req->type); + res = -EINVAL; + goto v4l2reqbuf_unlock_and_return; } - break; - - case VIDIOC_STREAMOFF: - { - int i, res = 0; - - dprintk(3, KERN_DEBUG "%s: VIDIOC_STREAMOFF\n", ZR_DEVNAME(zr)); - - mutex_lock(&zr->resource_lock); +v4l2reqbuf_unlock_and_return: + mutex_unlock(&zr->resource_lock); - switch (fh->map_mode) { - case ZORAN_MAP_MODE_RAW: /* raw capture */ - if (fh->v4l_buffers.active == ZORAN_FREE && - zr->v4l_buffers.active != ZORAN_FREE) { - res = -EPERM; /* stay off other's settings! */ - goto strmoff_unlock_and_return; - } - if (zr->v4l_buffers.active == ZORAN_FREE) - goto strmoff_unlock_and_return; + return res; +} - /* unload capture */ - if (zr->v4l_memgrab_active) { - unsigned long flags; +static int zoran_querybuf(struct file *file, void *__fh, struct v4l2_buffer *buf) +{ + struct zoran_fh *fh = __fh; + struct zoran *zr = fh->zr; + __u32 type = buf->type; + int index = buf->index, res; - spin_lock_irqsave(&zr->spinlock, flags); - zr36057_set_memgrab(zr, 0); - spin_unlock_irqrestore(&zr->spinlock, flags); - } + memset(buf, 0, sizeof(*buf)); + buf->type = type; + buf->index = index; - for (i = 0; i < fh->v4l_buffers.num_buffers; i++) - zr->v4l_buffers.buffer[i].state = - BUZ_STATE_USER; - fh->v4l_buffers = zr->v4l_buffers; + mutex_lock(&zr->resource_lock); + res = zoran_v4l2_buffer_status(file, buf, buf->index); + mutex_unlock(&zr->resource_lock); - zr->v4l_buffers.active = fh->v4l_buffers.active = - ZORAN_FREE; + return res; +} - zr->v4l_grab_seq = 0; - zr->v4l_pend_head = zr->v4l_pend_tail = 0; - zr->v4l_sync_tail = 0; +static int zoran_qbuf(struct file *file, void *__fh, struct v4l2_buffer *buf) +{ + struct zoran_fh *fh = __fh; + struct zoran *zr = fh->zr; + int res = 0, codec_mode, buf_type; - break; + mutex_lock(&zr->resource_lock); - case ZORAN_MAP_MODE_JPG_REC: - case ZORAN_MAP_MODE_JPG_PLAY: - if (fh->jpg_buffers.active == ZORAN_FREE && - zr->jpg_buffers.active != ZORAN_FREE) { - res = -EPERM; /* stay off other's settings! */ - goto strmoff_unlock_and_return; - } - if (zr->jpg_buffers.active == ZORAN_FREE) - goto strmoff_unlock_and_return; - - res = - jpg_qbuf(file, -1, - (fh->map_mode == - ZORAN_MAP_MODE_JPG_REC) ? - BUZ_MODE_MOTION_COMPRESS : - BUZ_MODE_MOTION_DECOMPRESS); - if (res) - goto strmoff_unlock_and_return; - break; - default: - dprintk(1, - KERN_ERR - "%s: VIDIOC_STREAMOFF - invalid map mode %d\n", - ZR_DEVNAME(zr), fh->map_mode); + switch (fh->map_mode) { + case ZORAN_MAP_MODE_RAW: + if (buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) { + dprintk(1, KERN_ERR + "%s: VIDIOC_QBUF - invalid buf->type=%d for map_mode=%d\n", + ZR_DEVNAME(zr), buf->type, fh->map_mode); res = -EINVAL; - goto strmoff_unlock_and_return; + goto qbuf_unlock_and_return; } - strmoff_unlock_and_return: - mutex_unlock(&zr->resource_lock); - return res; - } + res = zoran_v4l_queue_frame(file, buf->index); + if (res) + goto qbuf_unlock_and_return; + if (!zr->v4l_memgrab_active && + fh->v4l_buffers.active == ZORAN_LOCKED) + zr36057_set_memgrab(zr, 1); break; - case VIDIOC_QUERYCTRL: - { - struct v4l2_queryctrl *ctrl = arg; - - dprintk(3, KERN_DEBUG "%s: VIDIOC_QUERYCTRL - id=%d\n", - ZR_DEVNAME(zr), ctrl->id); - - /* we only support hue/saturation/contrast/brightness */ - if (ctrl->id < V4L2_CID_BRIGHTNESS || - ctrl->id > V4L2_CID_HUE) - return -EINVAL; - else { - int id = ctrl->id; - memset(ctrl, 0, sizeof(*ctrl)); - ctrl->id = id; + case ZORAN_MAP_MODE_JPG_REC: + case ZORAN_MAP_MODE_JPG_PLAY: + if (fh->map_mode == ZORAN_MAP_MODE_JPG_PLAY) { + buf_type = V4L2_BUF_TYPE_VIDEO_OUTPUT; + codec_mode = BUZ_MODE_MOTION_DECOMPRESS; + } else { + buf_type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + codec_mode = BUZ_MODE_MOTION_COMPRESS; } - switch (ctrl->id) { - case V4L2_CID_BRIGHTNESS: - strncpy(ctrl->name, "Brightness", sizeof(ctrl->name)-1); - break; - case V4L2_CID_CONTRAST: - strncpy(ctrl->name, "Contrast", sizeof(ctrl->name)-1); - break; - case V4L2_CID_SATURATION: - strncpy(ctrl->name, "Saturation", sizeof(ctrl->name)-1); - break; - case V4L2_CID_HUE: - strncpy(ctrl->name, "Hue", sizeof(ctrl->name)-1); - break; + if (buf->type != buf_type) { + dprintk(1, KERN_ERR + "%s: VIDIOC_QBUF - invalid buf->type=%d for map_mode=%d\n", + ZR_DEVNAME(zr), buf->type, fh->map_mode); + res = -EINVAL; + goto qbuf_unlock_and_return; } - ctrl->minimum = 0; - ctrl->maximum = 65535; - ctrl->step = 1; - ctrl->default_value = 32768; - ctrl->type = V4L2_CTRL_TYPE_INTEGER; - - return 0; - } - break; - - case VIDIOC_G_CTRL: - { - struct v4l2_control *ctrl = arg; - - dprintk(3, KERN_DEBUG "%s: VIDIOC_G_CTRL - id=%d\n", - ZR_DEVNAME(zr), ctrl->id); - - /* we only support hue/saturation/contrast/brightness */ - if (ctrl->id < V4L2_CID_BRIGHTNESS || - ctrl->id > V4L2_CID_HUE) - return -EINVAL; - - mutex_lock(&zr->resource_lock); - switch (ctrl->id) { - case V4L2_CID_BRIGHTNESS: - ctrl->value = zr->brightness; - break; - case V4L2_CID_CONTRAST: - ctrl->value = zr->contrast; - break; - case V4L2_CID_SATURATION: - ctrl->value = zr->saturation; - break; - case V4L2_CID_HUE: - ctrl->value = zr->hue; - break; + res = zoran_jpg_queue_frame(file, buf->index, + codec_mode); + if (res != 0) + goto qbuf_unlock_and_return; + if (zr->codec_mode == BUZ_MODE_IDLE && + fh->jpg_buffers.active == ZORAN_LOCKED) { + zr36057_enable_jpg(zr, codec_mode); } - mutex_unlock(&zr->resource_lock); + break; - return 0; - } + default: + dprintk(1, KERN_ERR + "%s: VIDIOC_QBUF - unsupported type %d\n", + ZR_DEVNAME(zr), buf->type); + res = -EINVAL; break; + } +qbuf_unlock_and_return: + mutex_unlock(&zr->resource_lock); - case VIDIOC_S_CTRL: - { - struct v4l2_control *ctrl = arg; - struct video_picture pict; + return res; +} - dprintk(3, KERN_DEBUG "%s: VIDIOC_S_CTRL - id=%d\n", - ZR_DEVNAME(zr), ctrl->id); +static int zoran_dqbuf(struct file *file, void *__fh, struct v4l2_buffer *buf) +{ + struct zoran_fh *fh = __fh; + struct zoran *zr = fh->zr; + int res = 0, buf_type, num = -1; /* compiler borks here (?) */ - /* we only support hue/saturation/contrast/brightness */ - if (ctrl->id < V4L2_CID_BRIGHTNESS || - ctrl->id > V4L2_CID_HUE) - return -EINVAL; + mutex_lock(&zr->resource_lock); - if (ctrl->value < 0 || ctrl->value > 65535) { - dprintk(1, - KERN_ERR - "%s: VIDIOC_S_CTRL - invalid value %d for id=%d\n", - ZR_DEVNAME(zr), ctrl->value, ctrl->id); - return -EINVAL; + switch (fh->map_mode) { + case ZORAN_MAP_MODE_RAW: + if (buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) { + dprintk(1, KERN_ERR + "%s: VIDIOC_QBUF - invalid buf->type=%d for map_mode=%d\n", + ZR_DEVNAME(zr), buf->type, fh->map_mode); + res = -EINVAL; + goto dqbuf_unlock_and_return; } - mutex_lock(&zr->resource_lock); - switch (ctrl->id) { - case V4L2_CID_BRIGHTNESS: - zr->brightness = ctrl->value; - break; - case V4L2_CID_CONTRAST: - zr->contrast = ctrl->value; - break; - case V4L2_CID_SATURATION: - zr->saturation = ctrl->value; - break; - case V4L2_CID_HUE: - zr->hue = ctrl->value; - break; + num = zr->v4l_pend[zr->v4l_sync_tail & V4L_MASK_FRAME]; + if (file->f_flags & O_NONBLOCK && + zr->v4l_buffers.buffer[num].state != BUZ_STATE_DONE) { + res = -EAGAIN; + goto dqbuf_unlock_and_return; } - pict.brightness = zr->brightness; - pict.contrast = zr->contrast; - pict.colour = zr->saturation; - pict.hue = zr->hue; - - decoder_command(zr, DECODER_SET_PICTURE, &pict); - - mutex_unlock(&zr->resource_lock); - - return 0; - } + res = v4l_sync(file, num); + if (res) + goto dqbuf_unlock_and_return; + zr->v4l_sync_tail++; + res = zoran_v4l2_buffer_status(file, buf, num); break; - case VIDIOC_ENUMSTD: + case ZORAN_MAP_MODE_JPG_REC: + case ZORAN_MAP_MODE_JPG_PLAY: { - struct v4l2_standard *std = arg; + struct zoran_sync bs; - dprintk(3, KERN_DEBUG "%s: VIDIOC_ENUMSTD - index=%d\n", - ZR_DEVNAME(zr), std->index); + if (fh->map_mode == ZORAN_MAP_MODE_JPG_PLAY) + buf_type = V4L2_BUF_TYPE_VIDEO_OUTPUT; + else + buf_type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - if (std->index < 0 || std->index >= (zr->card.norms + 1)) - return -EINVAL; - else { - int id = std->index; - memset(std, 0, sizeof(*std)); - std->index = id; + if (buf->type != buf_type) { + dprintk(1, KERN_ERR + "%s: VIDIOC_QBUF - invalid buf->type=%d for map_mode=%d\n", + ZR_DEVNAME(zr), buf->type, fh->map_mode); + res = -EINVAL; + goto dqbuf_unlock_and_return; } - if (std->index == zr->card.norms) { - /* if we have autodetect, ... */ - struct video_decoder_capability caps; - decoder_command(zr, DECODER_GET_CAPABILITIES, - &caps); - if (caps.flags & VIDEO_DECODER_AUTO) { - std->id = V4L2_STD_ALL; - strncpy(std->name, "Autodetect", sizeof(std->name)-1); - return 0; - } else - return -EINVAL; - } - switch (std->index) { - case 0: - std->id = V4L2_STD_PAL; - strncpy(std->name, "PAL", sizeof(std->name)-1); - std->frameperiod.numerator = 1; - std->frameperiod.denominator = 25; - std->framelines = zr->card.tvn[0]->Ht; - break; - case 1: - std->id = V4L2_STD_NTSC; - strncpy(std->name, "NTSC", sizeof(std->name)-1); - std->frameperiod.numerator = 1001; - std->frameperiod.denominator = 30000; - std->framelines = zr->card.tvn[1]->Ht; - break; - case 2: - std->id = V4L2_STD_SECAM; - strncpy(std->name, "SECAM", sizeof(std->name)-1); - std->frameperiod.numerator = 1; - std->frameperiod.denominator = 25; - std->framelines = zr->card.tvn[2]->Ht; - break; - } + num = zr->jpg_pend[zr->jpg_que_tail & BUZ_MASK_FRAME]; - return 0; + if (file->f_flags & O_NONBLOCK && + zr->jpg_buffers.buffer[num].state != BUZ_STATE_DONE) { + res = -EAGAIN; + goto dqbuf_unlock_and_return; + } + res = jpg_sync(file, &bs); + if (res) + goto dqbuf_unlock_and_return; + res = zoran_v4l2_buffer_status(file, buf, bs.frame); + break; } + + default: + dprintk(1, KERN_ERR + "%s: VIDIOC_DQBUF - unsupported type %d\n", + ZR_DEVNAME(zr), buf->type); + res = -EINVAL; break; + } +dqbuf_unlock_and_return: + mutex_unlock(&zr->resource_lock); - case VIDIOC_G_STD: - { - v4l2_std_id *std = arg; - int norm; + return res; +} - dprintk(3, KERN_DEBUG "%s: VIDIOC_G_STD\n", ZR_DEVNAME(zr)); +static int zoran_streamon(struct file *file, void *__fh, enum v4l2_buf_type type) +{ + struct zoran_fh *fh = __fh; + struct zoran *zr = fh->zr; + int res = 0; - mutex_lock(&zr->resource_lock); - norm = zr->norm; - mutex_unlock(&zr->resource_lock); + mutex_lock(&zr->resource_lock); - switch (norm) { - case VIDEO_MODE_PAL: - *std = V4L2_STD_PAL; - break; - case VIDEO_MODE_NTSC: - *std = V4L2_STD_NTSC; - break; - case VIDEO_MODE_SECAM: - *std = V4L2_STD_SECAM; - break; + switch (fh->map_mode) { + case ZORAN_MAP_MODE_RAW: /* raw capture */ + if (zr->v4l_buffers.active != ZORAN_ACTIVE || + fh->v4l_buffers.active != ZORAN_ACTIVE) { + res = -EBUSY; + goto strmon_unlock_and_return; } - return 0; - } + zr->v4l_buffers.active = fh->v4l_buffers.active = ZORAN_LOCKED; + zr->v4l_settings = fh->v4l_settings; + + zr->v4l_sync_tail = zr->v4l_pend_tail; + if (!zr->v4l_memgrab_active && + zr->v4l_pend_head != zr->v4l_pend_tail) { + zr36057_set_memgrab(zr, 1); + } break; - case VIDIOC_S_STD: - { - int norm = -1, res = 0; - v4l2_std_id *std = arg; + case ZORAN_MAP_MODE_JPG_REC: + case ZORAN_MAP_MODE_JPG_PLAY: + /* what is the codec mode right now? */ + if (zr->jpg_buffers.active != ZORAN_ACTIVE || + fh->jpg_buffers.active != ZORAN_ACTIVE) { + res = -EBUSY; + goto strmon_unlock_and_return; + } - dprintk(3, KERN_DEBUG "%s: VIDIOC_S_STD - norm=0x%llx\n", - ZR_DEVNAME(zr), (unsigned long long)*std); + zr->jpg_buffers.active = fh->jpg_buffers.active = ZORAN_LOCKED; - if ((*std & V4L2_STD_PAL) && !(*std & ~V4L2_STD_PAL)) - norm = VIDEO_MODE_PAL; - else if ((*std & V4L2_STD_NTSC) && !(*std & ~V4L2_STD_NTSC)) - norm = VIDEO_MODE_NTSC; - else if ((*std & V4L2_STD_SECAM) && !(*std & ~V4L2_STD_SECAM)) - norm = VIDEO_MODE_SECAM; - else if (*std == V4L2_STD_ALL) - norm = VIDEO_MODE_AUTO; - else { - dprintk(1, - KERN_ERR - "%s: VIDIOC_S_STD - invalid norm 0x%llx\n", - ZR_DEVNAME(zr), (unsigned long long)*std); - return -EINVAL; + if (zr->jpg_que_head != zr->jpg_que_tail) { + /* Start the jpeg codec when the first frame is queued */ + jpeg_start(zr); } + break; - mutex_lock(&zr->resource_lock); - if ((res = zoran_set_norm(zr, norm))) - goto sstd_unlock_and_return; - - res = wait_grab_pending(zr); - sstd_unlock_and_return: - mutex_unlock(&zr->resource_lock); - return res; - } + default: + dprintk(1, + KERN_ERR + "%s: VIDIOC_STREAMON - invalid map mode %d\n", + ZR_DEVNAME(zr), fh->map_mode); + res = -EINVAL; break; + } +strmon_unlock_and_return: + mutex_unlock(&zr->resource_lock); - case VIDIOC_ENUMINPUT: - { - struct v4l2_input *inp = arg; - int status; + return res; +} + +static int zoran_streamoff(struct file *file, void *__fh, enum v4l2_buf_type type) +{ + struct zoran_fh *fh = __fh; + struct zoran *zr = fh->zr; + int i, res = 0; - dprintk(3, KERN_DEBUG "%s: VIDIOC_ENUMINPUT - index=%d\n", - ZR_DEVNAME(zr), inp->index); + mutex_lock(&zr->resource_lock); - if (inp->index < 0 || inp->index >= zr->card.inputs) - return -EINVAL; - else { - int id = inp->index; - memset(inp, 0, sizeof(*inp)); - inp->index = id; + switch (fh->map_mode) { + case ZORAN_MAP_MODE_RAW: /* raw capture */ + if (fh->v4l_buffers.active == ZORAN_FREE && + zr->v4l_buffers.active != ZORAN_FREE) { + res = -EPERM; /* stay off other's settings! */ + goto strmoff_unlock_and_return; } + if (zr->v4l_buffers.active == ZORAN_FREE) + goto strmoff_unlock_and_return; - strncpy(inp->name, zr->card.input[inp->index].name, - sizeof(inp->name) - 1); - inp->type = V4L2_INPUT_TYPE_CAMERA; - inp->std = V4L2_STD_ALL; - - /* Get status of video decoder */ - mutex_lock(&zr->resource_lock); - decoder_command(zr, DECODER_GET_STATUS, &status); - mutex_unlock(&zr->resource_lock); + /* unload capture */ + if (zr->v4l_memgrab_active) { + unsigned long flags; - if (!(status & DECODER_STATUS_GOOD)) { - inp->status |= V4L2_IN_ST_NO_POWER; - inp->status |= V4L2_IN_ST_NO_SIGNAL; + spin_lock_irqsave(&zr->spinlock, flags); + zr36057_set_memgrab(zr, 0); + spin_unlock_irqrestore(&zr->spinlock, flags); } - if (!(status & DECODER_STATUS_COLOR)) - inp->status |= V4L2_IN_ST_NO_COLOR; - return 0; - } - break; + for (i = 0; i < fh->v4l_buffers.num_buffers; i++) + zr->v4l_buffers.buffer[i].state = BUZ_STATE_USER; + fh->v4l_buffers = zr->v4l_buffers; - case VIDIOC_G_INPUT: - { - int *input = arg; + zr->v4l_buffers.active = fh->v4l_buffers.active = ZORAN_FREE; - dprintk(3, KERN_DEBUG "%s: VIDIOC_G_INPUT\n", ZR_DEVNAME(zr)); + zr->v4l_grab_seq = 0; + zr->v4l_pend_head = zr->v4l_pend_tail = 0; + zr->v4l_sync_tail = 0; - mutex_lock(&zr->resource_lock); - *input = zr->input; - mutex_unlock(&zr->resource_lock); + break; - return 0; - } + case ZORAN_MAP_MODE_JPG_REC: + case ZORAN_MAP_MODE_JPG_PLAY: + if (fh->jpg_buffers.active == ZORAN_FREE && + zr->jpg_buffers.active != ZORAN_FREE) { + res = -EPERM; /* stay off other's settings! */ + goto strmoff_unlock_and_return; + } + if (zr->jpg_buffers.active == ZORAN_FREE) + goto strmoff_unlock_and_return; + + res = jpg_qbuf(file, -1, + (fh->map_mode == ZORAN_MAP_MODE_JPG_REC) ? + BUZ_MODE_MOTION_COMPRESS : + BUZ_MODE_MOTION_DECOMPRESS); + if (res) + goto strmoff_unlock_and_return; + break; + default: + dprintk(1, KERN_ERR + "%s: VIDIOC_STREAMOFF - invalid map mode %d\n", + ZR_DEVNAME(zr), fh->map_mode); + res = -EINVAL; break; + } +strmoff_unlock_and_return: + mutex_unlock(&zr->resource_lock); - case VIDIOC_S_INPUT: - { - int *input = arg, res = 0; - - dprintk(3, KERN_DEBUG "%s: VIDIOC_S_INPUT - input=%d\n", - ZR_DEVNAME(zr), *input); - - mutex_lock(&zr->resource_lock); - if ((res = zoran_set_input(zr, *input))) - goto sinput_unlock_and_return; + return res; +} - /* Make sure the changes come into effect */ - res = wait_grab_pending(zr); - sinput_unlock_and_return: - mutex_unlock(&zr->resource_lock); - return res; +static int zoran_queryctrl(struct file *file, void *__fh, + struct v4l2_queryctrl *ctrl) +{ + /* we only support hue/saturation/contrast/brightness */ + if (ctrl->id < V4L2_CID_BRIGHTNESS || + ctrl->id > V4L2_CID_HUE) + return -EINVAL; + else { + int id = ctrl->id; + memset(ctrl, 0, sizeof(*ctrl)); + ctrl->id = id; } + + switch (ctrl->id) { + case V4L2_CID_BRIGHTNESS: + strncpy(ctrl->name, "Brightness", sizeof(ctrl->name)-1); + break; + case V4L2_CID_CONTRAST: + strncpy(ctrl->name, "Contrast", sizeof(ctrl->name)-1); + break; + case V4L2_CID_SATURATION: + strncpy(ctrl->name, "Saturation", sizeof(ctrl->name)-1); break; + case V4L2_CID_HUE: + strncpy(ctrl->name, "Hue", sizeof(ctrl->name)-1); + break; + } - case VIDIOC_ENUMOUTPUT: - { - struct v4l2_output *outp = arg; + ctrl->minimum = 0; + ctrl->maximum = 65535; + ctrl->step = 1; + ctrl->default_value = 32768; + ctrl->type = V4L2_CTRL_TYPE_INTEGER; - dprintk(3, KERN_DEBUG "%s: VIDIOC_ENUMOUTPUT - index=%d\n", - ZR_DEVNAME(zr), outp->index); + return 0; +} - if (outp->index != 0) - return -EINVAL; +static int zoran_g_ctrl(struct file *file, void *__fh, struct v4l2_control *ctrl) +{ + struct zoran_fh *fh = __fh; + struct zoran *zr = fh->zr; - memset(outp, 0, sizeof(*outp)); - outp->index = 0; - outp->type = V4L2_OUTPUT_TYPE_ANALOGVGAOVERLAY; - strncpy(outp->name, "Autodetect", sizeof(outp->name)-1); + /* we only support hue/saturation/contrast/brightness */ + if (ctrl->id < V4L2_CID_BRIGHTNESS || + ctrl->id > V4L2_CID_HUE) + return -EINVAL; - return 0; - } + mutex_lock(&zr->resource_lock); + switch (ctrl->id) { + case V4L2_CID_BRIGHTNESS: + ctrl->value = zr->brightness; break; + case V4L2_CID_CONTRAST: + ctrl->value = zr->contrast; + break; + case V4L2_CID_SATURATION: + ctrl->value = zr->saturation; + break; + case V4L2_CID_HUE: + ctrl->value = zr->hue; + break; + } + mutex_unlock(&zr->resource_lock); - case VIDIOC_G_OUTPUT: - { - int *output = arg; + return 0; +} - dprintk(3, KERN_DEBUG "%s: VIDIOC_G_OUTPUT\n", ZR_DEVNAME(zr)); +static int zoran_s_ctrl(struct file *file, void *__fh, struct v4l2_control *ctrl) +{ + struct zoran_fh *fh = __fh; + struct zoran *zr = fh->zr; + struct video_picture pict; - *output = 0; + /* we only support hue/saturation/contrast/brightness */ + if (ctrl->id < V4L2_CID_BRIGHTNESS || + ctrl->id > V4L2_CID_HUE) + return -EINVAL; - return 0; + if (ctrl->value < 0 || ctrl->value > 65535) { + dprintk(1, KERN_ERR + "%s: VIDIOC_S_CTRL - invalid value %d for id=%d\n", + ZR_DEVNAME(zr), ctrl->value, ctrl->id); + return -EINVAL; } + + mutex_lock(&zr->resource_lock); + switch (ctrl->id) { + case V4L2_CID_BRIGHTNESS: + zr->brightness = ctrl->value; + break; + case V4L2_CID_CONTRAST: + zr->contrast = ctrl->value; break; + case V4L2_CID_SATURATION: + zr->saturation = ctrl->value; + break; + case V4L2_CID_HUE: + zr->hue = ctrl->value; + break; + } + pict.brightness = zr->brightness; + pict.contrast = zr->contrast; + pict.colour = zr->saturation; + pict.hue = zr->hue; - case VIDIOC_S_OUTPUT: - { - int *output = arg; + decoder_command(zr, DECODER_SET_PICTURE, &pict); - dprintk(3, KERN_DEBUG "%s: VIDIOC_S_OUTPUT - output=%d\n", - ZR_DEVNAME(zr), *output); + mutex_unlock(&zr->resource_lock); - if (*output != 0) - return -EINVAL; + return 0; +} - return 0; - } +static int zoran_g_std(struct file *file, void *__fh, v4l2_std_id *std) +{ + struct zoran_fh *fh = __fh; + struct zoran *zr = fh->zr; + int norm; + + mutex_lock(&zr->resource_lock); + norm = zr->norm; + mutex_unlock(&zr->resource_lock); + + switch (norm) { + case VIDEO_MODE_PAL: + *std = V4L2_STD_PAL; break; + case VIDEO_MODE_NTSC: + *std = V4L2_STD_NTSC; + break; + case VIDEO_MODE_SECAM: + *std = V4L2_STD_SECAM; + break; + } - /* cropping (sub-frame capture) */ - case VIDIOC_CROPCAP: - { - struct v4l2_cropcap *cropcap = arg; - int type = cropcap->type, res = 0; + return 0; +} - dprintk(3, KERN_ERR "%s: VIDIOC_CROPCAP - type=%d\n", - ZR_DEVNAME(zr), cropcap->type); +static int zoran_s_std(struct file *file, void *__fh, v4l2_std_id *std) +{ + struct zoran_fh *fh = __fh; + struct zoran *zr = fh->zr; + int norm = -1, res = 0; + + if ((*std & V4L2_STD_PAL) && !(*std & ~V4L2_STD_PAL)) + norm = VIDEO_MODE_PAL; + else if ((*std & V4L2_STD_NTSC) && !(*std & ~V4L2_STD_NTSC)) + norm = VIDEO_MODE_NTSC; + else if ((*std & V4L2_STD_SECAM) && !(*std & ~V4L2_STD_SECAM)) + norm = VIDEO_MODE_SECAM; + else if (*std == V4L2_STD_ALL) + norm = VIDEO_MODE_AUTO; + else { + dprintk(1, KERN_ERR + "%s: VIDIOC_S_STD - invalid norm 0x%llx\n", + ZR_DEVNAME(zr), (unsigned long long)*std); + return -EINVAL; + } - memset(cropcap, 0, sizeof(*cropcap)); - cropcap->type = type; + mutex_lock(&zr->resource_lock); + res = zoran_set_norm(zr, norm); + if (res) + goto sstd_unlock_and_return; - mutex_lock(&zr->resource_lock); + res = wait_grab_pending(zr); +sstd_unlock_and_return: + mutex_unlock(&zr->resource_lock); + return res; +} - if (cropcap->type != V4L2_BUF_TYPE_VIDEO_OUTPUT && - (cropcap->type != V4L2_BUF_TYPE_VIDEO_CAPTURE || - fh->map_mode == ZORAN_MAP_MODE_RAW)) { - dprintk(1, - KERN_ERR - "%s: VIDIOC_CROPCAP - subcapture only supported for compressed capture\n", - ZR_DEVNAME(zr)); - res = -EINVAL; - goto cropcap_unlock_and_return; - } +static int zoran_enum_input(struct file *file, void *__fh, + struct v4l2_input *inp) +{ + struct zoran_fh *fh = __fh; + struct zoran *zr = fh->zr; + int status; - cropcap->bounds.top = cropcap->bounds.left = 0; - cropcap->bounds.width = BUZ_MAX_WIDTH; - cropcap->bounds.height = BUZ_MAX_HEIGHT; - cropcap->defrect.top = cropcap->defrect.left = 0; - cropcap->defrect.width = BUZ_MIN_WIDTH; - cropcap->defrect.height = BUZ_MIN_HEIGHT; - cropcap_unlock_and_return: - mutex_unlock(&zr->resource_lock); - return res; + if (inp->index < 0 || inp->index >= zr->card.inputs) + return -EINVAL; + else { + int id = inp->index; + memset(inp, 0, sizeof(*inp)); + inp->index = id; } - break; - case VIDIOC_G_CROP: - { - struct v4l2_crop *crop = arg; - int type = crop->type, res = 0; + strncpy(inp->name, zr->card.input[inp->index].name, + sizeof(inp->name) - 1); + inp->type = V4L2_INPUT_TYPE_CAMERA; + inp->std = V4L2_STD_ALL; - dprintk(3, KERN_ERR "%s: VIDIOC_G_CROP - type=%d\n", - ZR_DEVNAME(zr), crop->type); + /* Get status of video decoder */ + mutex_lock(&zr->resource_lock); + decoder_command(zr, DECODER_GET_STATUS, &status); + mutex_unlock(&zr->resource_lock); - memset(crop, 0, sizeof(*crop)); - crop->type = type; + if (!(status & DECODER_STATUS_GOOD)) { + inp->status |= V4L2_IN_ST_NO_POWER; + inp->status |= V4L2_IN_ST_NO_SIGNAL; + } + if (!(status & DECODER_STATUS_COLOR)) + inp->status |= V4L2_IN_ST_NO_COLOR; - mutex_lock(&zr->resource_lock); + return 0; +} - if (crop->type != V4L2_BUF_TYPE_VIDEO_OUTPUT && - (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE || - fh->map_mode == ZORAN_MAP_MODE_RAW)) { - dprintk(1, - KERN_ERR - "%s: VIDIOC_G_CROP - subcapture only supported for compressed capture\n", - ZR_DEVNAME(zr)); - res = -EINVAL; - goto gcrop_unlock_and_return; - } +static int zoran_g_input(struct file *file, void *__fh, unsigned int *input) +{ + struct zoran_fh *fh = __fh; + struct zoran *zr = fh->zr; - crop->c.top = fh->jpg_settings.img_y; - crop->c.left = fh->jpg_settings.img_x; - crop->c.width = fh->jpg_settings.img_width; - crop->c.height = fh->jpg_settings.img_height; + mutex_lock(&zr->resource_lock); + *input = zr->input; + mutex_unlock(&zr->resource_lock); - gcrop_unlock_and_return: - mutex_unlock(&zr->resource_lock); + return 0; +} - return res; - } - break; +static int zoran_s_input(struct file *file, void *__fh, unsigned int input) +{ + struct zoran_fh *fh = __fh; + struct zoran *zr = fh->zr; + int res; - case VIDIOC_S_CROP: - { - struct v4l2_crop *crop = arg; - int res = 0; + mutex_lock(&zr->resource_lock); + res = zoran_set_input(zr, input); + if (res) + goto sinput_unlock_and_return; - settings = fh->jpg_settings; + /* Make sure the changes come into effect */ + res = wait_grab_pending(zr); +sinput_unlock_and_return: + mutex_unlock(&zr->resource_lock); + return res; +} - dprintk(3, - KERN_ERR - "%s: VIDIOC_S_CROP - type=%d, x=%d,y=%d,w=%d,h=%d\n", - ZR_DEVNAME(zr), crop->type, crop->c.left, crop->c.top, - crop->c.width, crop->c.height); +static int zoran_enum_output(struct file *file, void *__fh, + struct v4l2_output *outp) +{ + if (outp->index != 0) + return -EINVAL; - mutex_lock(&zr->resource_lock); + memset(outp, 0, sizeof(*outp)); + outp->index = 0; + outp->type = V4L2_OUTPUT_TYPE_ANALOGVGAOVERLAY; + strncpy(outp->name, "Autodetect", sizeof(outp->name)-1); - if (fh->jpg_buffers.allocated || fh->v4l_buffers.allocated) { - dprintk(1, - KERN_ERR - "%s: VIDIOC_S_CROP - cannot change settings while active\n", - ZR_DEVNAME(zr)); - res = -EBUSY; - goto scrop_unlock_and_return; - } + return 0; +} - if (crop->type != V4L2_BUF_TYPE_VIDEO_OUTPUT && - (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE || - fh->map_mode == ZORAN_MAP_MODE_RAW)) { - dprintk(1, - KERN_ERR - "%s: VIDIOC_G_CROP - subcapture only supported for compressed capture\n", - ZR_DEVNAME(zr)); - res = -EINVAL; - goto scrop_unlock_and_return; - } +static int zoran_g_output(struct file *file, void *__fh, unsigned int *output) +{ + *output = 0; + + return 0; +} - /* move into a form that we understand */ - settings.img_x = crop->c.left; - settings.img_y = crop->c.top; - settings.img_width = crop->c.width; - settings.img_height = crop->c.height; +static int zoran_s_output(struct file *file, void *__fh, unsigned int output) +{ + if (output != 0) + return -EINVAL; - /* check validity */ - if ((res = zoran_check_jpg_settings(zr, &settings))) - goto scrop_unlock_and_return; + return 0; +} - /* accept */ - fh->jpg_settings = settings; +/* cropping (sub-frame capture) */ +static int zoran_cropcap(struct file *file, void *__fh, + struct v4l2_cropcap *cropcap) +{ + struct zoran_fh *fh = __fh; + struct zoran *zr = fh->zr; + int type = cropcap->type, res = 0; - scrop_unlock_and_return: - mutex_unlock(&zr->resource_lock); - return res; - } - break; + memset(cropcap, 0, sizeof(*cropcap)); + cropcap->type = type; - case VIDIOC_G_JPEGCOMP: - { - struct v4l2_jpegcompression *params = arg; + mutex_lock(&zr->resource_lock); - dprintk(3, KERN_DEBUG "%s: VIDIOC_G_JPEGCOMP\n", + if (cropcap->type != V4L2_BUF_TYPE_VIDEO_OUTPUT && + (cropcap->type != V4L2_BUF_TYPE_VIDEO_CAPTURE || + fh->map_mode == ZORAN_MAP_MODE_RAW)) { + dprintk(1, KERN_ERR + "%s: VIDIOC_CROPCAP - subcapture only supported for compressed capture\n", ZR_DEVNAME(zr)); + res = -EINVAL; + goto cropcap_unlock_and_return; + } - memset(params, 0, sizeof(*params)); + cropcap->bounds.top = cropcap->bounds.left = 0; + cropcap->bounds.width = BUZ_MAX_WIDTH; + cropcap->bounds.height = BUZ_MAX_HEIGHT; + cropcap->defrect.top = cropcap->defrect.left = 0; + cropcap->defrect.width = BUZ_MIN_WIDTH; + cropcap->defrect.height = BUZ_MIN_HEIGHT; +cropcap_unlock_and_return: + mutex_unlock(&zr->resource_lock); + return res; +} - mutex_lock(&zr->resource_lock); +static int zoran_g_crop(struct file *file, void *__fh, struct v4l2_crop *crop) +{ + struct zoran_fh *fh = __fh; + struct zoran *zr = fh->zr; + int type = crop->type, res = 0; - params->quality = fh->jpg_settings.jpg_comp.quality; - params->APPn = fh->jpg_settings.jpg_comp.APPn; - memcpy(params->APP_data, - fh->jpg_settings.jpg_comp.APP_data, - fh->jpg_settings.jpg_comp.APP_len); - params->APP_len = fh->jpg_settings.jpg_comp.APP_len; - memcpy(params->COM_data, - fh->jpg_settings.jpg_comp.COM_data, - fh->jpg_settings.jpg_comp.COM_len); - params->COM_len = fh->jpg_settings.jpg_comp.COM_len; - params->jpeg_markers = - fh->jpg_settings.jpg_comp.jpeg_markers; + memset(crop, 0, sizeof(*crop)); + crop->type = type; - mutex_unlock(&zr->resource_lock); + mutex_lock(&zr->resource_lock); - return 0; + if (crop->type != V4L2_BUF_TYPE_VIDEO_OUTPUT && + (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE || + fh->map_mode == ZORAN_MAP_MODE_RAW)) { + dprintk(1, + KERN_ERR + "%s: VIDIOC_G_CROP - subcapture only supported for compressed capture\n", + ZR_DEVNAME(zr)); + res = -EINVAL; + goto gcrop_unlock_and_return; } - break; - - case VIDIOC_S_JPEGCOMP: - { - struct v4l2_jpegcompression *params = arg; - int res = 0; - settings = fh->jpg_settings; + crop->c.top = fh->jpg_settings.img_y; + crop->c.left = fh->jpg_settings.img_x; + crop->c.width = fh->jpg_settings.img_width; + crop->c.height = fh->jpg_settings.img_height; - dprintk(3, - KERN_DEBUG - "%s: VIDIOC_S_JPEGCOMP - quality=%d, APPN=%d, APP_len=%d, COM_len=%d\n", - ZR_DEVNAME(zr), params->quality, params->APPn, - params->APP_len, params->COM_len); +gcrop_unlock_and_return: + mutex_unlock(&zr->resource_lock); - settings.jpg_comp = *params; + return res; +} - mutex_lock(&zr->resource_lock); +static int zoran_s_crop(struct file *file, void *__fh, struct v4l2_crop *crop) +{ + struct zoran_fh *fh = __fh; + struct zoran *zr = fh->zr; + int res = 0; + struct zoran_jpg_settings settings; - if (fh->v4l_buffers.active != ZORAN_FREE || - fh->jpg_buffers.active != ZORAN_FREE) { - dprintk(1, - KERN_WARNING - "%s: VIDIOC_S_JPEGCOMP called while in playback/capture mode\n", - ZR_DEVNAME(zr)); - res = -EBUSY; - goto sjpegc_unlock_and_return; - } + settings = fh->jpg_settings; - if ((res = zoran_check_jpg_settings(zr, &settings))) - goto sjpegc_unlock_and_return; - if (!fh->jpg_buffers.allocated) - fh->jpg_buffers.buffer_size = - zoran_v4l2_calc_bufsize(&fh->jpg_settings); - fh->jpg_settings.jpg_comp = *params = settings.jpg_comp; - sjpegc_unlock_and_return: - mutex_unlock(&zr->resource_lock); + mutex_lock(&zr->resource_lock); - return 0; + if (fh->jpg_buffers.allocated || fh->v4l_buffers.allocated) { + dprintk(1, KERN_ERR + "%s: VIDIOC_S_CROP - cannot change settings while active\n", + ZR_DEVNAME(zr)); + res = -EBUSY; + goto scrop_unlock_and_return; } - break; - case VIDIOC_QUERYSTD: /* why is this useful? */ - { - v4l2_std_id *std = arg; + if (crop->type != V4L2_BUF_TYPE_VIDEO_OUTPUT && + (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE || + fh->map_mode == ZORAN_MAP_MODE_RAW)) { + dprintk(1, KERN_ERR + "%s: VIDIOC_G_CROP - subcapture only supported for compressed capture\n", + ZR_DEVNAME(zr)); + res = -EINVAL; + goto scrop_unlock_and_return; + } - dprintk(3, - KERN_DEBUG "%s: VIDIOC_QUERY_STD - std=0x%llx\n", - ZR_DEVNAME(zr), (unsigned long long)*std); + /* move into a form that we understand */ + settings.img_x = crop->c.left; + settings.img_y = crop->c.top; + settings.img_width = crop->c.width; + settings.img_height = crop->c.height; - if (*std == V4L2_STD_ALL || *std == V4L2_STD_NTSC || - *std == V4L2_STD_PAL || (*std == V4L2_STD_SECAM && - zr->card.norms == 3)) { - return 0; - } + /* check validity */ + res = zoran_check_jpg_settings(zr, &settings); + if (res) + goto scrop_unlock_and_return; - return -EINVAL; - } - break; + /* accept */ + fh->jpg_settings = settings; - case VIDIOC_TRY_FMT: - { - struct v4l2_format *fmt = arg; - int res = 0; +scrop_unlock_and_return: + mutex_unlock(&zr->resource_lock); + return res; +} - dprintk(3, KERN_DEBUG "%s: VIDIOC_TRY_FMT - type=%d\n", - ZR_DEVNAME(zr), fmt->type); +static int zoran_g_jpegcomp(struct file *file, void *__fh, + struct v4l2_jpegcompression *params) +{ + struct zoran_fh *fh = __fh; + struct zoran *zr = fh->zr; + memset(params, 0, sizeof(*params)); - switch (fmt->type) { - case V4L2_BUF_TYPE_VIDEO_OVERLAY: - mutex_lock(&zr->resource_lock); + mutex_lock(&zr->resource_lock); - if (fmt->fmt.win.w.width > BUZ_MAX_WIDTH) - fmt->fmt.win.w.width = BUZ_MAX_WIDTH; - if (fmt->fmt.win.w.width < BUZ_MIN_WIDTH) - fmt->fmt.win.w.width = BUZ_MIN_WIDTH; - if (fmt->fmt.win.w.height > BUZ_MAX_HEIGHT) - fmt->fmt.win.w.height = BUZ_MAX_HEIGHT; - if (fmt->fmt.win.w.height < BUZ_MIN_HEIGHT) - fmt->fmt.win.w.height = BUZ_MIN_HEIGHT; + params->quality = fh->jpg_settings.jpg_comp.quality; + params->APPn = fh->jpg_settings.jpg_comp.APPn; + memcpy(params->APP_data, + fh->jpg_settings.jpg_comp.APP_data, + fh->jpg_settings.jpg_comp.APP_len); + params->APP_len = fh->jpg_settings.jpg_comp.APP_len; + memcpy(params->COM_data, + fh->jpg_settings.jpg_comp.COM_data, + fh->jpg_settings.jpg_comp.COM_len); + params->COM_len = fh->jpg_settings.jpg_comp.COM_len; + params->jpeg_markers = + fh->jpg_settings.jpg_comp.jpeg_markers; - mutex_unlock(&zr->resource_lock); - break; + mutex_unlock(&zr->resource_lock); - case V4L2_BUF_TYPE_VIDEO_CAPTURE: - case V4L2_BUF_TYPE_VIDEO_OUTPUT: - if (fmt->fmt.pix.bytesperline > 0) - return -EINVAL; + return 0; +} - mutex_lock(&zr->resource_lock); - - if (fmt->fmt.pix.pixelformat == V4L2_PIX_FMT_MJPEG) { - settings = fh->jpg_settings; - - /* we actually need to set 'real' parameters now */ - if ((fmt->fmt.pix.height * 2) > - BUZ_MAX_HEIGHT) - settings.TmpDcm = 1; - else - settings.TmpDcm = 2; - settings.decimation = 0; - if (fmt->fmt.pix.height <= - fh->jpg_settings.img_height / 2) - settings.VerDcm = 2; - else - settings.VerDcm = 1; - if (fmt->fmt.pix.width <= - fh->jpg_settings.img_width / 4) - settings.HorDcm = 4; - else if (fmt->fmt.pix.width <= - fh->jpg_settings.img_width / 2) - settings.HorDcm = 2; - else - settings.HorDcm = 1; - if (settings.TmpDcm == 1) - settings.field_per_buff = 2; - else - settings.field_per_buff = 1; - - /* check */ - if ((res = - zoran_check_jpg_settings(zr, - &settings))) - goto tryfmt_unlock_and_return; - - /* tell the user what we actually did */ - fmt->fmt.pix.width = - settings.img_width / settings.HorDcm; - fmt->fmt.pix.height = - settings.img_height * 2 / - (settings.TmpDcm * settings.VerDcm); - if (settings.TmpDcm == 1) - fmt->fmt.pix.field = - (fh->jpg_settings. - odd_even ? V4L2_FIELD_SEQ_TB : - V4L2_FIELD_SEQ_BT); - else - fmt->fmt.pix.field = - (fh->jpg_settings. - odd_even ? V4L2_FIELD_TOP : - V4L2_FIELD_BOTTOM); - - fmt->fmt.pix.sizeimage = - zoran_v4l2_calc_bufsize(&settings); - } else if (fmt->type == - V4L2_BUF_TYPE_VIDEO_CAPTURE) { - int i; - - for (i = 0; i < NUM_FORMATS; i++) - if (zoran_formats[i].fourcc == - fmt->fmt.pix.pixelformat) - break; - if (i == NUM_FORMATS) { - res = -EINVAL; - goto tryfmt_unlock_and_return; - } +static int zoran_s_jpegcomp(struct file *file, void *__fh, + struct v4l2_jpegcompression *params) +{ + struct zoran_fh *fh = __fh; + struct zoran *zr = fh->zr; + int res = 0; + struct zoran_jpg_settings settings; - if (fmt->fmt.pix.width > BUZ_MAX_WIDTH) - fmt->fmt.pix.width = BUZ_MAX_WIDTH; - if (fmt->fmt.pix.width < BUZ_MIN_WIDTH) - fmt->fmt.pix.width = BUZ_MIN_WIDTH; - if (fmt->fmt.pix.height > BUZ_MAX_HEIGHT) - fmt->fmt.pix.height = - BUZ_MAX_HEIGHT; - if (fmt->fmt.pix.height < BUZ_MIN_HEIGHT) - fmt->fmt.pix.height = - BUZ_MIN_HEIGHT; - } else { - res = -EINVAL; - goto tryfmt_unlock_and_return; - } - tryfmt_unlock_and_return: - mutex_unlock(&zr->resource_lock); + settings = fh->jpg_settings; - return res; - break; + settings.jpg_comp = *params; - default: - return -EINVAL; - } + mutex_lock(&zr->resource_lock); - return 0; + if (fh->v4l_buffers.active != ZORAN_FREE || + fh->jpg_buffers.active != ZORAN_FREE) { + dprintk(1, KERN_WARNING + "%s: VIDIOC_S_JPEGCOMP called while in playback/capture mode\n", + ZR_DEVNAME(zr)); + res = -EBUSY; + goto sjpegc_unlock_and_return; } - break; - default: - dprintk(1, KERN_DEBUG "%s: UNKNOWN ioctl cmd: 0x%x\n", - ZR_DEVNAME(zr), cmd); - return -ENOIOCTLCMD; - break; + res = zoran_check_jpg_settings(zr, &settings); + if (res) + goto sjpegc_unlock_and_return; + if (!fh->jpg_buffers.allocated) + fh->jpg_buffers.buffer_size = + zoran_v4l2_calc_bufsize(&fh->jpg_settings); + fh->jpg_settings.jpg_comp = *params = settings.jpg_comp; +sjpegc_unlock_and_return: + mutex_unlock(&zr->resource_lock); - } return 0; } - -static long -zoran_ioctl(struct file *file, - unsigned int cmd, - unsigned long arg) -{ - return video_usercopy(file, cmd, arg, zoran_do_ioctl); -} - static unsigned int zoran_poll (struct file *file, poll_table *wait) @@ -4300,10 +3933,7 @@ zoran_vm_close (struct vm_area_struct *vma) fh->jpg_buffers.active = ZORAN_FREE; } - //jpg_fbuffer_free(file); - fh->jpg_buffers.allocated = 0; - fh->jpg_buffers.ready_to_be_freed = 1; - + jpg_fbuffer_free(file); mutex_unlock(&zr->resource_lock); } @@ -4340,10 +3970,7 @@ zoran_vm_close (struct vm_area_struct *vma) ZORAN_FREE; spin_unlock_irqrestore(&zr->spinlock, flags); } - //v4l_fbuffer_free(file); - fh->v4l_buffers.allocated = 0; - fh->v4l_buffers.ready_to_be_freed = 1; - + v4l_fbuffer_free(file); mutex_unlock(&zr->resource_lock); } @@ -4582,11 +4209,53 @@ zoran_mmap (struct file *file, return 0; } +static const struct v4l2_ioctl_ops zoran_ioctl_ops = { + .vidioc_querycap = zoran_querycap, + .vidioc_cropcap = zoran_cropcap, + .vidioc_s_crop = zoran_s_crop, + .vidioc_g_crop = zoran_g_crop, + .vidioc_enum_input = zoran_enum_input, + .vidioc_g_input = zoran_g_input, + .vidioc_s_input = zoran_s_input, + .vidioc_enum_output = zoran_enum_output, + .vidioc_g_output = zoran_g_output, + .vidioc_s_output = zoran_s_output, + .vidioc_g_fbuf = zoran_g_fbuf, + .vidioc_s_fbuf = zoran_s_fbuf, + .vidioc_g_std = zoran_g_std, + .vidioc_s_std = zoran_s_std, + .vidioc_g_jpegcomp = zoran_g_jpegcomp, + .vidioc_s_jpegcomp = zoran_s_jpegcomp, + .vidioc_overlay = zoran_overlay, + .vidioc_reqbufs = zoran_reqbufs, + .vidioc_querybuf = zoran_querybuf, + .vidioc_qbuf = zoran_qbuf, + .vidioc_dqbuf = zoran_dqbuf, + .vidioc_streamon = zoran_streamon, + .vidioc_streamoff = zoran_streamoff, + .vidioc_enum_fmt_vid_cap = zoran_enum_fmt_vid_cap, + .vidioc_enum_fmt_vid_out = zoran_enum_fmt_vid_out, + .vidioc_enum_fmt_vid_overlay = zoran_enum_fmt_vid_overlay, + .vidioc_g_fmt_vid_cap = zoran_g_fmt_vid_cap, + .vidioc_g_fmt_vid_out = zoran_g_fmt_vid_out, + .vidioc_g_fmt_vid_overlay = zoran_g_fmt_vid_overlay, + .vidioc_s_fmt_vid_cap = zoran_s_fmt_vid_cap, + .vidioc_s_fmt_vid_out = zoran_s_fmt_vid_out, + .vidioc_s_fmt_vid_overlay = zoran_s_fmt_vid_overlay, + .vidioc_try_fmt_vid_cap = zoran_try_fmt_vid_cap, + .vidioc_try_fmt_vid_out = zoran_try_fmt_vid_out, + .vidioc_try_fmt_vid_overlay = zoran_try_fmt_vid_overlay, + .vidioc_queryctrl = zoran_queryctrl, + .vidioc_s_ctrl = zoran_s_ctrl, + .vidioc_g_ctrl = zoran_g_ctrl, + .vidioc_default = zoran_default, +}; + static const struct v4l2_file_operations zoran_fops = { .owner = THIS_MODULE, .open = zoran_open, .release = zoran_close, - .ioctl = zoran_ioctl, + .ioctl = video_ioctl2, .read = zoran_read, .write = zoran_write, .mmap = zoran_mmap, @@ -4596,7 +4265,9 @@ static const struct v4l2_file_operations zoran_fops = { struct video_device zoran_template __devinitdata = { .name = ZORAN_NAME, .fops = &zoran_fops, + .ioctl_ops = &zoran_ioctl_ops, .release = &zoran_vdev_release, + .tvnorms = V4L2_STD_NTSC | V4L2_STD_PAL | V4L2_STD_SECAM, .minor = -1 }; -- cgit v1.2.3 From b80696b700b25b7aa054610af84a1f05e4f4ea58 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 18 Feb 2009 13:20:05 -0300 Subject: V4L/DVB (10704): zoran: remove broken BIGPHYS_AREA and BUZ_HIMEM code, and allow for kmallocs > 128 kB Remove memory allocation madness. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/zoran/zoran.h | 2 - drivers/media/video/zoran/zoran_driver.c | 189 +++++-------------------------- 2 files changed, 31 insertions(+), 160 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/zoran/zoran.h b/drivers/media/video/zoran/zoran.h index 1bf540cb546c..76668bda0494 100644 --- a/drivers/media/video/zoran/zoran.h +++ b/drivers/media/video/zoran/zoran.h @@ -170,8 +170,6 @@ Private IOCTL to set up for displaying MJPEG #endif #define V4L_MASK_FRAME (V4L_MAX_FRAME - 1) -#define MAX_KMALLOC_MEM (128*1024) - #include "zr36057.h" enum card_type { diff --git a/drivers/media/video/zoran/zoran_driver.c b/drivers/media/video/zoran/zoran_driver.c index dc6ba554597f..1f8d3a8b0cba 100644 --- a/drivers/media/video/zoran/zoran_driver.c +++ b/drivers/media/video/zoran/zoran_driver.c @@ -191,9 +191,6 @@ const struct zoran_format zoran_formats[] = { }; #define NUM_FORMATS ARRAY_SIZE(zoran_formats) -// RJ: Test only - want to test BUZ_USE_HIMEM even when CONFIG_BIGPHYS_AREA is defined - - 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)"); @@ -229,77 +226,8 @@ static void jpg_fbuffer_free(struct file *file); * Allocate the V4L grab buffers * * These have to be pysically contiguous. - * If v4l_bufsize <= MAX_KMALLOC_MEM we use kmalloc - * else we try to allocate them with bigphysarea_alloc_pages - * if the bigphysarea patch is present in the kernel, - * else we try to use high memory (if the user has bootet - * Linux with the necessary memory left over). - */ - -static unsigned long -get_high_mem (unsigned long size) -{ -/* - * Check if there is usable memory at the end of Linux memory - * of at least size. Return the physical address of this memory, - * return 0 on failure. - * - * The idea is from Alexandro Rubini's book "Linux device drivers". - * The driver from him which is downloadable from O'Reilly's - * web site misses the "virt_to_phys(high_memory)" part - * (and therefore doesn't work at all - at least with 2.2.x kernels). - * - * It should be unnecessary to mention that THIS IS DANGEROUS, - * if more than one driver at a time has the idea to use this memory!!!! */ - volatile unsigned char __iomem *mem; - unsigned char c; - unsigned long hi_mem_ph; - unsigned long i; - - /* Map the high memory to user space */ - - hi_mem_ph = virt_to_phys(high_memory); - - mem = ioremap(hi_mem_ph, size); - if (!mem) { - dprintk(1, - KERN_ERR "%s: get_high_mem() - ioremap failed\n", - ZORAN_NAME); - return 0; - } - - for (i = 0; i < size; i++) { - /* Check if it is memory */ - c = i & 0xff; - writeb(c, mem + i); - if (readb(mem + i) != c) - break; - c = 255 - c; - writeb(c, mem + i); - if (readb(mem + i) != c) - break; - writeb(0, mem + i); /* zero out memory */ - - /* give the kernel air to breath */ - if ((i & 0x3ffff) == 0x3ffff) - schedule(); - } - - iounmap(mem); - - if (i != size) { - dprintk(1, - KERN_ERR - "%s: get_high_mem() - requested %lu, avail %lu\n", - ZORAN_NAME, size, i); - return 0; - } - - return hi_mem_ph; -} - static int v4l_fbuffer_alloc (struct file *file) { @@ -307,82 +235,37 @@ v4l_fbuffer_alloc (struct file *file) struct zoran *zr = fh->zr; int i, off; unsigned char *mem; - unsigned long pmem = 0; for (i = 0; i < fh->v4l_buffers.num_buffers; i++) { if (fh->v4l_buffers.buffer[i].fbuffer) dprintk(2, KERN_WARNING - "%s: v4l_fbuffer_alloc() - buffer %d allready allocated!?\n", + "%s: v4l_fbuffer_alloc() - buffer %d already allocated!?\n", ZR_DEVNAME(zr), i); //udelay(20); - if (fh->v4l_buffers.buffer_size <= MAX_KMALLOC_MEM) { - /* Use kmalloc */ - - mem = kmalloc(fh->v4l_buffers.buffer_size, GFP_KERNEL); - if (!mem) { - dprintk(1, - KERN_ERR - "%s: v4l_fbuffer_alloc() - kmalloc for V4L buf %d failed\n", - ZR_DEVNAME(zr), i); - v4l_fbuffer_free(file); - return -ENOBUFS; - } - fh->v4l_buffers.buffer[i].fbuffer = mem; - fh->v4l_buffers.buffer[i].fbuffer_phys = - virt_to_phys(mem); - fh->v4l_buffers.buffer[i].fbuffer_bus = - virt_to_bus(mem); - for (off = 0; off < fh->v4l_buffers.buffer_size; - off += PAGE_SIZE) - SetPageReserved(MAP_NR(mem + off)); - dprintk(4, - KERN_INFO - "%s: v4l_fbuffer_alloc() - V4L frame %d mem 0x%lx (bus: 0x%llx)\n", - ZR_DEVNAME(zr), i, (unsigned long) mem, - (unsigned long long)virt_to_bus(mem)); - } else { - - /* Use high memory which has been left at boot time */ - - /* Ok., Ok. this is an evil hack - we make - * the assumption that physical addresses are - * the same as bus addresses (true at least - * for Intel processors). The whole method of - * obtaining and using this memory is not very - * nice - but I hope it saves some poor users - * from kernel hacking, which might have even - * more evil results */ - - if (i == 0) { - int size = - fh->v4l_buffers.num_buffers * - fh->v4l_buffers.buffer_size; - - pmem = get_high_mem(size); - if (pmem == 0) { - dprintk(1, - KERN_ERR - "%s: v4l_fbuffer_alloc() - get_high_mem (size = %d KB) for V4L bufs failed\n", - ZR_DEVNAME(zr), size >> 10); - return -ENOBUFS; - } - fh->v4l_buffers.buffer[0].fbuffer = NULL; - fh->v4l_buffers.buffer[0].fbuffer_phys = pmem; - fh->v4l_buffers.buffer[0].fbuffer_bus = pmem; - dprintk(4, - KERN_INFO - "%s: v4l_fbuffer_alloc() - using %d KB high memory\n", - ZR_DEVNAME(zr), size >> 10); - } else { - fh->v4l_buffers.buffer[i].fbuffer = NULL; - fh->v4l_buffers.buffer[i].fbuffer_phys = - pmem + i * fh->v4l_buffers.buffer_size; - fh->v4l_buffers.buffer[i].fbuffer_bus = - pmem + i * fh->v4l_buffers.buffer_size; - } + mem = kmalloc(fh->v4l_buffers.buffer_size, GFP_KERNEL); + if (!mem) { + dprintk(1, + KERN_ERR + "%s: v4l_fbuffer_alloc() - kmalloc for V4L buf %d failed\n", + ZR_DEVNAME(zr), i); + v4l_fbuffer_free(file); + return -ENOBUFS; } + fh->v4l_buffers.buffer[i].fbuffer = mem; + fh->v4l_buffers.buffer[i].fbuffer_phys = + virt_to_phys(mem); + fh->v4l_buffers.buffer[i].fbuffer_bus = + virt_to_bus(mem); + for (off = 0; off < fh->v4l_buffers.buffer_size; + off += PAGE_SIZE) + SetPageReserved(MAP_NR(mem + off)); + dprintk(4, + KERN_INFO + "%s: v4l_fbuffer_alloc() - V4L frame %d mem 0x%lx (bus: 0x%lx)\n", + ZR_DEVNAME(zr), i, (unsigned long) mem, + virt_to_bus(mem)); } fh->v4l_buffers.allocated = 1; @@ -405,13 +288,11 @@ v4l_fbuffer_free (struct file *file) if (!fh->v4l_buffers.buffer[i].fbuffer) continue; - if (fh->v4l_buffers.buffer_size <= MAX_KMALLOC_MEM) { - mem = fh->v4l_buffers.buffer[i].fbuffer; - for (off = 0; off < fh->v4l_buffers.buffer_size; - off += PAGE_SIZE) - ClearPageReserved(MAP_NR(mem + off)); - kfree((void *) fh->v4l_buffers.buffer[i].fbuffer); - } + mem = fh->v4l_buffers.buffer[i].fbuffer; + for (off = 0; off < fh->v4l_buffers.buffer_size; + off += PAGE_SIZE) + ClearPageReserved(MAP_NR(mem + off)); + kfree((void *) fh->v4l_buffers.buffer[i].fbuffer); fh->v4l_buffers.buffer[i].fbuffer = NULL; } @@ -421,16 +302,10 @@ v4l_fbuffer_free (struct file *file) /* * Allocate the MJPEG grab buffers. * - * If the requested buffer size is smaller than MAX_KMALLOC_MEM, - * kmalloc is used to request a physically contiguous area, - * else we allocate the memory in framgents with get_zeroed_page. - * * If a Natoma chipset is present and this is a revision 1 zr36057, * each MJPEG buffer needs to be physically contiguous. * (RJ: This statement is from Dave Perks' original driver, * I could never check it because I have a zr36067) - * The driver cares about this because it reduces the buffer - * size to MAX_KMALLOC_MEM in that case (which forces contiguous allocation). * * RJ: The contents grab buffers needs never be accessed in the driver. * Therefore there is no need to allocate them with vmalloc in order @@ -464,7 +339,7 @@ jpg_fbuffer_alloc (struct file *file) if (fh->jpg_buffers.buffer[i].frag_tab) dprintk(2, KERN_WARNING - "%s: jpg_fbuffer_alloc() - buffer %d allready allocated!?\n", + "%s: jpg_fbuffer_alloc() - buffer %d already allocated!?\n", ZR_DEVNAME(zr), i); /* Allocate fragment table for this buffer */ @@ -504,7 +379,7 @@ jpg_fbuffer_alloc (struct file *file) off += PAGE_SIZE) SetPageReserved(MAP_NR(mem + off)); } else { - /* jpg_bufsize is allreay page aligned */ + /* jpg_bufsize is already page aligned */ for (j = 0; j < fh->jpg_buffers.buffer_size / PAGE_SIZE; j++) { @@ -2173,6 +2048,7 @@ schan_unlock_and_return: return res; } + case VIDIOCGMBUF: { struct video_mbuf *vmbuf = arg; @@ -2369,16 +2245,13 @@ sparams_unlock_and_return: * tables to a Maximum of 2 MB */ if (breq->size > jpg_bufsize) breq->size = jpg_bufsize; - if (fh->jpg_buffers.need_contiguous && - breq->size > MAX_KMALLOC_MEM) - breq->size = MAX_KMALLOC_MEM; mutex_lock(&zr->resource_lock); if (fh->jpg_buffers.allocated || fh->v4l_buffers.allocated) { dprintk(1, KERN_ERR - "%s: BUZIOC_REQBUFS - buffers allready allocated\n", + "%s: BUZIOC_REQBUFS - buffers already allocated\n", ZR_DEVNAME(zr)); res = -EBUSY; goto jpgreqbuf_unlock_and_return; -- cgit v1.2.3 From 869826a1cbd30f2604de4add19cfa847e00f2d19 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 18 Feb 2009 13:23:24 -0300 Subject: V4L/DVB (10705): zoran: use slider flag with volume etc. controls. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/zoran/zoran_driver.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/media/video') diff --git a/drivers/media/video/zoran/zoran_driver.c b/drivers/media/video/zoran/zoran_driver.c index 1f8d3a8b0cba..c7806ac448b2 100644 --- a/drivers/media/video/zoran/zoran_driver.c +++ b/drivers/media/video/zoran/zoran_driver.c @@ -3260,6 +3260,7 @@ static int zoran_queryctrl(struct file *file, void *__fh, ctrl->step = 1; ctrl->default_value = 32768; ctrl->type = V4L2_CTRL_TYPE_INTEGER; + ctrl->flags = V4L2_CTRL_FLAG_SLIDER; return 0; } -- cgit v1.2.3 From 3e66793b622feb383dec59d9c044a4c908d7c5c7 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 18 Feb 2009 13:24:56 -0300 Subject: V4L/DVB (10706): zoran: fix field typo. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/zoran/zoran_driver.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/zoran/zoran_driver.c b/drivers/media/video/zoran/zoran_driver.c index c7806ac448b2..90ef3ae39c1c 100644 --- a/drivers/media/video/zoran/zoran_driver.c +++ b/drivers/media/video/zoran/zoran_driver.c @@ -2463,7 +2463,7 @@ static int zoran_g_fmt_vid_out(struct file *file, void *__fh, fmt->fmt.pix.pixelformat = V4L2_PIX_FMT_MJPEG; if (fh->jpg_settings.TmpDcm == 1) fmt->fmt.pix.field = (fh->jpg_settings.odd_even ? - V4L2_FIELD_SEQ_BT : V4L2_FIELD_SEQ_BT); + V4L2_FIELD_SEQ_TB : V4L2_FIELD_SEQ_BT); else fmt->fmt.pix.field = (fh->jpg_settings.odd_even ? V4L2_FIELD_TOP : V4L2_FIELD_BOTTOM); -- cgit v1.2.3 From 9f1b9efa6712201aacc590b3250e6f39f9e13f21 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 18 Feb 2009 13:28:28 -0300 Subject: V4L/DVB (10707): zoran: set bytesperline to 0 when using MJPEG. Remove bogus check on bytesperline in the try_fmt_vid_out call. Just set it to 0. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/zoran/zoran_driver.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/zoran/zoran_driver.c b/drivers/media/video/zoran/zoran_driver.c index 90ef3ae39c1c..db9ff4a8ad85 100644 --- a/drivers/media/video/zoran/zoran_driver.c +++ b/drivers/media/video/zoran/zoran_driver.c @@ -2549,12 +2549,11 @@ static int zoran_try_fmt_vid_out(struct file *file, void *__fh, struct zoran_jpg_settings settings; int res = 0; - if (fmt->fmt.pix.bytesperline > 0) - return -EINVAL; - if (fmt->fmt.pix.pixelformat != V4L2_PIX_FMT_MJPEG) return -EINVAL; + fmt->fmt.pix.bytesperline = 0; + mutex_lock(&zr->resource_lock); settings = fh->jpg_settings; @@ -2608,9 +2607,6 @@ static int zoran_try_fmt_vid_cap(struct file *file, void *__fh, struct zoran *zr = fh->zr; int i; - if (fmt->fmt.pix.bytesperline > 0) - return -EINVAL; - if (fmt->fmt.pix.pixelformat == V4L2_PIX_FMT_MJPEG) return zoran_try_fmt_vid_out(file, fh, fmt); -- cgit v1.2.3 From dcbd83b1777fa6ed566a8bba035332ed245c0826 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 18 Feb 2009 13:51:13 -0300 Subject: V4L/DVB (10708): zoran: remove old V4L1 ioctls, use v4l1-compat instead. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/zoran/Kconfig | 4 +- drivers/media/video/zoran/zoran_driver.c | 459 +++---------------------------- 2 files changed, 46 insertions(+), 417 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/zoran/Kconfig b/drivers/media/video/zoran/Kconfig index 8666e19f31a7..e35121fdf78a 100644 --- a/drivers/media/video/zoran/Kconfig +++ b/drivers/media/video/zoran/Kconfig @@ -1,6 +1,6 @@ config VIDEO_ZORAN tristate "Zoran ZR36057/36067 Video For Linux" - depends on PCI && I2C_ALGOBIT && VIDEO_V4L1 && VIRT_TO_BUS + depends on PCI && I2C_ALGOBIT && VIDEO_V4L2 && VIRT_TO_BUS help Say Y for support for MJPEG capture cards based on the Zoran 36057/36067 PCI controller chipset. This includes the Iomega @@ -66,7 +66,7 @@ config VIDEO_ZORAN_LML33R10 config VIDEO_ZORAN_AVS6EYES tristate "AverMedia 6 Eyes support (EXPERIMENTAL)" - depends on VIDEO_ZORAN_ZR36060 && EXPERIMENTAL && VIDEO_V4L1 + depends on VIDEO_ZORAN_ZR36060 && EXPERIMENTAL select VIDEO_BT856 if VIDEO_HELPER_CHIPS_AUTO select VIDEO_BT866 if VIDEO_HELPER_CHIPS_AUTO select VIDEO_KS0127 if VIDEO_HELPER_CHIPS_AUTO diff --git a/drivers/media/video/zoran/zoran_driver.c b/drivers/media/video/zoran/zoran_driver.c index db9ff4a8ad85..0e4b8d03fda3 100644 --- a/drivers/media/video/zoran/zoran_driver.c +++ b/drivers/media/video/zoran/zoran_driver.c @@ -613,64 +613,6 @@ zoran_v4l_queue_frame (struct file *file, return res; } -static int -v4l_grab (struct file *file, - struct video_mmap *mp) -{ - struct zoran_fh *fh = file->private_data; - struct zoran *zr = fh->zr; - int res = 0, i; - - for (i = 0; i < NUM_FORMATS; i++) { - if (zoran_formats[i].palette == mp->format && - zoran_formats[i].flags & ZORAN_FORMAT_CAPTURE && - !(zoran_formats[i].flags & ZORAN_FORMAT_COMPRESSED)) - break; - } - if (i == NUM_FORMATS || zoran_formats[i].depth == 0) { - dprintk(1, - KERN_ERR - "%s: v4l_grab() - wrong bytes-per-pixel format\n", - ZR_DEVNAME(zr)); - return -EINVAL; - } - - /* - * To minimize the time spent in the IRQ routine, we avoid setting up - * the video front end there. - * If this grab has different parameters from a running streaming capture - * we stop the streaming capture and start it over again. - */ - if (zr->v4l_memgrab_active && - (zr->v4l_settings.width != mp->width || - zr->v4l_settings.height != mp->height || - zr->v4l_settings.format->palette != mp->format)) { - res = wait_grab_pending(zr); - if (res) - return res; - } - if ((res = zoran_v4l_set_format(file, - mp->width, - mp->height, - &zoran_formats[i]))) - return res; - zr->v4l_settings = fh->v4l_settings; - - /* queue the frame in the pending queue */ - if ((res = zoran_v4l_queue_frame(file, mp->frame))) { - fh->v4l_buffers.active = ZORAN_FREE; - return res; - } - - /* put the 36057 into frame grabbing mode */ - if (!res && !zr->v4l_memgrab_active) - zr36057_set_memgrab(zr, 1); - - //dprintk(4, KERN_INFO "%s: Frame grab 3...\n", ZR_DEVNAME(zr)); - - return res; -} - /* * Sync on a V4L buffer */ @@ -1760,6 +1702,7 @@ zoran_set_input (struct zoran *zr, * ioctl routine */ +#ifdef CONFIG_VIDEO_V4L1_COMPAT static long zoran_default(struct file *file, void *__fh, int cmd, void *arg) { struct zoran_fh *fh = __fh; @@ -1767,363 +1710,6 @@ static long zoran_default(struct file *file, void *__fh, int cmd, void *arg) struct zoran_jpg_settings settings; switch (cmd) { - case VIDIOCGCAP: - { - struct video_capability *vcap = arg; - - dprintk(3, KERN_DEBUG "%s: VIDIOCGCAP\n", ZR_DEVNAME(zr)); - - memset(vcap, 0, sizeof(struct video_capability)); - strncpy(vcap->name, ZR_DEVNAME(zr), sizeof(vcap->name)-1); - vcap->type = ZORAN_VID_TYPE; - - vcap->channels = zr->card.inputs; - vcap->audios = 0; - mutex_lock(&zr->resource_lock); - vcap->maxwidth = BUZ_MAX_WIDTH; - vcap->maxheight = BUZ_MAX_HEIGHT; - vcap->minwidth = BUZ_MIN_WIDTH; - vcap->minheight = BUZ_MIN_HEIGHT; - mutex_unlock(&zr->resource_lock); - - return 0; - } - - case VIDIOCGCHAN: - { - struct video_channel *vchan = arg; - int channel = vchan->channel; - - dprintk(3, KERN_DEBUG "%s: VIDIOCGCHAN - channel=%d\n", - ZR_DEVNAME(zr), vchan->channel); - - memset(vchan, 0, sizeof(struct video_channel)); - if (channel > zr->card.inputs || channel < 0) { - dprintk(1, - KERN_ERR - "%s: VIDIOCGCHAN on not existing channel %d\n", - ZR_DEVNAME(zr), channel); - return -EINVAL; - } - - strcpy(vchan->name, zr->card.input[channel].name); - - vchan->tuners = 0; - vchan->flags = 0; - vchan->type = VIDEO_TYPE_CAMERA; - mutex_lock(&zr->resource_lock); - vchan->norm = zr->norm; - mutex_unlock(&zr->resource_lock); - vchan->channel = channel; - - return 0; - } - - /* RJ: the documentation at http://roadrunner.swansea.linux.org.uk/v4lapi.shtml says: - * - * * "The VIDIOCSCHAN ioctl takes an integer argument and switches the capture to this input." - * * ^^^^^^^ - * * The famos BTTV driver has it implemented with a struct video_channel argument - * * and we follow it for compatibility reasons - * * - * * BTW: this is the only way the user can set the norm! - */ - - case VIDIOCSCHAN: - { - struct video_channel *vchan = arg; - int res; - - dprintk(3, - KERN_DEBUG - "%s: VIDIOCSCHAN - channel=%d, norm=%d\n", - ZR_DEVNAME(zr), vchan->channel, vchan->norm); - - mutex_lock(&zr->resource_lock); - if ((res = zoran_set_input(zr, vchan->channel))) - goto schan_unlock_and_return; - if ((res = zoran_set_norm(zr, vchan->norm))) - goto schan_unlock_and_return; - - /* Make sure the changes come into effect */ - res = wait_grab_pending(zr); -schan_unlock_and_return: - mutex_unlock(&zr->resource_lock); - return res; - } - - case VIDIOCGPICT: - { - struct video_picture *vpict = arg; - - dprintk(3, KERN_DEBUG "%s: VIDIOCGPICT\n", ZR_DEVNAME(zr)); - - memset(vpict, 0, sizeof(struct video_picture)); - mutex_lock(&zr->resource_lock); - vpict->hue = zr->hue; - vpict->brightness = zr->brightness; - vpict->contrast = zr->contrast; - vpict->colour = zr->saturation; - if (fh->overlay_settings.format) { - vpict->depth = fh->overlay_settings.format->depth; - vpict->palette = fh->overlay_settings.format->palette; - } else { - vpict->depth = 0; - } - mutex_unlock(&zr->resource_lock); - - return 0; - } - - case VIDIOCSPICT: - { - struct video_picture *vpict = arg; - int i; - - dprintk(3, - KERN_DEBUG - "%s: VIDIOCSPICT - bri=%d, hue=%d, col=%d, con=%d, dep=%d, pal=%d\n", - ZR_DEVNAME(zr), vpict->brightness, vpict->hue, - vpict->colour, vpict->contrast, vpict->depth, - vpict->palette); - - for (i = 0; i < NUM_FORMATS; i++) { - const struct zoran_format *fmt = &zoran_formats[i]; - - if (fmt->palette != -1 && - fmt->flags & ZORAN_FORMAT_OVERLAY && - fmt->palette == vpict->palette && - fmt->depth == vpict->depth) - break; - } - if (i == NUM_FORMATS) { - dprintk(1, - KERN_ERR - "%s: VIDIOCSPICT - Invalid palette %d\n", - ZR_DEVNAME(zr), vpict->palette); - return -EINVAL; - } - - mutex_lock(&zr->resource_lock); - - decoder_command(zr, DECODER_SET_PICTURE, vpict); - - zr->hue = vpict->hue; - zr->contrast = vpict->contrast; - zr->saturation = vpict->colour; - zr->brightness = vpict->brightness; - - fh->overlay_settings.format = &zoran_formats[i]; - - mutex_unlock(&zr->resource_lock); - - return 0; - } - - case VIDIOCCAPTURE: - { - int *on = arg, res; - - dprintk(3, KERN_DEBUG "%s: VIDIOCCAPTURE - on=%d\n", - ZR_DEVNAME(zr), *on); - - mutex_lock(&zr->resource_lock); - res = setup_overlay(file, *on); - mutex_unlock(&zr->resource_lock); - - return res; - } - - case VIDIOCGWIN: - { - struct video_window *vwin = arg; - - dprintk(3, KERN_DEBUG "%s: VIDIOCGWIN\n", ZR_DEVNAME(zr)); - - memset(vwin, 0, sizeof(struct video_window)); - mutex_lock(&zr->resource_lock); - vwin->x = fh->overlay_settings.x; - vwin->y = fh->overlay_settings.y; - vwin->width = fh->overlay_settings.width; - vwin->height = fh->overlay_settings.height; - mutex_unlock(&zr->resource_lock); - vwin->clipcount = 0; - return 0; - } - - case VIDIOCSWIN: - { - struct video_window *vwin = arg; - int res; - - dprintk(3, - KERN_DEBUG - "%s: VIDIOCSWIN - x=%d, y=%d, w=%d, h=%d, clipcount=%d\n", - ZR_DEVNAME(zr), vwin->x, vwin->y, vwin->width, - vwin->height, vwin->clipcount); - - mutex_lock(&zr->resource_lock); - res = - setup_window(file, vwin->x, vwin->y, vwin->width, - vwin->height, vwin->clips, - vwin->clipcount, NULL); - mutex_unlock(&zr->resource_lock); - - return res; - } - - case VIDIOCGFBUF: - { - struct video_buffer *vbuf = arg; - - dprintk(3, KERN_DEBUG "%s: VIDIOCGFBUF\n", ZR_DEVNAME(zr)); - - mutex_lock(&zr->resource_lock); - *vbuf = zr->buffer; - mutex_unlock(&zr->resource_lock); - return 0; - } - - case VIDIOCSFBUF: - { - struct video_buffer *vbuf = arg; - int i, res = 0; - - dprintk(3, - KERN_DEBUG - "%s: VIDIOCSFBUF - base=%p, w=%d, h=%d, depth=%d, bpl=%d\n", - ZR_DEVNAME(zr), vbuf->base, vbuf->width, - vbuf->height, vbuf->depth, vbuf->bytesperline); - - for (i = 0; i < NUM_FORMATS; i++) - if (zoran_formats[i].depth == vbuf->depth) - break; - if (i == NUM_FORMATS) { - dprintk(1, - KERN_ERR - "%s: VIDIOCSFBUF - invalid fbuf depth %d\n", - ZR_DEVNAME(zr), vbuf->depth); - return -EINVAL; - } - - mutex_lock(&zr->resource_lock); - res = - setup_fbuffer(file, vbuf->base, &zoran_formats[i], - vbuf->width, vbuf->height, - vbuf->bytesperline); - mutex_unlock(&zr->resource_lock); - - return res; - } - - case VIDIOCSYNC: - { - int *frame = arg, res; - - dprintk(3, KERN_DEBUG "%s: VIDIOCSYNC - frame=%d\n", - ZR_DEVNAME(zr), *frame); - - mutex_lock(&zr->resource_lock); - res = v4l_sync(file, *frame); - mutex_unlock(&zr->resource_lock); - if (!res) - zr->v4l_sync_tail++; - return res; - } - - case VIDIOCMCAPTURE: - { - struct video_mmap *vmap = arg; - int res; - - dprintk(3, - KERN_DEBUG - "%s: VIDIOCMCAPTURE - frame=%d, geom=%dx%d, fmt=%d\n", - ZR_DEVNAME(zr), vmap->frame, vmap->width, vmap->height, - vmap->format); - - mutex_lock(&zr->resource_lock); - res = v4l_grab(file, vmap); - mutex_unlock(&zr->resource_lock); - return res; - } - - - case VIDIOCGMBUF: - { - struct video_mbuf *vmbuf = arg; - int i, res = 0; - - dprintk(3, KERN_DEBUG "%s: VIDIOCGMBUF\n", ZR_DEVNAME(zr)); - - vmbuf->size = - fh->v4l_buffers.num_buffers * - fh->v4l_buffers.buffer_size; - vmbuf->frames = fh->v4l_buffers.num_buffers; - for (i = 0; i < vmbuf->frames; i++) { - vmbuf->offsets[i] = - i * fh->v4l_buffers.buffer_size; - } - - mutex_lock(&zr->resource_lock); - - if (fh->jpg_buffers.allocated || fh->v4l_buffers.allocated) { - dprintk(1, - KERN_ERR - "%s: VIDIOCGMBUF - buffers already allocated\n", - ZR_DEVNAME(zr)); - res = -EINVAL; - goto v4l1reqbuf_unlock_and_return; - } - - if (v4l_fbuffer_alloc(file)) { - res = -ENOMEM; - goto v4l1reqbuf_unlock_and_return; - } - - /* The next mmap will map the V4L buffers */ - fh->map_mode = ZORAN_MAP_MODE_RAW; -v4l1reqbuf_unlock_and_return: - mutex_unlock(&zr->resource_lock); - - return res; - } - - case VIDIOCGUNIT: - { - struct video_unit *vunit = arg; - - dprintk(3, KERN_DEBUG "%s: VIDIOCGUNIT\n", ZR_DEVNAME(zr)); - - vunit->video = zr->video_dev->minor; - vunit->vbi = VIDEO_NO_UNIT; - vunit->radio = VIDEO_NO_UNIT; - vunit->audio = VIDEO_NO_UNIT; - vunit->teletext = VIDEO_NO_UNIT; - - return 0; - } - - /* - * RJ: In principal we could support subcaptures for V4L grabbing. - * Not even the famous BTTV driver has them, however. - * If there should be a strong demand, one could consider - * to implement them. - */ - case VIDIOCGCAPTURE: - { - dprintk(3, KERN_ERR "%s: VIDIOCGCAPTURE not supported\n", - ZR_DEVNAME(zr)); - return -EINVAL; - } - - case VIDIOCSCAPTURE: - { - dprintk(3, KERN_ERR "%s: VIDIOCSCAPTURE not supported\n", - ZR_DEVNAME(zr)); - return -EINVAL; - } - case BUZIOC_G_PARAMS: { struct zoran_params *bparams = arg; @@ -2383,6 +1969,46 @@ gstat_unlock_and_return: } } +static int zoran_vidiocgmbuf(struct file *file, void *__fh, struct video_mbuf *vmbuf) +{ + struct zoran_fh *fh = __fh; + struct zoran *zr = fh->zr; + int i, res = 0; + + vmbuf->size = + fh->v4l_buffers.num_buffers * + fh->v4l_buffers.buffer_size; + vmbuf->frames = fh->v4l_buffers.num_buffers; + for (i = 0; i < vmbuf->frames; i++) { + vmbuf->offsets[i] = + i * fh->v4l_buffers.buffer_size; + } + + mutex_lock(&zr->resource_lock); + + if (fh->jpg_buffers.allocated || fh->v4l_buffers.allocated) { + dprintk(1, + KERN_ERR + "%s: VIDIOCGMBUF - buffers already allocated\n", + ZR_DEVNAME(zr)); + res = -EINVAL; + goto v4l1reqbuf_unlock_and_return; + } + + if (v4l_fbuffer_alloc(file)) { + res = -ENOMEM; + goto v4l1reqbuf_unlock_and_return; + } + + /* The next mmap will map the V4L buffers */ + fh->map_mode = ZORAN_MAP_MODE_RAW; +v4l1reqbuf_unlock_and_return: + mutex_unlock(&zr->resource_lock); + + return res; +} +#endif + static int zoran_querycap(struct file *file, void *__fh, struct v4l2_capability *cap) { struct zoran_fh *fh = __fh; @@ -4118,7 +3744,10 @@ static const struct v4l2_ioctl_ops zoran_ioctl_ops = { .vidioc_queryctrl = zoran_queryctrl, .vidioc_s_ctrl = zoran_s_ctrl, .vidioc_g_ctrl = zoran_g_ctrl, +#ifdef CONFIG_VIDEO_V4L1_COMPAT .vidioc_default = zoran_default, + .vidiocgmbuf = zoran_vidiocgmbuf, +#endif }; static const struct v4l2_file_operations zoran_fops = { -- cgit v1.2.3 From aff88bca73a16039ed0988660dc7ab755c3e1741 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 18 Feb 2009 13:52:24 -0300 Subject: V4L/DVB (10709): zoran: set correct parent of the video device. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/zoran/zoran_card.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/media/video') diff --git a/drivers/media/video/zoran/zoran_card.c b/drivers/media/video/zoran/zoran_card.c index 5d2f090aa0f8..1ad9ed48dbdb 100644 --- a/drivers/media/video/zoran/zoran_card.c +++ b/drivers/media/video/zoran/zoran_card.c @@ -1137,6 +1137,7 @@ zr36057_init (struct zoran *zr) * Now add the template and register the device unit. */ memcpy(zr->video_dev, &zoran_template, sizeof(zoran_template)); + zr->video_dev->parent = &zr->pci_dev->dev; strcpy(zr->video_dev->name, ZR_DEVNAME(zr)); err = video_register_device(zr->video_dev, VFL_TYPE_GRABBER, video_nr[zr->id]); if (err < 0) -- cgit v1.2.3 From 7f37cc9bae7aa29d567460c3ac8178d587f710bc Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 18 Feb 2009 17:00:37 -0300 Subject: V4L/DVB (10710): zoran: cleanups in an attempt to make the source a bit more readable. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/zoran/zoran_card.c | 9 +- drivers/media/video/zoran/zoran_device.c | 404 ++++++++++++++----------------- drivers/media/video/zoran/zoran_driver.c | 4 +- 3 files changed, 184 insertions(+), 233 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/zoran/zoran_card.c b/drivers/media/video/zoran/zoran_card.c index 1ad9ed48dbdb..18834b18435b 100644 --- a/drivers/media/video/zoran/zoran_card.c +++ b/drivers/media/video/zoran/zoran_card.c @@ -919,15 +919,12 @@ zoran_check_jpg_settings (struct zoran *zr, err0++; if (settings->img_x + settings->img_width > BUZ_MAX_WIDTH) err0++; - if (settings->img_y + settings->img_height > - BUZ_MAX_HEIGHT / 2) + if (settings->img_y + settings->img_height > BUZ_MAX_HEIGHT / 2) err0++; if (settings->HorDcm && settings->VerDcm) { - if (settings->img_width % - (16 * settings->HorDcm) != 0) + if (settings->img_width % (16 * settings->HorDcm) != 0) err0++; - if (settings->img_height % - (8 * settings->VerDcm) != 0) + if (settings->img_height % (8 * settings->VerDcm) != 0) err0++; } diff --git a/drivers/media/video/zoran/zoran_device.c b/drivers/media/video/zoran/zoran_device.c index 5d948ff7faf0..1bcfa270d63d 100644 --- a/drivers/media/video/zoran/zoran_device.c +++ b/drivers/media/video/zoran/zoran_device.c @@ -1208,22 +1208,52 @@ zoran_reap_stat_com (struct zoran *zr) } } +static void zoran_restart(struct zoran *zr) +{ + /* Now the stat_comm buffer is ready for restart */ + int status, mode; + + if (zr->codec_mode == BUZ_MODE_MOTION_COMPRESS) { + decoder_command(zr, DECODER_GET_STATUS, &status); + mode = CODEC_DO_COMPRESSION; + } else { + status = 0; + mode = CODEC_DO_EXPANSION; + } + if (zr->codec_mode == BUZ_MODE_MOTION_DECOMPRESS || + (status & DECODER_STATUS_GOOD)) { + /********** RESTART code *************/ + jpeg_codec_reset(zr); + zr->codec->set_mode(zr->codec, mode); + zr36057_set_jpg(zr, zr->codec_mode); + jpeg_start(zr); + + if (zr->num_errors <= 8) + dprintk(2, KERN_INFO "%s: Restart\n", + ZR_DEVNAME(zr)); + + zr->JPEG_missed = 0; + zr->JPEG_error = 2; + /********** End RESTART code ***********/ + } +} + static void error_handler (struct zoran *zr, u32 astat, u32 stat) { + int i, j; + /* This is JPEG error handling part */ - if ((zr->codec_mode != BUZ_MODE_MOTION_COMPRESS) && - (zr->codec_mode != BUZ_MODE_MOTION_DECOMPRESS)) { - //dprintk(1, KERN_ERR "%s: Internal error: error handling request in mode %d\n", ZR_DEVNAME(zr), zr->codec_mode); + if (zr->codec_mode != BUZ_MODE_MOTION_COMPRESS && + zr->codec_mode != BUZ_MODE_MOTION_DECOMPRESS) { return; } if ((stat & 1) == 0 && zr->codec_mode == BUZ_MODE_MOTION_COMPRESS && - zr->jpg_dma_tail - zr->jpg_que_tail >= - zr->jpg_buffers.num_buffers) { + zr->jpg_dma_tail - zr->jpg_que_tail >= zr->jpg_buffers.num_buffers) { /* No free buffers... */ zoran_reap_stat_com(zr); zoran_feed_stat_com(zr); @@ -1232,142 +1262,95 @@ error_handler (struct zoran *zr, return; } - if (zr->JPEG_error != 1) { - /* - * First entry: error just happened during normal operation - * - * In BUZ_MODE_MOTION_COMPRESS: - * - * Possible glitch in TV signal. In this case we should - * stop the codec and wait for good quality signal before - * restarting it to avoid further problems - * - * In BUZ_MODE_MOTION_DECOMPRESS: - * - * Bad JPEG frame: we have to mark it as processed (codec crashed - * and was not able to do it itself), and to remove it from queue. - */ - btand(~ZR36057_JMC_Go_en, ZR36057_JMC); - udelay(1); - stat = stat | (post_office_read(zr, 7, 0) & 3) << 8; - btwrite(0, ZR36057_JPC); - btor(ZR36057_MCTCR_CFlush, ZR36057_MCTCR); - jpeg_codec_reset(zr); - jpeg_codec_sleep(zr, 1); - zr->JPEG_error = 1; - zr->num_errors++; - - /* Report error */ - if (zr36067_debug > 1 && zr->num_errors <= 8) { - long frame; - frame = - zr->jpg_pend[zr->jpg_dma_tail & BUZ_MASK_FRAME]; - printk(KERN_ERR - "%s: JPEG error stat=0x%08x(0x%08x) queue_state=%ld/%ld/%ld/%ld seq=%ld frame=%ld. Codec stopped. ", - ZR_DEVNAME(zr), stat, zr->last_isr, - zr->jpg_que_tail, zr->jpg_dma_tail, - zr->jpg_dma_head, zr->jpg_que_head, - zr->jpg_seq_num, frame); - printk("stat_com frames:"); - { - int i, j; - for (j = 0; j < BUZ_NUM_STAT_COM; j++) { - for (i = 0; - i < zr->jpg_buffers.num_buffers; - i++) { - if (le32_to_cpu(zr->stat_com[j]) == - zr->jpg_buffers. - buffer[i]. - frag_tab_bus) { - printk("% d->%d", - j, i); - } - } - } - printk("\n"); - } - } - /* Find an entry in stat_com and rotate contents */ - { - int i; - - if (zr->jpg_settings.TmpDcm == 1) - i = (zr->jpg_dma_tail - - zr->jpg_err_shift) & BUZ_MASK_STAT_COM; - else - i = ((zr->jpg_dma_tail - - zr->jpg_err_shift) & 1) * 2; - if (zr->codec_mode == BUZ_MODE_MOTION_DECOMPRESS) { - /* Mimic zr36067 operation */ - zr->stat_com[i] |= cpu_to_le32(1); - if (zr->jpg_settings.TmpDcm != 1) - zr->stat_com[i + 1] |= cpu_to_le32(1); - /* Refill */ - zoran_reap_stat_com(zr); - zoran_feed_stat_com(zr); - wake_up_interruptible(&zr->jpg_capq); - /* Find an entry in stat_com again after refill */ - if (zr->jpg_settings.TmpDcm == 1) - i = (zr->jpg_dma_tail - - zr->jpg_err_shift) & - BUZ_MASK_STAT_COM; - else - i = ((zr->jpg_dma_tail - - zr->jpg_err_shift) & 1) * 2; - } - if (i) { - /* Rotate stat_comm entries to make current entry first */ - int j; - __le32 bus_addr[BUZ_NUM_STAT_COM]; - - /* Here we are copying the stat_com array, which - * is already in little endian format, so - * no endian conversions here - */ - memcpy(bus_addr, zr->stat_com, - sizeof(bus_addr)); - for (j = 0; j < BUZ_NUM_STAT_COM; j++) { - zr->stat_com[j] = - bus_addr[(i + j) & - BUZ_MASK_STAT_COM]; + if (zr->JPEG_error == 1) { + zoran_restart(zr); + return; + } - } - zr->jpg_err_shift += i; - zr->jpg_err_shift &= BUZ_MASK_STAT_COM; + /* + * First entry: error just happened during normal operation + * + * In BUZ_MODE_MOTION_COMPRESS: + * + * Possible glitch in TV signal. In this case we should + * stop the codec and wait for good quality signal before + * restarting it to avoid further problems + * + * In BUZ_MODE_MOTION_DECOMPRESS: + * + * Bad JPEG frame: we have to mark it as processed (codec crashed + * and was not able to do it itself), and to remove it from queue. + */ + btand(~ZR36057_JMC_Go_en, ZR36057_JMC); + udelay(1); + stat = stat | (post_office_read(zr, 7, 0) & 3) << 8; + btwrite(0, ZR36057_JPC); + btor(ZR36057_MCTCR_CFlush, ZR36057_MCTCR); + jpeg_codec_reset(zr); + jpeg_codec_sleep(zr, 1); + zr->JPEG_error = 1; + zr->num_errors++; + + /* Report error */ + if (zr36067_debug > 1 && zr->num_errors <= 8) { + long frame; + + frame = zr->jpg_pend[zr->jpg_dma_tail & BUZ_MASK_FRAME]; + printk(KERN_ERR + "%s: JPEG error stat=0x%08x(0x%08x) queue_state=%ld/%ld/%ld/%ld seq=%ld frame=%ld. Codec stopped. ", + ZR_DEVNAME(zr), stat, zr->last_isr, + zr->jpg_que_tail, zr->jpg_dma_tail, + zr->jpg_dma_head, zr->jpg_que_head, + zr->jpg_seq_num, frame); + printk(KERN_INFO "stat_com frames:"); + for (j = 0; j < BUZ_NUM_STAT_COM; j++) { + for (i = 0; i < zr->jpg_buffers.num_buffers; i++) { + if (le32_to_cpu(zr->stat_com[j]) == zr->jpg_buffers.buffer[i].frag_tab_bus) + printk(KERN_CONT "% d->%d", j, i); } - if (zr->codec_mode == BUZ_MODE_MOTION_COMPRESS) - zr->jpg_err_seq = zr->jpg_seq_num; /* + 1; */ } + printk(KERN_CONT "\n"); } + /* Find an entry in stat_com and rotate contents */ + if (zr->jpg_settings.TmpDcm == 1) + i = (zr->jpg_dma_tail - zr->jpg_err_shift) & BUZ_MASK_STAT_COM; + else + i = ((zr->jpg_dma_tail - zr->jpg_err_shift) & 1) * 2; + if (zr->codec_mode == BUZ_MODE_MOTION_DECOMPRESS) { + /* Mimic zr36067 operation */ + zr->stat_com[i] |= cpu_to_le32(1); + if (zr->jpg_settings.TmpDcm != 1) + zr->stat_com[i + 1] |= cpu_to_le32(1); + /* Refill */ + zoran_reap_stat_com(zr); + zoran_feed_stat_com(zr); + wake_up_interruptible(&zr->jpg_capq); + /* Find an entry in stat_com again after refill */ + if (zr->jpg_settings.TmpDcm == 1) + i = (zr->jpg_dma_tail - zr->jpg_err_shift) & BUZ_MASK_STAT_COM; + else + i = ((zr->jpg_dma_tail - zr->jpg_err_shift) & 1) * 2; + } + if (i) { + /* Rotate stat_comm entries to make current entry first */ + int j; + __le32 bus_addr[BUZ_NUM_STAT_COM]; + + /* Here we are copying the stat_com array, which + * is already in little endian format, so + * no endian conversions here + */ + memcpy(bus_addr, zr->stat_com, sizeof(bus_addr)); - /* Now the stat_comm buffer is ready for restart */ - do { - int status, mode; - - if (zr->codec_mode == BUZ_MODE_MOTION_COMPRESS) { - decoder_command(zr, DECODER_GET_STATUS, &status); - mode = CODEC_DO_COMPRESSION; - } else { - status = 0; - mode = CODEC_DO_EXPANSION; - } - if (zr->codec_mode == BUZ_MODE_MOTION_DECOMPRESS || - (status & DECODER_STATUS_GOOD)) { - /********** RESTART code *************/ - jpeg_codec_reset(zr); - zr->codec->set_mode(zr->codec, mode); - zr36057_set_jpg(zr, zr->codec_mode); - jpeg_start(zr); - - if (zr->num_errors <= 8) - dprintk(2, KERN_INFO "%s: Restart\n", - ZR_DEVNAME(zr)); + for (j = 0; j < BUZ_NUM_STAT_COM; j++) + zr->stat_com[j] = bus_addr[(i + j) & BUZ_MASK_STAT_COM]; - zr->JPEG_missed = 0; - zr->JPEG_error = 2; - /********** End RESTART code ***********/ - } - } while (0); + zr->jpg_err_shift += i; + zr->jpg_err_shift &= BUZ_MASK_STAT_COM; + } + if (zr->codec_mode == BUZ_MODE_MOTION_COMPRESS) + zr->jpg_err_seq = zr->jpg_seq_num; /* + 1; */ + zoran_restart(zr); } irqreturn_t @@ -1425,10 +1408,8 @@ zoran_irq (int irq, * We simply ignore them */ if (zr->v4l_memgrab_active) { - /* A lot more checks should be here ... */ - if ((btread(ZR36057_VSSFGR) & - ZR36057_VSSFGR_SnapShot) == 0) + if ((btread(ZR36057_VSSFGR) & ZR36057_VSSFGR_SnapShot) == 0) dprintk(1, KERN_WARNING "%s: BuzIRQ with SnapShot off ???\n", @@ -1436,10 +1417,7 @@ zoran_irq (int irq, if (zr->v4l_grab_frame != NO_GRAB_ACTIVE) { /* There is a grab on a frame going on, check if it has finished */ - - if ((btread(ZR36057_VSSFGR) & - ZR36057_VSSFGR_FrameGrab) == - 0) { + if ((btread(ZR36057_VSSFGR) & ZR36057_VSSFGR_FrameGrab) == 0) { /* it is finished, notify the user */ zr->v4l_buffers.buffer[zr->v4l_grab_frame].state = BUZ_STATE_DONE; @@ -1457,9 +1435,7 @@ zoran_irq (int irq, if (zr->v4l_grab_frame == NO_GRAB_ACTIVE && zr->v4l_pend_tail != zr->v4l_pend_head) { - - int frame = zr->v4l_pend[zr->v4l_pend_tail & - V4L_MASK_FRAME]; + int frame = zr->v4l_pend[zr->v4l_pend_tail & V4L_MASK_FRAME]; u32 reg; zr->v4l_grab_frame = frame; @@ -1468,27 +1444,17 @@ zoran_irq (int irq, /* Buffer address */ - reg = - zr->v4l_buffers.buffer[frame]. - fbuffer_bus; + reg = zr->v4l_buffers.buffer[frame].fbuffer_bus; btwrite(reg, ZR36057_VDTR); - if (zr->v4l_settings.height > - BUZ_MAX_HEIGHT / 2) - reg += - zr->v4l_settings. - bytesperline; + if (zr->v4l_settings.height > BUZ_MAX_HEIGHT / 2) + reg += zr->v4l_settings.bytesperline; btwrite(reg, ZR36057_VDBR); /* video stride, status, and frame grab register */ reg = 0; - if (zr->v4l_settings.height > - BUZ_MAX_HEIGHT / 2) - reg += - zr->v4l_settings. - bytesperline; - reg = - (reg << - ZR36057_VSSFGR_DispStride); + if (zr->v4l_settings.height > BUZ_MAX_HEIGHT / 2) + reg += zr->v4l_settings.bytesperline; + reg = (reg << ZR36057_VSSFGR_DispStride); reg |= ZR36057_VSSFGR_VidOvf; reg |= ZR36057_VSSFGR_SnapShot; reg |= ZR36057_VSSFGR_FrameGrab; @@ -1506,77 +1472,66 @@ zoran_irq (int irq, #if (IRQ_MASK & ZR36057_ISR_CodRepIRQ) if (astat & ZR36057_ISR_CodRepIRQ) { zr->intr_counter_CodRepIRQ++; - IDEBUG(printk - (KERN_DEBUG "%s: ZR36057_ISR_CodRepIRQ\n", + IDEBUG(printk(KERN_DEBUG "%s: ZR36057_ISR_CodRepIRQ\n", ZR_DEVNAME(zr))); btand(~ZR36057_ICR_CodRepIRQ, ZR36057_ICR); } #endif /* (IRQ_MASK & ZR36057_ISR_CodRepIRQ) */ #if (IRQ_MASK & ZR36057_ISR_JPEGRepIRQ) - if (astat & ZR36057_ISR_JPEGRepIRQ) { - - if (zr->codec_mode == BUZ_MODE_MOTION_DECOMPRESS || - zr->codec_mode == BUZ_MODE_MOTION_COMPRESS) { - if (zr36067_debug > 1 && - (!zr->frame_num || zr->JPEG_error)) { - printk(KERN_INFO - "%s: first frame ready: state=0x%08x odd_even=%d field_per_buff=%d delay=%d\n", - ZR_DEVNAME(zr), stat, - zr->jpg_settings.odd_even, - zr->jpg_settings. - field_per_buff, - zr->JPEG_missed); - { - char sc[] = "0000"; - char sv[5]; - int i; - strcpy(sv, sc); - for (i = 0; i < 4; i++) { - if (le32_to_cpu(zr->stat_com[i]) & 1) - sv[i] = '1'; - } - sv[4] = 0; - printk(KERN_INFO - "%s: stat_com=%s queue_state=%ld/%ld/%ld/%ld\n", - ZR_DEVNAME(zr), sv, - zr->jpg_que_tail, - zr->jpg_dma_tail, - zr->jpg_dma_head, - zr->jpg_que_head); - } - } else { - if (zr->JPEG_missed > zr->JPEG_max_missed) // Get statistics - zr->JPEG_max_missed = - zr->JPEG_missed; - if (zr->JPEG_missed < - zr->JPEG_min_missed) - zr->JPEG_min_missed = - zr->JPEG_missed; + if ((astat & ZR36057_ISR_JPEGRepIRQ) && + (zr->codec_mode == BUZ_MODE_MOTION_DECOMPRESS || + zr->codec_mode == BUZ_MODE_MOTION_COMPRESS)) { + if (zr36067_debug > 1 && (!zr->frame_num || zr->JPEG_error)) { + char sc[] = "0000"; + char sv[5]; + int i; + + printk(KERN_INFO + "%s: first frame ready: state=0x%08x odd_even=%d field_per_buff=%d delay=%d\n", + ZR_DEVNAME(zr), stat, + zr->jpg_settings.odd_even, + zr->jpg_settings.field_per_buff, + zr->JPEG_missed); + + strcpy(sv, sc); + for (i = 0; i < 4; i++) { + if (le32_to_cpu(zr->stat_com[i]) & 1) + sv[i] = '1'; } + sv[4] = 0; + printk(KERN_INFO + "%s: stat_com=%s queue_state=%ld/%ld/%ld/%ld\n", + ZR_DEVNAME(zr), sv, + zr->jpg_que_tail, + zr->jpg_dma_tail, + zr->jpg_dma_head, + zr->jpg_que_head); + } else { + /* Get statistics */ + if (zr->JPEG_missed > zr->JPEG_max_missed) + zr->JPEG_max_missed = zr->JPEG_missed; + if (zr->JPEG_missed < zr->JPEG_min_missed) + zr->JPEG_min_missed = zr->JPEG_missed; + } - if (zr36067_debug > 2 && zr->frame_num < 6) { - int i; - printk("%s: seq=%ld stat_com:", - ZR_DEVNAME(zr), zr->jpg_seq_num); - for (i = 0; i < 4; i++) { - printk(" %08x", - le32_to_cpu(zr->stat_com[i])); - } - printk("\n"); + if (zr36067_debug > 2 && zr->frame_num < 6) { + int i; + + printk(KERN_INFO "%s: seq=%ld stat_com:", + ZR_DEVNAME(zr), zr->jpg_seq_num); + for (i = 0; i < 4; i++) { + printk(KERN_CONT " %08x", + le32_to_cpu(zr->stat_com[i])); } - zr->frame_num++; - zr->JPEG_missed = 0; - zr->JPEG_error = 0; - zoran_reap_stat_com(zr); - zoran_feed_stat_com(zr); - wake_up_interruptible(&zr->jpg_capq); - } /*else { - dprintk(1, - KERN_ERR - "%s: JPEG interrupt while not in motion (de)compress mode!\n", - ZR_DEVNAME(zr)); - }*/ + printk(KERN_CONT "\n"); + } + zr->frame_num++; + zr->JPEG_missed = 0; + zr->JPEG_error = 0; + zoran_reap_stat_com(zr); + zoran_feed_stat_com(zr); + wake_up_interruptible(&zr->jpg_capq); } #endif /* (IRQ_MASK & ZR36057_ISR_JPEGRepIRQ) */ @@ -1585,8 +1540,7 @@ zoran_irq (int irq, zr->JPEG_missed > 25 || zr->JPEG_error == 1 || ((zr->codec_mode == BUZ_MODE_MOTION_DECOMPRESS) && - (zr->frame_num & (zr->JPEG_missed > - zr->jpg_settings.field_per_buff)))) { + (zr->frame_num & (zr->JPEG_missed > zr->jpg_settings.field_per_buff)))) { error_handler(zr, astat, stat); } diff --git a/drivers/media/video/zoran/zoran_driver.c b/drivers/media/video/zoran/zoran_driver.c index 0e4b8d03fda3..0cce652011ff 100644 --- a/drivers/media/video/zoran/zoran_driver.c +++ b/drivers/media/video/zoran/zoran_driver.c @@ -2314,7 +2314,7 @@ static int zoran_s_fmt_vid_out(struct file *file, void *__fh, } /* we actually need to set 'real' parameters now */ - if ((fmt->fmt.pix.height * 2) > BUZ_MAX_HEIGHT) + if (fmt->fmt.pix.height * 2 > BUZ_MAX_HEIGHT) settings.TmpDcm = 1; else settings.TmpDcm = 2; @@ -2501,7 +2501,7 @@ static int zoran_reqbufs(struct file *file, void *__fh, struct v4l2_requestbuffe if (fh->v4l_buffers.allocated || fh->jpg_buffers.allocated) { dprintk(1, KERN_ERR - "%s: VIDIOC_REQBUFS - buffers allready allocated\n", + "%s: VIDIOC_REQBUFS - buffers already allocated\n", ZR_DEVNAME(zr)); res = -EBUSY; goto v4l2reqbuf_unlock_and_return; -- cgit v1.2.3 From 0ba514d5d39d017e320ffba6d2a98563b829d37c Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 18 Feb 2009 17:11:17 -0300 Subject: V4L/DVB (10711): zoran: fix TRY_FMT support Actually try to turn the format into something usable rather than just rejecting it if it isn't perfect. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/zoran/zoran_card.c | 63 +++++++++++++++++++++++--------- drivers/media/video/zoran/zoran_card.h | 3 +- drivers/media/video/zoran/zoran_driver.c | 21 ++++++++--- 3 files changed, 63 insertions(+), 24 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/zoran/zoran_card.c b/drivers/media/video/zoran/zoran_card.c index 18834b18435b..774717bf43cc 100644 --- a/drivers/media/video/zoran/zoran_card.c +++ b/drivers/media/video/zoran/zoran_card.c @@ -835,7 +835,8 @@ zoran_unregister_i2c (struct zoran *zr) int zoran_check_jpg_settings (struct zoran *zr, - struct zoran_jpg_settings *settings) + struct zoran_jpg_settings *settings, + int try) { int err = 0, err0 = 0; @@ -900,35 +901,61 @@ zoran_check_jpg_settings (struct zoran *zr, /* We have to check the data the user has set */ if (settings->HorDcm != 1 && settings->HorDcm != 2 && - (zr->card.type == DC10_new || settings->HorDcm != 4)) + (zr->card.type == DC10_new || settings->HorDcm != 4)) { + settings->HorDcm = clamp(settings->HorDcm, 1, 2); err0++; - if (settings->VerDcm != 1 && settings->VerDcm != 2) + } + if (settings->VerDcm != 1 && settings->VerDcm != 2) { + settings->VerDcm = clamp(settings->VerDcm, 1, 2); err0++; - if (settings->TmpDcm != 1 && settings->TmpDcm != 2) + } + if (settings->TmpDcm != 1 && settings->TmpDcm != 2) { + settings->TmpDcm = clamp(settings->TmpDcm, 1, 2); err0++; + } if (settings->field_per_buff != 1 && - settings->field_per_buff != 2) + settings->field_per_buff != 2) { + settings->field_per_buff = clamp(settings->field_per_buff, 1, 2); err0++; - if (settings->img_x < 0) + } + if (settings->img_x < 0) { + settings->img_x = 0; err0++; - if (settings->img_y < 0) + } + if (settings->img_y < 0) { + settings->img_y = 0; err0++; - if (settings->img_width < 0) + } + if (settings->img_width < 0 || settings->img_width > BUZ_MAX_WIDTH) { + settings->img_width = clamp(settings->img_width, 0, (int)BUZ_MAX_WIDTH); err0++; - if (settings->img_height < 0) + } + if (settings->img_height < 0 || settings->img_height > BUZ_MAX_HEIGHT / 2) { + settings->img_height = clamp(settings->img_height, 0, BUZ_MAX_HEIGHT / 2); err0++; - if (settings->img_x + settings->img_width > BUZ_MAX_WIDTH) + } + if (settings->img_x + settings->img_width > BUZ_MAX_WIDTH) { + settings->img_x = BUZ_MAX_WIDTH - settings->img_width; + err0++; + } + if (settings->img_y + settings->img_height > BUZ_MAX_HEIGHT / 2) { + settings->img_y = BUZ_MAX_HEIGHT / 2 - settings->img_height; err0++; - if (settings->img_y + settings->img_height > BUZ_MAX_HEIGHT / 2) + } + if (settings->img_width % (16 * settings->HorDcm) != 0) { + settings->img_width -= settings->img_width % (16 * settings->HorDcm); + if (settings->img_width == 0) + settings->img_width = 16 * settings->HorDcm; + err0++; + } + if (settings->img_height % (8 * settings->VerDcm) != 0) { + settings->img_height -= settings->img_height % (8 * settings->VerDcm); + if (settings->img_height == 0) + settings->img_height = 8 * settings->VerDcm; err0++; - if (settings->HorDcm && settings->VerDcm) { - if (settings->img_width % (16 * settings->HorDcm) != 0) - err0++; - if (settings->img_height % (8 * settings->VerDcm) != 0) - err0++; } - if (err0) { + if (!try && err0) { dprintk(1, KERN_ERR "%s: check_jpg_settings() - error in params for decimation = 0\n", @@ -1018,7 +1045,7 @@ zoran_open_init_params (struct zoran *zr) sizeof(zr->jpg_settings.jpg_comp.COM_data)); zr->jpg_settings.jpg_comp.jpeg_markers = JPEG_MARKER_DHT | JPEG_MARKER_DQT; - i = zoran_check_jpg_settings(zr, &zr->jpg_settings); + i = zoran_check_jpg_settings(zr, &zr->jpg_settings, 0); if (i) dprintk(1, KERN_ERR diff --git a/drivers/media/video/zoran/zoran_card.h b/drivers/media/video/zoran/zoran_card.h index 4507bdc5e338..4936fead73e8 100644 --- a/drivers/media/video/zoran/zoran_card.h +++ b/drivers/media/video/zoran/zoran_card.h @@ -44,7 +44,8 @@ extern int zr36067_debug; extern struct video_device zoran_template; extern int zoran_check_jpg_settings(struct zoran *zr, - struct zoran_jpg_settings *settings); + struct zoran_jpg_settings *settings, + int try); extern void zoran_open_init_params(struct zoran *zr); extern void zoran_vdev_release(struct video_device *vdev); diff --git a/drivers/media/video/zoran/zoran_driver.c b/drivers/media/video/zoran/zoran_driver.c index 0cce652011ff..cdfd3cc05151 100644 --- a/drivers/media/video/zoran/zoran_driver.c +++ b/drivers/media/video/zoran/zoran_driver.c @@ -1797,7 +1797,7 @@ static long zoran_default(struct file *file, void *__fh, int cmd, void *arg) /* Check the params first before overwriting our * nternal values */ - if (zoran_check_jpg_settings(zr, &settings)) { + if (zoran_check_jpg_settings(zr, &settings, 0)) { res = -EINVAL; goto sparams_unlock_and_return; } @@ -2205,7 +2205,7 @@ static int zoran_try_fmt_vid_out(struct file *file, void *__fh, settings.field_per_buff = 1; /* check */ - res = zoran_check_jpg_settings(zr, &settings); + res = zoran_check_jpg_settings(zr, &settings, 1); if (res) goto tryfmt_unlock_and_return; @@ -2231,6 +2231,7 @@ static int zoran_try_fmt_vid_cap(struct file *file, void *__fh, { struct zoran_fh *fh = __fh; struct zoran *zr = fh->zr; + int bpp; int i; if (fmt->fmt.pix.pixelformat == V4L2_PIX_FMT_MJPEG) @@ -2247,6 +2248,8 @@ static int zoran_try_fmt_vid_cap(struct file *file, void *__fh, return -EINVAL; } + bpp = (zoran_formats[i].depth + 7) / 8; + fmt->fmt.pix.width &= ~((bpp == 2) ? 1 : 3); if (fmt->fmt.pix.width > BUZ_MAX_WIDTH) fmt->fmt.pix.width = BUZ_MAX_WIDTH; if (fmt->fmt.pix.width < BUZ_MIN_WIDTH) @@ -2334,8 +2337,16 @@ static int zoran_s_fmt_vid_out(struct file *file, void *__fh, else settings.field_per_buff = 1; + if (settings.HorDcm > 1) { + settings.img_x = (BUZ_MAX_WIDTH == 720) ? 8 : 0; + settings.img_width = (BUZ_MAX_WIDTH == 720) ? 704 : BUZ_MAX_WIDTH; + } else { + settings.img_x = 0; + settings.img_width = BUZ_MAX_WIDTH; + } + /* check */ - res = zoran_check_jpg_settings(zr, &settings); + res = zoran_check_jpg_settings(zr, &settings, 0); if (res) goto sfmtjpg_unlock_and_return; @@ -3216,7 +3227,7 @@ static int zoran_s_crop(struct file *file, void *__fh, struct v4l2_crop *crop) settings.img_height = crop->c.height; /* check validity */ - res = zoran_check_jpg_settings(zr, &settings); + res = zoran_check_jpg_settings(zr, &settings, 0); if (res) goto scrop_unlock_and_return; @@ -3278,7 +3289,7 @@ static int zoran_s_jpegcomp(struct file *file, void *__fh, goto sjpegc_unlock_and_return; } - res = zoran_check_jpg_settings(zr, &settings); + res = zoran_check_jpg_settings(zr, &settings, 0); if (res) goto sjpegc_unlock_and_return; if (!fh->jpg_buffers.allocated) -- cgit v1.2.3 From 5ca75b00ffd0df5bae16e84830f2710537efed11 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 18 Feb 2009 17:12:34 -0300 Subject: V4L/DVB (10712): zoran: fix G_FMT Returned height was really height / 2. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/zoran/zoran_driver.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/zoran/zoran_driver.c b/drivers/media/video/zoran/zoran_driver.c index cdfd3cc05151..7129f9254e70 100644 --- a/drivers/media/video/zoran/zoran_driver.c +++ b/drivers/media/video/zoran/zoran_driver.c @@ -2083,7 +2083,7 @@ static int zoran_g_fmt_vid_out(struct file *file, void *__fh, mutex_lock(&zr->resource_lock); fmt->fmt.pix.width = fh->jpg_settings.img_width / fh->jpg_settings.HorDcm; - fmt->fmt.pix.height = fh->jpg_settings.img_height / + fmt->fmt.pix.height = fh->jpg_settings.img_height * 2 / (fh->jpg_settings.VerDcm * fh->jpg_settings.TmpDcm); fmt->fmt.pix.sizeimage = zoran_v4l2_calc_bufsize(&fh->jpg_settings); fmt->fmt.pix.pixelformat = V4L2_PIX_FMT_MJPEG; -- cgit v1.2.3 From 84c1b09495ea366276726b0df2dcd7898cda9d0f Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 18 Feb 2009 17:15:46 -0300 Subject: V4L/DVB (10713): zoran: if reqbufs is called with count == 0, do a streamoff. count == 0 has a special meaning, implement this. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/zoran/zoran_driver.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/zoran/zoran_driver.c b/drivers/media/video/zoran/zoran_driver.c index 7129f9254e70..07f2bdfef4ee 100644 --- a/drivers/media/video/zoran/zoran_driver.c +++ b/drivers/media/video/zoran/zoran_driver.c @@ -2493,6 +2493,8 @@ static int zoran_overlay(struct file *file, void *__fh, unsigned int on) return res; } +static int zoran_streamoff(struct file *file, void *__fh, enum v4l2_buf_type type); + static int zoran_reqbufs(struct file *file, void *__fh, struct v4l2_requestbuffers *req) { struct zoran_fh *fh = __fh; @@ -2500,17 +2502,19 @@ static int zoran_reqbufs(struct file *file, void *__fh, struct v4l2_requestbuffe int res = 0; if (req->memory != V4L2_MEMORY_MMAP) { - dprintk(1, + dprintk(2, KERN_ERR "%s: only MEMORY_MMAP capture is supported, not %d\n", ZR_DEVNAME(zr), req->memory); return -EINVAL; } - mutex_lock(&zr->resource_lock); + if (req->count == 0) + return zoran_streamoff(file, fh, req->type); + mutex_lock(&zr->resource_lock); if (fh->v4l_buffers.allocated || fh->jpg_buffers.allocated) { - dprintk(1, + dprintk(2, KERN_ERR "%s: VIDIOC_REQBUFS - buffers already allocated\n", ZR_DEVNAME(zr)); -- cgit v1.2.3 From 107063c6156a0cbf055e771baafc28a3e3c0fb9b Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 18 Feb 2009 17:26:06 -0300 Subject: V4L/DVB (10714): zoran et al: convert zoran i2c modules to V4L2. The zoran i2c modules were still using V4L1 internally. Replace this with V4L2. Also deleted saa7111.c and saa7114.c, we use saa7115.c instead. Signed-off-by: Hans Verkuil [mchehab@redhat.com: fix v4l2_ctrl_query_fill_std merge conflict] Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/Kconfig | 28 +- drivers/media/video/Makefile | 2 - drivers/media/video/adv7170.c | 74 +-- drivers/media/video/adv7175.c | 81 +-- drivers/media/video/bt819.c | 271 ++++---- drivers/media/video/bt856.c | 92 +-- drivers/media/video/bt866.c | 67 +- drivers/media/video/ks0127.c | 152 ++--- drivers/media/video/saa7110.c | 210 +++--- drivers/media/video/saa7111.c | 492 -------------- drivers/media/video/saa7114.c | 1068 ------------------------------ drivers/media/video/saa7185.c | 78 +-- drivers/media/video/vpx3220.c | 232 ++++--- drivers/media/video/zoran/Kconfig | 4 +- drivers/media/video/zoran/zoran.h | 6 +- drivers/media/video/zoran/zoran_card.c | 60 +- drivers/media/video/zoran/zoran_device.c | 61 +- drivers/media/video/zoran/zoran_driver.c | 220 ++---- 18 files changed, 636 insertions(+), 2562 deletions(-) delete mode 100644 drivers/media/video/saa7111.c delete mode 100644 drivers/media/video/saa7114.c (limited to 'drivers/media/video') diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig index 3e4ce4aade3e..bb7df8c18b03 100644 --- a/drivers/media/video/Kconfig +++ b/drivers/media/video/Kconfig @@ -307,38 +307,18 @@ config VIDEO_TCM825X config VIDEO_SAA7110 tristate "Philips SAA7110 video decoder" - depends on VIDEO_V4L1 && I2C + depends on VIDEO_V4L2 && I2C ---help--- Support for the Philips SAA7110 video decoders. To compile this driver as a module, choose M here: the module will be called saa7110. -config VIDEO_SAA7111 - tristate "Philips SAA7111 video decoder" - depends on VIDEO_V4L1 && I2C - ---help--- - Support for the Philips SAA711 video decoder. - - To compile this driver as a module, choose M here: the - module will be called saa7111. - -config VIDEO_SAA7114 - tristate "Philips SAA7114 video decoder" - depends on VIDEO_V4L1 && I2C - ---help--- - Support for the Philips SAA7114 video decoder. This driver - is used only on Zoran driver and should be moved soon to - SAA711x module. - - To compile this driver as a module, choose M here: the - module will be called saa7114. - config VIDEO_SAA711X - tristate "Philips SAA7113/4/5 video decoders" + tristate "Philips SAA7111/3/4/5 video decoders" depends on VIDEO_V4L2 && I2C ---help--- - Support for the Philips SAA7113/4/5 video decoders. + Support for the Philips SAA7111/3/4/5 video decoders. To compile this driver as a module, choose M here: the module will be called saa7115. @@ -639,7 +619,7 @@ config VIDEO_MXB depends on PCI && VIDEO_V4L1 && I2C select VIDEO_SAA7146_VV select VIDEO_TUNER - select VIDEO_SAA7115 if VIDEO_HELPER_CHIPS_AUTO + select VIDEO_SAA711X if VIDEO_HELPER_CHIPS_AUTO select VIDEO_TDA9840 if VIDEO_HELPER_CHIPS_AUTO select VIDEO_TEA6415C if VIDEO_HELPER_CHIPS_AUTO select VIDEO_TEA6420 if VIDEO_HELPER_CHIPS_AUTO diff --git a/drivers/media/video/Makefile b/drivers/media/video/Makefile index 6e2c69569f97..307490ebc230 100644 --- a/drivers/media/video/Makefile +++ b/drivers/media/video/Makefile @@ -43,8 +43,6 @@ obj-$(CONFIG_VIDEO_TDA9840) += tda9840.o obj-$(CONFIG_VIDEO_TEA6415C) += tea6415c.o obj-$(CONFIG_VIDEO_TEA6420) += tea6420.o obj-$(CONFIG_VIDEO_SAA7110) += saa7110.o -obj-$(CONFIG_VIDEO_SAA7111) += saa7111.o -obj-$(CONFIG_VIDEO_SAA7114) += saa7114.o obj-$(CONFIG_VIDEO_SAA711X) += saa7115.o obj-$(CONFIG_VIDEO_SAA717X) += saa717x.o obj-$(CONFIG_VIDEO_SAA7127) += saa7127.o diff --git a/drivers/media/video/adv7170.c b/drivers/media/video/adv7170.c index e0eb4f321442..ebafe78cb4c0 100644 --- a/drivers/media/video/adv7170.c +++ b/drivers/media/video/adv7170.c @@ -52,9 +52,8 @@ MODULE_PARM_DESC(debug, "Debug level (0-1)"); struct adv7170 { unsigned char reg[128]; - int norm; + v4l2_std_id norm; int input; - int enable; int bright; int contrast; int hue; @@ -62,7 +61,6 @@ struct adv7170 { }; static char *inputs[] = { "pass_through", "play_back" }; -static char *norms[] = { "PAL", "NTSC" }; /* ----------------------------------------------------------------------- */ @@ -191,7 +189,7 @@ static int adv7170_command(struct i2c_client *client, unsigned cmd, void *arg) struct adv7170 *encoder = i2c_get_clientdata(client); switch (cmd) { - case 0: + case VIDIOC_INT_INIT: #if 0 /* This is just for testing!!! */ adv7170_write_block(client, init_common, @@ -201,63 +199,47 @@ static int adv7170_command(struct i2c_client *client, unsigned cmd, void *arg) #endif break; - case ENCODER_GET_CAPABILITIES: + case VIDIOC_INT_S_STD_OUTPUT: { - struct video_encoder_capability *cap = arg; + v4l2_std_id iarg = *(v4l2_std_id *) arg; - cap->flags = VIDEO_ENCODER_PAL | - VIDEO_ENCODER_NTSC; - cap->inputs = 2; - cap->outputs = 1; - break; - } - - case ENCODER_SET_NORM: - { - int iarg = *(int *) arg; - - v4l_dbg(1, debug, client, "set norm %d\n", iarg); + v4l_dbg(1, debug, client, "set norm %llx\n", iarg); - switch (iarg) { - case VIDEO_MODE_NTSC: + if (iarg & V4L2_STD_NTSC) { adv7170_write_block(client, init_NTSC, sizeof(init_NTSC)); if (encoder->input == 0) adv7170_write(client, 0x02, 0x0e); // Enable genlock adv7170_write(client, 0x07, TR0MODE | TR0RST); adv7170_write(client, 0x07, TR0MODE); - break; - - case VIDEO_MODE_PAL: + } else if (iarg & V4L2_STD_PAL) { adv7170_write_block(client, init_PAL, sizeof(init_PAL)); if (encoder->input == 0) adv7170_write(client, 0x02, 0x0e); // Enable genlock adv7170_write(client, 0x07, TR0MODE | TR0RST); adv7170_write(client, 0x07, TR0MODE); - break; - - default: - v4l_dbg(1, debug, client, "illegal norm: %d\n", iarg); + } else { + v4l_dbg(1, debug, client, "illegal norm: %llx\n", iarg); return -EINVAL; } - v4l_dbg(1, debug, client, "switched to %s\n", norms[iarg]); + v4l_dbg(1, debug, client, "switched to %llx\n", iarg); encoder->norm = iarg; break; } - case ENCODER_SET_INPUT: + case VIDIOC_INT_S_VIDEO_ROUTING: { - int iarg = *(int *) arg; + struct v4l2_routing *route = arg; /* RJ: *iarg = 0: input is from decoder *iarg = 1: input is from ZR36060 *iarg = 2: color bar */ v4l_dbg(1, debug, client, "set input from %s\n", - iarg == 0 ? "decoder" : "ZR36060"); + route->input == 0 ? "decoder" : "ZR36060"); - switch (iarg) { + switch (route->input) { case 0: adv7170_write(client, 0x01, 0x20); adv7170_write(client, 0x08, TR1CAPT); /* TR1 */ @@ -277,30 +259,11 @@ static int adv7170_command(struct i2c_client *client, unsigned cmd, void *arg) break; default: - v4l_dbg(1, debug, client, "illegal input: %d\n", iarg); - return -EINVAL; - } - v4l_dbg(1, debug, client, "switched to %s\n", inputs[iarg]); - encoder->input = iarg; - break; - } - - case ENCODER_SET_OUTPUT: - { - int *iarg = arg; - - /* not much choice of outputs */ - if (*iarg != 0) { + v4l_dbg(1, debug, client, "illegal input: %d\n", route->input); return -EINVAL; } - break; - } - - case ENCODER_ENABLE_OUTPUT: - { - int *iarg = arg; - - encoder->enable = !!*iarg; + v4l_dbg(1, debug, client, "switched to %s\n", inputs[route->input]); + encoder->input = route->input; break; } @@ -337,9 +300,8 @@ static int adv7170_probe(struct i2c_client *client, encoder = kzalloc(sizeof(struct adv7170), GFP_KERNEL); if (encoder == NULL) return -ENOMEM; - encoder->norm = VIDEO_MODE_NTSC; + encoder->norm = V4L2_STD_NTSC; encoder->input = 0; - encoder->enable = 1; i2c_set_clientdata(client, encoder); i = adv7170_write_block(client, init_NTSC, sizeof(init_NTSC)); diff --git a/drivers/media/video/adv7175.c b/drivers/media/video/adv7175.c index 6008e84653f1..154dff03a7d8 100644 --- a/drivers/media/video/adv7175.c +++ b/drivers/media/video/adv7175.c @@ -46,9 +46,8 @@ MODULE_PARM_DESC(debug, "Debug level (0-1)"); /* ----------------------------------------------------------------------- */ struct adv7175 { - int norm; + v4l2_std_id norm; int input; - int enable; int bright; int contrast; int hue; @@ -59,7 +58,6 @@ struct adv7175 { #define I2C_ADV7176 0x54 static char *inputs[] = { "pass_through", "play_back", "color_bar" }; -static char *norms[] = { "PAL", "NTSC", "SECAM->PAL (may not work!)" }; /* ----------------------------------------------------------------------- */ @@ -189,7 +187,7 @@ static int adv7175_command(struct i2c_client *client, unsigned cmd, void *arg) struct adv7175 *encoder = i2c_get_clientdata(client); switch (cmd) { - case 0: + case VIDIOC_INT_INIT: /* This is just for testing!!! */ adv7175_write_block(client, init_common, sizeof(init_common)); @@ -197,42 +195,25 @@ static int adv7175_command(struct i2c_client *client, unsigned cmd, void *arg) adv7175_write(client, 0x07, TR0MODE); break; - case ENCODER_GET_CAPABILITIES: + case VIDIOC_INT_S_STD_OUTPUT: { - struct video_encoder_capability *cap = arg; + v4l2_std_id iarg = *(v4l2_std_id *) arg; - cap->flags = VIDEO_ENCODER_PAL | - VIDEO_ENCODER_NTSC | - VIDEO_ENCODER_SECAM; /* well, hacky */ - cap->inputs = 2; - cap->outputs = 1; - break; - } - - case ENCODER_SET_NORM: - { - int iarg = *(int *) arg; - - switch (iarg) { - case VIDEO_MODE_NTSC: + if (iarg & V4L2_STD_NTSC) { adv7175_write_block(client, init_ntsc, sizeof(init_ntsc)); if (encoder->input == 0) adv7175_write(client, 0x0d, 0x4f); // Enable genlock adv7175_write(client, 0x07, TR0MODE | TR0RST); adv7175_write(client, 0x07, TR0MODE); - break; - - case VIDEO_MODE_PAL: + } else if (iarg & V4L2_STD_PAL) { adv7175_write_block(client, init_pal, sizeof(init_pal)); if (encoder->input == 0) adv7175_write(client, 0x0d, 0x4f); // Enable genlock adv7175_write(client, 0x07, TR0MODE | TR0RST); adv7175_write(client, 0x07, TR0MODE); - break; - - case VIDEO_MODE_SECAM: // WARNING! ADV7176 does not support SECAM. + } else if (iarg & V4L2_STD_SECAM) { /* This is an attempt to convert * SECAM->PAL (typically it does not work * due to genlock: when decoder is in SECAM @@ -245,33 +226,32 @@ static int adv7175_command(struct i2c_client *client, unsigned cmd, void *arg) adv7175_write(client, 0x0d, 0x49); // Disable genlock adv7175_write(client, 0x07, TR0MODE | TR0RST); adv7175_write(client, 0x07, TR0MODE); - break; - default: - v4l_dbg(1, debug, client, "illegal norm: %d\n", iarg); + } else { + v4l_dbg(1, debug, client, "illegal norm: %llx\n", iarg); return -EINVAL; } - v4l_dbg(1, debug, client, "switched to %s\n", norms[iarg]); + v4l_dbg(1, debug, client, "switched to %llx\n", iarg); encoder->norm = iarg; break; } - case ENCODER_SET_INPUT: + case VIDIOC_INT_S_VIDEO_ROUTING: { - int iarg = *(int *) arg; + struct v4l2_routing *route = arg; /* RJ: *iarg = 0: input is from SAA7110 *iarg = 1: input is from ZR36060 *iarg = 2: color bar */ - switch (iarg) { + switch (route->input) { case 0: adv7175_write(client, 0x01, 0x00); - if (encoder->norm == VIDEO_MODE_NTSC) + if (encoder->norm & V4L2_STD_NTSC) set_subcarrier_freq(client, 1); adv7175_write(client, 0x0c, TR1CAPT); /* TR1 */ - if (encoder->norm == VIDEO_MODE_SECAM) + if (encoder->norm & V4L2_STD_SECAM) adv7175_write(client, 0x0d, 0x49); // Disable genlock else adv7175_write(client, 0x0d, 0x4f); // Enable genlock @@ -283,7 +263,7 @@ static int adv7175_command(struct i2c_client *client, unsigned cmd, void *arg) case 1: adv7175_write(client, 0x01, 0x00); - if (encoder->norm == VIDEO_MODE_NTSC) + if (encoder->norm & V4L2_STD_NTSC) set_subcarrier_freq(client, 0); adv7175_write(client, 0x0c, TR1PLAY); /* TR1 */ @@ -296,7 +276,7 @@ static int adv7175_command(struct i2c_client *client, unsigned cmd, void *arg) case 2: adv7175_write(client, 0x01, 0x80); - if (encoder->norm == VIDEO_MODE_NTSC) + if (encoder->norm & V4L2_STD_NTSC) set_subcarrier_freq(client, 0); adv7175_write(client, 0x0d, 0x49); @@ -306,29 +286,11 @@ static int adv7175_command(struct i2c_client *client, unsigned cmd, void *arg) break; default: - v4l_dbg(1, debug, client, "illegal input: %d\n", iarg); + v4l_dbg(1, debug, client, "illegal input: %d\n", route->input); return -EINVAL; } - v4l_dbg(1, debug, client, "switched to %s\n", inputs[iarg]); - encoder->input = iarg; - break; - } - - case ENCODER_SET_OUTPUT: - { - int *iarg = arg; - - /* not much choice of outputs */ - if (*iarg != 0) - return -EINVAL; - break; - } - - case ENCODER_ENABLE_OUTPUT: - { - int *iarg = arg; - - encoder->enable = !!*iarg; + v4l_dbg(1, debug, client, "switched to %s\n", inputs[route->input]); + encoder->input = route->input; break; } @@ -369,9 +331,8 @@ static int adv7175_probe(struct i2c_client *client, encoder = kzalloc(sizeof(struct adv7175), GFP_KERNEL); if (encoder == NULL) return -ENOMEM; - encoder->norm = VIDEO_MODE_PAL; + encoder->norm = V4L2_STD_NTSC; encoder->input = 0; - encoder->enable = 1; i2c_set_clientdata(client, encoder); i = adv7175_write_block(client, init_common, sizeof(init_common)); diff --git a/drivers/media/video/bt819.c b/drivers/media/video/bt819.c index a07b7b88e5b8..b8109a1b50ce 100644 --- a/drivers/media/video/bt819.c +++ b/drivers/media/video/bt819.c @@ -54,7 +54,7 @@ struct bt819 { unsigned char reg[32]; int initialized; - int norm; + v4l2_std_id norm; int input; int enable; int bright; @@ -178,7 +178,7 @@ static int bt819_init(struct i2c_client *client) 0x1a, 0x80, /* 0x1a ADC Interface */ }; - struct timing *timing = &timing_data[decoder->norm]; + struct timing *timing = &timing_data[(decoder->norm & V4L2_STD_525_60) ? 1 : 0]; init[0x03 * 2 - 1] = (((timing->vdelay >> 8) & 0x03) << 6) | @@ -192,7 +192,7 @@ static int bt819_init(struct i2c_client *client) init[0x08 * 2 - 1] = timing->hscale >> 8; init[0x09 * 2 - 1] = timing->hscale & 0xff; /* 0x15 in array is address 0x19 */ - init[0x15 * 2 - 1] = (decoder->norm == 0) ? 115 : 93; /* Chroma burst delay */ + init[0x15 * 2 - 1] = (decoder->norm & V4L2_STD_625_50) ? 115 : 93; /* Chroma burst delay */ /* reset */ bt819_write(client, 0x1f, 0x00); mdelay(1); @@ -215,121 +215,93 @@ static int bt819_command(struct i2c_client *client, unsigned cmd, void *arg) } switch (cmd) { - case 0: + case VIDIOC_INT_INIT: /* This is just for testing!!! */ bt819_init(client); break; - case DECODER_GET_CAPABILITIES: - { - struct video_decoder_capability *cap = arg; - - cap->flags = VIDEO_DECODER_PAL | - VIDEO_DECODER_NTSC | - VIDEO_DECODER_AUTO | - VIDEO_DECODER_CCIR; - cap->inputs = 8; - cap->outputs = 1; - break; - } - - case DECODER_GET_STATUS: - { + case VIDIOC_QUERYSTD: + case VIDIOC_INT_G_INPUT_STATUS: { int *iarg = arg; + v4l2_std_id *istd = arg; int status; - int res; + int res = V4L2_IN_ST_NO_SIGNAL; + v4l2_std_id std; status = bt819_read(client, 0x00); - res = 0; if ((status & 0x80)) - res |= DECODER_STATUS_GOOD; + res = 0; - switch (decoder->norm) { - case VIDEO_MODE_NTSC: - res |= DECODER_STATUS_NTSC; - break; - case VIDEO_MODE_PAL: - res |= DECODER_STATUS_PAL; - break; - default: - case VIDEO_MODE_AUTO: - if ((status & 0x10)) - res |= DECODER_STATUS_PAL; - else - res |= DECODER_STATUS_NTSC; - break; - } - res |= DECODER_STATUS_COLOR; - *iarg = res; + if ((status & 0x10)) + std = V4L2_STD_PAL; + else + std = V4L2_STD_NTSC; + if (cmd == VIDIOC_QUERYSTD) + *istd = std; + else + *iarg = res; v4l_dbg(1, debug, client, "get status %x\n", *iarg); break; } - case DECODER_SET_NORM: + case VIDIOC_S_STD: { - int *iarg = arg; + v4l2_std_id *iarg = arg; struct timing *timing = NULL; - v4l_dbg(1, debug, client, "set norm %x\n", *iarg); + v4l_dbg(1, debug, client, "set norm %llx\n", *iarg); - switch (*iarg) { - case VIDEO_MODE_NTSC: + if (*iarg & V4L2_STD_NTSC) { bt819_setbit(client, 0x01, 0, 1); bt819_setbit(client, 0x01, 1, 0); bt819_setbit(client, 0x01, 5, 0); bt819_write(client, 0x18, 0x68); bt819_write(client, 0x19, 0x5d); /* bt819_setbit(client, 0x1a, 5, 1); */ - timing = &timing_data[VIDEO_MODE_NTSC]; - break; - case VIDEO_MODE_PAL: + timing = &timing_data[1]; + } else if (*iarg & V4L2_STD_PAL) { bt819_setbit(client, 0x01, 0, 1); bt819_setbit(client, 0x01, 1, 1); bt819_setbit(client, 0x01, 5, 1); bt819_write(client, 0x18, 0x7f); bt819_write(client, 0x19, 0x72); /* bt819_setbit(client, 0x1a, 5, 0); */ - timing = &timing_data[VIDEO_MODE_PAL]; - break; - case VIDEO_MODE_AUTO: - bt819_setbit(client, 0x01, 0, 0); - bt819_setbit(client, 0x01, 1, 0); - break; - default: - v4l_dbg(1, debug, client, "unsupported norm %x\n", *iarg); + timing = &timing_data[0]; + } else { + v4l_dbg(1, debug, client, "unsupported norm %llx\n", *iarg); return -EINVAL; } - - if (timing) { - bt819_write(client, 0x03, - (((timing->vdelay >> 8) & 0x03) << 6) | - (((timing->vactive >> 8) & 0x03) << 4) | - (((timing->hdelay >> 8) & 0x03) << 2) | - ((timing->hactive >> 8) & 0x03) ); - bt819_write(client, 0x04, timing->vdelay & 0xff); - bt819_write(client, 0x05, timing->vactive & 0xff); - bt819_write(client, 0x06, timing->hdelay & 0xff); - bt819_write(client, 0x07, timing->hactive & 0xff); - bt819_write(client, 0x08, (timing->hscale >> 8) & 0xff); - bt819_write(client, 0x09, timing->hscale & 0xff); - } - +/* case VIDEO_MODE_AUTO: + bt819_setbit(client, 0x01, 0, 0); + bt819_setbit(client, 0x01, 1, 0);*/ + + bt819_write(client, 0x03, + (((timing->vdelay >> 8) & 0x03) << 6) | + (((timing->vactive >> 8) & 0x03) << 4) | + (((timing->hdelay >> 8) & 0x03) << 2) | + ((timing->hactive >> 8) & 0x03)); + bt819_write(client, 0x04, timing->vdelay & 0xff); + bt819_write(client, 0x05, timing->vactive & 0xff); + bt819_write(client, 0x06, timing->hdelay & 0xff); + bt819_write(client, 0x07, timing->hactive & 0xff); + bt819_write(client, 0x08, (timing->hscale >> 8) & 0xff); + bt819_write(client, 0x09, timing->hscale & 0xff); decoder->norm = *iarg; break; } - case DECODER_SET_INPUT: + case VIDIOC_INT_S_VIDEO_ROUTING: { - int *iarg = arg; + struct v4l2_routing *route = arg; - v4l_dbg(1, debug, client, "set input %x\n", *iarg); + v4l_dbg(1, debug, client, "set input %x\n", route->input); - if (*iarg < 0 || *iarg > 7) + if (route->input < 0 || route->input > 7) return -EINVAL; - if (decoder->input != *iarg) { - decoder->input = *iarg; + if (decoder->input != route->input) { + decoder->input = route->input; /* select mode */ if (decoder->input == 0) { bt819_setbit(client, 0x0b, 6, 0); @@ -342,75 +314,116 @@ static int bt819_command(struct i2c_client *client, unsigned cmd, void *arg) break; } - case DECODER_SET_OUTPUT: + case VIDIOC_STREAMON: + case VIDIOC_STREAMOFF: { - int *iarg = arg; + int enable = cmd == VIDIOC_STREAMON; - v4l_dbg(1, debug, client, "set output %x\n", *iarg); + v4l_dbg(1, debug, client, "enable output %x\n", enable); - /* not much choice of outputs */ - if (*iarg != 0) - return -EINVAL; + if (decoder->enable != enable) { + decoder->enable = enable; + bt819_setbit(client, 0x16, 7, !enable); + } break; } - case DECODER_ENABLE_OUTPUT: + case VIDIOC_QUERYCTRL: { - int *iarg = arg; - int enable = (*iarg != 0); + struct v4l2_queryctrl *qc = arg; - v4l_dbg(1, debug, client, "enable output %x\n", *iarg); + switch (qc->id) { + case V4L2_CID_BRIGHTNESS: + v4l2_ctrl_query_fill(qc, -128, 127, 1, 0); + break; - if (decoder->enable != enable) { - decoder->enable = enable; - bt819_setbit(client, 0x16, 7, !enable); + case V4L2_CID_CONTRAST: + v4l2_ctrl_query_fill(qc, 0, 511, 1, 256); + break; + + case V4L2_CID_SATURATION: + v4l2_ctrl_query_fill(qc, 0, 511, 1, 256); + break; + + case V4L2_CID_HUE: + v4l2_ctrl_query_fill(qc, -128, 127, 1, 0); + break; + + default: + return -EINVAL; } break; } - case DECODER_SET_PICTURE: + case VIDIOC_S_CTRL: { - struct video_picture *pic = arg; + struct v4l2_control *ctrl = arg; - v4l_dbg(1, debug, client, - "set picture brightness %d contrast %d colour %d\n", - pic->brightness, pic->contrast, pic->colour); + switch (ctrl->id) { + case V4L2_CID_BRIGHTNESS: + if (decoder->bright != ctrl->value) { + decoder->bright = ctrl->value; + bt819_write(client, 0x0a, decoder->bright); + } + break; + case V4L2_CID_CONTRAST: + if (decoder->contrast != ctrl->value) { + decoder->contrast = ctrl->value; + bt819_write(client, 0x0c, + decoder->contrast & 0xff); + bt819_setbit(client, 0x0b, 2, + ((decoder->contrast >> 8) & 0x01)); + } + break; - if (decoder->bright != pic->brightness) { - /* We want -128 to 127 we get 0-65535 */ - decoder->bright = pic->brightness; - bt819_write(client, 0x0a, - (decoder->bright >> 8) - 128); - } + case V4L2_CID_SATURATION: + if (decoder->sat != ctrl->value) { + decoder->sat = ctrl->value; + bt819_write(client, 0x0d, + (decoder->sat >> 7) & 0xff); + bt819_setbit(client, 0x0b, 1, + ((decoder->sat >> 15) & 0x01)); + + /* Ratio between U gain and V gain must stay the same as + the ratio between the default U and V gain values. */ + temp = (decoder->sat * 180) / 254; + bt819_write(client, 0x0e, (temp >> 7) & 0xff); + bt819_setbit(client, 0x0b, 0, (temp >> 15) & 0x01); + } + break; - if (decoder->contrast != pic->contrast) { - /* We want 0 to 511 we get 0-65535 */ - decoder->contrast = pic->contrast; - bt819_write(client, 0x0c, - (decoder->contrast >> 7) & 0xff); - bt819_setbit(client, 0x0b, 2, - ((decoder->contrast >> 15) & 0x01)); + case V4L2_CID_HUE: + if (decoder->hue != ctrl->value) { + decoder->hue = ctrl->value; + bt819_write(client, 0x0f, decoder->hue); + } + break; + default: + return -EINVAL; } + break; + } - if (decoder->sat != pic->colour) { - /* We want 0 to 511 we get 0-65535 */ - decoder->sat = pic->colour; - bt819_write(client, 0x0d, - (decoder->sat >> 7) & 0xff); - bt819_setbit(client, 0x0b, 1, - ((decoder->sat >> 15) & 0x01)); - - temp = (decoder->sat * 201) / 237; - bt819_write(client, 0x0e, (temp >> 7) & 0xff); - bt819_setbit(client, 0x0b, 0, (temp >> 15) & 0x01); - } + case VIDIOC_G_CTRL: + { + struct v4l2_control *ctrl = arg; - if (decoder->hue != pic->hue) { - /* We want -128 to 127 we get 0-65535 */ - decoder->hue = pic->hue; - bt819_write(client, 0x0f, - 128 - (decoder->hue >> 8)); + switch (ctrl->id) { + case V4L2_CID_BRIGHTNESS: + ctrl->value = decoder->bright; + break; + case V4L2_CID_CONTRAST: + ctrl->value = decoder->contrast; + break; + case V4L2_CID_SATURATION: + ctrl->value = decoder->sat; + break; + case V4L2_CID_HUE: + ctrl->value = decoder->hue; + break; + default: + return -EINVAL; } break; } @@ -462,13 +475,13 @@ static int bt819_probe(struct i2c_client *client, decoder = kzalloc(sizeof(struct bt819), GFP_KERNEL); if (decoder == NULL) return -ENOMEM; - decoder->norm = VIDEO_MODE_NTSC; + decoder->norm = V4L2_STD_NTSC; decoder->input = 0; decoder->enable = 1; - decoder->bright = 32768; - decoder->contrast = 32768; - decoder->hue = 32768; - decoder->sat = 32768; + decoder->bright = 0; + decoder->contrast = 0xd8; /* 100% of original signal */ + decoder->hue = 0; + decoder->sat = 0xfe; /* 100% of original signal */ decoder->initialized = 0; i2c_set_clientdata(client, decoder); diff --git a/drivers/media/video/bt856.c b/drivers/media/video/bt856.c index 4213867507f8..3e042c5ddaa7 100644 --- a/drivers/media/video/bt856.c +++ b/drivers/media/video/bt856.c @@ -55,8 +55,7 @@ MODULE_PARM_DESC(debug, "Debug level (0-1)"); struct bt856 { unsigned char reg[BT856_NR_REG]; - int norm; - int enable; + v4l2_std_id norm; }; /* ----------------------------------------------------------------------- */ @@ -96,7 +95,7 @@ static int bt856_command(struct i2c_client *client, unsigned cmd, void *arg) struct bt856 *encoder = i2c_get_clientdata(client); switch (cmd) { - case 0: + case VIDIOC_INT_INIT: /* This is just for testing!!! */ v4l_dbg(1, debug, client, "init\n"); bt856_write(client, 0xdc, 0x18); @@ -107,15 +106,10 @@ static int bt856_command(struct i2c_client *client, unsigned cmd, void *arg) //bt856_setbit(client, 0xdc, 6, 0); bt856_setbit(client, 0xdc, 4, 1); - switch (encoder->norm) { - case VIDEO_MODE_NTSC: + if (encoder->norm & V4L2_STD_NTSC) bt856_setbit(client, 0xdc, 2, 0); - break; - - case VIDEO_MODE_PAL: + else bt856_setbit(client, 0xdc, 2, 1); - break; - } bt856_setbit(client, 0xdc, 1, 1); bt856_setbit(client, 0xde, 4, 0); @@ -124,38 +118,19 @@ static int bt856_command(struct i2c_client *client, unsigned cmd, void *arg) bt856_dump(client); break; - case ENCODER_GET_CAPABILITIES: + case VIDIOC_INT_S_STD_OUTPUT: { - struct video_encoder_capability *cap = arg; - - v4l_dbg(1, debug, client, "get capabilities\n"); + v4l2_std_id *iarg = arg; - cap->flags = VIDEO_ENCODER_PAL | - VIDEO_ENCODER_NTSC | - VIDEO_ENCODER_CCIR; - cap->inputs = 2; - cap->outputs = 1; - break; - } - - case ENCODER_SET_NORM: - { - int *iarg = arg; + v4l_dbg(1, debug, client, "set norm %llx\n", *iarg); - v4l_dbg(1, debug, client, "set norm %d\n", *iarg); - - switch (*iarg) { - case VIDEO_MODE_NTSC: + if (*iarg & V4L2_STD_NTSC) { bt856_setbit(client, 0xdc, 2, 0); - break; - - case VIDEO_MODE_PAL: + } else if (*iarg & V4L2_STD_PAL) { bt856_setbit(client, 0xdc, 2, 1); bt856_setbit(client, 0xda, 0, 0); //bt856_setbit(client, 0xda, 0, 1); - break; - - default: + } else { return -EINVAL; } encoder->norm = *iarg; @@ -164,16 +139,16 @@ static int bt856_command(struct i2c_client *client, unsigned cmd, void *arg) break; } - case ENCODER_SET_INPUT: + case VIDIOC_INT_S_VIDEO_ROUTING: { - int *iarg = arg; + struct v4l2_routing *route = arg; - v4l_dbg(1, debug, client, "set input %d\n", *iarg); + v4l_dbg(1, debug, client, "set input %d\n", route->input); /* We only have video bus. - * iarg = 0: input is from bt819 - * iarg = 1: input is from ZR36060 */ - switch (*iarg) { + * route->input= 0: input is from bt819 + * route->input= 1: input is from ZR36060 */ + switch (route->input) { case 0: bt856_setbit(client, 0xde, 4, 0); bt856_setbit(client, 0xde, 3, 1); @@ -199,28 +174,6 @@ static int bt856_command(struct i2c_client *client, unsigned cmd, void *arg) break; } - case ENCODER_SET_OUTPUT: - { - int *iarg = arg; - - v4l_dbg(1, debug, client, "set output %d\n", *iarg); - - /* not much choice of outputs */ - if (*iarg != 0) - return -EINVAL; - break; - } - - case ENCODER_ENABLE_OUTPUT: - { - int *iarg = arg; - - encoder->enable = !!*iarg; - - v4l_dbg(1, debug, client, "enable output %d\n", encoder->enable); - break; - } - default: return -EINVAL; } @@ -249,8 +202,7 @@ static int bt856_probe(struct i2c_client *client, encoder = kzalloc(sizeof(struct bt856), GFP_KERNEL); if (encoder == NULL) return -ENOMEM; - encoder->norm = VIDEO_MODE_NTSC; - encoder->enable = 1; + encoder->norm = V4L2_STD_NTSC; i2c_set_clientdata(client, encoder); bt856_write(client, 0xdc, 0x18); @@ -261,16 +213,10 @@ static int bt856_probe(struct i2c_client *client, //bt856_setbit(client, 0xdc, 6, 0); bt856_setbit(client, 0xdc, 4, 1); - switch (encoder->norm) { - - case VIDEO_MODE_NTSC: + if (encoder->norm & V4L2_STD_NTSC) bt856_setbit(client, 0xdc, 2, 0); - break; - - case VIDEO_MODE_PAL: + else bt856_setbit(client, 0xdc, 2, 1); - break; - } bt856_setbit(client, 0xdc, 1, 1); bt856_setbit(client, 0xde, 4, 0); diff --git a/drivers/media/video/bt866.c b/drivers/media/video/bt866.c index 596f9e2376be..1df24c8776f3 100644 --- a/drivers/media/video/bt866.c +++ b/drivers/media/video/bt866.c @@ -52,8 +52,7 @@ MODULE_PARM_DESC(debug, "Debug level (0-1)"); struct bt866 { u8 reg[256]; - int norm; - int enable; + v4l2_std_id norm; int bright; int contrast; int hue; @@ -94,44 +93,21 @@ static int bt866_command(struct i2c_client *client, unsigned cmd, void *arg) struct bt866 *encoder = i2c_get_clientdata(client); switch (cmd) { - case ENCODER_GET_CAPABILITIES: + case VIDIOC_INT_S_STD_OUTPUT: { - struct video_encoder_capability *cap = arg; + v4l2_std_id *iarg = arg; - v4l_dbg(1, debug, client, "get capabilities\n"); + v4l_dbg(1, debug, client, "set norm %llx\n", *iarg); - cap->flags - = VIDEO_ENCODER_PAL - | VIDEO_ENCODER_NTSC - | VIDEO_ENCODER_CCIR; - cap->inputs = 2; - cap->outputs = 1; - break; - } - - case ENCODER_SET_NORM: - { - int *iarg = arg; - - v4l_dbg(1, debug, client, "set norm %d\n", *iarg); - - switch (*iarg) { - case VIDEO_MODE_NTSC: - break; - - case VIDEO_MODE_PAL: - break; - - default: + if (!(*iarg & (V4L2_STD_NTSC | V4L2_STD_PAL))) return -EINVAL; - } encoder->norm = *iarg; break; } - case ENCODER_SET_INPUT: + case VIDIOC_INT_S_VIDEO_ROUTING: { - int *iarg = arg; + struct v4l2_routing *route = arg; static const __u8 init[] = { 0xc8, 0xcc, /* CRSCALE */ 0xca, 0x91, /* CBSCALE */ @@ -167,7 +143,7 @@ static int bt866_command(struct i2c_client *client, unsigned cmd, void *arg) val = encoder->reg[0xdc]; - if (*iarg == 0) + if (route->input == 0) val |= 0x40; /* CBSWAP */ else val &= ~0x40; /* !CBSWAP */ @@ -175,15 +151,15 @@ static int bt866_command(struct i2c_client *client, unsigned cmd, void *arg) bt866_write(client, 0xdc, val); val = encoder->reg[0xcc]; - if (*iarg == 2) + if (route->input == 2) val |= 0x01; /* OSDBAR */ else val &= ~0x01; /* !OSDBAR */ bt866_write(client, 0xcc, val); - v4l_dbg(1, debug, client, "set input %d\n", *iarg); + v4l_dbg(1, debug, client, "set input %d\n", route->input); - switch (*iarg) { + switch (route->input) { case 0: break; case 1: @@ -194,27 +170,6 @@ static int bt866_command(struct i2c_client *client, unsigned cmd, void *arg) break; } - case ENCODER_SET_OUTPUT: - { - int *iarg = arg; - - v4l_dbg(1, debug, client, "set output %d\n", *iarg); - - /* not much choice of outputs */ - if (*iarg != 0) - return -EINVAL; - break; - } - - case ENCODER_ENABLE_OUTPUT: - { - int *iarg = arg; - encoder->enable = !!*iarg; - - v4l_dbg(1, debug, client, "enable output %d\n", encoder->enable); - break; - } - case 4711: { int *iarg = arg; diff --git a/drivers/media/video/ks0127.c b/drivers/media/video/ks0127.c index bae2d2beb709..c97d55a43c07 100644 --- a/drivers/media/video/ks0127.c +++ b/drivers/media/video/ks0127.c @@ -201,7 +201,7 @@ struct ks0127 { int format_height; int cap_width; int cap_height; - int norm; + v4l2_std_id norm; int ks_type; u8 regs[256]; }; @@ -408,20 +408,22 @@ static void ks0127_reset(struct i2c_client *c) static int ks0127_command(struct i2c_client *c, unsigned cmd, void *arg) { struct ks0127 *ks = i2c_get_clientdata(c); + struct v4l2_routing *route = arg; int *iarg = (int *)arg; + v4l2_std_id *istd = arg; int status; if (!ks) return -ENODEV; switch (cmd) { - case DECODER_INIT: - v4l_dbg(1, debug, c, "DECODER_INIT\n"); + case VIDIOC_INT_INIT: + v4l_dbg(1, debug, c, "VIDIOC_INT_INIT\n"); ks0127_reset(c); break; - case DECODER_SET_INPUT: - switch(*iarg) { + case VIDIOC_INT_S_VIDEO_ROUTING: + switch (route->input) { case KS_INPUT_COMPOSITE_1: case KS_INPUT_COMPOSITE_2: case KS_INPUT_COMPOSITE_3: @@ -429,7 +431,7 @@ static int ks0127_command(struct i2c_client *c, unsigned cmd, void *arg) case KS_INPUT_COMPOSITE_5: case KS_INPUT_COMPOSITE_6: v4l_dbg(1, debug, c, - "DECODER_SET_INPUT %d: Composite\n", *iarg); + "VIDIOC_S_INPUT %d: Composite\n", *iarg); /* autodetect 50/60 Hz */ ks0127_and_or(c, KS_CMDA, 0xfc, 0x00); /* VSE=0 */ @@ -463,7 +465,7 @@ static int ks0127_command(struct i2c_client *c, unsigned cmd, void *arg) case KS_INPUT_SVIDEO_2: case KS_INPUT_SVIDEO_3: v4l_dbg(1, debug, c, - "DECODER_SET_INPUT %d: S-Video\n", *iarg); + "VIDIOC_S_INPUT %d: S-Video\n", *iarg); /* autodetect 50/60 Hz */ ks0127_and_or(c, KS_CMDA, 0xfc, 0x00); /* VSE=0 */ @@ -495,9 +497,8 @@ static int ks0127_command(struct i2c_client *c, unsigned cmd, void *arg) case KS_INPUT_YUV656: v4l_dbg(1, debug, c, - "DECODER_SET_INPUT 15: YUV656\n"); - if (ks->norm == VIDEO_MODE_NTSC || - ks->norm == KS_STD_PAL_M) + "VIDIOC_S_INPUT 15: YUV656\n"); + if (ks->norm & V4L2_STD_525_60) /* force 60 Hz */ ks0127_and_or(c, KS_CMDA, 0xfc, 0x03); else @@ -541,7 +542,7 @@ static int ks0127_command(struct i2c_client *c, unsigned cmd, void *arg) default: v4l_dbg(1, debug, c, - "DECODER_SET_INPUT: Unknown input %d\n", *iarg); + "VIDIOC_INT_S_VIDEO_ROUTING: Unknown input %d\n", route->input); break; } @@ -550,77 +551,37 @@ static int ks0127_command(struct i2c_client *c, unsigned cmd, void *arg) ks0127_write(c, KS_DEMOD, reg_defaults[KS_DEMOD]); break; - case DECODER_SET_OUTPUT: - switch(*iarg) { - case KS_OUTPUT_YUV656E: - v4l_dbg(1, debug, c, - "DECODER_SET_OUTPUT: OUTPUT_YUV656E (Missing)\n"); - return -EINVAL; - - case KS_OUTPUT_EXV: - v4l_dbg(1, debug, c, - "DECODER_SET_OUTPUT: OUTPUT_EXV\n"); - ks0127_and_or(c, KS_OFMTA, 0xf0, 0x09); - break; - } - break; - - case DECODER_SET_NORM: /* sam This block mixes old and new norm names... */ + case VIDIOC_S_STD: /* sam This block mixes old and new norm names... */ /* Set to automatic SECAM/Fsc mode */ ks0127_and_or(c, KS_DEMOD, 0xf0, 0x00); - ks->norm = *iarg; - switch (*iarg) { - /* this is untested !! */ - /* It just detects PAL_N/NTSC_M (no special frequencies) */ - /* And you have to set the standard a second time afterwards */ - case VIDEO_MODE_AUTO: - v4l_dbg(1, debug, c, - "DECODER_SET_NORM: AUTO\n"); + ks->norm = *istd; - /* The chip determines the format */ - /* based on the current field rate */ - ks0127_and_or(c, KS_CMDA, 0xfc, 0x00); - ks0127_and_or(c, KS_CHROMA, 0x9f, 0x20); - /* This is wrong for PAL ! As I said, */ - /* you need to set the standard once again !! */ - ks->format_height = 240; - ks->format_width = 704; - break; - - case VIDEO_MODE_NTSC: + if (*istd & V4L2_STD_NTSC) { v4l_dbg(1, debug, c, - "DECODER_SET_NORM: NTSC_M\n"); + "VIDIOC_S_STD: NTSC_M\n"); ks0127_and_or(c, KS_CHROMA, 0x9f, 0x20); ks->format_height = 240; ks->format_width = 704; - break; - - case KS_STD_NTSC_N: + } else if (*istd & V4L2_STD_PAL_N) { v4l_dbg(1, debug, c, "KS0127_SET_NORM: NTSC_N (fixme)\n"); ks0127_and_or(c, KS_CHROMA, 0x9f, 0x40); ks->format_height = 240; ks->format_width = 704; - break; - - case VIDEO_MODE_PAL: + } else if (*istd & V4L2_STD_PAL) { v4l_dbg(1, debug, c, - "DECODER_SET_NORM: PAL_N\n"); + "VIDIOC_S_STD: PAL_N\n"); ks0127_and_or(c, KS_CHROMA, 0x9f, 0x20); ks->format_height = 290; ks->format_width = 704; - break; - - case KS_STD_PAL_M: + } else if (*istd & V4L2_STD_PAL_M) { v4l_dbg(1, debug, c, "KS0127_SET_NORM: PAL_M (fixme)\n"); ks0127_and_or(c, KS_CHROMA, 0x9f, 0x40); ks->format_height = 290; ks->format_width = 704; - break; - - case VIDEO_MODE_SECAM: + } else if (*istd & V4L2_STD_SECAM) { v4l_dbg(1, debug, c, "KS0127_SET_NORM: SECAM\n"); ks->format_height = 290; @@ -632,29 +593,34 @@ static int ks0127_command(struct i2c_client *c, unsigned cmd, void *arg) schedule_timeout_interruptible(HZ/10+1); /* did it autodetect? */ - if (ks0127_read(c, KS_DEMOD) & 0x40) - break; - - /* force to secam mode */ - ks0127_and_or(c, KS_DEMOD, 0xf0, 0x0f); - break; - - default: + if (!(ks0127_read(c, KS_DEMOD) & 0x40)) + /* force to secam mode */ + ks0127_and_or(c, KS_DEMOD, 0xf0, 0x0f); + } else { v4l_dbg(1, debug, c, - "DECODER_SET_NORM: Unknown norm %d\n", *iarg); - break; + "VIDIOC_S_STD: Unknown norm %llx\n", *istd); } break; - case DECODER_SET_PICTURE: + case VIDIOC_QUERYCTRL: + { + return -EINVAL; + } + + case VIDIOC_S_CTRL: v4l_dbg(1, debug, c, - "DECODER_SET_PICTURE: not yet supported\n"); + "VIDIOC_S_CTRL: not yet supported\n"); return -EINVAL; - /* sam todo: KS0127_SET_BRIGHTNESS: Merge into DECODER_SET_PICTURE */ - /* sam todo: KS0127_SET_CONTRAST: Merge into DECODER_SET_PICTURE */ - /* sam todo: KS0127_SET_HUE: Merge into DECODER_SET_PICTURE? */ - /* sam todo: KS0127_SET_SATURATION: Merge into DECODER_SET_PICTURE */ + case VIDIOC_G_CTRL: + v4l_dbg(1, debug, c, + "VIDIOC_G_CTRL: not yet supported\n"); + return -EINVAL; + + /* sam todo: KS0127_SET_BRIGHTNESS: Merge into VIDIOC_S_CTRL */ + /* sam todo: KS0127_SET_CONTRAST: Merge into VIDIOC_S_CTRL */ + /* sam todo: KS0127_SET_HUE: Merge into VIDIOC_S_CTRL? */ + /* sam todo: KS0127_SET_SATURATION: Merge into VIDIOC_S_CTRL */ /* sam todo: KS0127_SET_AGC_MODE: */ /* sam todo: KS0127_SET_AGC: */ /* sam todo: KS0127_SET_CHROMA_MODE: */ @@ -670,22 +636,21 @@ static int ks0127_command(struct i2c_client *c, unsigned cmd, void *arg) /* sam todo: KS0127_SET_UNUSEV: */ /* sam todo: KS0127_SET_VSALIGN_MODE: */ - case DECODER_ENABLE_OUTPUT: + case VIDIOC_STREAMON: + case VIDIOC_STREAMOFF: { - int enable; + int enable = cmd == VIDIOC_STREAMON; - iarg = arg; - enable = (*iarg != 0); if (enable) { v4l_dbg(1, debug, c, - "DECODER_ENABLE_OUTPUT on\n"); + "VIDIOC_STREAMON\n"); /* All output pins on */ ks0127_and_or(c, KS_OFMTA, 0xcf, 0x30); /* Obey the OEN pin */ ks0127_and_or(c, KS_CDEM, 0x7f, 0x00); } else { v4l_dbg(1, debug, c, - "DECODER_ENABLE_OUTPUT off\n"); + "VIDIOC_STREAMOFF\n"); /* Video output pins off */ ks0127_and_or(c, KS_OFMTA, 0xcf, 0x00); /* Ignore the OEN pin */ @@ -699,19 +664,26 @@ static int ks0127_command(struct i2c_client *c, unsigned cmd, void *arg) /* sam todo: KS0127_SET_HEIGHT: */ /* sam todo: KS0127_SET_HSCALE: */ - case DECODER_GET_STATUS: - v4l_dbg(1, debug, c, "DECODER_GET_STATUS\n"); - *iarg = 0; + case VIDIOC_QUERYSTD: + case VIDIOC_INT_G_INPUT_STATUS: { + int stat = V4L2_IN_ST_NO_SIGNAL; + v4l2_std_id std = V4L2_STD_ALL; + v4l_dbg(1, debug, c, "VIDIOC_QUERYSTD/VIDIOC_INT_G_INPUT_STATUS\n"); status = ks0127_read(c, KS_STAT); if (!(status & 0x20)) /* NOVID not set */ - *iarg = (*iarg | DECODER_STATUS_GOOD); - if ((status & 0x01)) /* CLOCK set */ - *iarg = (*iarg | DECODER_STATUS_COLOR); + stat = 0; + if (!(status & 0x01)) /* CLOCK set */ + stat |= V4L2_IN_ST_NO_COLOR; if ((status & 0x08)) /* PALDET set */ - *iarg = (*iarg | DECODER_STATUS_PAL); + std = V4L2_STD_PAL; else - *iarg = (*iarg | DECODER_STATUS_NTSC); + std = V4L2_STD_NTSC; + if (cmd == VIDIOC_QUERYSTD) + *istd = std; + else + *iarg = stat; break; + } /* Catch any unknown command */ default: diff --git a/drivers/media/video/saa7110.c b/drivers/media/video/saa7110.c index 37860698f782..9ef6b2bb1b77 100644 --- a/drivers/media/video/saa7110.c +++ b/drivers/media/video/saa7110.c @@ -54,7 +54,7 @@ MODULE_PARM_DESC(debug, "Debug level (0-1)"); struct saa7110 { u8 reg[SAA7110_NR_REG]; - int norm; + v4l2_std_id norm; int input; int enable; int bright; @@ -176,7 +176,7 @@ static const unsigned char initseq[1 + SAA7110_NR_REG] = { /* 0x30 */ 0x44, 0x71, 0x02, 0x8C, 0x02 }; -static int determine_norm(struct i2c_client *client) +static v4l2_std_id determine_norm(struct i2c_client *client) { DEFINE_WAIT(wait); struct saa7110 *decoder = i2c_get_clientdata(client); @@ -198,11 +198,11 @@ static int determine_norm(struct i2c_client *client) if (status & 0x20) { v4l_dbg(1, debug, client, "status=0x%02x (NTSC/no color)\n", status); //saa7110_write(client,0x2E,0x81); - return VIDEO_MODE_NTSC; + return V4L2_STD_NTSC; } v4l_dbg(1, debug, client, "status=0x%02x (PAL/no color)\n", status); //saa7110_write(client,0x2E,0x9A); - return VIDEO_MODE_PAL; + return V4L2_STD_PAL; } //saa7110_write(client,0x06,0x03); if (status & 0x20) { /* 60Hz */ @@ -211,7 +211,7 @@ static int determine_norm(struct i2c_client *client) saa7110_write(client, 0x0F, 0x50); saa7110_write(client, 0x11, 0x2C); //saa7110_write(client,0x2E,0x81); - return VIDEO_MODE_NTSC; + return V4L2_STD_NTSC; } /* 50Hz -> PAL/SECAM */ @@ -228,10 +228,10 @@ static int determine_norm(struct i2c_client *client) if ((status & 0x03) == 0x01) { v4l_dbg(1, debug, client, "status=0x%02x (SECAM)\n", status); saa7110_write(client, 0x0D, 0x87); - return VIDEO_MODE_SECAM; + return V4L2_STD_SECAM; } v4l_dbg(1, debug, client, "status=0x%02x (PAL)\n", status); - return VIDEO_MODE_PAL; + return V4L2_STD_PAL; } static int @@ -240,112 +240,81 @@ saa7110_command (struct i2c_client *client, void *arg) { struct saa7110 *decoder = i2c_get_clientdata(client); + struct v4l2_routing *route = arg; + v4l2_std_id std; int v; switch (cmd) { - case 0: + case VIDIOC_INT_INIT: //saa7110_write_block(client, initseq, sizeof(initseq)); break; - case DECODER_GET_CAPABILITIES: - { - struct video_decoder_capability *dc = arg; - - dc->flags = - VIDEO_DECODER_PAL | VIDEO_DECODER_NTSC | - VIDEO_DECODER_SECAM | VIDEO_DECODER_AUTO; - dc->inputs = SAA7110_MAX_INPUT; - dc->outputs = SAA7110_MAX_OUTPUT; - break; - } - - case DECODER_GET_STATUS: + case VIDIOC_INT_G_INPUT_STATUS: { + int res = V4L2_IN_ST_NO_SIGNAL; int status; - int res = 0; status = saa7110_read(client); - v4l_dbg(1, debug, client, "status=0x%02x norm=%d\n", + v4l_dbg(1, debug, client, "status=0x%02x norm=%llx\n", status, decoder->norm); if (!(status & 0x40)) - res |= DECODER_STATUS_GOOD; - if (status & 0x03) - res |= DECODER_STATUS_COLOR; + res = 0; + if (!(status & 0x03)) + res |= V4L2_IN_ST_NO_COLOR; - switch (decoder->norm) { - case VIDEO_MODE_NTSC: - res |= DECODER_STATUS_NTSC; - break; - case VIDEO_MODE_PAL: - res |= DECODER_STATUS_PAL; - break; - case VIDEO_MODE_SECAM: - res |= DECODER_STATUS_SECAM; - break; - } *(int *) arg = res; break; } - case DECODER_SET_NORM: - v = *(int *) arg; - if (decoder->norm != v) { - decoder->norm = v; + case VIDIOC_QUERYSTD: + { + *(v4l2_std_id *)arg = determine_norm(client); + break; + } + + case VIDIOC_S_STD: + std = *(v4l2_std_id *) arg; + if (decoder->norm != std) { + decoder->norm = std; //saa7110_write(client, 0x06, 0x03); - switch (v) { - case VIDEO_MODE_NTSC: + if (std & V4L2_STD_NTSC) { saa7110_write(client, 0x0D, 0x86); saa7110_write(client, 0x0F, 0x50); saa7110_write(client, 0x11, 0x2C); //saa7110_write(client, 0x2E, 0x81); v4l_dbg(1, debug, client, "switched to NTSC\n"); - break; - case VIDEO_MODE_PAL: + } else if (std & V4L2_STD_PAL) { saa7110_write(client, 0x0D, 0x86); saa7110_write(client, 0x0F, 0x10); saa7110_write(client, 0x11, 0x59); //saa7110_write(client, 0x2E, 0x9A); v4l_dbg(1, debug, client, "switched to PAL\n"); - break; - case VIDEO_MODE_SECAM: + } else if (std & V4L2_STD_SECAM) { saa7110_write(client, 0x0D, 0x87); saa7110_write(client, 0x0F, 0x10); saa7110_write(client, 0x11, 0x59); //saa7110_write(client, 0x2E, 0x9A); v4l_dbg(1, debug, client, "switched to SECAM\n"); - break; - case VIDEO_MODE_AUTO: - v4l_dbg(1, debug, client, "switched to AUTO\n"); - decoder->norm = determine_norm(client); - *(int *) arg = decoder->norm; - break; - default: - return -EPERM; + } else { + return -EINVAL; } } break; - case DECODER_SET_INPUT: - v = *(int *) arg; - if (v < 0 || v >= SAA7110_MAX_INPUT) { - v4l_dbg(1, debug, client, "input=%d not available\n", v); + case VIDIOC_INT_S_VIDEO_ROUTING: + if (route->input < 0 || route->input >= SAA7110_MAX_INPUT) { + v4l_dbg(1, debug, client, "input=%d not available\n", route->input); return -EINVAL; } - if (decoder->input != v) { - saa7110_selmux(client, v); - v4l_dbg(1, debug, client, "switched to input=%d\n", v); + if (decoder->input != route->input) { + saa7110_selmux(client, route->input); + v4l_dbg(1, debug, client, "switched to input=%d\n", route->input); } break; - case DECODER_SET_OUTPUT: - v = *(int *) arg; - /* not much choice of outputs */ - if (v != 0) - return -EINVAL; - break; - - case DECODER_ENABLE_OUTPUT: - v = *(int *) arg; + case VIDIOC_STREAMON: + case VIDIOC_STREAMOFF: + v = cmd == VIDIOC_STREAMON; if (decoder->enable != v) { decoder->enable = v; saa7110_write(client, 0x0E, v ? 0x18 : 0x80); @@ -353,46 +322,81 @@ saa7110_command (struct i2c_client *client, } break; - case DECODER_SET_PICTURE: + case VIDIOC_QUERYCTRL: { - struct video_picture *pic = arg; - - if (decoder->bright != pic->brightness) { - /* We want 0 to 255 we get 0-65535 */ - decoder->bright = pic->brightness; - saa7110_write(client, 0x19, decoder->bright >> 8); - } - if (decoder->contrast != pic->contrast) { - /* We want 0 to 127 we get 0-65535 */ - decoder->contrast = pic->contrast; - saa7110_write(client, 0x13, - decoder->contrast >> 9); - } - if (decoder->sat != pic->colour) { - /* We want 0 to 127 we get 0-65535 */ - decoder->sat = pic->colour; - saa7110_write(client, 0x12, decoder->sat >> 9); + struct v4l2_queryctrl *qc = arg; + + switch (qc->id) { + case V4L2_CID_BRIGHTNESS: + return v4l2_ctrl_query_fill(qc, 0, 255, 1, 128); + case V4L2_CID_CONTRAST: + case V4L2_CID_SATURATION: + return v4l2_ctrl_query_fill(qc, 0, 127, 1, 64); + case V4L2_CID_HUE: + return v4l2_ctrl_query_fill(qc, -128, 127, 1, 0); + default: + return -EINVAL; } - if (decoder->hue != pic->hue) { - /* We want -128 to 127 we get 0-65535 */ - decoder->hue = pic->hue; - saa7110_write(client, 0x07, - (decoder->hue >> 8) - 128); + break; + } + + case VIDIOC_G_CTRL: + { + struct v4l2_control *ctrl = arg; + + switch (ctrl->id) { + case V4L2_CID_BRIGHTNESS: + ctrl->value = decoder->bright; + break; + case V4L2_CID_CONTRAST: + ctrl->value = decoder->contrast; + break; + case V4L2_CID_SATURATION: + ctrl->value = decoder->sat; + break; + case V4L2_CID_HUE: + ctrl->value = decoder->hue; + break; + default: + return -EINVAL; } break; } - case DECODER_DUMP: - if (!debug) + case VIDIOC_S_CTRL: + { + struct v4l2_control *ctrl = arg; + + switch (ctrl->id) { + case V4L2_CID_BRIGHTNESS: + if (decoder->bright != ctrl->value) { + decoder->bright = ctrl->value; + saa7110_write(client, 0x19, decoder->bright); + } break; - for (v = 0; v < SAA7110_NR_REG; v += 16) { - int j; - v4l_dbg(1, debug, client, "%02x:", v); - for (j = 0; j < 16 && v + j < SAA7110_NR_REG; j++) - printk(KERN_CONT " %02x", decoder->reg[v + j]); - printk(KERN_CONT "\n"); + case V4L2_CID_CONTRAST: + if (decoder->contrast != ctrl->value) { + decoder->contrast = ctrl->value; + saa7110_write(client, 0x13, decoder->contrast); + } + break; + case V4L2_CID_SATURATION: + if (decoder->sat != ctrl->value) { + decoder->sat = ctrl->value; + saa7110_write(client, 0x12, decoder->sat); + } + break; + case V4L2_CID_HUE: + if (decoder->hue != ctrl->value) { + decoder->hue = ctrl->value; + saa7110_write(client, 0x07, decoder->hue); + } + break; + default: + return -EINVAL; } break; + } default: v4l_dbg(1, debug, client, "unknown command %08x\n", cmd); @@ -429,7 +433,7 @@ static int saa7110_probe(struct i2c_client *client, decoder = kzalloc(sizeof(struct saa7110), GFP_KERNEL); if (!decoder) return -ENOMEM; - decoder->norm = VIDEO_MODE_PAL; + decoder->norm = V4L2_STD_PAL; decoder->input = 0; decoder->enable = 1; decoder->bright = 32768; diff --git a/drivers/media/video/saa7111.c b/drivers/media/video/saa7111.c deleted file mode 100644 index a4738a2fb4d3..000000000000 --- a/drivers/media/video/saa7111.c +++ /dev/null @@ -1,492 +0,0 @@ -/* - * saa7111 - Philips SAA7111A video decoder driver version 0.0.3 - * - * Copyright (C) 1998 Dave Perks - * - * Slight changes for video timing and attachment output by - * Wolfgang Scherr - * - * Changes by Ronald Bultje - * - moved over to linux>=2.4.x i2c protocol (1/1/2003) - * - * Changes by Michael Hunold - * - implemented DECODER_SET_GPIO, DECODER_INIT, DECODER_SET_VBI_BYPASS - * - * 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. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -MODULE_DESCRIPTION("Philips SAA7111 video decoder driver"); -MODULE_AUTHOR("Dave Perks"); -MODULE_LICENSE("GPL"); - -static int debug; -module_param(debug, int, 0644); -MODULE_PARM_DESC(debug, "Debug level (0-1)"); - -/* ----------------------------------------------------------------------- */ - -#define SAA7111_NR_REG 0x18 - -struct saa7111 { - unsigned char reg[SAA7111_NR_REG]; - - int norm; - int input; - int enable; -}; - -/* ----------------------------------------------------------------------- */ - -static inline int saa7111_write(struct i2c_client *client, u8 reg, u8 value) -{ - struct saa7111 *decoder = i2c_get_clientdata(client); - - decoder->reg[reg] = value; - return i2c_smbus_write_byte_data(client, reg, value); -} - -static inline void saa7111_write_if_changed(struct i2c_client *client, u8 reg, u8 value) -{ - struct saa7111 *decoder = i2c_get_clientdata(client); - - if (decoder->reg[reg] != value) { - decoder->reg[reg] = value; - i2c_smbus_write_byte_data(client, reg, value); - } -} - -static int saa7111_write_block(struct i2c_client *client, const u8 *data, unsigned int len) -{ - int ret = -1; - u8 reg; - - /* the saa7111 has an autoincrement function, use it if - * the adapter understands raw I2C */ - if (i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { - /* do raw I2C, not smbus compatible */ - struct saa7111 *decoder = i2c_get_clientdata(client); - u8 block_data[32]; - int block_len; - - while (len >= 2) { - block_len = 0; - block_data[block_len++] = reg = data[0]; - do { - block_data[block_len++] = - decoder->reg[reg++] = data[1]; - len -= 2; - data += 2; - } while (len >= 2 && data[0] == reg && block_len < 32); - ret = i2c_master_send(client, block_data, block_len); - if (ret < 0) - break; - } - } else { - /* do some slow I2C emulation kind of thing */ - while (len >= 2) { - reg = *data++; - ret = saa7111_write(client, reg, *data++); - if (ret < 0) - break; - len -= 2; - } - } - - return ret; -} - -static int saa7111_init_decoder(struct i2c_client *client, - struct video_decoder_init *init) -{ - return saa7111_write_block(client, init->data, init->len); -} - -static inline int saa7111_read(struct i2c_client *client, u8 reg) -{ - return i2c_smbus_read_byte_data(client, reg); -} - -/* ----------------------------------------------------------------------- */ - -static const unsigned char saa7111_i2c_init[] = { - 0x00, 0x00, /* 00 - ID byte */ - 0x01, 0x00, /* 01 - reserved */ - - /*front end */ - 0x02, 0xd0, /* 02 - FUSE=3, GUDL=2, MODE=0 */ - 0x03, 0x23, /* 03 - HLNRS=0, VBSL=1, WPOFF=0, - * HOLDG=0, GAFIX=0, GAI1=256, GAI2=256 */ - 0x04, 0x00, /* 04 - GAI1=256 */ - 0x05, 0x00, /* 05 - GAI2=256 */ - - /* decoder */ - 0x06, 0xf3, /* 06 - HSB at 13(50Hz) / 17(60Hz) - * pixels after end of last line */ - /*0x07, 0x13, * 07 - HSS at 113(50Hz) / 117(60Hz) pixels - * after end of last line */ - 0x07, 0xe8, /* 07 - HSS seems to be needed to - * work with NTSC, too */ - 0x08, 0xc8, /* 08 - AUFD=1, FSEL=1, EXFIL=0, - * VTRC=1, HPLL=0, VNOI=0 */ - 0x09, 0x01, /* 09 - BYPS=0, PREF=0, BPSS=0, - * VBLB=0, UPTCV=0, APER=1 */ - 0x0a, 0x80, /* 0a - BRIG=128 */ - 0x0b, 0x47, /* 0b - CONT=1.109 */ - 0x0c, 0x40, /* 0c - SATN=1.0 */ - 0x0d, 0x00, /* 0d - HUE=0 */ - 0x0e, 0x01, /* 0e - CDTO=0, CSTD=0, DCCF=0, - * FCTC=0, CHBW=1 */ - 0x0f, 0x00, /* 0f - reserved */ - 0x10, 0x48, /* 10 - OFTS=1, HDEL=0, VRLN=1, YDEL=0 */ - 0x11, 0x1c, /* 11 - GPSW=0, CM99=0, FECO=0, COMPO=1, - * OEYC=1, OEHV=1, VIPB=0, COLO=0 */ - 0x12, 0x00, /* 12 - output control 2 */ - 0x13, 0x00, /* 13 - output control 3 */ - 0x14, 0x00, /* 14 - reserved */ - 0x15, 0x00, /* 15 - VBI */ - 0x16, 0x00, /* 16 - VBI */ - 0x17, 0x00, /* 17 - VBI */ -}; - -static int saa7111_command(struct i2c_client *client, unsigned cmd, void *arg) -{ - struct saa7111 *decoder = i2c_get_clientdata(client); - - switch (cmd) { - case 0: - break; - case DECODER_INIT: - { - struct video_decoder_init *init = arg; - struct video_decoder_init vdi; - - if (NULL != init) - return saa7111_init_decoder(client, init); - vdi.data = saa7111_i2c_init; - vdi.len = sizeof(saa7111_i2c_init); - return saa7111_init_decoder(client, &vdi); - } - - case DECODER_DUMP: - { - int i; - - for (i = 0; i < SAA7111_NR_REG; i += 16) { - int j; - - v4l_info(client, "%03x", i); - for (j = 0; j < 16 && i + j < SAA7111_NR_REG; ++j) { - printk(KERN_CONT " %02x", - saa7111_read(client, i + j)); - } - printk(KERN_CONT "\n"); - } - break; - } - - case DECODER_GET_CAPABILITIES: - { - struct video_decoder_capability *cap = arg; - - cap->flags = VIDEO_DECODER_PAL | - VIDEO_DECODER_NTSC | - VIDEO_DECODER_SECAM | - VIDEO_DECODER_AUTO | - VIDEO_DECODER_CCIR; - cap->inputs = 8; - cap->outputs = 1; - break; - } - - case DECODER_GET_STATUS: - { - int *iarg = arg; - int status; - int res; - - status = saa7111_read(client, 0x1f); - v4l_dbg(1, debug, client, "status: 0x%02x\n", status); - res = 0; - if ((status & (1 << 6)) == 0) { - res |= DECODER_STATUS_GOOD; - } - switch (decoder->norm) { - case VIDEO_MODE_NTSC: - res |= DECODER_STATUS_NTSC; - break; - case VIDEO_MODE_PAL: - res |= DECODER_STATUS_PAL; - break; - case VIDEO_MODE_SECAM: - res |= DECODER_STATUS_SECAM; - break; - default: - case VIDEO_MODE_AUTO: - if ((status & (1 << 5)) != 0) { - res |= DECODER_STATUS_NTSC; - } else { - res |= DECODER_STATUS_PAL; - } - break; - } - if ((status & (1 << 0)) != 0) { - res |= DECODER_STATUS_COLOR; - } - *iarg = res; - break; - } - - case DECODER_SET_GPIO: - { - int *iarg = arg; - if (0 != *iarg) { - saa7111_write(client, 0x11, - (decoder->reg[0x11] | 0x80)); - } else { - saa7111_write(client, 0x11, - (decoder->reg[0x11] & 0x7f)); - } - break; - } - - case DECODER_SET_VBI_BYPASS: - { - int *iarg = arg; - if (0 != *iarg) { - saa7111_write(client, 0x13, - (decoder->reg[0x13] & 0xf0) | 0x0a); - } else { - saa7111_write(client, 0x13, - (decoder->reg[0x13] & 0xf0)); - } - break; - } - - case DECODER_SET_NORM: - { - int *iarg = arg; - - switch (*iarg) { - - case VIDEO_MODE_NTSC: - saa7111_write(client, 0x08, - (decoder->reg[0x08] & 0x3f) | 0x40); - saa7111_write(client, 0x0e, - (decoder->reg[0x0e] & 0x8f)); - break; - - case VIDEO_MODE_PAL: - saa7111_write(client, 0x08, - (decoder->reg[0x08] & 0x3f) | 0x00); - saa7111_write(client, 0x0e, - (decoder->reg[0x0e] & 0x8f)); - break; - - case VIDEO_MODE_SECAM: - saa7111_write(client, 0x08, - (decoder->reg[0x08] & 0x3f) | 0x00); - saa7111_write(client, 0x0e, - (decoder->reg[0x0e] & 0x8f) | 0x50); - break; - - case VIDEO_MODE_AUTO: - saa7111_write(client, 0x08, - (decoder->reg[0x08] & 0x3f) | 0x80); - saa7111_write(client, 0x0e, - (decoder->reg[0x0e] & 0x8f)); - break; - - default: - return -EINVAL; - - } - decoder->norm = *iarg; - break; - } - - case DECODER_SET_INPUT: - { - int *iarg = arg; - - if (*iarg < 0 || *iarg > 7) { - return -EINVAL; - } - - if (decoder->input != *iarg) { - decoder->input = *iarg; - /* select mode */ - saa7111_write(client, 0x02, - (decoder-> - reg[0x02] & 0xf8) | decoder->input); - /* bypass chrominance trap for modes 4..7 */ - saa7111_write(client, 0x09, - (decoder-> - reg[0x09] & 0x7f) | ((decoder-> - input > - 3) ? 0x80 : - 0)); - } - break; - } - - case DECODER_SET_OUTPUT: - { - int *iarg = arg; - - /* not much choice of outputs */ - if (*iarg != 0) { - return -EINVAL; - } - break; - } - - case DECODER_ENABLE_OUTPUT: - { - int *iarg = arg; - int enable = (*iarg != 0); - - if (decoder->enable != enable) { - decoder->enable = enable; - - /* RJ: If output should be disabled (for - * playing videos), we also need a open PLL. - * The input is set to 0 (where no input - * source is connected), although this - * is not necessary. - * - * If output should be enabled, we have to - * reverse the above. - */ - - if (decoder->enable) { - saa7111_write(client, 0x02, - (decoder-> - reg[0x02] & 0xf8) | - decoder->input); - saa7111_write(client, 0x08, - (decoder->reg[0x08] & 0xfb)); - saa7111_write(client, 0x11, - (decoder-> - reg[0x11] & 0xf3) | 0x0c); - } else { - saa7111_write(client, 0x02, - (decoder->reg[0x02] & 0xf8)); - saa7111_write(client, 0x08, - (decoder-> - reg[0x08] & 0xfb) | 0x04); - saa7111_write(client, 0x11, - (decoder->reg[0x11] & 0xf3)); - } - } - break; - } - - case DECODER_SET_PICTURE: - { - struct video_picture *pic = arg; - - /* We want 0 to 255 we get 0-65535 */ - saa7111_write_if_changed(client, 0x0a, pic->brightness >> 8); - /* We want 0 to 127 we get 0-65535 */ - saa7111_write(client, 0x0b, pic->contrast >> 9); - /* We want 0 to 127 we get 0-65535 */ - saa7111_write(client, 0x0c, pic->colour >> 9); - /* We want -128 to 127 we get 0-65535 */ - saa7111_write(client, 0x0d, (pic->hue - 32768) >> 8); - break; - } - - default: - return -EINVAL; - } - - return 0; -} - -/* ----------------------------------------------------------------------- */ - -static unsigned short normal_i2c[] = { 0x48 >> 1, I2C_CLIENT_END }; - -I2C_CLIENT_INSMOD; - -static int saa7111_probe(struct i2c_client *client, - const struct i2c_device_id *id) -{ - int i; - struct saa7111 *decoder; - struct video_decoder_init vdi; - - /* Check if the adapter supports the needed features */ - if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) - return -ENODEV; - - v4l_info(client, "chip found @ 0x%x (%s)\n", - client->addr << 1, client->adapter->name); - - decoder = kzalloc(sizeof(struct saa7111), GFP_KERNEL); - if (decoder == NULL) { - kfree(client); - return -ENOMEM; - } - decoder->norm = VIDEO_MODE_NTSC; - decoder->input = 0; - decoder->enable = 1; - i2c_set_clientdata(client, decoder); - - vdi.data = saa7111_i2c_init; - vdi.len = sizeof(saa7111_i2c_init); - i = saa7111_init_decoder(client, &vdi); - if (i < 0) { - v4l_dbg(1, debug, client, "init status %d\n", i); - } else { - v4l_dbg(1, debug, client, "revision %x\n", - saa7111_read(client, 0x00) >> 4); - } - return 0; -} - -static int saa7111_remove(struct i2c_client *client) -{ - kfree(i2c_get_clientdata(client)); - return 0; -} - -/* ----------------------------------------------------------------------- */ - -static const struct i2c_device_id saa7111_id[] = { - { "saa7111_old", 0 }, /* "saa7111" maps to the saa7115 driver */ - { } -}; -MODULE_DEVICE_TABLE(i2c, saa7111_id); - -static struct v4l2_i2c_driver_data v4l2_i2c_data = { - .name = "saa7111", - .driverid = I2C_DRIVERID_SAA7111A, - .command = saa7111_command, - .probe = saa7111_probe, - .remove = saa7111_remove, - .id_table = saa7111_id, -}; diff --git a/drivers/media/video/saa7114.c b/drivers/media/video/saa7114.c deleted file mode 100644 index 7ca709fda5f4..000000000000 --- a/drivers/media/video/saa7114.c +++ /dev/null @@ -1,1068 +0,0 @@ -/* - * saa7114 - Philips SAA7114H video decoder driver version 0.0.1 - * - * Copyright (C) 2002 Maxim Yevtyushkin - * - * Based on saa7111 driver by Dave Perks - * - * Copyright (C) 1998 Dave Perks - * - * Slight changes for video timing and attachment output by - * Wolfgang Scherr - * - * Changes by Ronald Bultje - * - moved over to linux>=2.4.x i2c protocol (1/1/2003) - * - * 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. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -MODULE_DESCRIPTION("Philips SAA7114H video decoder driver"); -MODULE_AUTHOR("Maxim Yevtyushkin"); -MODULE_LICENSE("GPL"); - -static int debug; -module_param(debug, int, 0); -MODULE_PARM_DESC(debug, "Debug level (0-1)"); - -/* ----------------------------------------------------------------------- */ - -struct saa7114 { - unsigned char reg[0xf0 * 2]; - - int norm; - int input; - int enable; - int bright; - int contrast; - int hue; - int sat; - int playback; -}; - -#define I2C_DELAY 10 - - -//#define SAA_7114_NTSC_HSYNC_START (-3) -//#define SAA_7114_NTSC_HSYNC_STOP (-18) - -#define SAA_7114_NTSC_HSYNC_START (-17) -#define SAA_7114_NTSC_HSYNC_STOP (-32) - -//#define SAA_7114_NTSC_HOFFSET (5) -#define SAA_7114_NTSC_HOFFSET (6) -#define SAA_7114_NTSC_VOFFSET (10) -#define SAA_7114_NTSC_WIDTH (720) -#define SAA_7114_NTSC_HEIGHT (250) - -#define SAA_7114_SECAM_HSYNC_START (-17) -#define SAA_7114_SECAM_HSYNC_STOP (-32) - -#define SAA_7114_SECAM_HOFFSET (2) -#define SAA_7114_SECAM_VOFFSET (10) -#define SAA_7114_SECAM_WIDTH (720) -#define SAA_7114_SECAM_HEIGHT (300) - -#define SAA_7114_PAL_HSYNC_START (-17) -#define SAA_7114_PAL_HSYNC_STOP (-32) - -#define SAA_7114_PAL_HOFFSET (2) -#define SAA_7114_PAL_VOFFSET (10) -#define SAA_7114_PAL_WIDTH (720) -#define SAA_7114_PAL_HEIGHT (300) - - - -#define SAA_7114_VERTICAL_CHROMA_OFFSET 0 //0x50504040 -#define SAA_7114_VERTICAL_LUMA_OFFSET 0 - -#define REG_ADDR(x) (((x) << 1) + 1) -#define LOBYTE(x) ((unsigned char)((x) & 0xff)) -#define HIBYTE(x) ((unsigned char)(((x) >> 8) & 0xff)) -#define LOWORD(x) ((unsigned short int)((x) & 0xffff)) -#define HIWORD(x) ((unsigned short int)(((x) >> 16) & 0xffff)) - - -/* ----------------------------------------------------------------------- */ - -static inline int saa7114_write(struct i2c_client *client, u8 reg, u8 value) -{ - return i2c_smbus_write_byte_data(client, reg, value); -} - -static int saa7114_write_block(struct i2c_client *client, const u8 *data, unsigned int len) -{ - int ret = -1; - u8 reg; - - /* the saa7114 has an autoincrement function, use it if - * the adapter understands raw I2C */ - if (i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { - /* do raw I2C, not smbus compatible */ - u8 block_data[32]; - int block_len; - - while (len >= 2) { - block_len = 0; - block_data[block_len++] = reg = data[0]; - do { - block_data[block_len++] = data[1]; - reg++; - len -= 2; - data += 2; - } while (len >= 2 && data[0] == reg && block_len < 32); - ret = i2c_master_send(client, block_data, block_len); - if (ret < 0) - break; - } - } else { - /* do some slow I2C emulation kind of thing */ - while (len >= 2) { - reg = *data++; - ret = saa7114_write(client, reg, *data++); - if (ret < 0) - break; - len -= 2; - } - } - - return ret; -} - -static inline int saa7114_read(struct i2c_client *client, u8 reg) -{ - return i2c_smbus_read_byte_data(client, reg); -} - -/* ----------------------------------------------------------------------- */ - -// initially set NTSC, composite - - -static const unsigned char init[] = { - 0x00, 0x00, /* 00 - ID byte , chip version, - * read only */ - 0x01, 0x08, /* 01 - X,X,X,X, IDEL3 to IDEL0 - - * horizontal increment delay, - * recommended position */ - 0x02, 0x00, /* 02 - FUSE=3, GUDL=2, MODE=0 ; - * input control */ - 0x03, 0x10, /* 03 - HLNRS=0, VBSL=1, WPOFF=0, - * HOLDG=0, GAFIX=0, GAI1=256, GAI2=256 */ - 0x04, 0x90, /* 04 - GAI1=256 */ - 0x05, 0x90, /* 05 - GAI2=256 */ - 0x06, SAA_7114_NTSC_HSYNC_START, /* 06 - HSB: hsync start, - * depends on the video standard */ - 0x07, SAA_7114_NTSC_HSYNC_STOP, /* 07 - HSS: hsync stop, depends - *on the video standard */ - 0x08, 0xb8, /* 08 - AUFD=1, FSEL=1, EXFIL=0, VTRC=1, - * HPLL: free running in playback, locked - * in capture, VNOI=0 */ - 0x09, 0x80, /* 09 - BYPS=0, PREF=0, BPSS=0, VBLB=0, - * UPTCV=0, APER=1; depends from input */ - 0x0a, 0x80, /* 0a - BRIG=128 */ - 0x0b, 0x44, /* 0b - CONT=1.109 */ - 0x0c, 0x40, /* 0c - SATN=1.0 */ - 0x0d, 0x00, /* 0d - HUE=0 */ - 0x0e, 0x84, /* 0e - CDTO, CSTD2 to 0, DCVF, FCTC, - * CCOMB; depends from video standard */ - 0x0f, 0x24, /* 0f - ACGC,CGAIN6 to CGAIN0; depends - * from video standard */ - 0x10, 0x03, /* 10 - OFFU1 to 0, OFFV1 to 0, CHBW, - * LCBW2 to 0 */ - 0x11, 0x59, /* 11 - COLO, RTP1, HEDL1 to 0, RTP0, - * YDEL2 to 0 */ - 0x12, 0xc9, /* 12 - RT signal control RTSE13 to 10 - * and 03 to 00 */ - 0x13, 0x80, /* 13 - RT/X port output control */ - 0x14, 0x00, /* 14 - analog, ADC, compatibility control */ - 0x15, 0x00, /* 15 - VGATE start FID change */ - 0x16, 0xfe, /* 16 - VGATE stop */ - 0x17, 0x00, /* 17 - Misc., VGATE MSBs */ - 0x18, 0x40, /* RAWG */ - 0x19, 0x80, /* RAWO */ - 0x1a, 0x00, - 0x1b, 0x00, - 0x1c, 0x00, - 0x1d, 0x00, - 0x1e, 0x00, - 0x1f, 0x00, /* status byte, read only */ - 0x20, 0x00, /* video decoder reserved part */ - 0x21, 0x00, - 0x22, 0x00, - 0x23, 0x00, - 0x24, 0x00, - 0x25, 0x00, - 0x26, 0x00, - 0x27, 0x00, - 0x28, 0x00, - 0x29, 0x00, - 0x2a, 0x00, - 0x2b, 0x00, - 0x2c, 0x00, - 0x2d, 0x00, - 0x2e, 0x00, - 0x2f, 0x00, - 0x30, 0xbc, /* audio clock generator */ - 0x31, 0xdf, - 0x32, 0x02, - 0x33, 0x00, - 0x34, 0xcd, - 0x35, 0xcc, - 0x36, 0x3a, - 0x37, 0x00, - 0x38, 0x03, - 0x39, 0x10, - 0x3a, 0x00, - 0x3b, 0x00, - 0x3c, 0x00, - 0x3d, 0x00, - 0x3e, 0x00, - 0x3f, 0x00, - 0x40, 0x00, /* VBI data slicer */ - 0x41, 0xff, - 0x42, 0xff, - 0x43, 0xff, - 0x44, 0xff, - 0x45, 0xff, - 0x46, 0xff, - 0x47, 0xff, - 0x48, 0xff, - 0x49, 0xff, - 0x4a, 0xff, - 0x4b, 0xff, - 0x4c, 0xff, - 0x4d, 0xff, - 0x4e, 0xff, - 0x4f, 0xff, - 0x50, 0xff, - 0x51, 0xff, - 0x52, 0xff, - 0x53, 0xff, - 0x54, 0xff, - 0x55, 0xff, - 0x56, 0xff, - 0x57, 0xff, - 0x58, 0x40, // framing code - 0x59, 0x47, // horizontal offset - 0x5a, 0x06, // vertical offset - 0x5b, 0x83, // field offset - 0x5c, 0x00, // reserved - 0x5d, 0x3e, // header and data - 0x5e, 0x00, // sliced data - 0x5f, 0x00, // reserved - 0x60, 0x00, /* video decoder reserved part */ - 0x61, 0x00, - 0x62, 0x00, - 0x63, 0x00, - 0x64, 0x00, - 0x65, 0x00, - 0x66, 0x00, - 0x67, 0x00, - 0x68, 0x00, - 0x69, 0x00, - 0x6a, 0x00, - 0x6b, 0x00, - 0x6c, 0x00, - 0x6d, 0x00, - 0x6e, 0x00, - 0x6f, 0x00, - 0x70, 0x00, /* video decoder reserved part */ - 0x71, 0x00, - 0x72, 0x00, - 0x73, 0x00, - 0x74, 0x00, - 0x75, 0x00, - 0x76, 0x00, - 0x77, 0x00, - 0x78, 0x00, - 0x79, 0x00, - 0x7a, 0x00, - 0x7b, 0x00, - 0x7c, 0x00, - 0x7d, 0x00, - 0x7e, 0x00, - 0x7f, 0x00, - 0x80, 0x00, /* X-port, I-port and scaler */ - 0x81, 0x00, - 0x82, 0x00, - 0x83, 0x00, - 0x84, 0xc5, - 0x85, 0x0d, // hsync and vsync ? - 0x86, 0x40, - 0x87, 0x01, - 0x88, 0x00, - 0x89, 0x00, - 0x8a, 0x00, - 0x8b, 0x00, - 0x8c, 0x00, - 0x8d, 0x00, - 0x8e, 0x00, - 0x8f, 0x00, - 0x90, 0x03, /* Task A definition */ - 0x91, 0x08, - 0x92, 0x00, - 0x93, 0x40, - 0x94, 0x00, // window settings - 0x95, 0x00, - 0x96, 0x00, - 0x97, 0x00, - 0x98, 0x00, - 0x99, 0x00, - 0x9a, 0x00, - 0x9b, 0x00, - 0x9c, 0x00, - 0x9d, 0x00, - 0x9e, 0x00, - 0x9f, 0x00, - 0xa0, 0x01, /* horizontal integer prescaling ratio */ - 0xa1, 0x00, /* horizontal prescaler accumulation - * sequence length */ - 0xa2, 0x00, /* UV FIR filter, Y FIR filter, prescaler - * DC gain */ - 0xa3, 0x00, - 0xa4, 0x80, // luminance brightness - 0xa5, 0x40, // luminance gain - 0xa6, 0x40, // chrominance saturation - 0xa7, 0x00, - 0xa8, 0x00, // horizontal luminance scaling increment - 0xa9, 0x04, - 0xaa, 0x00, // horizontal luminance phase offset - 0xab, 0x00, - 0xac, 0x00, // horizontal chrominance scaling increment - 0xad, 0x02, - 0xae, 0x00, // horizontal chrominance phase offset - 0xaf, 0x00, - 0xb0, 0x00, // vertical luminance scaling increment - 0xb1, 0x04, - 0xb2, 0x00, // vertical chrominance scaling increment - 0xb3, 0x04, - 0xb4, 0x00, - 0xb5, 0x00, - 0xb6, 0x00, - 0xb7, 0x00, - 0xb8, 0x00, - 0xb9, 0x00, - 0xba, 0x00, - 0xbb, 0x00, - 0xbc, 0x00, - 0xbd, 0x00, - 0xbe, 0x00, - 0xbf, 0x00, - 0xc0, 0x02, // Task B definition - 0xc1, 0x08, - 0xc2, 0x00, - 0xc3, 0x40, - 0xc4, 0x00, // window settings - 0xc5, 0x00, - 0xc6, 0x00, - 0xc7, 0x00, - 0xc8, 0x00, - 0xc9, 0x00, - 0xca, 0x00, - 0xcb, 0x00, - 0xcc, 0x00, - 0xcd, 0x00, - 0xce, 0x00, - 0xcf, 0x00, - 0xd0, 0x01, // horizontal integer prescaling ratio - 0xd1, 0x00, // horizontal prescaler accumulation sequence length - 0xd2, 0x00, // UV FIR filter, Y FIR filter, prescaler DC gain - 0xd3, 0x00, - 0xd4, 0x80, // luminance brightness - 0xd5, 0x40, // luminance gain - 0xd6, 0x40, // chrominance saturation - 0xd7, 0x00, - 0xd8, 0x00, // horizontal luminance scaling increment - 0xd9, 0x04, - 0xda, 0x00, // horizontal luminance phase offset - 0xdb, 0x00, - 0xdc, 0x00, // horizontal chrominance scaling increment - 0xdd, 0x02, - 0xde, 0x00, // horizontal chrominance phase offset - 0xdf, 0x00, - 0xe0, 0x00, // vertical luminance scaling increment - 0xe1, 0x04, - 0xe2, 0x00, // vertical chrominance scaling increment - 0xe3, 0x04, - 0xe4, 0x00, - 0xe5, 0x00, - 0xe6, 0x00, - 0xe7, 0x00, - 0xe8, 0x00, - 0xe9, 0x00, - 0xea, 0x00, - 0xeb, 0x00, - 0xec, 0x00, - 0xed, 0x00, - 0xee, 0x00, - 0xef, 0x00 -}; - -static int saa7114_command(struct i2c_client *client, unsigned cmd, void *arg) -{ - struct saa7114 *decoder = i2c_get_clientdata(client); - - switch (cmd) { - case 0: - //dprintk(1, KERN_INFO "%s: writing init\n", I2C_NAME(client)); - //saa7114_write_block(client, init, sizeof(init)); - break; - - case DECODER_DUMP: - { - int i; - - if (!debug) - break; - v4l_info(client, "decoder dump\n"); - - for (i = 0; i < 32; i += 16) { - int j; - - v4l_info(client, "%03x", i); - for (j = 0; j < 16; ++j) { - printk(KERN_CONT " %02x", - saa7114_read(client, i + j)); - } - printk(KERN_CONT "\n"); - } - break; - } - - case DECODER_GET_CAPABILITIES: - { - struct video_decoder_capability *cap = arg; - - v4l_dbg(1, debug, client, "get capabilities\n"); - - cap->flags = VIDEO_DECODER_PAL | - VIDEO_DECODER_NTSC | - VIDEO_DECODER_AUTO | - VIDEO_DECODER_CCIR; - cap->inputs = 8; - cap->outputs = 1; - break; - } - - case DECODER_GET_STATUS: - { - int *iarg = arg; - int status; - int res; - - status = saa7114_read(client, 0x1f); - - v4l_dbg(1, debug, client, "status: 0x%02x\n", status); - res = 0; - if ((status & (1 << 6)) == 0) { - res |= DECODER_STATUS_GOOD; - } - switch (decoder->norm) { - case VIDEO_MODE_NTSC: - res |= DECODER_STATUS_NTSC; - break; - case VIDEO_MODE_PAL: - res |= DECODER_STATUS_PAL; - break; - case VIDEO_MODE_SECAM: - res |= DECODER_STATUS_SECAM; - break; - default: - case VIDEO_MODE_AUTO: - if ((status & (1 << 5)) != 0) { - res |= DECODER_STATUS_NTSC; - } else { - res |= DECODER_STATUS_PAL; - } - break; - } - if ((status & (1 << 0)) != 0) { - res |= DECODER_STATUS_COLOR; - } - *iarg = res; - break; - } - - case DECODER_SET_NORM: - { - int *iarg = arg; - - short int hoff = 0, voff = 0, w = 0, h = 0; - - v4l_dbg(1, debug, client, "set norm\n"); - - switch (*iarg) { - case VIDEO_MODE_NTSC: - v4l_dbg(1, debug, client, "NTSC\n"); - decoder->reg[REG_ADDR(0x06)] = - SAA_7114_NTSC_HSYNC_START; - decoder->reg[REG_ADDR(0x07)] = - SAA_7114_NTSC_HSYNC_STOP; - - decoder->reg[REG_ADDR(0x08)] = decoder->playback ? 0x7c : 0xb8; // PLL free when playback, PLL close when capture - - decoder->reg[REG_ADDR(0x0e)] = 0x85; - decoder->reg[REG_ADDR(0x0f)] = 0x24; - - hoff = SAA_7114_NTSC_HOFFSET; - voff = SAA_7114_NTSC_VOFFSET; - w = SAA_7114_NTSC_WIDTH; - h = SAA_7114_NTSC_HEIGHT; - - break; - - case VIDEO_MODE_PAL: - v4l_dbg(1, debug, client, "PAL\n"); - decoder->reg[REG_ADDR(0x06)] = - SAA_7114_PAL_HSYNC_START; - decoder->reg[REG_ADDR(0x07)] = - SAA_7114_PAL_HSYNC_STOP; - - decoder->reg[REG_ADDR(0x08)] = decoder->playback ? 0x7c : 0xb8; // PLL free when playback, PLL close when capture - - decoder->reg[REG_ADDR(0x0e)] = 0x81; - decoder->reg[REG_ADDR(0x0f)] = 0x24; - - hoff = SAA_7114_PAL_HOFFSET; - voff = SAA_7114_PAL_VOFFSET; - w = SAA_7114_PAL_WIDTH; - h = SAA_7114_PAL_HEIGHT; - - break; - - default: - v4l_dbg(1, debug, client, "Unknown video mode\n"); - return -EINVAL; - } - - - decoder->reg[REG_ADDR(0x94)] = LOBYTE(hoff); // hoffset low - decoder->reg[REG_ADDR(0x95)] = HIBYTE(hoff) & 0x0f; // hoffset high - decoder->reg[REG_ADDR(0x96)] = LOBYTE(w); // width low - decoder->reg[REG_ADDR(0x97)] = HIBYTE(w) & 0x0f; // width high - decoder->reg[REG_ADDR(0x98)] = LOBYTE(voff); // voffset low - decoder->reg[REG_ADDR(0x99)] = HIBYTE(voff) & 0x0f; // voffset high - decoder->reg[REG_ADDR(0x9a)] = LOBYTE(h + 2); // height low - decoder->reg[REG_ADDR(0x9b)] = HIBYTE(h + 2) & 0x0f; // height high - decoder->reg[REG_ADDR(0x9c)] = LOBYTE(w); // out width low - decoder->reg[REG_ADDR(0x9d)] = HIBYTE(w) & 0x0f; // out width high - decoder->reg[REG_ADDR(0x9e)] = LOBYTE(h); // out height low - decoder->reg[REG_ADDR(0x9f)] = HIBYTE(h) & 0x0f; // out height high - - decoder->reg[REG_ADDR(0xc4)] = LOBYTE(hoff); // hoffset low - decoder->reg[REG_ADDR(0xc5)] = HIBYTE(hoff) & 0x0f; // hoffset high - decoder->reg[REG_ADDR(0xc6)] = LOBYTE(w); // width low - decoder->reg[REG_ADDR(0xc7)] = HIBYTE(w) & 0x0f; // width high - decoder->reg[REG_ADDR(0xc8)] = LOBYTE(voff); // voffset low - decoder->reg[REG_ADDR(0xc9)] = HIBYTE(voff) & 0x0f; // voffset high - decoder->reg[REG_ADDR(0xca)] = LOBYTE(h + 2); // height low - decoder->reg[REG_ADDR(0xcb)] = HIBYTE(h + 2) & 0x0f; // height high - decoder->reg[REG_ADDR(0xcc)] = LOBYTE(w); // out width low - decoder->reg[REG_ADDR(0xcd)] = HIBYTE(w) & 0x0f; // out width high - decoder->reg[REG_ADDR(0xce)] = LOBYTE(h); // out height low - decoder->reg[REG_ADDR(0xcf)] = HIBYTE(h) & 0x0f; // out height high - - - saa7114_write(client, 0x80, 0x06); // i-port and scaler back end clock selection, task A&B off - saa7114_write(client, 0x88, 0xd8); // sw reset scaler - saa7114_write(client, 0x88, 0xf8); // sw reset scaler release - - saa7114_write_block(client, decoder->reg + (0x06 << 1), - 3 << 1); - saa7114_write_block(client, decoder->reg + (0x0e << 1), - 2 << 1); - saa7114_write_block(client, decoder->reg + (0x5a << 1), - 2 << 1); - - saa7114_write_block(client, decoder->reg + (0x94 << 1), - (0x9f + 1 - 0x94) << 1); - saa7114_write_block(client, decoder->reg + (0xc4 << 1), - (0xcf + 1 - 0xc4) << 1); - - saa7114_write(client, 0x88, 0xd8); // sw reset scaler - saa7114_write(client, 0x88, 0xf8); // sw reset scaler release - saa7114_write(client, 0x80, 0x36); // i-port and scaler back end clock selection - - decoder->norm = *iarg; - break; - } - - case DECODER_SET_INPUT: - { - int *iarg = arg; - - v4l_dbg(1, debug, client, "set input (%d)\n", *iarg); - if (*iarg < 0 || *iarg > 7) { - return -EINVAL; - } - - if (decoder->input != *iarg) { - v4l_dbg(1, debug, client, "now setting %s input\n", - *iarg >= 6 ? "S-Video" : "Composite"); - decoder->input = *iarg; - - /* select mode */ - decoder->reg[REG_ADDR(0x02)] = - (decoder-> - reg[REG_ADDR(0x02)] & 0xf0) | (decoder-> - input < - 6 ? 0x0 : 0x9); - saa7114_write(client, 0x02, - decoder->reg[REG_ADDR(0x02)]); - - /* bypass chrominance trap for modes 6..9 */ - decoder->reg[REG_ADDR(0x09)] = - (decoder-> - reg[REG_ADDR(0x09)] & 0x7f) | (decoder-> - input < - 6 ? 0x0 : - 0x80); - saa7114_write(client, 0x09, - decoder->reg[REG_ADDR(0x09)]); - - decoder->reg[REG_ADDR(0x0e)] = - decoder->input < - 6 ? decoder-> - reg[REG_ADDR(0x0e)] | 1 : decoder-> - reg[REG_ADDR(0x0e)] & ~1; - saa7114_write(client, 0x0e, - decoder->reg[REG_ADDR(0x0e)]); - } - break; - } - - case DECODER_SET_OUTPUT: - { - int *iarg = arg; - - v4l_dbg(1, debug, client, "set output\n"); - - /* not much choice of outputs */ - if (*iarg != 0) { - return -EINVAL; - } - break; - } - - case DECODER_ENABLE_OUTPUT: - { - int *iarg = arg; - int enable = (*iarg != 0); - - v4l_dbg(1, debug, client, "%s output\n", - enable ? "enable" : "disable"); - - decoder->playback = !enable; - - if (decoder->enable != enable) { - decoder->enable = enable; - - /* RJ: If output should be disabled (for - * playing videos), we also need a open PLL. - * The input is set to 0 (where no input - * source is connected), although this - * is not necessary. - * - * If output should be enabled, we have to - * reverse the above. - */ - - if (decoder->enable) { - decoder->reg[REG_ADDR(0x08)] = 0xb8; - decoder->reg[REG_ADDR(0x12)] = 0xc9; - decoder->reg[REG_ADDR(0x13)] = 0x80; - decoder->reg[REG_ADDR(0x87)] = 0x01; - } else { - decoder->reg[REG_ADDR(0x08)] = 0x7c; - decoder->reg[REG_ADDR(0x12)] = 0x00; - decoder->reg[REG_ADDR(0x13)] = 0x00; - decoder->reg[REG_ADDR(0x87)] = 0x00; - } - - saa7114_write_block(client, - decoder->reg + (0x12 << 1), - 2 << 1); - saa7114_write(client, 0x08, - decoder->reg[REG_ADDR(0x08)]); - saa7114_write(client, 0x87, - decoder->reg[REG_ADDR(0x87)]); - saa7114_write(client, 0x88, 0xd8); // sw reset scaler - saa7114_write(client, 0x88, 0xf8); // sw reset scaler release - saa7114_write(client, 0x80, 0x36); - - } - break; - } - - case DECODER_SET_PICTURE: - { - struct video_picture *pic = arg; - - v4l_dbg(1, debug, client, - "decoder set picture bright=%d contrast=%d saturation=%d hue=%d\n", - pic->brightness, pic->contrast, pic->colour, pic->hue); - - if (decoder->bright != pic->brightness) { - /* We want 0 to 255 we get 0-65535 */ - decoder->bright = pic->brightness; - saa7114_write(client, 0x0a, decoder->bright >> 8); - } - if (decoder->contrast != pic->contrast) { - /* We want 0 to 127 we get 0-65535 */ - decoder->contrast = pic->contrast; - saa7114_write(client, 0x0b, - decoder->contrast >> 9); - } - if (decoder->sat != pic->colour) { - /* We want 0 to 127 we get 0-65535 */ - decoder->sat = pic->colour; - saa7114_write(client, 0x0c, decoder->sat >> 9); - } - if (decoder->hue != pic->hue) { - /* We want -128 to 127 we get 0-65535 */ - decoder->hue = pic->hue; - saa7114_write(client, 0x0d, - (decoder->hue - 32768) >> 8); - } - break; - } - - default: - return -EINVAL; - } - - return 0; -} - -/* ----------------------------------------------------------------------- */ - -static unsigned short normal_i2c[] = { 0x42 >> 1, 0x40 >> 1, I2C_CLIENT_END }; - -I2C_CLIENT_INSMOD; - -static int saa7114_probe(struct i2c_client *client, - const struct i2c_device_id *id) -{ - int i, err[30]; - short int hoff = SAA_7114_NTSC_HOFFSET; - short int voff = SAA_7114_NTSC_VOFFSET; - short int w = SAA_7114_NTSC_WIDTH; - short int h = SAA_7114_NTSC_HEIGHT; - struct saa7114 *decoder; - - /* Check if the adapter supports the needed features */ - if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) - return -ENODEV; - - v4l_info(client, "chip found @ 0x%x (%s)\n", - client->addr << 1, client->adapter->name); - - decoder = kzalloc(sizeof(struct saa7114), GFP_KERNEL); - if (decoder == NULL) - return -ENOMEM; - decoder->norm = VIDEO_MODE_NTSC; - decoder->input = -1; - decoder->enable = 1; - decoder->bright = 32768; - decoder->contrast = 32768; - decoder->hue = 32768; - decoder->sat = 32768; - decoder->playback = 0; // initially capture mode useda - i2c_set_clientdata(client, decoder); - - memcpy(decoder->reg, init, sizeof(init)); - - decoder->reg[REG_ADDR(0x94)] = LOBYTE(hoff); // hoffset low - decoder->reg[REG_ADDR(0x95)] = HIBYTE(hoff) & 0x0f; // hoffset high - decoder->reg[REG_ADDR(0x96)] = LOBYTE(w); // width low - decoder->reg[REG_ADDR(0x97)] = HIBYTE(w) & 0x0f; // width high - decoder->reg[REG_ADDR(0x98)] = LOBYTE(voff); // voffset low - decoder->reg[REG_ADDR(0x99)] = HIBYTE(voff) & 0x0f; // voffset high - decoder->reg[REG_ADDR(0x9a)] = LOBYTE(h + 2); // height low - decoder->reg[REG_ADDR(0x9b)] = HIBYTE(h + 2) & 0x0f; // height high - decoder->reg[REG_ADDR(0x9c)] = LOBYTE(w); // out width low - decoder->reg[REG_ADDR(0x9d)] = HIBYTE(w) & 0x0f; // out width high - decoder->reg[REG_ADDR(0x9e)] = LOBYTE(h); // out height low - decoder->reg[REG_ADDR(0x9f)] = HIBYTE(h) & 0x0f; // out height high - - decoder->reg[REG_ADDR(0xc4)] = LOBYTE(hoff); // hoffset low - decoder->reg[REG_ADDR(0xc5)] = HIBYTE(hoff) & 0x0f; // hoffset high - decoder->reg[REG_ADDR(0xc6)] = LOBYTE(w); // width low - decoder->reg[REG_ADDR(0xc7)] = HIBYTE(w) & 0x0f; // width high - decoder->reg[REG_ADDR(0xc8)] = LOBYTE(voff); // voffset low - decoder->reg[REG_ADDR(0xc9)] = HIBYTE(voff) & 0x0f; // voffset high - decoder->reg[REG_ADDR(0xca)] = LOBYTE(h + 2); // height low - decoder->reg[REG_ADDR(0xcb)] = HIBYTE(h + 2) & 0x0f; // height high - decoder->reg[REG_ADDR(0xcc)] = LOBYTE(w); // out width low - decoder->reg[REG_ADDR(0xcd)] = HIBYTE(w) & 0x0f; // out width high - decoder->reg[REG_ADDR(0xce)] = LOBYTE(h); // out height low - decoder->reg[REG_ADDR(0xcf)] = HIBYTE(h) & 0x0f; // out height high - - decoder->reg[REG_ADDR(0xb8)] = - LOBYTE(LOWORD(SAA_7114_VERTICAL_CHROMA_OFFSET)); - decoder->reg[REG_ADDR(0xb9)] = - HIBYTE(LOWORD(SAA_7114_VERTICAL_CHROMA_OFFSET)); - decoder->reg[REG_ADDR(0xba)] = - LOBYTE(HIWORD(SAA_7114_VERTICAL_CHROMA_OFFSET)); - decoder->reg[REG_ADDR(0xbb)] = - HIBYTE(HIWORD(SAA_7114_VERTICAL_CHROMA_OFFSET)); - - decoder->reg[REG_ADDR(0xbc)] = - LOBYTE(LOWORD(SAA_7114_VERTICAL_LUMA_OFFSET)); - decoder->reg[REG_ADDR(0xbd)] = - HIBYTE(LOWORD(SAA_7114_VERTICAL_LUMA_OFFSET)); - decoder->reg[REG_ADDR(0xbe)] = - LOBYTE(HIWORD(SAA_7114_VERTICAL_LUMA_OFFSET)); - decoder->reg[REG_ADDR(0xbf)] = - HIBYTE(HIWORD(SAA_7114_VERTICAL_LUMA_OFFSET)); - - decoder->reg[REG_ADDR(0xe8)] = - LOBYTE(LOWORD(SAA_7114_VERTICAL_CHROMA_OFFSET)); - decoder->reg[REG_ADDR(0xe9)] = - HIBYTE(LOWORD(SAA_7114_VERTICAL_CHROMA_OFFSET)); - decoder->reg[REG_ADDR(0xea)] = - LOBYTE(HIWORD(SAA_7114_VERTICAL_CHROMA_OFFSET)); - decoder->reg[REG_ADDR(0xeb)] = - HIBYTE(HIWORD(SAA_7114_VERTICAL_CHROMA_OFFSET)); - - decoder->reg[REG_ADDR(0xec)] = - LOBYTE(LOWORD(SAA_7114_VERTICAL_LUMA_OFFSET)); - decoder->reg[REG_ADDR(0xed)] = - HIBYTE(LOWORD(SAA_7114_VERTICAL_LUMA_OFFSET)); - decoder->reg[REG_ADDR(0xee)] = - LOBYTE(HIWORD(SAA_7114_VERTICAL_LUMA_OFFSET)); - decoder->reg[REG_ADDR(0xef)] = - HIBYTE(HIWORD(SAA_7114_VERTICAL_LUMA_OFFSET)); - - - decoder->reg[REG_ADDR(0x13)] = 0x80; // RTC0 on - decoder->reg[REG_ADDR(0x87)] = 0x01; // I-Port - decoder->reg[REG_ADDR(0x12)] = 0xc9; // RTS0 - - decoder->reg[REG_ADDR(0x02)] = 0xc0; // set composite1 input, aveasy - decoder->reg[REG_ADDR(0x09)] = 0x00; // chrominance trap - decoder->reg[REG_ADDR(0x0e)] |= 1; // combfilter on - - - v4l_dbg(1, debug, client, "starting init\n"); - - err[0] = - saa7114_write_block(client, decoder->reg + (0x20 << 1), - 0x10 << 1); - err[1] = - saa7114_write_block(client, decoder->reg + (0x30 << 1), - 0x10 << 1); - err[2] = - saa7114_write_block(client, decoder->reg + (0x63 << 1), - (0x7f + 1 - 0x63) << 1); - err[3] = - saa7114_write_block(client, decoder->reg + (0x89 << 1), - 6 << 1); - err[4] = - saa7114_write_block(client, decoder->reg + (0xb8 << 1), - 8 << 1); - err[5] = - saa7114_write_block(client, decoder->reg + (0xe8 << 1), - 8 << 1); - - - for (i = 0; i <= 5; i++) { - if (err[i] < 0) { - v4l_dbg(1, debug, client, - "init error %d at stage %d, leaving attach.\n", - i, err[i]); - kfree(decoder); - return -EIO; - } - } - - for (i = 6; i < 8; i++) { - v4l_dbg(1, debug, client, - "reg[0x%02x] = 0x%02x (0x%02x)\n", - i, saa7114_read(client, i), - decoder->reg[REG_ADDR(i)]); - } - - v4l_dbg(1, debug, client, - "performing decoder reset sequence\n"); - - err[6] = saa7114_write(client, 0x80, 0x06); // i-port and scaler backend clock selection, task A&B off - err[7] = saa7114_write(client, 0x88, 0xd8); // sw reset scaler - err[8] = saa7114_write(client, 0x88, 0xf8); // sw reset scaler release - - for (i = 6; i <= 8; i++) { - if (err[i] < 0) { - v4l_dbg(1, debug, client, - "init error %d at stage %d, leaving attach.\n", - i, err[i]); - kfree(decoder); - return -EIO; - } - } - - v4l_dbg(1, debug, client, "performing the rest of init\n"); - - err[9] = saa7114_write(client, 0x01, decoder->reg[REG_ADDR(0x01)]); - err[10] = saa7114_write_block(client, decoder->reg + (0x03 << 1), (0x1e + 1 - 0x03) << 1); // big seq - err[11] = saa7114_write_block(client, decoder->reg + (0x40 << 1), (0x5f + 1 - 0x40) << 1); // slicer - err[12] = saa7114_write_block(client, decoder->reg + (0x81 << 1), 2 << 1); // ? - err[13] = saa7114_write_block(client, decoder->reg + (0x83 << 1), 5 << 1); // ? - err[14] = saa7114_write_block(client, decoder->reg + (0x90 << 1), 4 << 1); // Task A - err[15] = - saa7114_write_block(client, decoder->reg + (0x94 << 1), - 12 << 1); - err[16] = - saa7114_write_block(client, decoder->reg + (0xa0 << 1), - 8 << 1); - err[17] = - saa7114_write_block(client, decoder->reg + (0xa8 << 1), - 8 << 1); - err[18] = - saa7114_write_block(client, decoder->reg + (0xb0 << 1), - 8 << 1); - err[19] = saa7114_write_block(client, decoder->reg + (0xc0 << 1), 4 << 1); // Task B - err[15] = - saa7114_write_block(client, decoder->reg + (0xc4 << 1), - 12 << 1); - err[16] = - saa7114_write_block(client, decoder->reg + (0xd0 << 1), - 8 << 1); - err[17] = - saa7114_write_block(client, decoder->reg + (0xd8 << 1), - 8 << 1); - err[18] = - saa7114_write_block(client, decoder->reg + (0xe0 << 1), - 8 << 1); - - for (i = 9; i <= 18; i++) { - if (err[i] < 0) { - v4l_dbg(1, debug, client, - "init error %d at stage %d, leaving attach.\n", - i, err[i]); - kfree(decoder); - return -EIO; - } - } - - - for (i = 6; i < 8; i++) { - v4l_dbg(1, debug, client, - "reg[0x%02x] = 0x%02x (0x%02x)\n", - i, saa7114_read(client, i), - decoder->reg[REG_ADDR(i)]); - } - - - for (i = 0x11; i <= 0x13; i++) { - v4l_dbg(1, debug, client, - "reg[0x%02x] = 0x%02x (0x%02x)\n", - i, saa7114_read(client, i), - decoder->reg[REG_ADDR(i)]); - } - - - v4l_dbg(1, debug, client, "setting video input\n"); - - err[19] = - saa7114_write(client, 0x02, decoder->reg[REG_ADDR(0x02)]); - err[20] = - saa7114_write(client, 0x09, decoder->reg[REG_ADDR(0x09)]); - err[21] = - saa7114_write(client, 0x0e, decoder->reg[REG_ADDR(0x0e)]); - - for (i = 19; i <= 21; i++) { - if (err[i] < 0) { - v4l_dbg(1, debug, client, - "init error %d at stage %d, leaving attach.\n", - i, err[i]); - kfree(decoder); - return -EIO; - } - } - - v4l_dbg(1, debug, client, "performing decoder reset sequence\n"); - - err[22] = saa7114_write(client, 0x88, 0xd8); // sw reset scaler - err[23] = saa7114_write(client, 0x88, 0xf8); // sw reset scaler release - err[24] = saa7114_write(client, 0x80, 0x36); // i-port and scaler backend clock selection, task A&B off - - - for (i = 22; i <= 24; i++) { - if (err[i] < 0) { - v4l_dbg(1, debug, client, - "init error %d at stage %d, leaving attach.\n", - i, err[i]); - kfree(decoder); - return -EIO; - } - } - - err[25] = saa7114_write(client, 0x06, init[REG_ADDR(0x06)]); - err[26] = saa7114_write(client, 0x07, init[REG_ADDR(0x07)]); - err[27] = saa7114_write(client, 0x10, init[REG_ADDR(0x10)]); - - v4l_dbg(1, debug, client, "chip version %x, decoder status 0x%02x\n", - saa7114_read(client, 0x00) >> 4, - saa7114_read(client, 0x1f)); - v4l_dbg(1, debug, client, - "power save control: 0x%02x, scaler status: 0x%02x\n", - saa7114_read(client, 0x88), - saa7114_read(client, 0x8f)); - - - for (i = 0x94; i < 0x96; i++) { - v4l_dbg(1, debug, client, - "reg[0x%02x] = 0x%02x (0x%02x)\n", - i, saa7114_read(client, i), - decoder->reg[REG_ADDR(i)]); - } - - //i = saa7114_write_block(client, init, sizeof(init)); - return 0; -} - -static int saa7114_remove(struct i2c_client *client) -{ - kfree(i2c_get_clientdata(client)); - return 0; -} - -/* ----------------------------------------------------------------------- */ - -static const struct i2c_device_id saa7114_id[] = { - { "saa7114_old", 0 }, /* "saa7114" maps to the saa7115 driver */ - { } -}; -MODULE_DEVICE_TABLE(i2c, saa7114_id); - -static struct v4l2_i2c_driver_data v4l2_i2c_data = { - .name = "saa7114", - .driverid = I2C_DRIVERID_SAA7114, - .command = saa7114_command, - .probe = saa7114_probe, - .remove = saa7114_remove, - .id_table = saa7114_id, -}; diff --git a/drivers/media/video/saa7185.c b/drivers/media/video/saa7185.c index 8d06bb312c55..fc51e6c9cb95 100644 --- a/drivers/media/video/saa7185.c +++ b/drivers/media/video/saa7185.c @@ -49,8 +49,7 @@ MODULE_PARM_DESC(debug, "Debug level (0-1)"); struct saa7185 { unsigned char reg[128]; - int norm; - int enable; + v4l2_std_id norm; int bright; int contrast; int hue; @@ -218,68 +217,43 @@ static int saa7185_command(struct i2c_client *client, unsigned cmd, void *arg) struct saa7185 *encoder = i2c_get_clientdata(client); switch (cmd) { - case 0: + case VIDIOC_INT_INIT: saa7185_write_block(client, init_common, sizeof(init_common)); - switch (encoder->norm) { - - case VIDEO_MODE_NTSC: + if (encoder->norm & V4L2_STD_NTSC) saa7185_write_block(client, init_ntsc, sizeof(init_ntsc)); - break; - - case VIDEO_MODE_PAL: + else saa7185_write_block(client, init_pal, sizeof(init_pal)); - break; - } - break; - - case ENCODER_GET_CAPABILITIES: - { - struct video_encoder_capability *cap = arg; - - cap->flags = - VIDEO_ENCODER_PAL | VIDEO_ENCODER_NTSC | - VIDEO_ENCODER_SECAM | VIDEO_ENCODER_CCIR; - cap->inputs = 1; - cap->outputs = 1; break; - } - case ENCODER_SET_NORM: + case VIDIOC_INT_S_STD_OUTPUT: { - int *iarg = arg; + v4l2_std_id *iarg = arg; //saa7185_write_block(client, init_common, sizeof(init_common)); - switch (*iarg) { - case VIDEO_MODE_NTSC: + if (*iarg & V4L2_STD_NTSC) saa7185_write_block(client, init_ntsc, sizeof(init_ntsc)); - break; - - case VIDEO_MODE_PAL: + else if (*iarg & V4L2_STD_PAL) saa7185_write_block(client, init_pal, sizeof(init_pal)); - break; - - case VIDEO_MODE_SECAM: - default: + else return -EINVAL; - } encoder->norm = *iarg; break; } - case ENCODER_SET_INPUT: + case VIDIOC_INT_S_VIDEO_ROUTING: { - int *iarg = arg; + struct v4l2_routing *route = arg; - /* RJ: *iarg = 0: input is from SA7111 - *iarg = 1: input is from ZR36060 */ + /* RJ: route->input = 0: input is from SA7111 + route->input = 1: input is from ZR36060 */ - switch (*iarg) { + switch (route->input) { case 0: /* turn off colorbar */ saa7185_write(client, 0x3a, 0x0f); @@ -315,27 +289,6 @@ static int saa7185_command(struct i2c_client *client, unsigned cmd, void *arg) break; } - case ENCODER_SET_OUTPUT: - { - int *iarg = arg; - - /* not much choice of outputs */ - if (*iarg != 0) - return -EINVAL; - break; - } - - case ENCODER_ENABLE_OUTPUT: - { - int *iarg = arg; - - encoder->enable = !!*iarg; - saa7185_write(client, 0x61, - (encoder->reg[0x61] & 0xbf) | - (encoder->enable ? 0x00 : 0x40)); - break; - } - default: return -EINVAL; } @@ -365,8 +318,7 @@ static int saa7185_probe(struct i2c_client *client, encoder = kzalloc(sizeof(struct saa7185), GFP_KERNEL); if (encoder == NULL) return -ENOMEM; - encoder->norm = VIDEO_MODE_NTSC; - encoder->enable = 1; + encoder->norm = V4L2_STD_NTSC; i2c_set_clientdata(client, encoder); i = saa7185_write_block(client, init_common, sizeof(init_common)); diff --git a/drivers/media/video/vpx3220.c b/drivers/media/video/vpx3220.c index 67aa0db4b81a..cd2064e7733b 100644 --- a/drivers/media/video/vpx3220.c +++ b/drivers/media/video/vpx3220.c @@ -27,6 +27,7 @@ #include #include #include +#include #include MODULE_DESCRIPTION("vpx3220a/vpx3216b/vpx3214c video decoder driver"); @@ -44,7 +45,7 @@ MODULE_PARM_DESC(debug, "Debug level (0-1)"); struct vpx3220 { unsigned char reg[255]; - int norm; + v4l2_std_id norm; int input; int enable; int bright; @@ -259,79 +260,41 @@ static const unsigned short init_fp[] = { 0x4b, 0x298, /* PLL gain */ }; -static void vpx3220_dump_i2c(struct i2c_client *client) -{ - int len = sizeof(init_common); - const unsigned char *data = init_common; - - while (len > 1) { - v4l_dbg(1, debug, client, "i2c reg 0x%02x data 0x%02x\n", - *data, vpx3220_read(client, *data)); - data += 2; - len -= 2; - } -} static int vpx3220_command(struct i2c_client *client, unsigned cmd, void *arg) { struct vpx3220 *decoder = i2c_get_clientdata(client); switch (cmd) { - case 0: + case VIDIOC_INT_INIT: { vpx3220_write_block(client, init_common, sizeof(init_common)); vpx3220_write_fp_block(client, init_fp, sizeof(init_fp) >> 1); - switch (decoder->norm) { - case VIDEO_MODE_NTSC: + if (decoder->norm & V4L2_STD_NTSC) { vpx3220_write_fp_block(client, init_ntsc, sizeof(init_ntsc) >> 1); - break; - - case VIDEO_MODE_PAL: + } else if (decoder->norm & V4L2_STD_PAL) { vpx3220_write_fp_block(client, init_pal, sizeof(init_pal) >> 1); - break; - case VIDEO_MODE_SECAM: + } else if (decoder->norm & V4L2_STD_SECAM) { vpx3220_write_fp_block(client, init_secam, sizeof(init_secam) >> 1); - break; - default: + } else { vpx3220_write_fp_block(client, init_pal, sizeof(init_pal) >> 1); - break; } break; } - case DECODER_DUMP: - { - vpx3220_dump_i2c(client); - break; - } - - case DECODER_GET_CAPABILITIES: - { - struct video_decoder_capability *cap = arg; - - v4l_dbg(1, debug, client, "DECODER_GET_CAPABILITIES\n"); - - cap->flags = VIDEO_DECODER_PAL | - VIDEO_DECODER_NTSC | - VIDEO_DECODER_SECAM | - VIDEO_DECODER_AUTO | - VIDEO_DECODER_CCIR; - cap->inputs = 3; - cap->outputs = 1; - break; - } - - case DECODER_GET_STATUS: + case VIDIOC_QUERYSTD: + case VIDIOC_INT_G_INPUT_STATUS: { - int res = 0, status; + int res = V4L2_IN_ST_NO_SIGNAL, status; + v4l2_std_id std = 0; - v4l_dbg(1, debug, client, "DECODER_GET_STATUS\n"); + v4l_dbg(1, debug, client, "VIDIOC_QUERYSTD/VIDIOC_INT_G_INPUT_STATUS\n"); status = vpx3220_fp_read(client, 0x0f3); @@ -341,35 +304,38 @@ static int vpx3220_command(struct i2c_client *client, unsigned cmd, void *arg) return status; if ((status & 0x20) == 0) { - res |= DECODER_STATUS_GOOD | DECODER_STATUS_COLOR; + res = 0; switch (status & 0x18) { case 0x00: case 0x10: case 0x14: case 0x18: - res |= DECODER_STATUS_PAL; + std = V4L2_STD_PAL; break; case 0x08: - res |= DECODER_STATUS_SECAM; + std = V4L2_STD_SECAM; break; case 0x04: case 0x0c: case 0x1c: - res |= DECODER_STATUS_NTSC; + std = V4L2_STD_NTSC; break; } } - *(int *) arg = res; + if (cmd == VIDIOC_QUERYSTD) + *(v4l2_std_id *)arg = std; + else + *(int *)arg = res; break; } - case DECODER_SET_NORM: + case VIDIOC_S_STD: { - int *iarg = arg, data; + v4l2_std_id *iarg = arg; int temp_input; /* Here we back up the input selection because it gets @@ -377,36 +343,23 @@ static int vpx3220_command(struct i2c_client *client, unsigned cmd, void *arg) choosen video norm */ temp_input = vpx3220_fp_read(client, 0xf2); - v4l_dbg(1, debug, client, "DECODER_SET_NORM %d\n", *iarg); - switch (*iarg) { - case VIDEO_MODE_NTSC: + v4l_dbg(1, debug, client, "VIDIOC_S_STD %llx\n", *iarg); + if (*iarg & V4L2_STD_NTSC) { vpx3220_write_fp_block(client, init_ntsc, sizeof(init_ntsc) >> 1); v4l_dbg(1, debug, client, "norm switched to NTSC\n"); - break; - - case VIDEO_MODE_PAL: + } else if (*iarg & V4L2_STD_PAL) { vpx3220_write_fp_block(client, init_pal, sizeof(init_pal) >> 1); v4l_dbg(1, debug, client, "norm switched to PAL\n"); - break; - - case VIDEO_MODE_SECAM: + } else if (*iarg & V4L2_STD_SECAM) { vpx3220_write_fp_block(client, init_secam, sizeof(init_secam) >> 1); v4l_dbg(1, debug, client, "norm switched to SECAM\n"); - break; - - case VIDEO_MODE_AUTO: - /* FIXME This is only preliminary support */ - data = vpx3220_fp_read(client, 0xf2) & 0x20; - vpx3220_fp_write(client, 0xf2, 0x00c0 | data); - v4l_dbg(1, debug, client, "norm switched to AUTO\n"); - break; - - default: + } else { return -EINVAL; } + decoder->norm = *iarg; /* And here we set the backed up video input again */ @@ -415,9 +368,10 @@ static int vpx3220_command(struct i2c_client *client, unsigned cmd, void *arg) break; } - case DECODER_SET_INPUT: + case VIDIOC_INT_S_VIDEO_ROUTING: { - int *iarg = arg, data; + struct v4l2_routing *route = arg; + int data; /* RJ: *iarg = 0: ST8 (PCTV) input *iarg = 1: COMPOSITE input @@ -429,73 +383,117 @@ static int vpx3220_command(struct i2c_client *client, unsigned cmd, void *arg) {0x0e, 1} }; - if (*iarg < 0 || *iarg > 2) + if (route->input < 0 || route->input > 2) return -EINVAL; - v4l_dbg(1, debug, client, "input switched to %s\n", inputs[*iarg]); + v4l_dbg(1, debug, client, "input switched to %s\n", inputs[route->input]); - vpx3220_write(client, 0x33, input[*iarg][0]); + vpx3220_write(client, 0x33, input[route->input][0]); data = vpx3220_fp_read(client, 0xf2) & ~(0x0020); if (data < 0) return data; /* 0x0010 is required to latch the setting */ vpx3220_fp_write(client, 0xf2, - data | (input[*iarg][1] << 5) | 0x0010); + data | (input[route->input][1] << 5) | 0x0010); udelay(10); break; } - case DECODER_SET_OUTPUT: + case VIDIOC_STREAMON: + case VIDIOC_STREAMOFF: { - int *iarg = arg; + int on = cmd == VIDIOC_STREAMON; + v4l_dbg(1, debug, client, "VIDIOC_STREAM%s\n", on ? "ON" : "OFF"); - /* not much choice of outputs */ - if (*iarg != 0) { - return -EINVAL; - } + vpx3220_write(client, 0xf2, (on ? 0x1b : 0x00)); break; } - case DECODER_ENABLE_OUTPUT: + case VIDIOC_QUERYCTRL: { - int *iarg = arg; + struct v4l2_queryctrl *qc = arg; - v4l_dbg(1, debug, client, "DECODER_ENABLE_OUTPUT %d\n", *iarg); + switch (qc->id) { + case V4L2_CID_BRIGHTNESS: + v4l2_ctrl_query_fill(qc, -128, 127, 1, 0); + break; + + case V4L2_CID_CONTRAST: + v4l2_ctrl_query_fill(qc, 0, 63, 1, 32); + break; + + case V4L2_CID_SATURATION: + v4l2_ctrl_query_fill(qc, 0, 4095, 1, 2048); + break; - vpx3220_write(client, 0xf2, (*iarg ? 0x1b : 0x00)); + case V4L2_CID_HUE: + v4l2_ctrl_query_fill(qc, -512, 511, 1, 0); + break; + + default: + return -EINVAL; + } break; } - case DECODER_SET_PICTURE: + case VIDIOC_G_CTRL: { - struct video_picture *pic = arg; + struct v4l2_control *ctrl = arg; - if (decoder->bright != pic->brightness) { - /* We want -128 to 128 we get 0-65535 */ - decoder->bright = pic->brightness; - vpx3220_write(client, 0xe6, - (decoder->bright - 32768) >> 8); - } - if (decoder->contrast != pic->contrast) { - /* We want 0 to 64 we get 0-65535 */ - /* Bit 7 and 8 is for noise shaping */ - decoder->contrast = pic->contrast; - vpx3220_write(client, 0xe7, - (decoder->contrast >> 10) + 192); - } - if (decoder->sat != pic->colour) { - /* We want 0 to 4096 we get 0-65535 */ - decoder->sat = pic->colour; - vpx3220_fp_write(client, 0xa0, - decoder->sat >> 4); + switch (ctrl->id) { + case V4L2_CID_BRIGHTNESS: + ctrl->value = decoder->bright; + break; + case V4L2_CID_CONTRAST: + ctrl->value = decoder->contrast; + break; + case V4L2_CID_SATURATION: + ctrl->value = decoder->sat; + break; + case V4L2_CID_HUE: + ctrl->value = decoder->hue; + break; + default: + return -EINVAL; } - if (decoder->hue != pic->hue) { - /* We want -512 to 512 we get 0-65535 */ - decoder->hue = pic->hue; - vpx3220_fp_write(client, 0x1c, - ((decoder->hue - 32768) >> 6) & 0xFFF); + break; + } + + case VIDIOC_S_CTRL: + { + struct v4l2_control *ctrl = arg; + + switch (ctrl->id) { + case V4L2_CID_BRIGHTNESS: + if (decoder->bright != ctrl->value) { + decoder->bright = ctrl->value; + vpx3220_write(client, 0xe6, decoder->bright); + } + break; + case V4L2_CID_CONTRAST: + if (decoder->contrast != ctrl->value) { + /* Bit 7 and 8 is for noise shaping */ + decoder->contrast = ctrl->value; + vpx3220_write(client, 0xe7, + decoder->contrast + 192); + } + break; + case V4L2_CID_SATURATION: + if (decoder->sat != ctrl->value) { + decoder->sat = ctrl->value; + vpx3220_fp_write(client, 0xa0, decoder->sat); + } + break; + case V4L2_CID_HUE: + if (decoder->hue != ctrl->value) { + decoder->hue = ctrl->value; + vpx3220_fp_write(client, 0x1c, decoder->hue); + } + break; + default: + return -EINVAL; } break; } @@ -541,7 +539,7 @@ static int vpx3220_probe(struct i2c_client *client, decoder = kzalloc(sizeof(struct vpx3220), GFP_KERNEL); if (decoder == NULL) return -ENOMEM; - decoder->norm = VIDEO_MODE_PAL; + decoder->norm = V4L2_STD_PAL; decoder->input = 0; decoder->enable = 1; decoder->bright = 32768; diff --git a/drivers/media/video/zoran/Kconfig b/drivers/media/video/zoran/Kconfig index e35121fdf78a..fd4120e4c104 100644 --- a/drivers/media/video/zoran/Kconfig +++ b/drivers/media/video/zoran/Kconfig @@ -32,7 +32,7 @@ config VIDEO_ZORAN_ZR36060 config VIDEO_ZORAN_BUZ tristate "Iomega Buz support" depends on VIDEO_ZORAN_ZR36060 - select VIDEO_SAA7111 if VIDEO_HELPER_CHIPS_AUTO + select VIDEO_SAA711X if VIDEO_HELPER_CHIPS_AUTO select VIDEO_SAA7185 if VIDEO_HELPER_CHIPS_AUTO help Support for the Iomega Buz MJPEG capture/playback card. @@ -58,7 +58,7 @@ config VIDEO_ZORAN_LML33 config VIDEO_ZORAN_LML33R10 tristate "Linux Media Labs LML33R10 support" depends on VIDEO_ZORAN_ZR36060 - select VIDEO_SAA7114 if VIDEO_HELPER_CHIPS_AUTO + select VIDEO_SAA711X if VIDEO_HELPER_CHIPS_AUTO select VIDEO_ADV7170 if VIDEO_HELPER_CHIPS_AUTO help support for the Linux Media Labs LML33R10 MJPEG capture/playback diff --git a/drivers/media/video/zoran/zoran.h b/drivers/media/video/zoran/zoran.h index 76668bda0494..ee31bfc3428f 100644 --- a/drivers/media/video/zoran/zoran.h +++ b/drivers/media/video/zoran/zoran.h @@ -352,7 +352,7 @@ struct card_info { char name[32]; } input[BUZ_MAX_INPUT]; - int norms; + v4l2_std_id norms; struct tvnorm *tvn[3]; /* supported TV norms */ u32 jpeg_int; /* JPEG interrupt */ @@ -401,8 +401,8 @@ struct zoran { spinlock_t spinlock; /* Spinlock */ /* Video for Linux parameters */ - int input, norm; /* card's norm and input - norm=VIDEO_MODE_* */ - int hue, saturation, contrast, brightness; /* Current picture params */ + int input; /* card's norm and input - norm=VIDEO_MODE_* */ + v4l2_std_id norm; struct video_buffer buffer; /* Current buffer params */ struct zoran_overlay_settings overlay_settings; u32 *overlay_mask; /* overlay mask */ diff --git a/drivers/media/video/zoran/zoran_card.c b/drivers/media/video/zoran/zoran_card.c index 774717bf43cc..51ae37effdeb 100644 --- a/drivers/media/video/zoran/zoran_card.c +++ b/drivers/media/video/zoran/zoran_card.c @@ -340,11 +340,8 @@ i2cid_to_modulename (u16 i2c_id) case I2C_DRIVERID_SAA7110: name = "saa7110"; break; - case I2C_DRIVERID_SAA7111A: - name = "saa7111"; - break; - case I2C_DRIVERID_SAA7114: - name = "saa7114"; + case I2C_DRIVERID_SAA711X: + name = "saa7115"; break; case I2C_DRIVERID_SAA7185B: name = "saa7185"; @@ -439,7 +436,7 @@ static struct card_info zoran_cards[NUM_CARDS] __devinitdata = { { 2, "S-Video" }, { 0, "Internal/comp" } }, - .norms = 3, + .norms = V4L2_STD_NTSC|V4L2_STD_PAL|V4L2_STD_SECAM, .tvn = { &f50sqpixel_dc10, &f60sqpixel_dc10, @@ -467,7 +464,7 @@ static struct card_info zoran_cards[NUM_CARDS] __devinitdata = { { 7, "S-Video" }, { 5, "Internal/comp" } }, - .norms = 3, + .norms = V4L2_STD_NTSC|V4L2_STD_PAL|V4L2_STD_SECAM, .tvn = { &f50sqpixel, &f60sqpixel, @@ -494,7 +491,7 @@ static struct card_info zoran_cards[NUM_CARDS] __devinitdata = { { 7, "S-Video" }, { 5, "Internal/comp" } }, - .norms = 3, + .norms = V4L2_STD_NTSC|V4L2_STD_PAL|V4L2_STD_SECAM, .tvn = { &f50sqpixel, &f60sqpixel, @@ -523,7 +520,7 @@ static struct card_info zoran_cards[NUM_CARDS] __devinitdata = { { 2, "S-Video" }, { 0, "Internal/comp" } }, - .norms = 3, + .norms = V4L2_STD_NTSC|V4L2_STD_PAL|V4L2_STD_SECAM, .tvn = { &f50sqpixel_dc10, &f60sqpixel_dc10, @@ -552,7 +549,7 @@ static struct card_info zoran_cards[NUM_CARDS] __devinitdata = { { 2, "S-Video" }, { 0, "Internal/comp" } }, - .norms = 3, + .norms = V4L2_STD_NTSC|V4L2_STD_PAL|V4L2_STD_SECAM, .tvn = { &f50sqpixel_dc10, &f60sqpixel_dc10, @@ -579,7 +576,7 @@ static struct card_info zoran_cards[NUM_CARDS] __devinitdata = { { 0, "Composite" }, { 7, "S-Video" } }, - .norms = 2, + .norms = V4L2_STD_NTSC|V4L2_STD_PAL, .tvn = { &f50ccir601_lml33, &f60ccir601_lml33, @@ -597,7 +594,7 @@ static struct card_info zoran_cards[NUM_CARDS] __devinitdata = { }, { .type = LML33R10, .name = "LML33R10", - .i2c_decoder = I2C_DRIVERID_SAA7114, + .i2c_decoder = I2C_DRIVERID_SAA711X, .i2c_encoder = I2C_DRIVERID_ADV7170, .video_codec = CODEC_TYPE_ZR36060, @@ -606,7 +603,7 @@ static struct card_info zoran_cards[NUM_CARDS] __devinitdata = { { 0, "Composite" }, { 7, "S-Video" } }, - .norms = 2, + .norms = V4L2_STD_NTSC|V4L2_STD_PAL, .tvn = { &f50ccir601_lm33r10, &f60ccir601_lm33r10, @@ -624,7 +621,7 @@ static struct card_info zoran_cards[NUM_CARDS] __devinitdata = { }, { .type = BUZ, .name = "Buz", - .i2c_decoder = I2C_DRIVERID_SAA7111A, + .i2c_decoder = I2C_DRIVERID_SAA711X, .i2c_encoder = I2C_DRIVERID_SAA7185B, .video_codec = CODEC_TYPE_ZR36060, @@ -633,7 +630,7 @@ static struct card_info zoran_cards[NUM_CARDS] __devinitdata = { { 3, "Composite" }, { 7, "S-Video" } }, - .norms = 3, + .norms = V4L2_STD_NTSC|V4L2_STD_PAL|V4L2_STD_SECAM, .tvn = { &f50ccir601, &f60ccir601, @@ -670,7 +667,7 @@ static struct card_info zoran_cards[NUM_CARDS] __devinitdata = { {10, "S-Video 3" }, {15, "YCbCr" } }, - .norms = 2, + .norms = V4L2_STD_NTSC|V4L2_STD_PAL, .tvn = { &f50ccir601_avs6eyes, &f60ccir601_avs6eyes, @@ -1086,8 +1083,6 @@ static int __devinit zr36057_init (struct zoran *zr) { int j, err; - int two = 2; - int zero = 0; dprintk(1, KERN_INFO @@ -1113,14 +1108,23 @@ zr36057_init (struct zoran *zr) if (default_norm < VIDEO_MODE_PAL && default_norm > VIDEO_MODE_SECAM) default_norm = VIDEO_MODE_PAL; - zr->norm = default_norm; - if (!(zr->timing = zr->card.tvn[zr->norm])) { + if (default_norm == VIDEO_MODE_PAL) { + zr->norm = V4L2_STD_PAL; + zr->timing = zr->card.tvn[0]; + } else if (default_norm == VIDEO_MODE_NTSC) { + zr->norm = V4L2_STD_NTSC; + zr->timing = zr->card.tvn[1]; + } else { + zr->norm = V4L2_STD_SECAM; + zr->timing = zr->card.tvn[2]; + } + if (zr->timing == NULL) { dprintk(1, KERN_WARNING "%s: zr36057_init() - default TV standard not supported by hardware. PAL will be used.\n", ZR_DEVNAME(zr)); - zr->norm = VIDEO_MODE_PAL; - zr->timing = zr->card.tvn[zr->norm]; + zr->norm = V4L2_STD_PAL; + zr->timing = zr->card.tvn[0]; } if (default_input > zr->card.inputs-1) { @@ -1132,12 +1136,6 @@ zr36057_init (struct zoran *zr) } zr->input = default_input; - /* Should the following be reset at every open ? */ - zr->hue = 32768; - zr->contrast = 32768; - zr->saturation = 32768; - zr->brightness = 32768; - /* default setup (will be repeated at every open) */ zoran_open_init_params(zr); @@ -1173,8 +1171,10 @@ zr36057_init (struct zoran *zr) detect_guest_activity(zr); test_interrupts(zr); if (!pass_through) { - decoder_command(zr, DECODER_ENABLE_OUTPUT, &zero); - encoder_command(zr, ENCODER_SET_INPUT, &two); + struct v4l2_routing route = { 2, 0 }; + + decoder_command(zr, VIDIOC_STREAMOFF, 0); + encoder_command(zr, VIDIOC_INT_S_VIDEO_ROUTING, &route); } zr->zoran_proc = NULL; diff --git a/drivers/media/video/zoran/zoran_device.c b/drivers/media/video/zoran/zoran_device.c index 1bcfa270d63d..712599a5ed72 100644 --- a/drivers/media/video/zoran/zoran_device.c +++ b/drivers/media/video/zoran/zoran_device.c @@ -37,6 +37,8 @@ #include #include #include +#include +#include #include #include @@ -312,9 +314,9 @@ zr36057_adjust_vfe (struct zoran *zr, case BUZ_MODE_MOTION_COMPRESS: case BUZ_MODE_IDLE: default: - if (zr->norm == VIDEO_MODE_NTSC || + if ((zr->norm & V4L2_STD_NTSC) || (zr->card.type == LML33R10 && - zr->norm == VIDEO_MODE_PAL)) + (zr->norm & V4L2_STD_PAL))) btand(~ZR36057_VFESPFR_ExtFl, ZR36057_VFESPFR); else btor(ZR36057_VFESPFR_ExtFl, ZR36057_VFESPFR); @@ -355,14 +357,6 @@ zr36057_set_vfe (struct zoran *zr, dprintk(2, KERN_INFO "%s: set_vfe() - width = %d, height = %d\n", ZR_DEVNAME(zr), video_width, video_height); - if (zr->norm != VIDEO_MODE_PAL && - zr->norm != VIDEO_MODE_NTSC && - zr->norm != VIDEO_MODE_SECAM) { - dprintk(1, - KERN_ERR "%s: set_vfe() - norm = %d not valid\n", - ZR_DEVNAME(zr), zr->norm); - return; - } if (video_width < BUZ_MIN_WIDTH || video_height < BUZ_MIN_HEIGHT || video_width > Wa || video_height > Ha) { @@ -426,7 +420,7 @@ zr36057_set_vfe (struct zoran *zr, * we get the correct colors when uncompressing to the screen */ //reg |= ZR36057_VFESPFR_VCLKPol; /**/ /* RJ: Don't know if that is needed for NTSC also */ - if (zr->norm != VIDEO_MODE_NTSC) + if (!(zr->norm & V4L2_STD_NTSC)) reg |= ZR36057_VFESPFR_ExtFl; // NEEDED!!!!!!! Wolfgang reg |= ZR36057_VFESPFR_TopField; if (HorDcm >= 48) { @@ -981,11 +975,10 @@ void zr36057_enable_jpg (struct zoran *zr, enum zoran_codec_mode mode) { - static int zero; - static int one = 1; struct vfe_settings cap; int field_size = zr->jpg_buffers.buffer_size / zr->jpg_settings.field_per_buff; + struct v4l2_routing route = { 0, 0 }; zr->codec_mode = mode; @@ -1007,8 +1000,9 @@ zr36057_enable_jpg (struct zoran *zr, * the video bus direction set to input. */ set_videobus_dir(zr, 0); - decoder_command(zr, DECODER_ENABLE_OUTPUT, &one); - encoder_command(zr, ENCODER_SET_INPUT, &zero); + decoder_command(zr, VIDIOC_STREAMON, 0); + route.input = 0; + encoder_command(zr, VIDIOC_INT_S_VIDEO_ROUTING, &route); /* Take the JPEG codec and the VFE out of sleep */ jpeg_codec_sleep(zr, 0); @@ -1054,9 +1048,10 @@ zr36057_enable_jpg (struct zoran *zr, /* In motion decompression mode, the decoder output must be disabled, and * the video bus direction set to output. */ - decoder_command(zr, DECODER_ENABLE_OUTPUT, &zero); + decoder_command(zr, VIDIOC_STREAMOFF, 0); set_videobus_dir(zr, 1); - encoder_command(zr, ENCODER_SET_INPUT, &one); + route.input = 1; + encoder_command(zr, VIDIOC_INT_S_VIDEO_ROUTING, &route); /* Take the JPEG codec and the VFE out of sleep */ jpeg_codec_sleep(zr, 0); @@ -1100,8 +1095,9 @@ zr36057_enable_jpg (struct zoran *zr, jpeg_codec_sleep(zr, 1); zr36057_adjust_vfe(zr, mode); - decoder_command(zr, DECODER_ENABLE_OUTPUT, &one); - encoder_command(zr, ENCODER_SET_INPUT, &zero); + decoder_command(zr, VIDIOC_STREAMON, 0); + route.input = 0; + encoder_command(zr, VIDIOC_INT_S_VIDEO_ROUTING, &route); dprintk(2, KERN_INFO "%s: enable_jpg(IDLE)\n", ZR_DEVNAME(zr)); break; @@ -1211,17 +1207,17 @@ zoran_reap_stat_com (struct zoran *zr) static void zoran_restart(struct zoran *zr) { /* Now the stat_comm buffer is ready for restart */ - int status, mode; + int status = 0, mode; if (zr->codec_mode == BUZ_MODE_MOTION_COMPRESS) { - decoder_command(zr, DECODER_GET_STATUS, &status); + decoder_command(zr, VIDIOC_INT_G_INPUT_STATUS, &status); mode = CODEC_DO_COMPRESSION; } else { - status = 0; + status = V4L2_IN_ST_NO_SIGNAL; mode = CODEC_DO_EXPANSION; } if (zr->codec_mode == BUZ_MODE_MOTION_DECOMPRESS || - (status & DECODER_STATUS_GOOD)) { + !(status & V4L2_IN_ST_NO_SIGNAL)) { /********** RESTART code *************/ jpeg_codec_reset(zr); zr->codec->set_mode(zr->codec, mode); @@ -1582,7 +1578,7 @@ zoran_set_pci_master (struct zoran *zr, void zoran_init_hardware (struct zoran *zr) { - int j, zero = 0; + struct v4l2_routing route = { 0, 0 }; /* Enable bus-mastering */ zoran_set_pci_master(zr, 1); @@ -1592,15 +1588,16 @@ zoran_init_hardware (struct zoran *zr) zr->card.init(zr); } - j = zr->card.input[zr->input].muxsel; + route.input = zr->card.input[zr->input].muxsel; - decoder_command(zr, 0, NULL); - decoder_command(zr, DECODER_SET_NORM, &zr->norm); - decoder_command(zr, DECODER_SET_INPUT, &j); + decoder_command(zr, VIDIOC_INT_INIT, NULL); + decoder_command(zr, VIDIOC_S_STD, &zr->norm); + decoder_command(zr, VIDIOC_INT_S_VIDEO_ROUTING, &route); - encoder_command(zr, 0, NULL); - encoder_command(zr, ENCODER_SET_NORM, &zr->norm); - encoder_command(zr, ENCODER_SET_INPUT, &zero); + encoder_command(zr, VIDIOC_INT_INIT, NULL); + encoder_command(zr, VIDIOC_INT_S_STD_OUTPUT, &zr->norm); + route.input = 0; + encoder_command(zr, VIDIOC_INT_S_VIDEO_ROUTING, &route); /* toggle JPEG codec sleep to sync PLL */ jpeg_codec_sleep(zr, 1); @@ -1674,7 +1671,7 @@ decoder_command (struct zoran *zr, return -EIO; if (zr->card.type == LML33 && - (cmd == DECODER_SET_NORM || cmd == DECODER_SET_INPUT)) { + (cmd == VIDIOC_S_STD || cmd == VIDIOC_INT_S_VIDEO_ROUTING)) { int res; // Bt819 needs to reset its FIFO buffer using #FRST pin and diff --git a/drivers/media/video/zoran/zoran_driver.c b/drivers/media/video/zoran/zoran_driver.c index 07f2bdfef4ee..ed8ac660a0c1 100644 --- a/drivers/media/video/zoran/zoran_driver.c +++ b/drivers/media/video/zoran/zoran_driver.c @@ -1145,9 +1145,10 @@ zoran_close(struct file *file) zoran_set_pci_master(zr, 0); if (!pass_through) { /* Switch to color bar */ - int zero = 0, two = 2; - decoder_command(zr, DECODER_ENABLE_OUTPUT, &zero); - encoder_command(zr, ENCODER_SET_INPUT, &two); + struct v4l2_routing route = { 2, 0 }; + + decoder_command(zr, VIDIOC_STREAMOFF, 0); + encoder_command(zr, VIDIOC_INT_S_VIDEO_ROUTING, &route); } } @@ -1569,9 +1570,9 @@ zoran_v4l2_buffer_status (struct file *file, static int zoran_set_norm (struct zoran *zr, - int norm) /* VIDEO_MODE_* */ + v4l2_std_id norm) { - int norm_encoder, on; + int on; if (zr->v4l_buffers.active != ZORAN_FREE || zr->jpg_buffers.active != ZORAN_FREE) { @@ -1598,52 +1599,42 @@ zoran_set_norm (struct zoran *zr, } } - if (norm != VIDEO_MODE_AUTO && - (norm < 0 || norm >= zr->card.norms || - !zr->card.tvn[norm])) { + if (!(norm & zr->card.norms)) { dprintk(1, - KERN_ERR "%s: set_norm() - unsupported norm %d\n", + KERN_ERR "%s: set_norm() - unsupported norm %llx\n", ZR_DEVNAME(zr), norm); return -EINVAL; } - if (norm == VIDEO_MODE_AUTO) { - int status; + if (norm == V4L2_STD_ALL) { + int status = 0; + v4l2_std_id std = 0; - /* if we have autodetect, ... */ - struct video_decoder_capability caps; - decoder_command(zr, DECODER_GET_CAPABILITIES, &caps); - if (!(caps.flags & VIDEO_DECODER_AUTO)) { - dprintk(1, KERN_ERR "%s: norm=auto unsupported\n", - ZR_DEVNAME(zr)); - return -EINVAL; - } - - decoder_command(zr, DECODER_SET_NORM, &norm); + decoder_command(zr, VIDIOC_QUERYSTD, &std); + decoder_command(zr, VIDIOC_S_STD, &std); /* let changes come into effect */ ssleep(2); - decoder_command(zr, DECODER_GET_STATUS, &status); - if (!(status & DECODER_STATUS_GOOD)) { + decoder_command(zr, VIDIOC_INT_G_INPUT_STATUS, &status); + if (status & V4L2_IN_ST_NO_SIGNAL) { dprintk(1, KERN_ERR "%s: set_norm() - no norm detected\n", ZR_DEVNAME(zr)); /* reset norm */ - decoder_command(zr, DECODER_SET_NORM, &zr->norm); + decoder_command(zr, VIDIOC_S_STD, &zr->norm); return -EIO; } - if (status & DECODER_STATUS_NTSC) - norm = VIDEO_MODE_NTSC; - else if (status & DECODER_STATUS_SECAM) - norm = VIDEO_MODE_SECAM; - else - norm = VIDEO_MODE_PAL; + norm = std; } - zr->timing = zr->card.tvn[norm]; - norm_encoder = norm; + if (norm & V4L2_STD_SECAM) + zr->timing = zr->card.tvn[2]; + else if (norm & V4L2_STD_NTSC) + zr->timing = zr->card.tvn[1]; + else + zr->timing = zr->card.tvn[0]; /* We switch overlay off and on since a change in the * norm needs different VFE settings */ @@ -1651,8 +1642,8 @@ zoran_set_norm (struct zoran *zr, if (on) zr36057_overlay(zr, 0); - decoder_command(zr, DECODER_SET_NORM, &norm); - encoder_command(zr, ENCODER_SET_NORM, &norm_encoder); + decoder_command(zr, VIDIOC_S_STD, &norm); + encoder_command(zr, VIDIOC_INT_S_STD_OUTPUT, &norm); if (on) zr36057_overlay(zr, 1); @@ -1667,7 +1658,7 @@ static int zoran_set_input (struct zoran *zr, int input) { - int realinput; + struct v4l2_routing route = { 0, 0 }; if (input == zr->input) { return 0; @@ -1690,10 +1681,10 @@ zoran_set_input (struct zoran *zr, return -EINVAL; } - realinput = zr->card.input[input].muxsel; + route.input = zr->card.input[input].muxsel; zr->input = input; - decoder_command(zr, DECODER_SET_INPUT, &realinput); + decoder_command(zr, VIDIOC_INT_S_VIDEO_ROUTING, &route); return 0; } @@ -1722,7 +1713,13 @@ static long zoran_default(struct file *file, void *__fh, int cmd, void *arg) mutex_lock(&zr->resource_lock); - bparams->norm = zr->norm; + if (zr->norm & V4L2_STD_NTSC) + bparams->norm = VIDEO_MODE_NTSC; + else if (zr->norm & V4L2_STD_PAL) + bparams->norm = VIDEO_MODE_PAL; + else + bparams->norm = VIDEO_MODE_SECAM; + bparams->input = zr->input; bparams->decimation = fh->jpg_settings.decimation; @@ -1905,7 +1902,9 @@ jpgreqbuf_unlock_and_return: case BUZIOC_G_STATUS: { struct zoran_status *bstat = arg; - int norm, input, status, res = 0; + struct v4l2_routing route = { 0, 0 }; + int status = 0, res = 0; + v4l2_std_id norm; dprintk(3, KERN_DEBUG "%s: BUZIOC_G_STATUS\n", ZR_DEVNAME(zr)); @@ -1917,8 +1916,7 @@ jpgreqbuf_unlock_and_return: return -EINVAL; } - input = zr->card.input[bstat->input].muxsel; - norm = VIDEO_MODE_AUTO; + route.input = zr->card.input[bstat->input].muxsel; mutex_lock(&zr->resource_lock); @@ -1931,34 +1929,33 @@ jpgreqbuf_unlock_and_return: goto gstat_unlock_and_return; } - decoder_command(zr, DECODER_SET_INPUT, &input); - decoder_command(zr, DECODER_SET_NORM, &norm); + decoder_command(zr, VIDIOC_INT_S_VIDEO_ROUTING, &route); /* sleep 1 second */ ssleep(1); /* Get status of video decoder */ - decoder_command(zr, DECODER_GET_STATUS, &status); + decoder_command(zr, VIDIOC_QUERYSTD, &norm); + decoder_command(zr, VIDIOC_INT_G_INPUT_STATUS, &status); /* restore previous input and norm */ - input = zr->card.input[zr->input].muxsel; - decoder_command(zr, DECODER_SET_INPUT, &input); - decoder_command(zr, DECODER_SET_NORM, &zr->norm); + route.input = zr->card.input[zr->input].muxsel; + decoder_command(zr, VIDIOC_INT_S_VIDEO_ROUTING, &route); gstat_unlock_and_return: mutex_unlock(&zr->resource_lock); if (!res) { bstat->signal = - (status & DECODER_STATUS_GOOD) ? 1 : 0; - if (status & DECODER_STATUS_NTSC) + (status & V4L2_IN_ST_NO_SIGNAL) ? 0 : 1; + if (norm & V4L2_STD_NTSC) bstat->norm = VIDEO_MODE_NTSC; - else if (status & DECODER_STATUS_SECAM) + else if (norm & V4L2_STD_SECAM) bstat->norm = VIDEO_MODE_SECAM; else bstat->norm = VIDEO_MODE_PAL; bstat->color = - (status & DECODER_STATUS_COLOR) ? 1 : 0; + (status & V4L2_IN_ST_NO_COLOR) ? 0 : 1; } return res; @@ -2867,37 +2864,15 @@ strmoff_unlock_and_return: static int zoran_queryctrl(struct file *file, void *__fh, struct v4l2_queryctrl *ctrl) { + struct zoran_fh *fh = __fh; + struct zoran *zr = fh->zr; + /* we only support hue/saturation/contrast/brightness */ if (ctrl->id < V4L2_CID_BRIGHTNESS || ctrl->id > V4L2_CID_HUE) return -EINVAL; - else { - int id = ctrl->id; - memset(ctrl, 0, sizeof(*ctrl)); - ctrl->id = id; - } - - switch (ctrl->id) { - case V4L2_CID_BRIGHTNESS: - strncpy(ctrl->name, "Brightness", sizeof(ctrl->name)-1); - break; - case V4L2_CID_CONTRAST: - strncpy(ctrl->name, "Contrast", sizeof(ctrl->name)-1); - break; - case V4L2_CID_SATURATION: - strncpy(ctrl->name, "Saturation", sizeof(ctrl->name)-1); - break; - case V4L2_CID_HUE: - strncpy(ctrl->name, "Hue", sizeof(ctrl->name)-1); - break; - } - ctrl->minimum = 0; - ctrl->maximum = 65535; - ctrl->step = 1; - ctrl->default_value = 32768; - ctrl->type = V4L2_CTRL_TYPE_INTEGER; - ctrl->flags = V4L2_CTRL_FLAG_SLIDER; + decoder_command(zr, VIDIOC_QUERYCTRL, ctrl); return 0; } @@ -2913,20 +2888,7 @@ static int zoran_g_ctrl(struct file *file, void *__fh, struct v4l2_control *ctrl return -EINVAL; mutex_lock(&zr->resource_lock); - switch (ctrl->id) { - case V4L2_CID_BRIGHTNESS: - ctrl->value = zr->brightness; - break; - case V4L2_CID_CONTRAST: - ctrl->value = zr->contrast; - break; - case V4L2_CID_SATURATION: - ctrl->value = zr->saturation; - break; - case V4L2_CID_HUE: - ctrl->value = zr->hue; - break; - } + decoder_command(zr, VIDIOC_G_CTRL, ctrl); mutex_unlock(&zr->resource_lock); return 0; @@ -2936,42 +2898,14 @@ static int zoran_s_ctrl(struct file *file, void *__fh, struct v4l2_control *ctrl { struct zoran_fh *fh = __fh; struct zoran *zr = fh->zr; - struct video_picture pict; /* we only support hue/saturation/contrast/brightness */ if (ctrl->id < V4L2_CID_BRIGHTNESS || ctrl->id > V4L2_CID_HUE) return -EINVAL; - if (ctrl->value < 0 || ctrl->value > 65535) { - dprintk(1, KERN_ERR - "%s: VIDIOC_S_CTRL - invalid value %d for id=%d\n", - ZR_DEVNAME(zr), ctrl->value, ctrl->id); - return -EINVAL; - } - mutex_lock(&zr->resource_lock); - switch (ctrl->id) { - case V4L2_CID_BRIGHTNESS: - zr->brightness = ctrl->value; - break; - case V4L2_CID_CONTRAST: - zr->contrast = ctrl->value; - break; - case V4L2_CID_SATURATION: - zr->saturation = ctrl->value; - break; - case V4L2_CID_HUE: - zr->hue = ctrl->value; - break; - } - pict.brightness = zr->brightness; - pict.contrast = zr->contrast; - pict.colour = zr->saturation; - pict.hue = zr->hue; - - decoder_command(zr, DECODER_SET_PICTURE, &pict); - + decoder_command(zr, VIDIOC_S_CTRL, ctrl); mutex_unlock(&zr->resource_lock); return 0; @@ -2981,24 +2915,10 @@ static int zoran_g_std(struct file *file, void *__fh, v4l2_std_id *std) { struct zoran_fh *fh = __fh; struct zoran *zr = fh->zr; - int norm; mutex_lock(&zr->resource_lock); - norm = zr->norm; + *std = zr->norm; mutex_unlock(&zr->resource_lock); - - switch (norm) { - case VIDEO_MODE_PAL: - *std = V4L2_STD_PAL; - break; - case VIDEO_MODE_NTSC: - *std = V4L2_STD_NTSC; - break; - case VIDEO_MODE_SECAM: - *std = V4L2_STD_SECAM; - break; - } - return 0; } @@ -3006,25 +2926,10 @@ static int zoran_s_std(struct file *file, void *__fh, v4l2_std_id *std) { struct zoran_fh *fh = __fh; struct zoran *zr = fh->zr; - int norm = -1, res = 0; - - if ((*std & V4L2_STD_PAL) && !(*std & ~V4L2_STD_PAL)) - norm = VIDEO_MODE_PAL; - else if ((*std & V4L2_STD_NTSC) && !(*std & ~V4L2_STD_NTSC)) - norm = VIDEO_MODE_NTSC; - else if ((*std & V4L2_STD_SECAM) && !(*std & ~V4L2_STD_SECAM)) - norm = VIDEO_MODE_SECAM; - else if (*std == V4L2_STD_ALL) - norm = VIDEO_MODE_AUTO; - else { - dprintk(1, KERN_ERR - "%s: VIDIOC_S_STD - invalid norm 0x%llx\n", - ZR_DEVNAME(zr), (unsigned long long)*std); - return -EINVAL; - } + int res = 0; mutex_lock(&zr->resource_lock); - res = zoran_set_norm(zr, norm); + res = zoran_set_norm(zr, *std); if (res) goto sstd_unlock_and_return; @@ -3039,7 +2944,6 @@ static int zoran_enum_input(struct file *file, void *__fh, { struct zoran_fh *fh = __fh; struct zoran *zr = fh->zr; - int status; if (inp->index < 0 || inp->index >= zr->card.inputs) return -EINVAL; @@ -3056,16 +2960,8 @@ static int zoran_enum_input(struct file *file, void *__fh, /* Get status of video decoder */ mutex_lock(&zr->resource_lock); - decoder_command(zr, DECODER_GET_STATUS, &status); + decoder_command(zr, VIDIOC_INT_G_INPUT_STATUS, &inp->status); mutex_unlock(&zr->resource_lock); - - if (!(status & DECODER_STATUS_GOOD)) { - inp->status |= V4L2_IN_ST_NO_POWER; - inp->status |= V4L2_IN_ST_NO_SIGNAL; - } - if (!(status & DECODER_STATUS_COLOR)) - inp->status |= V4L2_IN_ST_NO_COLOR; - return 0; } -- cgit v1.2.3 From 602dd48a35e8697be441d1749103187e6b5a922a Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 18 Feb 2009 17:39:45 -0300 Subject: V4L/DVB (10715): zoran: clean up some old V4L1 left-overs and remove the MAP_NR macro. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/zoran/zoran.h | 3 - drivers/media/video/zoran/zoran_driver.c | 130 ++++++++++--------------------- 2 files changed, 43 insertions(+), 90 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/zoran/zoran.h b/drivers/media/video/zoran/zoran.h index ee31bfc3428f..a323eb66e7cf 100644 --- a/drivers/media/video/zoran/zoran.h +++ b/drivers/media/video/zoran/zoran.h @@ -238,9 +238,6 @@ enum gpcs_type { struct zoran_format { char *name; -#ifdef CONFIG_VIDEO_V4L1_COMPAT - int palette; -#endif __u32 fourcc; int colorspace; int depth; diff --git a/drivers/media/video/zoran/zoran_driver.c b/drivers/media/video/zoran/zoran_driver.c index ed8ac660a0c1..a3a6f61187b0 100644 --- a/drivers/media/video/zoran/zoran_driver.c +++ b/drivers/media/video/zoran/zoran_driver.c @@ -58,16 +58,6 @@ #include #include -#define MAP_NR(x) virt_to_page(x) -#define ZORAN_VID_TYPE ( \ - VID_TYPE_CAPTURE | \ - VID_TYPE_OVERLAY | \ - VID_TYPE_CLIPPING | \ - VID_TYPE_FRAMERAM | \ - VID_TYPE_SCALES | \ - VID_TYPE_MJPEG_DECODER | \ - VID_TYPE_MJPEG_ENCODER \ - ) #include #include @@ -86,29 +76,12 @@ #include "zoran_device.h" #include "zoran_card.h" - /* we declare some card type definitions here, they mean - * the same as the v4l1 ZORAN_VID_TYPE above, except it's v4l2 */ -#define ZORAN_V4L2_VID_FLAGS ( \ - V4L2_CAP_STREAMING |\ - V4L2_CAP_VIDEO_CAPTURE |\ - V4L2_CAP_VIDEO_OUTPUT |\ - V4L2_CAP_VIDEO_OVERLAY \ - ) - - -#if defined(CONFIG_VIDEO_V4L1_COMPAT) -#define ZFMT(pal, fcc, cs) \ - .palette = (pal), .fourcc = (fcc), .colorspace = (cs) -#else -#define ZFMT(pal, fcc, cs) \ - .fourcc = (fcc), .colorspace = (cs) -#endif const struct zoran_format zoran_formats[] = { { .name = "15-bit RGB LE", - ZFMT(VIDEO_PALETTE_RGB555, - V4L2_PIX_FMT_RGB555, V4L2_COLORSPACE_SRGB), + .fourcc = V4L2_PIX_FMT_RGB555, + .colorspace = V4L2_COLORSPACE_SRGB, .depth = 15, .flags = ZORAN_FORMAT_CAPTURE | ZORAN_FORMAT_OVERLAY, @@ -116,16 +89,16 @@ const struct zoran_format zoran_formats[] = { ZR36057_VFESPFR_LittleEndian, }, { .name = "15-bit RGB BE", - ZFMT(-1, - V4L2_PIX_FMT_RGB555X, V4L2_COLORSPACE_SRGB), + .fourcc = V4L2_PIX_FMT_RGB555X, + .colorspace = V4L2_COLORSPACE_SRGB, .depth = 15, .flags = ZORAN_FORMAT_CAPTURE | ZORAN_FORMAT_OVERLAY, .vfespfr = ZR36057_VFESPFR_RGB555|ZR36057_VFESPFR_ErrDif, }, { .name = "16-bit RGB LE", - ZFMT(VIDEO_PALETTE_RGB565, - V4L2_PIX_FMT_RGB565, V4L2_COLORSPACE_SRGB), + .fourcc = V4L2_PIX_FMT_RGB565, + .colorspace = V4L2_COLORSPACE_SRGB, .depth = 16, .flags = ZORAN_FORMAT_CAPTURE | ZORAN_FORMAT_OVERLAY, @@ -133,56 +106,56 @@ const struct zoran_format zoran_formats[] = { ZR36057_VFESPFR_LittleEndian, }, { .name = "16-bit RGB BE", - ZFMT(-1, - V4L2_PIX_FMT_RGB565X, V4L2_COLORSPACE_SRGB), + .fourcc = V4L2_PIX_FMT_RGB565X, + .colorspace = V4L2_COLORSPACE_SRGB, .depth = 16, .flags = ZORAN_FORMAT_CAPTURE | ZORAN_FORMAT_OVERLAY, .vfespfr = ZR36057_VFESPFR_RGB565|ZR36057_VFESPFR_ErrDif, }, { .name = "24-bit RGB", - ZFMT(VIDEO_PALETTE_RGB24, - V4L2_PIX_FMT_BGR24, V4L2_COLORSPACE_SRGB), + .fourcc = V4L2_PIX_FMT_BGR24, + .colorspace = V4L2_COLORSPACE_SRGB, .depth = 24, .flags = ZORAN_FORMAT_CAPTURE | ZORAN_FORMAT_OVERLAY, .vfespfr = ZR36057_VFESPFR_RGB888|ZR36057_VFESPFR_Pack24, }, { .name = "32-bit RGB LE", - ZFMT(VIDEO_PALETTE_RGB32, - V4L2_PIX_FMT_BGR32, V4L2_COLORSPACE_SRGB), + .fourcc = V4L2_PIX_FMT_BGR32, + .colorspace = V4L2_COLORSPACE_SRGB, .depth = 32, .flags = ZORAN_FORMAT_CAPTURE | ZORAN_FORMAT_OVERLAY, .vfespfr = ZR36057_VFESPFR_RGB888|ZR36057_VFESPFR_LittleEndian, }, { .name = "32-bit RGB BE", - ZFMT(-1, - V4L2_PIX_FMT_RGB32, V4L2_COLORSPACE_SRGB), + .fourcc = V4L2_PIX_FMT_RGB32, + .colorspace = V4L2_COLORSPACE_SRGB, .depth = 32, .flags = ZORAN_FORMAT_CAPTURE | ZORAN_FORMAT_OVERLAY, .vfespfr = ZR36057_VFESPFR_RGB888, }, { .name = "4:2:2, packed, YUYV", - ZFMT(VIDEO_PALETTE_YUV422, - V4L2_PIX_FMT_YUYV, V4L2_COLORSPACE_SMPTE170M), + .fourcc = V4L2_PIX_FMT_YUYV, + .colorspace = V4L2_COLORSPACE_SMPTE170M, .depth = 16, .flags = ZORAN_FORMAT_CAPTURE | ZORAN_FORMAT_OVERLAY, .vfespfr = ZR36057_VFESPFR_YUV422, }, { .name = "4:2:2, packed, UYVY", - ZFMT(VIDEO_PALETTE_UYVY, - V4L2_PIX_FMT_UYVY, V4L2_COLORSPACE_SMPTE170M), + .fourcc = V4L2_PIX_FMT_UYVY, + .colorspace = V4L2_COLORSPACE_SMPTE170M, .depth = 16, .flags = ZORAN_FORMAT_CAPTURE | ZORAN_FORMAT_OVERLAY, .vfespfr = ZR36057_VFESPFR_YUV422|ZR36057_VFESPFR_LittleEndian, }, { .name = "Hardware-encoded Motion-JPEG", - ZFMT(-1, - V4L2_PIX_FMT_MJPEG, V4L2_COLORSPACE_SMPTE170M), + .fourcc = V4L2_PIX_FMT_MJPEG, + .colorspace = V4L2_COLORSPACE_SMPTE170M, .depth = 0, .flags = ZORAN_FORMAT_CAPTURE | ZORAN_FORMAT_PLAYBACK | @@ -260,7 +233,7 @@ v4l_fbuffer_alloc (struct file *file) virt_to_bus(mem); for (off = 0; off < fh->v4l_buffers.buffer_size; off += PAGE_SIZE) - SetPageReserved(MAP_NR(mem + off)); + SetPageReserved(virt_to_page(mem + off)); dprintk(4, KERN_INFO "%s: v4l_fbuffer_alloc() - V4L frame %d mem 0x%lx (bus: 0x%lx)\n", @@ -291,7 +264,7 @@ v4l_fbuffer_free (struct file *file) mem = fh->v4l_buffers.buffer[i].fbuffer; for (off = 0; off < fh->v4l_buffers.buffer_size; off += PAGE_SIZE) - ClearPageReserved(MAP_NR(mem + off)); + ClearPageReserved(virt_to_page(mem + off)); kfree((void *) fh->v4l_buffers.buffer[i].fbuffer); fh->v4l_buffers.buffer[i].fbuffer = NULL; } @@ -377,7 +350,7 @@ jpg_fbuffer_alloc (struct file *file) cpu_to_le32(((fh->jpg_buffers.buffer_size / 4) << 1) | 1); for (off = 0; off < fh->jpg_buffers.buffer_size; off += PAGE_SIZE) - SetPageReserved(MAP_NR(mem + off)); + SetPageReserved(virt_to_page(mem + off)); } else { /* jpg_bufsize is already page aligned */ for (j = 0; @@ -398,7 +371,7 @@ jpg_fbuffer_alloc (struct file *file) fh->jpg_buffers.buffer[i].frag_tab[2 * j + 1] = cpu_to_le32((PAGE_SIZE / 4) << 1); - SetPageReserved(MAP_NR(mem)); + SetPageReserved(virt_to_page(mem)); } fh->jpg_buffers.buffer[i].frag_tab[2 * j - 1] |= cpu_to_le32(1); @@ -424,6 +397,7 @@ jpg_fbuffer_free (struct file *file) struct zoran *zr = fh->zr; int i, j, off; unsigned char *mem; + __le32 frag_tab; dprintk(4, KERN_DEBUG "%s: jpg_fbuffer_free()\n", ZR_DEVNAME(zr)); @@ -431,48 +405,31 @@ jpg_fbuffer_free (struct file *file) if (!fh->jpg_buffers.buffer[i].frag_tab) continue; - //if (alloc_contig) { if (fh->jpg_buffers.need_contiguous) { - if (fh->jpg_buffers.buffer[i].frag_tab[0]) { - mem = (unsigned char *) bus_to_virt(le32_to_cpu( - fh->jpg_buffers.buffer[i].frag_tab[0])); - for (off = 0; - off < fh->jpg_buffers.buffer_size; - off += PAGE_SIZE) - ClearPageReserved(MAP_NR - (mem + off)); + frag_tab = fh->jpg_buffers.buffer[i].frag_tab[0]; + + if (frag_tab) { + mem = (unsigned char *)bus_to_virt(le32_to_cpu(frag_tab)); + for (off = 0; off < fh->jpg_buffers.buffer_size; off += PAGE_SIZE) + ClearPageReserved(virt_to_page(mem + off)); kfree(mem); fh->jpg_buffers.buffer[i].frag_tab[0] = 0; fh->jpg_buffers.buffer[i].frag_tab[1] = 0; } } else { - for (j = 0; - j < fh->jpg_buffers.buffer_size / PAGE_SIZE; - j++) { - if (!fh->jpg_buffers.buffer[i]. - frag_tab[2 * j]) + for (j = 0; j < fh->jpg_buffers.buffer_size / PAGE_SIZE; j++) { + frag_tab = fh->jpg_buffers.buffer[i].frag_tab[2 * j]; + + if (!frag_tab) break; - ClearPageReserved(MAP_NR - (bus_to_virt - (le32_to_cpu - (fh->jpg_buffers. - buffer[i].frag_tab[2 * - j])))); - free_page((unsigned long) - bus_to_virt - (le32_to_cpu - (fh->jpg_buffers. - buffer[i]. - frag_tab[2 * j]))); - fh->jpg_buffers.buffer[i].frag_tab[2 * j] = - 0; - fh->jpg_buffers.buffer[i].frag_tab[2 * j + - 1] = 0; + ClearPageReserved(virt_to_page(bus_to_virt(le32_to_cpu(frag_tab)))); + free_page((unsigned long)bus_to_virt(le32_to_cpu(frag_tab))); + fh->jpg_buffers.buffer[i].frag_tab[2 * j] = 0; + fh->jpg_buffers.buffer[i].frag_tab[2 * j + 1] = 0; } } - free_page((unsigned long) fh->jpg_buffers.buffer[i]. - frag_tab); + free_page((unsigned long)fh->jpg_buffers.buffer[i].frag_tab); fh->jpg_buffers.buffer[i].frag_tab = NULL; } @@ -2016,11 +1973,10 @@ static int zoran_querycap(struct file *file, void *__fh, struct v4l2_capability strncpy(cap->driver, "zoran", sizeof(cap->driver)-1); snprintf(cap->bus_info, sizeof(cap->bus_info), "PCI:%s", pci_name(zr->pci_dev)); - cap->version = - KERNEL_VERSION(MAJOR_VERSION, MINOR_VERSION, + cap->version = KERNEL_VERSION(MAJOR_VERSION, MINOR_VERSION, RELEASE_VERSION); - cap->capabilities = ZORAN_V4L2_VID_FLAGS; - + cap->capabilities = V4L2_CAP_STREAMING | V4L2_CAP_VIDEO_CAPTURE | + V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_VIDEO_OVERLAY; return 0; } -- cgit v1.2.3 From 497d7d0b92b1eccbd76bbe054d791e471d29b599 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 18 Feb 2009 18:33:35 -0300 Subject: V4L/DVB (10716): zoran: change buffer defaults to something that works with tvtime By popular request increased the default number and size of the buffers to something that tvtime likes. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/zoran/zoran_card.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/zoran/zoran_card.c b/drivers/media/video/zoran/zoran_card.c index 51ae37effdeb..38166d40c716 100644 --- a/drivers/media/video/zoran/zoran_card.c +++ b/drivers/media/video/zoran/zoran_card.c @@ -125,8 +125,8 @@ MODULE_PARM_DESC(video_nr, "Video device number (-1=Auto)"); */ -int v4l_nbufs = 2; -int v4l_bufsize = 128; /* Everybody should be able to work with this setting */ +int v4l_nbufs = 4; +int v4l_bufsize = 810; /* Everybody should be able to work with this setting */ module_param(v4l_nbufs, int, 0644); MODULE_PARM_DESC(v4l_nbufs, "Maximum number of V4L buffers to use"); module_param(v4l_bufsize, int, 0644); -- cgit v1.2.3 From 886fe23d1ce99e35f95449a004647d24508a3d63 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 18 Feb 2009 18:34:55 -0300 Subject: V4L/DVB (10717): zoran: TRY_FMT and S_FMT now do the same parameter checks. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/zoran/zoran_driver.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/zoran/zoran_driver.c b/drivers/media/video/zoran/zoran_driver.c index a3a6f61187b0..611fc7f18e16 100644 --- a/drivers/media/video/zoran/zoran_driver.c +++ b/drivers/media/video/zoran/zoran_driver.c @@ -2131,8 +2131,6 @@ static int zoran_try_fmt_vid_out(struct file *file, void *__fh, if (fmt->fmt.pix.pixelformat != V4L2_PIX_FMT_MJPEG) return -EINVAL; - fmt->fmt.pix.bytesperline = 0; - mutex_lock(&zr->resource_lock); settings = fh->jpg_settings; @@ -2157,6 +2155,14 @@ static int zoran_try_fmt_vid_out(struct file *file, void *__fh, else settings.field_per_buff = 1; + if (settings.HorDcm > 1) { + settings.img_x = (BUZ_MAX_WIDTH == 720) ? 8 : 0; + settings.img_width = (BUZ_MAX_WIDTH == 720) ? 704 : BUZ_MAX_WIDTH; + } else { + settings.img_x = 0; + settings.img_width = BUZ_MAX_WIDTH; + } + /* check */ res = zoran_check_jpg_settings(zr, &settings, 1); if (res) @@ -2174,6 +2180,8 @@ static int zoran_try_fmt_vid_out(struct file *file, void *__fh, V4L2_FIELD_TOP : V4L2_FIELD_BOTTOM); fmt->fmt.pix.sizeimage = zoran_v4l2_calc_bufsize(&settings); + fmt->fmt.pix.bytesperline = 0; + fmt->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; tryfmt_unlock_and_return: mutex_unlock(&zr->resource_lock); return res; -- cgit v1.2.3 From 8e4e1d8054b037e867849162ba78cf9b153b0dcc Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Thu, 19 Feb 2009 04:49:29 -0300 Subject: V4L/DVB (10718): bt866: convert to v4l2_subdev. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/bt866.c | 233 +++++++++++++++++++++------------------- include/media/v4l2-chip-ident.h | 3 + 2 files changed, 126 insertions(+), 110 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/bt866.c b/drivers/media/video/bt866.c index 1df24c8776f3..18d383877ece 100644 --- a/drivers/media/video/bt866.c +++ b/drivers/media/video/bt866.c @@ -34,9 +34,9 @@ #include #include #include -#include -#include -#include +#include +#include +#include #include MODULE_DESCRIPTION("Brooktree-866 video encoder driver"); @@ -47,21 +47,25 @@ static int debug; module_param(debug, int, 0); MODULE_PARM_DESC(debug, "Debug level (0-1)"); +static unsigned short normal_i2c[] = { 0x88 >> 1, I2C_CLIENT_END }; + +I2C_CLIENT_INSMOD; + /* ----------------------------------------------------------------------- */ struct bt866 { + struct v4l2_subdev sd; u8 reg[256]; - - v4l2_std_id norm; - int bright; - int contrast; - int hue; - int sat; }; -static int bt866_write(struct i2c_client *client, u8 subaddr, u8 data) +static inline struct bt866 *to_bt866(struct v4l2_subdev *sd) { - struct bt866 *encoder = i2c_get_clientdata(client); + return container_of(sd, struct bt866, sd); +} + +static int bt866_write(struct bt866 *encoder, u8 subaddr, u8 data) +{ + struct i2c_client *client = v4l2_get_subdevdata(&encoder->sd); u8 buffer[2]; int err; @@ -88,119 +92,125 @@ static int bt866_write(struct i2c_client *client, u8 subaddr, u8 data) return 0; } -static int bt866_command(struct i2c_client *client, unsigned cmd, void *arg) +static int bt866_s_std_output(struct v4l2_subdev *sd, v4l2_std_id std) { - struct bt866 *encoder = i2c_get_clientdata(client); - - switch (cmd) { - case VIDIOC_INT_S_STD_OUTPUT: - { - v4l2_std_id *iarg = arg; - - v4l_dbg(1, debug, client, "set norm %llx\n", *iarg); + v4l2_dbg(1, debug, sd, "set norm %llx\n", std); - if (!(*iarg & (V4L2_STD_NTSC | V4L2_STD_PAL))) - return -EINVAL; - encoder->norm = *iarg; - break; - } + /* Only PAL supported by this driver at the moment! */ + if (!(std & V4L2_STD_NTSC)) + return -EINVAL; + return 0; +} - case VIDIOC_INT_S_VIDEO_ROUTING: - { - struct v4l2_routing *route = arg; - static const __u8 init[] = { - 0xc8, 0xcc, /* CRSCALE */ - 0xca, 0x91, /* CBSCALE */ - 0xcc, 0x24, /* YC16 | OSDNUM */ - 0xda, 0x00, /* */ - 0xdc, 0x24, /* SETMODE | PAL */ - 0xde, 0x02, /* EACTIVE */ - - /* overlay colors */ - 0x70, 0xEB, 0x90, 0x80, 0xB0, 0x80, /* white */ - 0x72, 0xA2, 0x92, 0x8E, 0xB2, 0x2C, /* yellow */ - 0x74, 0x83, 0x94, 0x2C, 0xB4, 0x9C, /* cyan */ - 0x76, 0x70, 0x96, 0x3A, 0xB6, 0x48, /* green */ - 0x78, 0x54, 0x98, 0xC6, 0xB8, 0xB8, /* magenta */ - 0x7A, 0x41, 0x9A, 0xD4, 0xBA, 0x64, /* red */ - 0x7C, 0x23, 0x9C, 0x72, 0xBC, 0xD4, /* blue */ - 0x7E, 0x10, 0x9E, 0x80, 0xBE, 0x80, /* black */ - - 0x60, 0xEB, 0x80, 0x80, 0xc0, 0x80, /* white */ - 0x62, 0xA2, 0x82, 0x8E, 0xc2, 0x2C, /* yellow */ - 0x64, 0x83, 0x84, 0x2C, 0xc4, 0x9C, /* cyan */ - 0x66, 0x70, 0x86, 0x3A, 0xc6, 0x48, /* green */ - 0x68, 0x54, 0x88, 0xC6, 0xc8, 0xB8, /* magenta */ - 0x6A, 0x41, 0x8A, 0xD4, 0xcA, 0x64, /* red */ - 0x6C, 0x23, 0x8C, 0x72, 0xcC, 0xD4, /* blue */ - 0x6E, 0x10, 0x8E, 0x80, 0xcE, 0x80, /* black */ - }; - int i; - u8 val; - - for (i = 0; i < ARRAY_SIZE(init) / 2; i += 2) - bt866_write(client, init[i], init[i+1]); - - val = encoder->reg[0xdc]; - - if (route->input == 0) - val |= 0x40; /* CBSWAP */ - else - val &= ~0x40; /* !CBSWAP */ - - bt866_write(client, 0xdc, val); - - val = encoder->reg[0xcc]; - if (route->input == 2) - val |= 0x01; /* OSDBAR */ - else - val &= ~0x01; /* !OSDBAR */ - bt866_write(client, 0xcc, val); - - v4l_dbg(1, debug, client, "set input %d\n", route->input); - - switch (route->input) { - case 0: - break; - case 1: - break; - default: - return -EINVAL; - } +static int bt866_s_routing(struct v4l2_subdev *sd, const struct v4l2_routing *route) +{ + static const __u8 init[] = { + 0xc8, 0xcc, /* CRSCALE */ + 0xca, 0x91, /* CBSCALE */ + 0xcc, 0x24, /* YC16 | OSDNUM */ + 0xda, 0x00, /* */ + 0xdc, 0x24, /* SETMODE | PAL */ + 0xde, 0x02, /* EACTIVE */ + + /* overlay colors */ + 0x70, 0xEB, 0x90, 0x80, 0xB0, 0x80, /* white */ + 0x72, 0xA2, 0x92, 0x8E, 0xB2, 0x2C, /* yellow */ + 0x74, 0x83, 0x94, 0x2C, 0xB4, 0x9C, /* cyan */ + 0x76, 0x70, 0x96, 0x3A, 0xB6, 0x48, /* green */ + 0x78, 0x54, 0x98, 0xC6, 0xB8, 0xB8, /* magenta */ + 0x7A, 0x41, 0x9A, 0xD4, 0xBA, 0x64, /* red */ + 0x7C, 0x23, 0x9C, 0x72, 0xBC, 0xD4, /* blue */ + 0x7E, 0x10, 0x9E, 0x80, 0xBE, 0x80, /* black */ + + 0x60, 0xEB, 0x80, 0x80, 0xc0, 0x80, /* white */ + 0x62, 0xA2, 0x82, 0x8E, 0xc2, 0x2C, /* yellow */ + 0x64, 0x83, 0x84, 0x2C, 0xc4, 0x9C, /* cyan */ + 0x66, 0x70, 0x86, 0x3A, 0xc6, 0x48, /* green */ + 0x68, 0x54, 0x88, 0xC6, 0xc8, 0xB8, /* magenta */ + 0x6A, 0x41, 0x8A, 0xD4, 0xcA, 0x64, /* red */ + 0x6C, 0x23, 0x8C, 0x72, 0xcC, 0xD4, /* blue */ + 0x6E, 0x10, 0x8E, 0x80, 0xcE, 0x80, /* black */ + }; + struct bt866 *encoder = to_bt866(sd); + u8 val; + int i; + + for (i = 0; i < ARRAY_SIZE(init) / 2; i += 2) + bt866_write(encoder, init[i], init[i+1]); + + val = encoder->reg[0xdc]; + + if (route->input == 0) + val |= 0x40; /* CBSWAP */ + else + val &= ~0x40; /* !CBSWAP */ + + bt866_write(encoder, 0xdc, val); + + val = encoder->reg[0xcc]; + if (route->input == 2) + val |= 0x01; /* OSDBAR */ + else + val &= ~0x01; /* !OSDBAR */ + bt866_write(encoder, 0xcc, val); + + v4l2_dbg(1, debug, sd, "set input %d\n", route->input); + + switch (route->input) { + case 0: + case 1: + case 2: break; + default: + return -EINVAL; } + return 0; +} - case 4711: - { - int *iarg = arg; - __u8 val; +#if 0 +/* Code to setup square pixels, might be of some use in the future, + but is currently unused. */ + val = encoder->reg[0xdc]; + if (*iarg) + val |= 1; /* SQUARE */ + else + val &= ~1; /* !SQUARE */ + bt866_write(client, 0xdc, val); +#endif + +static int bt866_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip) +{ + struct i2c_client *client = v4l2_get_subdevdata(sd); - v4l_dbg(1, debug, client, "square %d\n", *iarg); + return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_BT866, 0); +} - val = encoder->reg[0xdc]; - if (*iarg) - val |= 1; /* SQUARE */ - else - val &= ~1; /* !SQUARE */ - bt866_write(client, 0xdc, val); - break; - } +static int bt866_command(struct i2c_client *client, unsigned cmd, void *arg) +{ + return v4l2_subdev_command(i2c_get_clientdata(client), cmd, arg); +} - default: - return -EINVAL; - } +/* ----------------------------------------------------------------------- */ - return 0; -} +static const struct v4l2_subdev_core_ops bt866_core_ops = { + .g_chip_ident = bt866_g_chip_ident, +}; -static unsigned short normal_i2c[] = { 0x88 >> 1, I2C_CLIENT_END }; +static const struct v4l2_subdev_video_ops bt866_video_ops = { + .s_std_output = bt866_s_std_output, + .s_routing = bt866_s_routing, +}; -I2C_CLIENT_INSMOD; +static const struct v4l2_subdev_ops bt866_ops = { + .core = &bt866_core_ops, + .video = &bt866_video_ops, +}; static int bt866_probe(struct i2c_client *client, const struct i2c_device_id *id) { struct bt866 *encoder; + struct v4l2_subdev *sd; v4l_info(client, "chip found @ 0x%x (%s)\n", client->addr << 1, client->adapter->name); @@ -208,14 +218,17 @@ static int bt866_probe(struct i2c_client *client, encoder = kzalloc(sizeof(*encoder), GFP_KERNEL); if (encoder == NULL) return -ENOMEM; - - i2c_set_clientdata(client, encoder); + sd = &encoder->sd; + v4l2_i2c_subdev_init(sd, client, &bt866_ops); return 0; } static int bt866_remove(struct i2c_client *client) { - kfree(i2c_get_clientdata(client)); + struct v4l2_subdev *sd = i2c_get_clientdata(client); + + v4l2_device_unregister_subdev(sd); + kfree(to_bt866(sd)); return 0; } diff --git a/include/media/v4l2-chip-ident.h b/include/media/v4l2-chip-ident.h index bbe2bb6a596a..cfb236e5a1cc 100644 --- a/include/media/v4l2-chip-ident.h +++ b/include/media/v4l2-chip-ident.h @@ -71,6 +71,9 @@ enum { V4L2_IDENT_CX23416 = 416, V4L2_IDENT_CX23418 = 418, + /* module bt866: just ident 866 */ + V4L2_IDENT_BT866 = 866, + /* module vp27smpx: just ident 2700 */ V4L2_IDENT_VP27SMPX = 2700, -- cgit v1.2.3 From c2179ad87240cf31b751f198c55140211e8cef89 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Thu, 19 Feb 2009 06:36:36 -0300 Subject: V4L/DVB (10719): bt819: convert to v4l2_subdev. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/bt819.c | 477 +++++++++++++++++++++------------------- include/media/v4l2-chip-ident.h | 5 + 2 files changed, 257 insertions(+), 225 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/bt819.c b/drivers/media/video/bt819.c index b8109a1b50ce..ce2a8f3ef64d 100644 --- a/drivers/media/video/bt819.c +++ b/drivers/media/video/bt819.c @@ -29,15 +29,14 @@ */ #include -#include #include #include #include #include #include -#include -#include -#include +#include +#include +#include #include MODULE_DESCRIPTION("Brooktree-819 video decoder driver"); @@ -48,13 +47,18 @@ static int debug; module_param(debug, int, 0); MODULE_PARM_DESC(debug, "Debug level (0-1)"); +static unsigned short normal_i2c[] = { 0x8a >> 1, I2C_CLIENT_END }; + +I2C_CLIENT_INSMOD; + /* ----------------------------------------------------------------------- */ struct bt819 { + struct v4l2_subdev sd; unsigned char reg[32]; - int initialized; v4l2_std_id norm; + int ident; int input; int enable; int bright; @@ -63,6 +67,11 @@ struct bt819 { int sat; }; +static inline struct bt819 *to_bt819(struct v4l2_subdev *sd) +{ + return container_of(sd, struct bt819, sd); +} + struct timing { int hactive; int hdelay; @@ -80,24 +89,23 @@ static struct timing timing_data[] = { /* ----------------------------------------------------------------------- */ -static inline int bt819_write(struct i2c_client *client, u8 reg, u8 value) +static inline int bt819_write(struct bt819 *decoder, u8 reg, u8 value) { - struct bt819 *decoder = i2c_get_clientdata(client); + struct i2c_client *client = v4l2_get_subdevdata(&decoder->sd); decoder->reg[reg] = value; return i2c_smbus_write_byte_data(client, reg, value); } -static inline int bt819_setbit(struct i2c_client *client, u8 reg, u8 bit, u8 value) +static inline int bt819_setbit(struct bt819 *decoder, u8 reg, u8 bit, u8 value) { - struct bt819 *decoder = i2c_get_clientdata(client); - - return bt819_write(client, reg, + return bt819_write(decoder, reg, (decoder->reg[reg] & ~(1 << bit)) | (value ? (1 << bit) : 0)); } -static int bt819_write_block(struct i2c_client *client, const u8 *data, unsigned int len) +static int bt819_write_block(struct bt819 *decoder, const u8 *data, unsigned int len) { + struct i2c_client *client = v4l2_get_subdevdata(&decoder->sd); int ret = -1; u8 reg; @@ -105,7 +113,6 @@ static int bt819_write_block(struct i2c_client *client, const u8 *data, unsigned * the adapter understands raw I2C */ if (i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { /* do raw I2C, not smbus compatible */ - struct bt819 *decoder = i2c_get_clientdata(client); u8 block_data[32]; int block_len; @@ -126,7 +133,8 @@ static int bt819_write_block(struct i2c_client *client, const u8 *data, unsigned /* do some slow I2C emulation kind of thing */ while (len >= 2) { reg = *data++; - if ((ret = bt819_write(client, reg, *data++)) < 0) + ret = bt819_write(decoder, reg, *data++); + if (ret < 0) break; len -= 2; } @@ -135,15 +143,15 @@ static int bt819_write_block(struct i2c_client *client, const u8 *data, unsigned return ret; } -static inline int bt819_read(struct i2c_client *client, u8 reg) +static inline int bt819_read(struct bt819 *decoder, u8 reg) { + struct i2c_client *client = v4l2_get_subdevdata(&decoder->sd); + return i2c_smbus_read_byte_data(client, reg); } -static int bt819_init(struct i2c_client *client) +static int bt819_init(struct v4l2_subdev *sd) { - struct bt819 *decoder = i2c_get_clientdata(client); - static unsigned char init[] = { /*0x1f, 0x00,*/ /* Reset */ 0x01, 0x59, /* 0x01 input format */ @@ -178,6 +186,7 @@ static int bt819_init(struct i2c_client *client) 0x1a, 0x80, /* 0x1a ADC Interface */ }; + struct bt819 *decoder = to_bt819(sd); struct timing *timing = &timing_data[(decoder->norm & V4L2_STD_525_60) ? 1 : 0]; init[0x03 * 2 - 1] = @@ -194,277 +203,297 @@ static int bt819_init(struct i2c_client *client) /* 0x15 in array is address 0x19 */ init[0x15 * 2 - 1] = (decoder->norm & V4L2_STD_625_50) ? 115 : 93; /* Chroma burst delay */ /* reset */ - bt819_write(client, 0x1f, 0x00); + bt819_write(decoder, 0x1f, 0x00); mdelay(1); /* init */ - return bt819_write_block(client, init, sizeof(init)); + return bt819_write_block(decoder, init, sizeof(init)); } /* ----------------------------------------------------------------------- */ -static int bt819_command(struct i2c_client *client, unsigned cmd, void *arg) +static int bt819_status(struct v4l2_subdev *sd, u32 *pstatus, v4l2_std_id *pstd) { - int temp; + struct bt819 *decoder = to_bt819(sd); + int status = bt819_read(decoder, 0x00); + int res = V4L2_IN_ST_NO_SIGNAL; + v4l2_std_id std; + + if ((status & 0x80)) + res = 0; + + if ((status & 0x10)) + std = V4L2_STD_PAL; + else + std = V4L2_STD_NTSC; + if (pstd) + *pstd = std; + if (pstatus) + *pstatus = status; + + v4l2_dbg(1, debug, sd, "get status %x\n", status); + return 0; +} - struct bt819 *decoder = i2c_get_clientdata(client); +static int bt819_querystd(struct v4l2_subdev *sd, v4l2_std_id *std) +{ + return bt819_status(sd, NULL, std); +} - if (!decoder->initialized) { /* First call to bt819_init could be */ - bt819_init(client); /* without #FRST = 0 */ - decoder->initialized = 1; +static int bt819_g_input_status(struct v4l2_subdev *sd, u32 *status) +{ + return bt819_status(sd, status, NULL); +} + +static int bt819_s_std(struct v4l2_subdev *sd, v4l2_std_id std) +{ + struct bt819 *decoder = to_bt819(sd); + struct timing *timing = NULL; + + v4l2_dbg(1, debug, sd, "set norm %llx\n", std); + + if (std & V4L2_STD_NTSC) { + bt819_setbit(decoder, 0x01, 0, 1); + bt819_setbit(decoder, 0x01, 1, 0); + bt819_setbit(decoder, 0x01, 5, 0); + bt819_write(decoder, 0x18, 0x68); + bt819_write(decoder, 0x19, 0x5d); + /* bt819_setbit(decoder, 0x1a, 5, 1); */ + timing = &timing_data[1]; + } else if (std & V4L2_STD_PAL) { + bt819_setbit(decoder, 0x01, 0, 1); + bt819_setbit(decoder, 0x01, 1, 1); + bt819_setbit(decoder, 0x01, 5, 1); + bt819_write(decoder, 0x18, 0x7f); + bt819_write(decoder, 0x19, 0x72); + /* bt819_setbit(decoder, 0x1a, 5, 0); */ + timing = &timing_data[0]; + } else { + v4l2_dbg(1, debug, sd, "unsupported norm %llx\n", std); + return -EINVAL; } + bt819_write(decoder, 0x03, + (((timing->vdelay >> 8) & 0x03) << 6) | + (((timing->vactive >> 8) & 0x03) << 4) | + (((timing->hdelay >> 8) & 0x03) << 2) | + ((timing->hactive >> 8) & 0x03)); + bt819_write(decoder, 0x04, timing->vdelay & 0xff); + bt819_write(decoder, 0x05, timing->vactive & 0xff); + bt819_write(decoder, 0x06, timing->hdelay & 0xff); + bt819_write(decoder, 0x07, timing->hactive & 0xff); + bt819_write(decoder, 0x08, (timing->hscale >> 8) & 0xff); + bt819_write(decoder, 0x09, timing->hscale & 0xff); + decoder->norm = std; + return 0; +} - switch (cmd) { - case VIDIOC_INT_INIT: - /* This is just for testing!!! */ - bt819_init(client); - break; +static int bt819_s_routing(struct v4l2_subdev *sd, const struct v4l2_routing *route) +{ + struct bt819 *decoder = to_bt819(sd); - case VIDIOC_QUERYSTD: - case VIDIOC_INT_G_INPUT_STATUS: { - int *iarg = arg; - v4l2_std_id *istd = arg; - int status; - int res = V4L2_IN_ST_NO_SIGNAL; - v4l2_std_id std; - - status = bt819_read(client, 0x00); - if ((status & 0x80)) - res = 0; - - if ((status & 0x10)) - std = V4L2_STD_PAL; - else - std = V4L2_STD_NTSC; - if (cmd == VIDIOC_QUERYSTD) - *istd = std; - else - *iarg = res; - - v4l_dbg(1, debug, client, "get status %x\n", *iarg); - break; - } + v4l2_dbg(1, debug, sd, "set input %x\n", route->input); - case VIDIOC_S_STD: - { - v4l2_std_id *iarg = arg; - struct timing *timing = NULL; - - v4l_dbg(1, debug, client, "set norm %llx\n", *iarg); - - if (*iarg & V4L2_STD_NTSC) { - bt819_setbit(client, 0x01, 0, 1); - bt819_setbit(client, 0x01, 1, 0); - bt819_setbit(client, 0x01, 5, 0); - bt819_write(client, 0x18, 0x68); - bt819_write(client, 0x19, 0x5d); - /* bt819_setbit(client, 0x1a, 5, 1); */ - timing = &timing_data[1]; - } else if (*iarg & V4L2_STD_PAL) { - bt819_setbit(client, 0x01, 0, 1); - bt819_setbit(client, 0x01, 1, 1); - bt819_setbit(client, 0x01, 5, 1); - bt819_write(client, 0x18, 0x7f); - bt819_write(client, 0x19, 0x72); - /* bt819_setbit(client, 0x1a, 5, 0); */ - timing = &timing_data[0]; - } else { - v4l_dbg(1, debug, client, "unsupported norm %llx\n", *iarg); - return -EINVAL; - } -/* case VIDEO_MODE_AUTO: - bt819_setbit(client, 0x01, 0, 0); - bt819_setbit(client, 0x01, 1, 0);*/ - - bt819_write(client, 0x03, - (((timing->vdelay >> 8) & 0x03) << 6) | - (((timing->vactive >> 8) & 0x03) << 4) | - (((timing->hdelay >> 8) & 0x03) << 2) | - ((timing->hactive >> 8) & 0x03)); - bt819_write(client, 0x04, timing->vdelay & 0xff); - bt819_write(client, 0x05, timing->vactive & 0xff); - bt819_write(client, 0x06, timing->hdelay & 0xff); - bt819_write(client, 0x07, timing->hactive & 0xff); - bt819_write(client, 0x08, (timing->hscale >> 8) & 0xff); - bt819_write(client, 0x09, timing->hscale & 0xff); - decoder->norm = *iarg; - break; - } + if (route->input < 0 || route->input > 7) + return -EINVAL; - case VIDIOC_INT_S_VIDEO_ROUTING: - { - struct v4l2_routing *route = arg; - - v4l_dbg(1, debug, client, "set input %x\n", route->input); - - if (route->input < 0 || route->input > 7) - return -EINVAL; - - if (decoder->input != route->input) { - decoder->input = route->input; - /* select mode */ - if (decoder->input == 0) { - bt819_setbit(client, 0x0b, 6, 0); - bt819_setbit(client, 0x1a, 1, 1); - } else { - bt819_setbit(client, 0x0b, 6, 1); - bt819_setbit(client, 0x1a, 1, 0); - } + if (decoder->input != route->input) { + decoder->input = route->input; + /* select mode */ + if (decoder->input == 0) { + bt819_setbit(decoder, 0x0b, 6, 0); + bt819_setbit(decoder, 0x1a, 1, 1); + } else { + bt819_setbit(decoder, 0x0b, 6, 1); + bt819_setbit(decoder, 0x1a, 1, 0); } - break; } + return 0; +} - case VIDIOC_STREAMON: - case VIDIOC_STREAMOFF: - { - int enable = cmd == VIDIOC_STREAMON; +static int bt819_s_stream(struct v4l2_subdev *sd, int enable) +{ + struct bt819 *decoder = to_bt819(sd); - v4l_dbg(1, debug, client, "enable output %x\n", enable); + v4l2_dbg(1, debug, sd, "enable output %x\n", enable); - if (decoder->enable != enable) { - decoder->enable = enable; - bt819_setbit(client, 0x16, 7, !enable); - } - break; + if (decoder->enable != enable) { + decoder->enable = enable; + bt819_setbit(decoder, 0x16, 7, !enable); } + return 0; +} - case VIDIOC_QUERYCTRL: - { - struct v4l2_queryctrl *qc = arg; - - switch (qc->id) { - case V4L2_CID_BRIGHTNESS: - v4l2_ctrl_query_fill(qc, -128, 127, 1, 0); - break; - - case V4L2_CID_CONTRAST: - v4l2_ctrl_query_fill(qc, 0, 511, 1, 256); - break; +static int bt819_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qc) +{ + switch (qc->id) { + case V4L2_CID_BRIGHTNESS: + v4l2_ctrl_query_fill(qc, -128, 127, 1, 0); + break; - case V4L2_CID_SATURATION: - v4l2_ctrl_query_fill(qc, 0, 511, 1, 256); - break; + case V4L2_CID_CONTRAST: + v4l2_ctrl_query_fill(qc, 0, 511, 1, 256); + break; - case V4L2_CID_HUE: - v4l2_ctrl_query_fill(qc, -128, 127, 1, 0); - break; + case V4L2_CID_SATURATION: + v4l2_ctrl_query_fill(qc, 0, 511, 1, 256); + break; - default: - return -EINVAL; - } + case V4L2_CID_HUE: + v4l2_ctrl_query_fill(qc, -128, 127, 1, 0); break; + + default: + return -EINVAL; } + return 0; +} - case VIDIOC_S_CTRL: - { - struct v4l2_control *ctrl = arg; +static int bt819_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) +{ + struct bt819 *decoder = to_bt819(sd); + int temp; - switch (ctrl->id) { - case V4L2_CID_BRIGHTNESS: - if (decoder->bright != ctrl->value) { - decoder->bright = ctrl->value; - bt819_write(client, 0x0a, decoder->bright); - } + switch (ctrl->id) { + case V4L2_CID_BRIGHTNESS: + if (decoder->bright == ctrl->value) break; + decoder->bright = ctrl->value; + bt819_write(decoder, 0x0a, decoder->bright); + break; - case V4L2_CID_CONTRAST: - if (decoder->contrast != ctrl->value) { - decoder->contrast = ctrl->value; - bt819_write(client, 0x0c, - decoder->contrast & 0xff); - bt819_setbit(client, 0x0b, 2, - ((decoder->contrast >> 8) & 0x01)); - } + case V4L2_CID_CONTRAST: + if (decoder->contrast == ctrl->value) break; + decoder->contrast = ctrl->value; + bt819_write(decoder, 0x0c, decoder->contrast & 0xff); + bt819_setbit(decoder, 0x0b, 2, ((decoder->contrast >> 8) & 0x01)); + break; - case V4L2_CID_SATURATION: - if (decoder->sat != ctrl->value) { - decoder->sat = ctrl->value; - bt819_write(client, 0x0d, - (decoder->sat >> 7) & 0xff); - bt819_setbit(client, 0x0b, 1, - ((decoder->sat >> 15) & 0x01)); - - /* Ratio between U gain and V gain must stay the same as - the ratio between the default U and V gain values. */ - temp = (decoder->sat * 180) / 254; - bt819_write(client, 0x0e, (temp >> 7) & 0xff); - bt819_setbit(client, 0x0b, 0, (temp >> 15) & 0x01); - } + case V4L2_CID_SATURATION: + if (decoder->sat == ctrl->value) break; + decoder->sat = ctrl->value; + bt819_write(decoder, 0x0d, (decoder->sat >> 7) & 0xff); + bt819_setbit(decoder, 0x0b, 1, ((decoder->sat >> 15) & 0x01)); + + /* Ratio between U gain and V gain must stay the same as + the ratio between the default U and V gain values. */ + temp = (decoder->sat * 180) / 254; + bt819_write(decoder, 0x0e, (temp >> 7) & 0xff); + bt819_setbit(decoder, 0x0b, 0, (temp >> 15) & 0x01); + break; - case V4L2_CID_HUE: - if (decoder->hue != ctrl->value) { - decoder->hue = ctrl->value; - bt819_write(client, 0x0f, decoder->hue); - } + case V4L2_CID_HUE: + if (decoder->hue == ctrl->value) break; - default: - return -EINVAL; - } + decoder->hue = ctrl->value; + bt819_write(decoder, 0x0f, decoder->hue); break; + + default: + return -EINVAL; } + return 0; +} - case VIDIOC_G_CTRL: - { - struct v4l2_control *ctrl = arg; +static int bt819_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) +{ + struct bt819 *decoder = to_bt819(sd); - switch (ctrl->id) { - case V4L2_CID_BRIGHTNESS: - ctrl->value = decoder->bright; - break; - case V4L2_CID_CONTRAST: - ctrl->value = decoder->contrast; - break; - case V4L2_CID_SATURATION: - ctrl->value = decoder->sat; - break; - case V4L2_CID_HUE: - ctrl->value = decoder->hue; - break; - default: - return -EINVAL; - } + switch (ctrl->id) { + case V4L2_CID_BRIGHTNESS: + ctrl->value = decoder->bright; + break; + case V4L2_CID_CONTRAST: + ctrl->value = decoder->contrast; + break; + case V4L2_CID_SATURATION: + ctrl->value = decoder->sat; + break; + case V4L2_CID_HUE: + ctrl->value = decoder->hue; break; - } - default: return -EINVAL; } - return 0; } +static int bt819_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip) +{ + struct bt819 *decoder = to_bt819(sd); + struct i2c_client *client = v4l2_get_subdevdata(sd); + + return v4l2_chip_ident_i2c_client(client, chip, decoder->ident, 0); +} + +static int bt819_command(struct i2c_client *client, unsigned cmd, void *arg) +{ + return v4l2_subdev_command(i2c_get_clientdata(client), cmd, arg); +} + /* ----------------------------------------------------------------------- */ -static unsigned short normal_i2c[] = { 0x8a >> 1, I2C_CLIENT_END }; +static const struct v4l2_subdev_core_ops bt819_core_ops = { + .g_chip_ident = bt819_g_chip_ident, + .g_ctrl = bt819_g_ctrl, + .s_ctrl = bt819_s_ctrl, + .queryctrl = bt819_queryctrl, +}; -I2C_CLIENT_INSMOD; +static const struct v4l2_subdev_tuner_ops bt819_tuner_ops = { + .s_std = bt819_s_std, +}; + +static const struct v4l2_subdev_video_ops bt819_video_ops = { + .s_routing = bt819_s_routing, + .s_stream = bt819_s_stream, + .querystd = bt819_querystd, + .g_input_status = bt819_g_input_status, +}; + +static const struct v4l2_subdev_ops bt819_ops = { + .core = &bt819_core_ops, + .tuner = &bt819_tuner_ops, + .video = &bt819_video_ops, +}; + +/* ----------------------------------------------------------------------- */ static int bt819_probe(struct i2c_client *client, const struct i2c_device_id *id) { int i, ver; struct bt819 *decoder; + struct v4l2_subdev *sd; const char *name; /* Check if the adapter supports the needed features */ if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) return -ENODEV; - ver = bt819_read(client, 0x17); + decoder = kzalloc(sizeof(struct bt819), GFP_KERNEL); + if (decoder == NULL) + return -ENOMEM; + sd = &decoder->sd; + v4l2_i2c_subdev_init(sd, client, &bt819_ops); + + ver = bt819_read(decoder, 0x17); switch (ver & 0xf0) { case 0x70: name = "bt819a"; + decoder->ident = V4L2_IDENT_BT819A; break; case 0x60: name = "bt817a"; + decoder->ident = V4L2_IDENT_BT817A; break; case 0x20: name = "bt815a"; + decoder->ident = V4L2_IDENT_BT815A; break; default: - v4l_dbg(1, debug, client, + v4l2_dbg(1, debug, sd, "unknown chip version 0x%02x\n", ver); return -ENODEV; } @@ -472,28 +501,26 @@ static int bt819_probe(struct i2c_client *client, v4l_info(client, "%s found @ 0x%x (%s)\n", name, client->addr << 1, client->adapter->name); - decoder = kzalloc(sizeof(struct bt819), GFP_KERNEL); - if (decoder == NULL) - return -ENOMEM; decoder->norm = V4L2_STD_NTSC; decoder->input = 0; decoder->enable = 1; decoder->bright = 0; decoder->contrast = 0xd8; /* 100% of original signal */ decoder->hue = 0; - decoder->sat = 0xfe; /* 100% of original signal */ - decoder->initialized = 0; - i2c_set_clientdata(client, decoder); + decoder->sat = 0xfe; /* 100% of original signal */ - i = bt819_init(client); + i = bt819_init(sd); if (i < 0) - v4l_dbg(1, debug, client, "init status %d\n", i); + v4l2_dbg(1, debug, sd, "init status %d\n", i); return 0; } static int bt819_remove(struct i2c_client *client) { - kfree(i2c_get_clientdata(client)); + struct v4l2_subdev *sd = i2c_get_clientdata(client); + + v4l2_device_unregister_subdev(sd); + kfree(to_bt819(sd)); return 0; } diff --git a/include/media/v4l2-chip-ident.h b/include/media/v4l2-chip-ident.h index cfb236e5a1cc..0766106beb82 100644 --- a/include/media/v4l2-chip-ident.h +++ b/include/media/v4l2-chip-ident.h @@ -71,6 +71,11 @@ enum { V4L2_IDENT_CX23416 = 416, V4L2_IDENT_CX23418 = 418, + /* module bt819: reserved range 810-819 */ + V4L2_IDENT_BT815A = 815, + V4L2_IDENT_BT817A = 817, + V4L2_IDENT_BT819A = 819, + /* module bt866: just ident 866 */ V4L2_IDENT_BT866 = 866, -- cgit v1.2.3 From 2883913c5e06a04d04eeeae9ad7ff9b737559355 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Thu, 19 Feb 2009 08:08:07 -0300 Subject: V4L/DVB (10720): bt819: that delay include is needed after all. Thanks to Jean Delvare for pointing this out. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/bt819.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/media/video') diff --git a/drivers/media/video/bt819.c b/drivers/media/video/bt819.c index ce2a8f3ef64d..821af1269293 100644 --- a/drivers/media/video/bt819.c +++ b/drivers/media/video/bt819.c @@ -31,6 +31,7 @@ #include #include #include +#include #include #include #include -- cgit v1.2.3 From a91f56e7ebe8f33861c613f03faee0b354bea6c1 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Thu, 19 Feb 2009 08:54:36 -0300 Subject: V4L/DVB (10721): bt856: convert to v4l2_subdev. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/bt856.c | 243 ++++++++++++++++++++++------------------ include/media/v4l2-chip-ident.h | 3 + 2 files changed, 139 insertions(+), 107 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/bt856.c b/drivers/media/video/bt856.c index 3e042c5ddaa7..182da6ab3845 100644 --- a/drivers/media/video/bt856.c +++ b/drivers/media/video/bt856.c @@ -34,9 +34,9 @@ #include #include #include -#include -#include -#include +#include +#include +#include #include MODULE_DESCRIPTION("Brooktree-856A video encoder driver"); @@ -47,42 +47,49 @@ static int debug; module_param(debug, int, 0); MODULE_PARM_DESC(debug, "Debug level (0-1)"); +static unsigned short normal_i2c[] = { 0x88 >> 1, I2C_CLIENT_END }; + +I2C_CLIENT_INSMOD; + /* ----------------------------------------------------------------------- */ #define BT856_REG_OFFSET 0xDA #define BT856_NR_REG 6 struct bt856 { + struct v4l2_subdev sd; unsigned char reg[BT856_NR_REG]; v4l2_std_id norm; }; +static inline struct bt856 *to_bt856(struct v4l2_subdev *sd) +{ + return container_of(sd, struct bt856, sd); +} + /* ----------------------------------------------------------------------- */ -static inline int bt856_write(struct i2c_client *client, u8 reg, u8 value) +static inline int bt856_write(struct bt856 *encoder, u8 reg, u8 value) { - struct bt856 *encoder = i2c_get_clientdata(client); + struct i2c_client *client = v4l2_get_subdevdata(&encoder->sd); encoder->reg[reg - BT856_REG_OFFSET] = value; return i2c_smbus_write_byte_data(client, reg, value); } -static inline int bt856_setbit(struct i2c_client *client, u8 reg, u8 bit, u8 value) +static inline int bt856_setbit(struct bt856 *encoder, u8 reg, u8 bit, u8 value) { - struct bt856 *encoder = i2c_get_clientdata(client); - - return bt856_write(client, reg, + return bt856_write(encoder, reg, (encoder->reg[reg - BT856_REG_OFFSET] & ~(1 << bit)) | (value ? (1 << bit) : 0)); } -static void bt856_dump(struct i2c_client *client) +static void bt856_dump(struct bt856 *encoder) { int i; - struct bt856 *encoder = i2c_get_clientdata(client); - v4l_info(client, "register dump:\n"); + v4l2_info(&encoder->sd, "register dump:\n"); for (i = 0; i < BT856_NR_REG; i += 2) printk(KERN_CONT " %02x", encoder->reg[i]); printk(KERN_CONT "\n"); @@ -90,107 +97,125 @@ static void bt856_dump(struct i2c_client *client) /* ----------------------------------------------------------------------- */ -static int bt856_command(struct i2c_client *client, unsigned cmd, void *arg) +static int bt856_init(struct v4l2_subdev *sd, u32 arg) { - struct bt856 *encoder = i2c_get_clientdata(client); - - switch (cmd) { - case VIDIOC_INT_INIT: - /* This is just for testing!!! */ - v4l_dbg(1, debug, client, "init\n"); - bt856_write(client, 0xdc, 0x18); - bt856_write(client, 0xda, 0); - bt856_write(client, 0xde, 0); - - bt856_setbit(client, 0xdc, 3, 1); - //bt856_setbit(client, 0xdc, 6, 0); - bt856_setbit(client, 0xdc, 4, 1); - - if (encoder->norm & V4L2_STD_NTSC) - bt856_setbit(client, 0xdc, 2, 0); - else - bt856_setbit(client, 0xdc, 2, 1); - - bt856_setbit(client, 0xdc, 1, 1); - bt856_setbit(client, 0xde, 4, 0); - bt856_setbit(client, 0xde, 3, 1); - if (debug != 0) - bt856_dump(client); - break; + struct bt856 *encoder = to_bt856(sd); - case VIDIOC_INT_S_STD_OUTPUT: - { - v4l2_std_id *iarg = arg; - - v4l_dbg(1, debug, client, "set norm %llx\n", *iarg); - - if (*iarg & V4L2_STD_NTSC) { - bt856_setbit(client, 0xdc, 2, 0); - } else if (*iarg & V4L2_STD_PAL) { - bt856_setbit(client, 0xdc, 2, 1); - bt856_setbit(client, 0xda, 0, 0); - //bt856_setbit(client, 0xda, 0, 1); - } else { - return -EINVAL; - } - encoder->norm = *iarg; - if (debug != 0) - bt856_dump(client); - break; - } + /* This is just for testing!!! */ + v4l2_dbg(1, debug, sd, "init\n"); + bt856_write(encoder, 0xdc, 0x18); + bt856_write(encoder, 0xda, 0); + bt856_write(encoder, 0xde, 0); - case VIDIOC_INT_S_VIDEO_ROUTING: - { - struct v4l2_routing *route = arg; - - v4l_dbg(1, debug, client, "set input %d\n", route->input); - - /* We only have video bus. - * route->input= 0: input is from bt819 - * route->input= 1: input is from ZR36060 */ - switch (route->input) { - case 0: - bt856_setbit(client, 0xde, 4, 0); - bt856_setbit(client, 0xde, 3, 1); - bt856_setbit(client, 0xdc, 3, 1); - bt856_setbit(client, 0xdc, 6, 0); - break; - case 1: - bt856_setbit(client, 0xde, 4, 0); - bt856_setbit(client, 0xde, 3, 1); - bt856_setbit(client, 0xdc, 3, 1); - bt856_setbit(client, 0xdc, 6, 1); - break; - case 2: // Color bar - bt856_setbit(client, 0xdc, 3, 0); - bt856_setbit(client, 0xde, 4, 1); - break; - default: - return -EINVAL; - } - - if (debug != 0) - bt856_dump(client); - break; + bt856_setbit(encoder, 0xdc, 3, 1); + /*bt856_setbit(encoder, 0xdc, 6, 0);*/ + bt856_setbit(encoder, 0xdc, 4, 1); + + if (encoder->norm & V4L2_STD_NTSC) + bt856_setbit(encoder, 0xdc, 2, 0); + else + bt856_setbit(encoder, 0xdc, 2, 1); + + bt856_setbit(encoder, 0xdc, 1, 1); + bt856_setbit(encoder, 0xde, 4, 0); + bt856_setbit(encoder, 0xde, 3, 1); + if (debug != 0) + bt856_dump(encoder); + return 0; +} + +static int bt856_s_std_output(struct v4l2_subdev *sd, v4l2_std_id std) +{ + struct bt856 *encoder = to_bt856(sd); + + v4l2_dbg(1, debug, sd, "set norm %llx\n", std); + + if (std & V4L2_STD_NTSC) { + bt856_setbit(encoder, 0xdc, 2, 0); + } else if (std & V4L2_STD_PAL) { + bt856_setbit(encoder, 0xdc, 2, 1); + bt856_setbit(encoder, 0xda, 0, 0); + /*bt856_setbit(encoder, 0xda, 0, 1);*/ + } else { + return -EINVAL; } + encoder->norm = std; + if (debug != 0) + bt856_dump(encoder); + return 0; +} +static int bt856_s_routing(struct v4l2_subdev *sd, const struct v4l2_routing *route) +{ + struct bt856 *encoder = to_bt856(sd); + + v4l2_dbg(1, debug, sd, "set input %d\n", route->input); + + /* We only have video bus. + * route->input= 0: input is from bt819 + * route->input= 1: input is from ZR36060 */ + switch (route->input) { + case 0: + bt856_setbit(encoder, 0xde, 4, 0); + bt856_setbit(encoder, 0xde, 3, 1); + bt856_setbit(encoder, 0xdc, 3, 1); + bt856_setbit(encoder, 0xdc, 6, 0); + break; + case 1: + bt856_setbit(encoder, 0xde, 4, 0); + bt856_setbit(encoder, 0xde, 3, 1); + bt856_setbit(encoder, 0xdc, 3, 1); + bt856_setbit(encoder, 0xdc, 6, 1); + break; + case 2: /* Color bar */ + bt856_setbit(encoder, 0xdc, 3, 0); + bt856_setbit(encoder, 0xde, 4, 1); + break; default: return -EINVAL; } + if (debug != 0) + bt856_dump(encoder); return 0; } +static int bt856_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip) +{ + struct i2c_client *client = v4l2_get_subdevdata(sd); + + return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_BT856, 0); +} + +static int bt856_command(struct i2c_client *client, unsigned cmd, void *arg) +{ + return v4l2_subdev_command(i2c_get_clientdata(client), cmd, arg); +} + /* ----------------------------------------------------------------------- */ -static unsigned short normal_i2c[] = { 0x88 >> 1, I2C_CLIENT_END }; +static const struct v4l2_subdev_core_ops bt856_core_ops = { + .g_chip_ident = bt856_g_chip_ident, + .init = bt856_init, +}; -I2C_CLIENT_INSMOD; +static const struct v4l2_subdev_video_ops bt856_video_ops = { + .s_std_output = bt856_s_std_output, + .s_routing = bt856_s_routing, +}; + +static const struct v4l2_subdev_ops bt856_ops = { + .core = &bt856_core_ops, + .video = &bt856_video_ops, +}; + +/* ----------------------------------------------------------------------- */ static int bt856_probe(struct i2c_client *client, const struct i2c_device_id *id) { struct bt856 *encoder; + struct v4l2_subdev *sd; /* Check if the adapter supports the needed features */ if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) @@ -202,34 +227,38 @@ static int bt856_probe(struct i2c_client *client, encoder = kzalloc(sizeof(struct bt856), GFP_KERNEL); if (encoder == NULL) return -ENOMEM; + sd = &encoder->sd; + v4l2_i2c_subdev_init(sd, client, &bt856_ops); encoder->norm = V4L2_STD_NTSC; - i2c_set_clientdata(client, encoder); - bt856_write(client, 0xdc, 0x18); - bt856_write(client, 0xda, 0); - bt856_write(client, 0xde, 0); + bt856_write(encoder, 0xdc, 0x18); + bt856_write(encoder, 0xda, 0); + bt856_write(encoder, 0xde, 0); - bt856_setbit(client, 0xdc, 3, 1); - //bt856_setbit(client, 0xdc, 6, 0); - bt856_setbit(client, 0xdc, 4, 1); + bt856_setbit(encoder, 0xdc, 3, 1); + /*bt856_setbit(encoder, 0xdc, 6, 0);*/ + bt856_setbit(encoder, 0xdc, 4, 1); if (encoder->norm & V4L2_STD_NTSC) - bt856_setbit(client, 0xdc, 2, 0); + bt856_setbit(encoder, 0xdc, 2, 0); else - bt856_setbit(client, 0xdc, 2, 1); + bt856_setbit(encoder, 0xdc, 2, 1); - bt856_setbit(client, 0xdc, 1, 1); - bt856_setbit(client, 0xde, 4, 0); - bt856_setbit(client, 0xde, 3, 1); + bt856_setbit(encoder, 0xdc, 1, 1); + bt856_setbit(encoder, 0xde, 4, 0); + bt856_setbit(encoder, 0xde, 3, 1); if (debug != 0) - bt856_dump(client); + bt856_dump(encoder); return 0; } static int bt856_remove(struct i2c_client *client) { - kfree(i2c_get_clientdata(client)); + struct v4l2_subdev *sd = i2c_get_clientdata(client); + + v4l2_device_unregister_subdev(sd); + kfree(to_bt856(sd)); return 0; } diff --git a/include/media/v4l2-chip-ident.h b/include/media/v4l2-chip-ident.h index 0766106beb82..69e3092fd288 100644 --- a/include/media/v4l2-chip-ident.h +++ b/include/media/v4l2-chip-ident.h @@ -76,6 +76,9 @@ enum { V4L2_IDENT_BT817A = 817, V4L2_IDENT_BT819A = 819, + /* module bt856: just ident 856 */ + V4L2_IDENT_BT856 = 856, + /* module bt866: just ident 866 */ V4L2_IDENT_BT866 = 866, -- cgit v1.2.3 From 0750e9719ea42ce84af1e55183d6329d6b49ba5e Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Thu, 19 Feb 2009 11:50:27 -0300 Subject: V4L/DVB (10722): ks0127: convert to v4l2_subdev. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/ks0127.c | 646 +++++++++++++++++++--------------------- include/media/v4l2-chip-ident.h | 5 + 2 files changed, 315 insertions(+), 336 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/ks0127.c b/drivers/media/video/ks0127.c index c97d55a43c07..9ae94484da64 100644 --- a/drivers/media/video/ks0127.c +++ b/drivers/media/video/ks0127.c @@ -39,8 +39,9 @@ #include #include #include -#include -#include +#include +#include +#include #include #include "ks0127.h" @@ -48,10 +49,17 @@ MODULE_DESCRIPTION("KS0127 video decoder driver"); MODULE_AUTHOR("Ryan Drake"); MODULE_LICENSE("GPL"); -#define KS_TYPE_UNKNOWN 0 -#define KS_TYPE_0122S 1 -#define KS_TYPE_0127 2 -#define KS_TYPE_0127B 3 +/* Addresses to scan */ +#define I2C_KS0127_ADDON 0xD8 +#define I2C_KS0127_ONBOARD 0xDA + +static unsigned short normal_i2c[] = { + I2C_KS0127_ADDON >> 1, + I2C_KS0127_ONBOARD >> 1, + I2C_CLIENT_END +}; + +I2C_CLIENT_INSMOD; /* ks0127 control registers */ #define KS_STAT 0x00 @@ -197,15 +205,17 @@ struct adjust { }; struct ks0127 { - int format_width; - int format_height; - int cap_width; - int cap_height; + struct v4l2_subdev sd; v4l2_std_id norm; - int ks_type; + int ident; u8 regs[256]; }; +static inline struct ks0127 *to_ks0127(struct v4l2_subdev *sd) +{ + return container_of(sd, struct ks0127, sd); +} + static int debug; /* insmod parameter */ @@ -311,43 +321,45 @@ static void init_reg_defaults(void) */ -static u8 ks0127_read(struct i2c_client *c, u8 reg) +static u8 ks0127_read(struct v4l2_subdev *sd, u8 reg) { + struct i2c_client *client = v4l2_get_subdevdata(sd); char val = 0; struct i2c_msg msgs[] = { - { c->addr, 0, sizeof(reg), ® }, - { c->addr, I2C_M_RD | I2C_M_NO_RD_ACK, sizeof(val), &val } + { client->addr, 0, sizeof(reg), ® }, + { client->addr, I2C_M_RD | I2C_M_NO_RD_ACK, sizeof(val), &val } }; int ret; - ret = i2c_transfer(c->adapter, msgs, ARRAY_SIZE(msgs)); + ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs)); if (ret != ARRAY_SIZE(msgs)) - v4l_dbg(1, debug, c, "read error\n"); + v4l2_dbg(1, debug, sd, "read error\n"); return val; } -static void ks0127_write(struct i2c_client *c, u8 reg, u8 val) +static void ks0127_write(struct v4l2_subdev *sd, u8 reg, u8 val) { - struct ks0127 *ks = i2c_get_clientdata(c); + struct i2c_client *client = v4l2_get_subdevdata(sd); + struct ks0127 *ks = to_ks0127(sd); char msg[] = { reg, val }; - if (i2c_master_send(c, msg, sizeof(msg)) != sizeof(msg)) - v4l_dbg(1, debug, c, "write error\n"); + if (i2c_master_send(client, msg, sizeof(msg)) != sizeof(msg)) + v4l2_dbg(1, debug, sd, "write error\n"); ks->regs[reg] = val; } /* generic bit-twiddling */ -static void ks0127_and_or(struct i2c_client *client, u8 reg, u8 and_v, u8 or_v) +static void ks0127_and_or(struct v4l2_subdev *sd, u8 reg, u8 and_v, u8 or_v) { - struct ks0127 *ks = i2c_get_clientdata(client); + struct ks0127 *ks = to_ks0127(sd); u8 val = ks->regs[reg]; val = (val & and_v) | or_v; - ks0127_write(client, reg, val); + ks0127_write(sd, reg, val); } @@ -355,391 +367,353 @@ static void ks0127_and_or(struct i2c_client *client, u8 reg, u8 and_v, u8 or_v) /**************************************************************************** * ks0127 private api ****************************************************************************/ -static void ks0127_reset(struct i2c_client *c) +static void ks0127_init(struct v4l2_subdev *sd) { - struct ks0127 *ks = i2c_get_clientdata(c); + struct ks0127 *ks = to_ks0127(sd); u8 *table = reg_defaults; int i; - ks->ks_type = KS_TYPE_UNKNOWN; + ks->ident = V4L2_IDENT_KS0127; - v4l_dbg(1, debug, c, "reset\n"); + v4l2_dbg(1, debug, sd, "reset\n"); msleep(1); /* initialize all registers to known values */ /* (except STAT, 0x21, 0x22, TEST and 0x38,0x39) */ for (i = 1; i < 33; i++) - ks0127_write(c, i, table[i]); + ks0127_write(sd, i, table[i]); for (i = 35; i < 40; i++) - ks0127_write(c, i, table[i]); + ks0127_write(sd, i, table[i]); for (i = 41; i < 56; i++) - ks0127_write(c, i, table[i]); + ks0127_write(sd, i, table[i]); for (i = 58; i < 64; i++) - ks0127_write(c, i, table[i]); + ks0127_write(sd, i, table[i]); - if ((ks0127_read(c, KS_STAT) & 0x80) == 0) { - ks->ks_type = KS_TYPE_0122S; - v4l_dbg(1, debug, c, "ks0122s found\n"); + if ((ks0127_read(sd, KS_STAT) & 0x80) == 0) { + ks->ident = V4L2_IDENT_KS0122S; + v4l2_dbg(1, debug, sd, "ks0122s found\n"); return; } - switch (ks0127_read(c, KS_CMDE) & 0x0f) { + switch (ks0127_read(sd, KS_CMDE) & 0x0f) { case 0: - ks->ks_type = KS_TYPE_0127; - v4l_dbg(1, debug, c, "ks0127 found\n"); + v4l2_dbg(1, debug, sd, "ks0127 found\n"); break; case 9: - ks->ks_type = KS_TYPE_0127B; - v4l_dbg(1, debug, c, "ks0127B Revision A found\n"); + ks->ident = V4L2_IDENT_KS0127B; + v4l2_dbg(1, debug, sd, "ks0127B Revision A found\n"); break; default: - v4l_dbg(1, debug, c, "unknown revision\n"); + v4l2_dbg(1, debug, sd, "unknown revision\n"); break; } } -static int ks0127_command(struct i2c_client *c, unsigned cmd, void *arg) +static int ks0127_s_routing(struct v4l2_subdev *sd, const struct v4l2_routing *route) { - struct ks0127 *ks = i2c_get_clientdata(c); - struct v4l2_routing *route = arg; - int *iarg = (int *)arg; - v4l2_std_id *istd = arg; - int status; - - if (!ks) - return -ENODEV; - - switch (cmd) { - case VIDIOC_INT_INIT: - v4l_dbg(1, debug, c, "VIDIOC_INT_INIT\n"); - ks0127_reset(c); + struct ks0127 *ks = to_ks0127(sd); + + switch (route->input) { + case KS_INPUT_COMPOSITE_1: + case KS_INPUT_COMPOSITE_2: + case KS_INPUT_COMPOSITE_3: + case KS_INPUT_COMPOSITE_4: + case KS_INPUT_COMPOSITE_5: + case KS_INPUT_COMPOSITE_6: + v4l2_dbg(1, debug, sd, + "VIDIOC_S_INPUT %d: Composite\n", route->input); + /* autodetect 50/60 Hz */ + ks0127_and_or(sd, KS_CMDA, 0xfc, 0x00); + /* VSE=0 */ + ks0127_and_or(sd, KS_CMDA, ~0x40, 0x00); + /* set input line */ + ks0127_and_or(sd, KS_CMDB, 0xb0, route->input); + /* non-freerunning mode */ + ks0127_and_or(sd, KS_CMDC, 0x70, 0x0a); + /* analog input */ + ks0127_and_or(sd, KS_CMDD, 0x03, 0x00); + /* enable chroma demodulation */ + ks0127_and_or(sd, KS_CTRACK, 0xcf, 0x00); + /* chroma trap, HYBWR=1 */ + ks0127_and_or(sd, KS_LUMA, 0x00, + (reg_defaults[KS_LUMA])|0x0c); + /* scaler fullbw, luma comb off */ + ks0127_and_or(sd, KS_VERTIA, 0x08, 0x81); + /* manual chroma comb .25 .5 .25 */ + ks0127_and_or(sd, KS_VERTIC, 0x0f, 0x90); + + /* chroma path delay */ + ks0127_and_or(sd, KS_CHROMB, 0x0f, 0x90); + + ks0127_write(sd, KS_UGAIN, reg_defaults[KS_UGAIN]); + ks0127_write(sd, KS_VGAIN, reg_defaults[KS_VGAIN]); + ks0127_write(sd, KS_UVOFFH, reg_defaults[KS_UVOFFH]); + ks0127_write(sd, KS_UVOFFL, reg_defaults[KS_UVOFFL]); break; - case VIDIOC_INT_S_VIDEO_ROUTING: - switch (route->input) { - case KS_INPUT_COMPOSITE_1: - case KS_INPUT_COMPOSITE_2: - case KS_INPUT_COMPOSITE_3: - case KS_INPUT_COMPOSITE_4: - case KS_INPUT_COMPOSITE_5: - case KS_INPUT_COMPOSITE_6: - v4l_dbg(1, debug, c, - "VIDIOC_S_INPUT %d: Composite\n", *iarg); - /* autodetect 50/60 Hz */ - ks0127_and_or(c, KS_CMDA, 0xfc, 0x00); - /* VSE=0 */ - ks0127_and_or(c, KS_CMDA, ~0x40, 0x00); - /* set input line */ - ks0127_and_or(c, KS_CMDB, 0xb0, *iarg); - /* non-freerunning mode */ - ks0127_and_or(c, KS_CMDC, 0x70, 0x0a); - /* analog input */ - ks0127_and_or(c, KS_CMDD, 0x03, 0x00); - /* enable chroma demodulation */ - ks0127_and_or(c, KS_CTRACK, 0xcf, 0x00); - /* chroma trap, HYBWR=1 */ - ks0127_and_or(c, KS_LUMA, 0x00, - (reg_defaults[KS_LUMA])|0x0c); - /* scaler fullbw, luma comb off */ - ks0127_and_or(c, KS_VERTIA, 0x08, 0x81); - /* manual chroma comb .25 .5 .25 */ - ks0127_and_or(c, KS_VERTIC, 0x0f, 0x90); - - /* chroma path delay */ - ks0127_and_or(c, KS_CHROMB, 0x0f, 0x90); - - ks0127_write(c, KS_UGAIN, reg_defaults[KS_UGAIN]); - ks0127_write(c, KS_VGAIN, reg_defaults[KS_VGAIN]); - ks0127_write(c, KS_UVOFFH, reg_defaults[KS_UVOFFH]); - ks0127_write(c, KS_UVOFFL, reg_defaults[KS_UVOFFL]); - break; - - case KS_INPUT_SVIDEO_1: - case KS_INPUT_SVIDEO_2: - case KS_INPUT_SVIDEO_3: - v4l_dbg(1, debug, c, - "VIDIOC_S_INPUT %d: S-Video\n", *iarg); - /* autodetect 50/60 Hz */ - ks0127_and_or(c, KS_CMDA, 0xfc, 0x00); - /* VSE=0 */ - ks0127_and_or(c, KS_CMDA, ~0x40, 0x00); - /* set input line */ - ks0127_and_or(c, KS_CMDB, 0xb0, *iarg); - /* non-freerunning mode */ - ks0127_and_or(c, KS_CMDC, 0x70, 0x0a); - /* analog input */ - ks0127_and_or(c, KS_CMDD, 0x03, 0x00); - /* enable chroma demodulation */ - ks0127_and_or(c, KS_CTRACK, 0xcf, 0x00); - ks0127_and_or(c, KS_LUMA, 0x00, - reg_defaults[KS_LUMA]); - /* disable luma comb */ - ks0127_and_or(c, KS_VERTIA, 0x08, - (reg_defaults[KS_VERTIA]&0xf0)|0x01); - ks0127_and_or(c, KS_VERTIC, 0x0f, - reg_defaults[KS_VERTIC]&0xf0); - - ks0127_and_or(c, KS_CHROMB, 0x0f, - reg_defaults[KS_CHROMB]&0xf0); - - ks0127_write(c, KS_UGAIN, reg_defaults[KS_UGAIN]); - ks0127_write(c, KS_VGAIN, reg_defaults[KS_VGAIN]); - ks0127_write(c, KS_UVOFFH, reg_defaults[KS_UVOFFH]); - ks0127_write(c, KS_UVOFFL, reg_defaults[KS_UVOFFL]); - break; - - case KS_INPUT_YUV656: - v4l_dbg(1, debug, c, - "VIDIOC_S_INPUT 15: YUV656\n"); - if (ks->norm & V4L2_STD_525_60) - /* force 60 Hz */ - ks0127_and_or(c, KS_CMDA, 0xfc, 0x03); - else - /* force 50 Hz */ - ks0127_and_or(c, KS_CMDA, 0xfc, 0x02); - - ks0127_and_or(c, KS_CMDA, 0xff, 0x40); /* VSE=1 */ - /* set input line and VALIGN */ - ks0127_and_or(c, KS_CMDB, 0xb0, (*iarg | 0x40)); - /* freerunning mode, */ - /* TSTGEN = 1 TSTGFR=11 TSTGPH=0 TSTGPK=0 VMEM=1*/ - ks0127_and_or(c, KS_CMDC, 0x70, 0x87); - /* digital input, SYNDIR = 0 INPSL=01 CLKDIR=0 EAV=0 */ - ks0127_and_or(c, KS_CMDD, 0x03, 0x08); - /* disable chroma demodulation */ - ks0127_and_or(c, KS_CTRACK, 0xcf, 0x30); - /* HYPK =01 CTRAP = 0 HYBWR=0 PED=1 RGBH=1 UNIT=1 */ - ks0127_and_or(c, KS_LUMA, 0x00, 0x71); - ks0127_and_or(c, KS_VERTIC, 0x0f, - reg_defaults[KS_VERTIC]&0xf0); - - /* scaler fullbw, luma comb off */ - ks0127_and_or(c, KS_VERTIA, 0x08, 0x81); - - ks0127_and_or(c, KS_CHROMB, 0x0f, - reg_defaults[KS_CHROMB]&0xf0); - - ks0127_and_or(c, KS_CON, 0x00, 0x00); - ks0127_and_or(c, KS_BRT, 0x00, 32); /* spec: 34 */ - /* spec: 229 (e5) */ - ks0127_and_or(c, KS_SAT, 0x00, 0xe8); - ks0127_and_or(c, KS_HUE, 0x00, 0); - - ks0127_and_or(c, KS_UGAIN, 0x00, 238); - ks0127_and_or(c, KS_VGAIN, 0x00, 0x00); - - /*UOFF:0x30, VOFF:0x30, TSTCGN=1 */ - ks0127_and_or(c, KS_UVOFFH, 0x00, 0x4f); - ks0127_and_or(c, KS_UVOFFL, 0x00, 0x00); - break; - - default: - v4l_dbg(1, debug, c, - "VIDIOC_INT_S_VIDEO_ROUTING: Unknown input %d\n", route->input); - break; - } - - /* hack: CDMLPF sometimes spontaneously switches on; */ - /* force back off */ - ks0127_write(c, KS_DEMOD, reg_defaults[KS_DEMOD]); + case KS_INPUT_SVIDEO_1: + case KS_INPUT_SVIDEO_2: + case KS_INPUT_SVIDEO_3: + v4l2_dbg(1, debug, sd, + "VIDIOC_S_INPUT %d: S-Video\n", route->input); + /* autodetect 50/60 Hz */ + ks0127_and_or(sd, KS_CMDA, 0xfc, 0x00); + /* VSE=0 */ + ks0127_and_or(sd, KS_CMDA, ~0x40, 0x00); + /* set input line */ + ks0127_and_or(sd, KS_CMDB, 0xb0, route->input); + /* non-freerunning mode */ + ks0127_and_or(sd, KS_CMDC, 0x70, 0x0a); + /* analog input */ + ks0127_and_or(sd, KS_CMDD, 0x03, 0x00); + /* enable chroma demodulation */ + ks0127_and_or(sd, KS_CTRACK, 0xcf, 0x00); + ks0127_and_or(sd, KS_LUMA, 0x00, + reg_defaults[KS_LUMA]); + /* disable luma comb */ + ks0127_and_or(sd, KS_VERTIA, 0x08, + (reg_defaults[KS_VERTIA]&0xf0)|0x01); + ks0127_and_or(sd, KS_VERTIC, 0x0f, + reg_defaults[KS_VERTIC]&0xf0); + + ks0127_and_or(sd, KS_CHROMB, 0x0f, + reg_defaults[KS_CHROMB]&0xf0); + + ks0127_write(sd, KS_UGAIN, reg_defaults[KS_UGAIN]); + ks0127_write(sd, KS_VGAIN, reg_defaults[KS_VGAIN]); + ks0127_write(sd, KS_UVOFFH, reg_defaults[KS_UVOFFH]); + ks0127_write(sd, KS_UVOFFL, reg_defaults[KS_UVOFFL]); break; - case VIDIOC_S_STD: /* sam This block mixes old and new norm names... */ - /* Set to automatic SECAM/Fsc mode */ - ks0127_and_or(c, KS_DEMOD, 0xf0, 0x00); - - ks->norm = *istd; - - if (*istd & V4L2_STD_NTSC) { - v4l_dbg(1, debug, c, - "VIDIOC_S_STD: NTSC_M\n"); - ks0127_and_or(c, KS_CHROMA, 0x9f, 0x20); - ks->format_height = 240; - ks->format_width = 704; - } else if (*istd & V4L2_STD_PAL_N) { - v4l_dbg(1, debug, c, - "KS0127_SET_NORM: NTSC_N (fixme)\n"); - ks0127_and_or(c, KS_CHROMA, 0x9f, 0x40); - ks->format_height = 240; - ks->format_width = 704; - } else if (*istd & V4L2_STD_PAL) { - v4l_dbg(1, debug, c, - "VIDIOC_S_STD: PAL_N\n"); - ks0127_and_or(c, KS_CHROMA, 0x9f, 0x20); - ks->format_height = 290; - ks->format_width = 704; - } else if (*istd & V4L2_STD_PAL_M) { - v4l_dbg(1, debug, c, - "KS0127_SET_NORM: PAL_M (fixme)\n"); - ks0127_and_or(c, KS_CHROMA, 0x9f, 0x40); - ks->format_height = 290; - ks->format_width = 704; - } else if (*istd & V4L2_STD_SECAM) { - v4l_dbg(1, debug, c, - "KS0127_SET_NORM: SECAM\n"); - ks->format_height = 290; - ks->format_width = 704; - - /* set to secam autodetection */ - ks0127_and_or(c, KS_CHROMA, 0xdf, 0x20); - ks0127_and_or(c, KS_DEMOD, 0xf0, 0x00); - schedule_timeout_interruptible(HZ/10+1); - - /* did it autodetect? */ - if (!(ks0127_read(c, KS_DEMOD) & 0x40)) - /* force to secam mode */ - ks0127_and_or(c, KS_DEMOD, 0xf0, 0x0f); - } else { - v4l_dbg(1, debug, c, - "VIDIOC_S_STD: Unknown norm %llx\n", *istd); - } + case KS_INPUT_YUV656: + v4l2_dbg(1, debug, sd, "VIDIOC_S_INPUT 15: YUV656\n"); + if (ks->norm & V4L2_STD_525_60) + /* force 60 Hz */ + ks0127_and_or(sd, KS_CMDA, 0xfc, 0x03); + else + /* force 50 Hz */ + ks0127_and_or(sd, KS_CMDA, 0xfc, 0x02); + + ks0127_and_or(sd, KS_CMDA, 0xff, 0x40); /* VSE=1 */ + /* set input line and VALIGN */ + ks0127_and_or(sd, KS_CMDB, 0xb0, (route->input | 0x40)); + /* freerunning mode, */ + /* TSTGEN = 1 TSTGFR=11 TSTGPH=0 TSTGPK=0 VMEM=1*/ + ks0127_and_or(sd, KS_CMDC, 0x70, 0x87); + /* digital input, SYNDIR = 0 INPSL=01 CLKDIR=0 EAV=0 */ + ks0127_and_or(sd, KS_CMDD, 0x03, 0x08); + /* disable chroma demodulation */ + ks0127_and_or(sd, KS_CTRACK, 0xcf, 0x30); + /* HYPK =01 CTRAP = 0 HYBWR=0 PED=1 RGBH=1 UNIT=1 */ + ks0127_and_or(sd, KS_LUMA, 0x00, 0x71); + ks0127_and_or(sd, KS_VERTIC, 0x0f, + reg_defaults[KS_VERTIC]&0xf0); + + /* scaler fullbw, luma comb off */ + ks0127_and_or(sd, KS_VERTIA, 0x08, 0x81); + + ks0127_and_or(sd, KS_CHROMB, 0x0f, + reg_defaults[KS_CHROMB]&0xf0); + + ks0127_and_or(sd, KS_CON, 0x00, 0x00); + ks0127_and_or(sd, KS_BRT, 0x00, 32); /* spec: 34 */ + /* spec: 229 (e5) */ + ks0127_and_or(sd, KS_SAT, 0x00, 0xe8); + ks0127_and_or(sd, KS_HUE, 0x00, 0); + + ks0127_and_or(sd, KS_UGAIN, 0x00, 238); + ks0127_and_or(sd, KS_VGAIN, 0x00, 0x00); + + /*UOFF:0x30, VOFF:0x30, TSTCGN=1 */ + ks0127_and_or(sd, KS_UVOFFH, 0x00, 0x4f); + ks0127_and_or(sd, KS_UVOFFL, 0x00, 0x00); break; - case VIDIOC_QUERYCTRL: - { - return -EINVAL; - } - - case VIDIOC_S_CTRL: - v4l_dbg(1, debug, c, - "VIDIOC_S_CTRL: not yet supported\n"); - return -EINVAL; - - case VIDIOC_G_CTRL: - v4l_dbg(1, debug, c, - "VIDIOC_G_CTRL: not yet supported\n"); - return -EINVAL; - - /* sam todo: KS0127_SET_BRIGHTNESS: Merge into VIDIOC_S_CTRL */ - /* sam todo: KS0127_SET_CONTRAST: Merge into VIDIOC_S_CTRL */ - /* sam todo: KS0127_SET_HUE: Merge into VIDIOC_S_CTRL? */ - /* sam todo: KS0127_SET_SATURATION: Merge into VIDIOC_S_CTRL */ - /* sam todo: KS0127_SET_AGC_MODE: */ - /* sam todo: KS0127_SET_AGC: */ - /* sam todo: KS0127_SET_CHROMA_MODE: */ - /* sam todo: KS0127_SET_PIXCLK_MODE: */ - /* sam todo: KS0127_SET_GAMMA_MODE: */ - /* sam todo: KS0127_SET_UGAIN: */ - /* sam todo: KS0127_SET_VGAIN: */ - /* sam todo: KS0127_SET_INVALY: */ - /* sam todo: KS0127_SET_INVALU: */ - /* sam todo: KS0127_SET_INVALV: */ - /* sam todo: KS0127_SET_UNUSEY: */ - /* sam todo: KS0127_SET_UNUSEU: */ - /* sam todo: KS0127_SET_UNUSEV: */ - /* sam todo: KS0127_SET_VSALIGN_MODE: */ - - case VIDIOC_STREAMON: - case VIDIOC_STREAMOFF: - { - int enable = cmd == VIDIOC_STREAMON; - - if (enable) { - v4l_dbg(1, debug, c, - "VIDIOC_STREAMON\n"); - /* All output pins on */ - ks0127_and_or(c, KS_OFMTA, 0xcf, 0x30); - /* Obey the OEN pin */ - ks0127_and_or(c, KS_CDEM, 0x7f, 0x00); - } else { - v4l_dbg(1, debug, c, - "VIDIOC_STREAMOFF\n"); - /* Video output pins off */ - ks0127_and_or(c, KS_OFMTA, 0xcf, 0x00); - /* Ignore the OEN pin */ - ks0127_and_or(c, KS_CDEM, 0x7f, 0x80); - } + default: + v4l2_dbg(1, debug, sd, + "VIDIOC_INT_S_VIDEO_ROUTING: Unknown input %d\n", route->input); break; } - /* sam todo: KS0127_SET_OUTPUT_MODE: */ - /* sam todo: KS0127_SET_WIDTH: */ - /* sam todo: KS0127_SET_HEIGHT: */ - /* sam todo: KS0127_SET_HSCALE: */ - - case VIDIOC_QUERYSTD: - case VIDIOC_INT_G_INPUT_STATUS: { - int stat = V4L2_IN_ST_NO_SIGNAL; - v4l2_std_id std = V4L2_STD_ALL; - v4l_dbg(1, debug, c, "VIDIOC_QUERYSTD/VIDIOC_INT_G_INPUT_STATUS\n"); - status = ks0127_read(c, KS_STAT); - if (!(status & 0x20)) /* NOVID not set */ - stat = 0; - if (!(status & 0x01)) /* CLOCK set */ - stat |= V4L2_IN_ST_NO_COLOR; - if ((status & 0x08)) /* PALDET set */ - std = V4L2_STD_PAL; - else - std = V4L2_STD_NTSC; - if (cmd == VIDIOC_QUERYSTD) - *istd = std; - else - *iarg = stat; - break; + /* hack: CDMLPF sometimes spontaneously switches on; */ + /* force back off */ + ks0127_write(sd, KS_DEMOD, reg_defaults[KS_DEMOD]); + return 0; +} + +static int ks0127_s_std(struct v4l2_subdev *sd, v4l2_std_id std) +{ + struct ks0127 *ks = to_ks0127(sd); + + /* Set to automatic SECAM/Fsc mode */ + ks0127_and_or(sd, KS_DEMOD, 0xf0, 0x00); + + ks->norm = std; + if (std & V4L2_STD_NTSC) { + v4l2_dbg(1, debug, sd, + "VIDIOC_S_STD: NTSC_M\n"); + ks0127_and_or(sd, KS_CHROMA, 0x9f, 0x20); + } else if (std & V4L2_STD_PAL_N) { + v4l2_dbg(1, debug, sd, + "KS0127_SET_NORM: NTSC_N (fixme)\n"); + ks0127_and_or(sd, KS_CHROMA, 0x9f, 0x40); + } else if (std & V4L2_STD_PAL) { + v4l2_dbg(1, debug, sd, + "VIDIOC_S_STD: PAL_N\n"); + ks0127_and_or(sd, KS_CHROMA, 0x9f, 0x20); + } else if (std & V4L2_STD_PAL_M) { + v4l2_dbg(1, debug, sd, + "KS0127_SET_NORM: PAL_M (fixme)\n"); + ks0127_and_or(sd, KS_CHROMA, 0x9f, 0x40); + } else if (std & V4L2_STD_SECAM) { + v4l2_dbg(1, debug, sd, + "KS0127_SET_NORM: SECAM\n"); + + /* set to secam autodetection */ + ks0127_and_or(sd, KS_CHROMA, 0xdf, 0x20); + ks0127_and_or(sd, KS_DEMOD, 0xf0, 0x00); + schedule_timeout_interruptible(HZ/10+1); + + /* did it autodetect? */ + if (!(ks0127_read(sd, KS_DEMOD) & 0x40)) + /* force to secam mode */ + ks0127_and_or(sd, KS_DEMOD, 0xf0, 0x0f); + } else { + v4l2_dbg(1, debug, sd, + "VIDIOC_S_STD: Unknown norm %llx\n", std); } + return 0; +} - /* Catch any unknown command */ - default: - v4l_dbg(1, debug, c, "unknown: 0x%08x\n", cmd); - return -EINVAL; +static int ks0127_s_stream(struct v4l2_subdev *sd, int enable) +{ + v4l2_dbg(1, debug, sd, "s_stream(%d)\n", enable); + if (enable) { + /* All output pins on */ + ks0127_and_or(sd, KS_OFMTA, 0xcf, 0x30); + /* Obey the OEN pin */ + ks0127_and_or(sd, KS_CDEM, 0x7f, 0x00); + } else { + /* Video output pins off */ + ks0127_and_or(sd, KS_OFMTA, 0xcf, 0x00); + /* Ignore the OEN pin */ + ks0127_and_or(sd, KS_CDEM, 0x7f, 0x80); } return 0; } +static int ks0127_status(struct v4l2_subdev *sd, u32 *pstatus, v4l2_std_id *pstd) +{ + int stat = V4L2_IN_ST_NO_SIGNAL; + u8 status; + v4l2_std_id std = V4L2_STD_ALL; + + v4l2_dbg(1, debug, sd, "VIDIOC_QUERYSTD/VIDIOC_INT_G_INPUT_STATUS\n"); + status = ks0127_read(sd, KS_STAT); + if (!(status & 0x20)) /* NOVID not set */ + stat = 0; + if (!(status & 0x01)) /* CLOCK set */ + stat |= V4L2_IN_ST_NO_COLOR; + if ((status & 0x08)) /* PALDET set */ + std = V4L2_STD_PAL; + else + std = V4L2_STD_NTSC; + if (pstd) + *pstd = std; + if (pstatus) + *pstatus = stat; + return 0; +} -/* Addresses to scan */ -#define I2C_KS0127_ADDON 0xD8 -#define I2C_KS0127_ONBOARD 0xDA +static int ks0127_querystd(struct v4l2_subdev *sd, v4l2_std_id *std) +{ + return ks0127_status(sd, NULL, std); +} -static unsigned short normal_i2c[] = { - I2C_KS0127_ADDON >> 1, - I2C_KS0127_ONBOARD >> 1, - I2C_CLIENT_END +static int ks0127_g_input_status(struct v4l2_subdev *sd, u32 *status) +{ + return ks0127_status(sd, status, NULL); +} + +static int ks0127_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip) +{ + struct i2c_client *client = v4l2_get_subdevdata(sd); + struct ks0127 *ks = to_ks0127(sd); + + return v4l2_chip_ident_i2c_client(client, chip, ks->ident, 0); +} + +static int ks0127_command(struct i2c_client *client, unsigned cmd, void *arg) +{ + return v4l2_subdev_command(i2c_get_clientdata(client), cmd, arg); +} + +/* ----------------------------------------------------------------------- */ + +static const struct v4l2_subdev_core_ops ks0127_core_ops = { + .g_chip_ident = ks0127_g_chip_ident, }; -I2C_CLIENT_INSMOD; +static const struct v4l2_subdev_tuner_ops ks0127_tuner_ops = { + .s_std = ks0127_s_std, +}; + +static const struct v4l2_subdev_video_ops ks0127_video_ops = { + .s_routing = ks0127_s_routing, + .s_stream = ks0127_s_stream, + .querystd = ks0127_querystd, + .g_input_status = ks0127_g_input_status, +}; -static int ks0127_probe(struct i2c_client *c, const struct i2c_device_id *id) +static const struct v4l2_subdev_ops ks0127_ops = { + .core = &ks0127_core_ops, + .tuner = &ks0127_tuner_ops, + .video = &ks0127_video_ops, +}; + +/* ----------------------------------------------------------------------- */ + + +static int ks0127_probe(struct i2c_client *client, const struct i2c_device_id *id) { struct ks0127 *ks; + struct v4l2_subdev *sd; - v4l_info(c, "%s chip found @ 0x%x (%s)\n", - c->addr == (I2C_KS0127_ADDON >> 1) ? "addon" : "on-board", - c->addr << 1, c->adapter->name); + v4l_info(client, "%s chip found @ 0x%x (%s)\n", + client->addr == (I2C_KS0127_ADDON >> 1) ? "addon" : "on-board", + client->addr << 1, client->adapter->name); ks = kzalloc(sizeof(*ks), GFP_KERNEL); if (ks == NULL) return -ENOMEM; - - i2c_set_clientdata(c, ks); - - ks->ks_type = KS_TYPE_UNKNOWN; + sd = &ks->sd; + v4l2_i2c_subdev_init(sd, client, &ks0127_ops); /* power up */ init_reg_defaults(); - ks0127_write(c, KS_CMDA, 0x2c); + ks0127_write(sd, KS_CMDA, 0x2c); mdelay(10); /* reset the device */ - ks0127_reset(c); + ks0127_init(sd); return 0; } -static int ks0127_remove(struct i2c_client *c) +static int ks0127_remove(struct i2c_client *client) { - struct ks0127 *ks = i2c_get_clientdata(c); - - ks0127_write(c, KS_OFMTA, 0x20); /* tristate */ - ks0127_write(c, KS_CMDA, 0x2c | 0x80); /* power down */ + struct v4l2_subdev *sd = i2c_get_clientdata(client); - kfree(ks); + v4l2_device_unregister_subdev(sd); + ks0127_write(sd, KS_OFMTA, 0x20); /* tristate */ + ks0127_write(sd, KS_CMDA, 0x2c | 0x80); /* power down */ + kfree(to_ks0127(sd)); return 0; } diff --git a/include/media/v4l2-chip-ident.h b/include/media/v4l2-chip-ident.h index 69e3092fd288..b5ed91a4ce92 100644 --- a/include/media/v4l2-chip-ident.h +++ b/include/media/v4l2-chip-ident.h @@ -82,6 +82,11 @@ enum { /* module bt866: just ident 866 */ V4L2_IDENT_BT866 = 866, + /* module ks0127: reserved range 1120-1129 */ + V4L2_IDENT_KS0122S = 1122, + V4L2_IDENT_KS0127 = 1127, + V4L2_IDENT_KS0127B = 1128, + /* module vp27smpx: just ident 2700 */ V4L2_IDENT_VP27SMPX = 2700, -- cgit v1.2.3 From 18d135ad6dbd6f4a32759ac9bd74ac92c96ae182 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Thu, 19 Feb 2009 11:51:16 -0300 Subject: V4L/DVB (10723): ks0127: add supported ks0127 variants to the i2c device list. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/ks0127.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/media/video') diff --git a/drivers/media/video/ks0127.c b/drivers/media/video/ks0127.c index 9ae94484da64..07c79250f8fd 100644 --- a/drivers/media/video/ks0127.c +++ b/drivers/media/video/ks0127.c @@ -724,6 +724,8 @@ static int ks0127_legacy_probe(struct i2c_adapter *adapter) static const struct i2c_device_id ks0127_id[] = { { "ks0127", 0 }, + { "ks0127b", 0 }, + { "ks0122s", 0 }, { } }; MODULE_DEVICE_TABLE(i2c, ks0127_id); -- cgit v1.2.3 From e7946844e676b5d33876d36db92f386a9907a0f4 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Thu, 19 Feb 2009 12:24:27 -0300 Subject: V4L/DVB (10724): saa7110: convert to v4l2_subdev. Signed-off-by: Hans Verkuil [mchehab@redhat.com: fix merge conflict with removal of v4l2_ctrl_query_fill_std()] Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/saa7110.c | 468 +++++++++++++++++++++------------------- include/media/v4l2-chip-ident.h | 4 +- 2 files changed, 251 insertions(+), 221 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/saa7110.c b/drivers/media/video/saa7110.c index 9ef6b2bb1b77..ea16e3cf1793 100644 --- a/drivers/media/video/saa7110.c +++ b/drivers/media/video/saa7110.c @@ -33,15 +33,19 @@ #include #include #include -#include -#include -#include +#include +#include +#include #include MODULE_DESCRIPTION("Philips SAA7110 video decoder driver"); MODULE_AUTHOR("Pauline Middelink"); MODULE_LICENSE("GPL"); +static unsigned short normal_i2c[] = { 0x9c >> 1, 0x9e >> 1, I2C_CLIENT_END }; + +I2C_CLIENT_INSMOD; + static int debug; module_param(debug, int, 0); MODULE_PARM_DESC(debug, "Debug level (0-1)"); @@ -52,6 +56,7 @@ MODULE_PARM_DESC(debug, "Debug level (0-1)"); #define SAA7110_NR_REG 0x35 struct saa7110 { + struct v4l2_subdev sd; u8 reg[SAA7110_NR_REG]; v4l2_std_id norm; @@ -65,20 +70,28 @@ struct saa7110 { wait_queue_head_t wq; }; +static inline struct saa7110 *to_saa7110(struct v4l2_subdev *sd) +{ + return container_of(sd, struct saa7110, sd); +} + /* ----------------------------------------------------------------------- */ /* I2C support functions */ /* ----------------------------------------------------------------------- */ -static int saa7110_write(struct i2c_client *client, u8 reg, u8 value) +static int saa7110_write(struct v4l2_subdev *sd, u8 reg, u8 value) { - struct saa7110 *decoder = i2c_get_clientdata(client); + struct i2c_client *client = v4l2_get_subdevdata(sd); + struct saa7110 *decoder = to_saa7110(sd); decoder->reg[reg] = value; return i2c_smbus_write_byte_data(client, reg, value); } -static int saa7110_write_block(struct i2c_client *client, const u8 *data, unsigned int len) +static int saa7110_write_block(struct v4l2_subdev *sd, const u8 *data, unsigned int len) { + struct i2c_client *client = v4l2_get_subdevdata(sd); + struct saa7110 *decoder = to_saa7110(sd); int ret = -1; u8 reg = *data; /* first register to write to */ @@ -89,15 +102,13 @@ static int saa7110_write_block(struct i2c_client *client, const u8 *data, unsign /* the saa7110 has an autoincrement function, use it if * the adapter understands raw I2C */ if (i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { - struct saa7110 *decoder = i2c_get_clientdata(client); - ret = i2c_master_send(client, data, len); /* Cache the written data */ memcpy(decoder->reg + reg, data + 1, len - 1); } else { for (++data, --len; len; len--) { - ret = saa7110_write(client, reg++, *data++); + ret = saa7110_write(sd, reg++, *data++); if (ret < 0) break; } @@ -106,8 +117,10 @@ static int saa7110_write_block(struct i2c_client *client, const u8 *data, unsign return ret; } -static inline int saa7110_read(struct i2c_client *client) +static inline int saa7110_read(struct v4l2_subdev *sd) { + struct i2c_client *client = v4l2_get_subdevdata(sd); + return i2c_smbus_read_byte(client); } @@ -115,11 +128,11 @@ static inline int saa7110_read(struct i2c_client *client) /* SAA7110 functions */ /* ----------------------------------------------------------------------- */ -#define FRESP_06H_COMPST 0x03 //0x13 -#define FRESP_06H_SVIDEO 0x83 //0xC0 +#define FRESP_06H_COMPST 0x03 /*0x13*/ +#define FRESP_06H_SVIDEO 0x83 /*0xC0*/ -static int saa7110_selmux(struct i2c_client *client, int chan) +static int saa7110_selmux(struct v4l2_subdev *sd, int chan) { static const unsigned char modes[9][8] = { /* mode 0 */ @@ -150,17 +163,17 @@ static int saa7110_selmux(struct i2c_client *client, int chan) {FRESP_06H_SVIDEO, 0x3C, 0x27, 0xC1, 0x23, 0x44, 0x75, 0x21} }; - struct saa7110 *decoder = i2c_get_clientdata(client); + struct saa7110 *decoder = to_saa7110(sd); const unsigned char *ptr = modes[chan]; - saa7110_write(client, 0x06, ptr[0]); /* Luminance control */ - saa7110_write(client, 0x20, ptr[1]); /* Analog Control #1 */ - saa7110_write(client, 0x21, ptr[2]); /* Analog Control #2 */ - saa7110_write(client, 0x22, ptr[3]); /* Mixer Control #1 */ - saa7110_write(client, 0x2C, ptr[4]); /* Mixer Control #2 */ - saa7110_write(client, 0x30, ptr[5]); /* ADCs gain control */ - saa7110_write(client, 0x31, ptr[6]); /* Mixer Control #3 */ - saa7110_write(client, 0x21, ptr[7]); /* Analog Control #2 */ + saa7110_write(sd, 0x06, ptr[0]); /* Luminance control */ + saa7110_write(sd, 0x20, ptr[1]); /* Analog Control #1 */ + saa7110_write(sd, 0x21, ptr[2]); /* Analog Control #2 */ + saa7110_write(sd, 0x22, ptr[3]); /* Mixer Control #1 */ + saa7110_write(sd, 0x2C, ptr[4]); /* Mixer Control #2 */ + saa7110_write(sd, 0x30, ptr[5]); /* ADCs gain control */ + saa7110_write(sd, 0x31, ptr[6]); /* Mixer Control #3 */ + saa7110_write(sd, 0x21, ptr[7]); /* Analog Control #2 */ decoder->input = chan; return 0; @@ -176,250 +189,265 @@ static const unsigned char initseq[1 + SAA7110_NR_REG] = { /* 0x30 */ 0x44, 0x71, 0x02, 0x8C, 0x02 }; -static v4l2_std_id determine_norm(struct i2c_client *client) +static v4l2_std_id determine_norm(struct v4l2_subdev *sd) { DEFINE_WAIT(wait); - struct saa7110 *decoder = i2c_get_clientdata(client); + struct saa7110 *decoder = to_saa7110(sd); int status; /* mode changed, start automatic detection */ - saa7110_write_block(client, initseq, sizeof(initseq)); - saa7110_selmux(client, decoder->input); + saa7110_write_block(sd, initseq, sizeof(initseq)); + saa7110_selmux(sd, decoder->input); prepare_to_wait(&decoder->wq, &wait, TASK_UNINTERRUPTIBLE); schedule_timeout(msecs_to_jiffies(250)); finish_wait(&decoder->wq, &wait); - status = saa7110_read(client); + status = saa7110_read(sd); if (status & 0x40) { - v4l_dbg(1, debug, client, "status=0x%02x (no signal)\n", status); - return decoder->norm; // no change + v4l2_dbg(1, debug, sd, "status=0x%02x (no signal)\n", status); + return decoder->norm; /* no change*/ } if ((status & 3) == 0) { - saa7110_write(client, 0x06, 0x83); + saa7110_write(sd, 0x06, 0x83); if (status & 0x20) { - v4l_dbg(1, debug, client, "status=0x%02x (NTSC/no color)\n", status); - //saa7110_write(client,0x2E,0x81); + v4l2_dbg(1, debug, sd, "status=0x%02x (NTSC/no color)\n", status); + /*saa7110_write(sd,0x2E,0x81);*/ return V4L2_STD_NTSC; } - v4l_dbg(1, debug, client, "status=0x%02x (PAL/no color)\n", status); - //saa7110_write(client,0x2E,0x9A); + v4l2_dbg(1, debug, sd, "status=0x%02x (PAL/no color)\n", status); + /*saa7110_write(sd,0x2E,0x9A);*/ return V4L2_STD_PAL; } - //saa7110_write(client,0x06,0x03); + /*saa7110_write(sd,0x06,0x03);*/ if (status & 0x20) { /* 60Hz */ - v4l_dbg(1, debug, client, "status=0x%02x (NTSC)\n", status); - saa7110_write(client, 0x0D, 0x86); - saa7110_write(client, 0x0F, 0x50); - saa7110_write(client, 0x11, 0x2C); - //saa7110_write(client,0x2E,0x81); + v4l2_dbg(1, debug, sd, "status=0x%02x (NTSC)\n", status); + saa7110_write(sd, 0x0D, 0x86); + saa7110_write(sd, 0x0F, 0x50); + saa7110_write(sd, 0x11, 0x2C); + /*saa7110_write(sd,0x2E,0x81);*/ return V4L2_STD_NTSC; } /* 50Hz -> PAL/SECAM */ - saa7110_write(client, 0x0D, 0x86); - saa7110_write(client, 0x0F, 0x10); - saa7110_write(client, 0x11, 0x59); - //saa7110_write(client,0x2E,0x9A); + saa7110_write(sd, 0x0D, 0x86); + saa7110_write(sd, 0x0F, 0x10); + saa7110_write(sd, 0x11, 0x59); + /*saa7110_write(sd,0x2E,0x9A);*/ prepare_to_wait(&decoder->wq, &wait, TASK_UNINTERRUPTIBLE); schedule_timeout(msecs_to_jiffies(250)); finish_wait(&decoder->wq, &wait); - status = saa7110_read(client); + status = saa7110_read(sd); if ((status & 0x03) == 0x01) { - v4l_dbg(1, debug, client, "status=0x%02x (SECAM)\n", status); - saa7110_write(client, 0x0D, 0x87); + v4l2_dbg(1, debug, sd, "status=0x%02x (SECAM)\n", status); + saa7110_write(sd, 0x0D, 0x87); return V4L2_STD_SECAM; } - v4l_dbg(1, debug, client, "status=0x%02x (PAL)\n", status); + v4l2_dbg(1, debug, sd, "status=0x%02x (PAL)\n", status); return V4L2_STD_PAL; } -static int -saa7110_command (struct i2c_client *client, - unsigned int cmd, - void *arg) +static int saa7110_g_input_status(struct v4l2_subdev *sd, u32 *pstatus) { - struct saa7110 *decoder = i2c_get_clientdata(client); - struct v4l2_routing *route = arg; - v4l2_std_id std; - int v; - - switch (cmd) { - case VIDIOC_INT_INIT: - //saa7110_write_block(client, initseq, sizeof(initseq)); - break; + struct saa7110 *decoder = to_saa7110(sd); + int res = V4L2_IN_ST_NO_SIGNAL; + int status = saa7110_read(sd); + + v4l2_dbg(1, debug, sd, "status=0x%02x norm=%llx\n", + status, decoder->norm); + if (!(status & 0x40)) + res = 0; + if (!(status & 0x03)) + res |= V4L2_IN_ST_NO_COLOR; + + *pstatus = res; + return 0; +} - case VIDIOC_INT_G_INPUT_STATUS: - { - int res = V4L2_IN_ST_NO_SIGNAL; - int status; +static int saa7110_querystd(struct v4l2_subdev *sd, v4l2_std_id *std) +{ + *(v4l2_std_id *)std = determine_norm(sd); + return 0; +} - status = saa7110_read(client); - v4l_dbg(1, debug, client, "status=0x%02x norm=%llx\n", - status, decoder->norm); - if (!(status & 0x40)) - res = 0; - if (!(status & 0x03)) - res |= V4L2_IN_ST_NO_COLOR; +static int saa7110_s_std(struct v4l2_subdev *sd, v4l2_std_id std) +{ + struct saa7110 *decoder = to_saa7110(sd); + + if (decoder->norm != std) { + decoder->norm = std; + /*saa7110_write(sd, 0x06, 0x03);*/ + if (std & V4L2_STD_NTSC) { + saa7110_write(sd, 0x0D, 0x86); + saa7110_write(sd, 0x0F, 0x50); + saa7110_write(sd, 0x11, 0x2C); + /*saa7110_write(sd, 0x2E, 0x81);*/ + v4l2_dbg(1, debug, sd, "switched to NTSC\n"); + } else if (std & V4L2_STD_PAL) { + saa7110_write(sd, 0x0D, 0x86); + saa7110_write(sd, 0x0F, 0x10); + saa7110_write(sd, 0x11, 0x59); + /*saa7110_write(sd, 0x2E, 0x9A);*/ + v4l2_dbg(1, debug, sd, "switched to PAL\n"); + } else if (std & V4L2_STD_SECAM) { + saa7110_write(sd, 0x0D, 0x87); + saa7110_write(sd, 0x0F, 0x10); + saa7110_write(sd, 0x11, 0x59); + /*saa7110_write(sd, 0x2E, 0x9A);*/ + v4l2_dbg(1, debug, sd, "switched to SECAM\n"); + } else { + return -EINVAL; + } + } + return 0; +} - *(int *) arg = res; - break; +static int saa7110_s_routing(struct v4l2_subdev *sd, const struct v4l2_routing *route) +{ + struct saa7110 *decoder = to_saa7110(sd); + + if (route->input < 0 || route->input >= SAA7110_MAX_INPUT) { + v4l2_dbg(1, debug, sd, "input=%d not available\n", route->input); + return -EINVAL; } + if (decoder->input != route->input) { + saa7110_selmux(sd, route->input); + v4l2_dbg(1, debug, sd, "switched to input=%d\n", route->input); + } + return 0; +} - case VIDIOC_QUERYSTD: - { - *(v4l2_std_id *)arg = determine_norm(client); - break; +static int saa7110_s_stream(struct v4l2_subdev *sd, int enable) +{ + struct saa7110 *decoder = to_saa7110(sd); + + if (decoder->enable != enable) { + decoder->enable = enable; + saa7110_write(sd, 0x0E, enable ? 0x18 : 0x80); + v4l2_dbg(1, debug, sd, "YUV %s\n", enable ? "on" : "off"); } + return 0; +} - case VIDIOC_S_STD: - std = *(v4l2_std_id *) arg; - if (decoder->norm != std) { - decoder->norm = std; - //saa7110_write(client, 0x06, 0x03); - if (std & V4L2_STD_NTSC) { - saa7110_write(client, 0x0D, 0x86); - saa7110_write(client, 0x0F, 0x50); - saa7110_write(client, 0x11, 0x2C); - //saa7110_write(client, 0x2E, 0x81); - v4l_dbg(1, debug, client, "switched to NTSC\n"); - } else if (std & V4L2_STD_PAL) { - saa7110_write(client, 0x0D, 0x86); - saa7110_write(client, 0x0F, 0x10); - saa7110_write(client, 0x11, 0x59); - //saa7110_write(client, 0x2E, 0x9A); - v4l_dbg(1, debug, client, "switched to PAL\n"); - } else if (std & V4L2_STD_SECAM) { - saa7110_write(client, 0x0D, 0x87); - saa7110_write(client, 0x0F, 0x10); - saa7110_write(client, 0x11, 0x59); - //saa7110_write(client, 0x2E, 0x9A); - v4l_dbg(1, debug, client, "switched to SECAM\n"); - } else { - return -EINVAL; - } - } - break; +static int saa7110_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qc) +{ + switch (qc->id) { + case V4L2_CID_BRIGHTNESS: + return v4l2_ctrl_query_fill(qc, 0, 255, 1, 128); + case V4L2_CID_CONTRAST: + case V4L2_CID_SATURATION: + return v4l2_ctrl_query_fill(qc, 0, 127, 1, 64); + case V4L2_CID_HUE: + return v4l2_ctrl_query_fill(qc, -128, 127, 1, 0); + default: + return -EINVAL; + } + return 0; +} - case VIDIOC_INT_S_VIDEO_ROUTING: - if (route->input < 0 || route->input >= SAA7110_MAX_INPUT) { - v4l_dbg(1, debug, client, "input=%d not available\n", route->input); - return -EINVAL; - } - if (decoder->input != route->input) { - saa7110_selmux(client, route->input); - v4l_dbg(1, debug, client, "switched to input=%d\n", route->input); - } +static int saa7110_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) +{ + struct saa7110 *decoder = to_saa7110(sd); + + switch (ctrl->id) { + case V4L2_CID_BRIGHTNESS: + ctrl->value = decoder->bright; + break; + case V4L2_CID_CONTRAST: + ctrl->value = decoder->contrast; + break; + case V4L2_CID_SATURATION: + ctrl->value = decoder->sat; + break; + case V4L2_CID_HUE: + ctrl->value = decoder->hue; break; + default: + return -EINVAL; + } + return 0; +} - case VIDIOC_STREAMON: - case VIDIOC_STREAMOFF: - v = cmd == VIDIOC_STREAMON; - if (decoder->enable != v) { - decoder->enable = v; - saa7110_write(client, 0x0E, v ? 0x18 : 0x80); - v4l_dbg(1, debug, client, "YUV %s\n", v ? "on" : "off"); +static int saa7110_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) +{ + struct saa7110 *decoder = to_saa7110(sd); + + switch (ctrl->id) { + case V4L2_CID_BRIGHTNESS: + if (decoder->bright != ctrl->value) { + decoder->bright = ctrl->value; + saa7110_write(sd, 0x19, decoder->bright); } break; - - case VIDIOC_QUERYCTRL: - { - struct v4l2_queryctrl *qc = arg; - - switch (qc->id) { - case V4L2_CID_BRIGHTNESS: - return v4l2_ctrl_query_fill(qc, 0, 255, 1, 128); - case V4L2_CID_CONTRAST: - case V4L2_CID_SATURATION: - return v4l2_ctrl_query_fill(qc, 0, 127, 1, 64); - case V4L2_CID_HUE: - return v4l2_ctrl_query_fill(qc, -128, 127, 1, 0); - default: - return -EINVAL; + case V4L2_CID_CONTRAST: + if (decoder->contrast != ctrl->value) { + decoder->contrast = ctrl->value; + saa7110_write(sd, 0x13, decoder->contrast); } break; - } - - case VIDIOC_G_CTRL: - { - struct v4l2_control *ctrl = arg; - - switch (ctrl->id) { - case V4L2_CID_BRIGHTNESS: - ctrl->value = decoder->bright; - break; - case V4L2_CID_CONTRAST: - ctrl->value = decoder->contrast; - break; - case V4L2_CID_SATURATION: - ctrl->value = decoder->sat; - break; - case V4L2_CID_HUE: - ctrl->value = decoder->hue; - break; - default: - return -EINVAL; + case V4L2_CID_SATURATION: + if (decoder->sat != ctrl->value) { + decoder->sat = ctrl->value; + saa7110_write(sd, 0x12, decoder->sat); } break; - } - - case VIDIOC_S_CTRL: - { - struct v4l2_control *ctrl = arg; - - switch (ctrl->id) { - case V4L2_CID_BRIGHTNESS: - if (decoder->bright != ctrl->value) { - decoder->bright = ctrl->value; - saa7110_write(client, 0x19, decoder->bright); - } - break; - case V4L2_CID_CONTRAST: - if (decoder->contrast != ctrl->value) { - decoder->contrast = ctrl->value; - saa7110_write(client, 0x13, decoder->contrast); - } - break; - case V4L2_CID_SATURATION: - if (decoder->sat != ctrl->value) { - decoder->sat = ctrl->value; - saa7110_write(client, 0x12, decoder->sat); - } - break; - case V4L2_CID_HUE: - if (decoder->hue != ctrl->value) { - decoder->hue = ctrl->value; - saa7110_write(client, 0x07, decoder->hue); - } - break; - default: - return -EINVAL; + case V4L2_CID_HUE: + if (decoder->hue != ctrl->value) { + decoder->hue = ctrl->value; + saa7110_write(sd, 0x07, decoder->hue); } break; - } - default: - v4l_dbg(1, debug, client, "unknown command %08x\n", cmd); return -EINVAL; } return 0; } +static int saa7110_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip) +{ + struct i2c_client *client = v4l2_get_subdevdata(sd); + + return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_SAA7110, 0); +} + +static int saa7110_command(struct i2c_client *client, unsigned cmd, void *arg) +{ + return v4l2_subdev_command(i2c_get_clientdata(client), cmd, arg); +} + /* ----------------------------------------------------------------------- */ -/* - * Generic i2c probe - * concerning the addresses: i2c wants 7 bit (without the r/w bit), so '>>1' - */ +static const struct v4l2_subdev_core_ops saa7110_core_ops = { + .g_chip_ident = saa7110_g_chip_ident, + .g_ctrl = saa7110_g_ctrl, + .s_ctrl = saa7110_s_ctrl, + .queryctrl = saa7110_queryctrl, +}; -static unsigned short normal_i2c[] = { 0x9c >> 1, 0x9e >> 1, I2C_CLIENT_END }; +static const struct v4l2_subdev_tuner_ops saa7110_tuner_ops = { + .s_std = saa7110_s_std, +}; -I2C_CLIENT_INSMOD; +static const struct v4l2_subdev_video_ops saa7110_video_ops = { + .s_routing = saa7110_s_routing, + .s_stream = saa7110_s_stream, + .querystd = saa7110_querystd, + .g_input_status = saa7110_g_input_status, +}; + +static const struct v4l2_subdev_ops saa7110_ops = { + .core = &saa7110_core_ops, + .tuner = &saa7110_tuner_ops, + .video = &saa7110_video_ops, +}; + +/* ----------------------------------------------------------------------- */ static int saa7110_probe(struct i2c_client *client, const struct i2c_device_id *id) { struct saa7110 *decoder; + struct v4l2_subdev *sd; int rv; /* Check if the adapter supports the needed features */ @@ -433,6 +461,8 @@ static int saa7110_probe(struct i2c_client *client, decoder = kzalloc(sizeof(struct saa7110), GFP_KERNEL); if (!decoder) return -ENOMEM; + sd = &decoder->sd; + v4l2_i2c_subdev_init(sd, client, &saa7110_ops); decoder->norm = V4L2_STD_PAL; decoder->input = 0; decoder->enable = 1; @@ -441,30 +471,29 @@ static int saa7110_probe(struct i2c_client *client, decoder->hue = 32768; decoder->sat = 32768; init_waitqueue_head(&decoder->wq); - i2c_set_clientdata(client, decoder); - rv = saa7110_write_block(client, initseq, sizeof(initseq)); + rv = saa7110_write_block(sd, initseq, sizeof(initseq)); if (rv < 0) { - v4l_dbg(1, debug, client, "init status %d\n", rv); + v4l2_dbg(1, debug, sd, "init status %d\n", rv); } else { int ver, status; - saa7110_write(client, 0x21, 0x10); - saa7110_write(client, 0x0e, 0x18); - saa7110_write(client, 0x0D, 0x04); - ver = saa7110_read(client); - saa7110_write(client, 0x0D, 0x06); - //mdelay(150); - status = saa7110_read(client); - v4l_dbg(1, debug, client, "version %x, status=0x%02x\n", + saa7110_write(sd, 0x21, 0x10); + saa7110_write(sd, 0x0e, 0x18); + saa7110_write(sd, 0x0D, 0x04); + ver = saa7110_read(sd); + saa7110_write(sd, 0x0D, 0x06); + /*mdelay(150);*/ + status = saa7110_read(sd); + v4l2_dbg(1, debug, sd, "version %x, status=0x%02x\n", ver, status); - saa7110_write(client, 0x0D, 0x86); - saa7110_write(client, 0x0F, 0x10); - saa7110_write(client, 0x11, 0x59); - //saa7110_write(client, 0x2E, 0x9A); + saa7110_write(sd, 0x0D, 0x86); + saa7110_write(sd, 0x0F, 0x10); + saa7110_write(sd, 0x11, 0x59); + /*saa7110_write(sd, 0x2E, 0x9A);*/ } - //saa7110_selmux(client,0); - //determine_norm(client); + /*saa7110_selmux(sd,0);*/ + /*determine_norm(sd);*/ /* setup and implicit mode 0 select has been performed */ return 0; @@ -472,7 +501,10 @@ static int saa7110_probe(struct i2c_client *client, static int saa7110_remove(struct i2c_client *client) { - kfree(i2c_get_clientdata(client)); + struct v4l2_subdev *sd = i2c_get_clientdata(client); + + v4l2_device_unregister_subdev(sd); + kfree(to_saa7110(sd)); return 0; } diff --git a/include/media/v4l2-chip-ident.h b/include/media/v4l2-chip-ident.h index b5ed91a4ce92..f3fdada21963 100644 --- a/include/media/v4l2-chip-ident.h +++ b/include/media/v4l2-chip-ident.h @@ -37,10 +37,8 @@ enum { /* module saa7110: just ident 100 */ V4L2_IDENT_SAA7110 = 100, - /* module saa7111: just ident 101 */ + /* module saa7115: reserved range 101-149 */ V4L2_IDENT_SAA7111 = 101, - - /* module saa7115: reserved range 102-149 */ V4L2_IDENT_SAA7113 = 103, V4L2_IDENT_SAA7114 = 104, V4L2_IDENT_SAA7115 = 105, -- cgit v1.2.3 From 780d8e1552efb61122c269382b3fa8987aca3e89 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Thu, 19 Feb 2009 13:24:47 -0300 Subject: V4L/DVB (10725): saa7185: convert to v4l2_subdev. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/saa7185.c | 217 ++++++++++++++++++++++------------------ include/media/v4l2-chip-ident.h | 3 + 2 files changed, 122 insertions(+), 98 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/saa7185.c b/drivers/media/video/saa7185.c index fc51e6c9cb95..b4eb66253bc2 100644 --- a/drivers/media/video/saa7185.c +++ b/drivers/media/video/saa7185.c @@ -30,51 +30,61 @@ #include #include #include -#include -#include -#include +#include +#include +#include #include MODULE_DESCRIPTION("Philips SAA7185 video encoder driver"); MODULE_AUTHOR("Dave Perks"); MODULE_LICENSE("GPL"); - static int debug; module_param(debug, int, 0); MODULE_PARM_DESC(debug, "Debug level (0-1)"); +static unsigned short normal_i2c[] = { 0x88 >> 1, I2C_CLIENT_END }; + +I2C_CLIENT_INSMOD; + /* ----------------------------------------------------------------------- */ struct saa7185 { + struct v4l2_subdev sd; unsigned char reg[128]; v4l2_std_id norm; - int bright; - int contrast; - int hue; - int sat; }; +static inline struct saa7185 *to_saa7185(struct v4l2_subdev *sd) +{ + return container_of(sd, struct saa7185, sd); +} + /* ----------------------------------------------------------------------- */ -static inline int saa7185_read(struct i2c_client *client) +static inline int saa7185_read(struct v4l2_subdev *sd) { + struct i2c_client *client = v4l2_get_subdevdata(sd); + return i2c_smbus_read_byte(client); } -static int saa7185_write(struct i2c_client *client, u8 reg, u8 value) +static int saa7185_write(struct v4l2_subdev *sd, u8 reg, u8 value) { - struct saa7185 *encoder = i2c_get_clientdata(client); + struct i2c_client *client = v4l2_get_subdevdata(sd); + struct saa7185 *encoder = to_saa7185(sd); - v4l_dbg(1, debug, client, "%02x set to %02x\n", reg, value); + v4l2_dbg(1, debug, sd, "%02x set to %02x\n", reg, value); encoder->reg[reg] = value; return i2c_smbus_write_byte_data(client, reg, value); } -static int saa7185_write_block(struct i2c_client *client, +static int saa7185_write_block(struct v4l2_subdev *sd, const u8 *data, unsigned int len) { + struct i2c_client *client = v4l2_get_subdevdata(sd); + struct saa7185 *encoder = to_saa7185(sd); int ret = -1; u8 reg; @@ -82,7 +92,6 @@ static int saa7185_write_block(struct i2c_client *client, * the adapter understands raw I2C */ if (i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { /* do raw I2C, not smbus compatible */ - struct saa7185 *encoder = i2c_get_clientdata(client); u8 block_data[32]; int block_len; @@ -103,7 +112,7 @@ static int saa7185_write_block(struct i2c_client *client, /* do some slow I2C emulation kind of thing */ while (len >= 2) { reg = *data++; - ret = saa7185_write(client, reg, *data++); + ret = saa7185_write(sd, reg, *data++); if (ret < 0) break; len -= 2; @@ -212,101 +221,111 @@ static const unsigned char init_ntsc[] = { 0x66, 0x21, /* FSC3 */ }; -static int saa7185_command(struct i2c_client *client, unsigned cmd, void *arg) + +static int saa7185_init(struct v4l2_subdev *sd, u32 val) +{ + struct saa7185 *encoder = to_saa7185(sd); + + saa7185_write_block(sd, init_common, sizeof(init_common)); + if (encoder->norm & V4L2_STD_NTSC) + saa7185_write_block(sd, init_ntsc, sizeof(init_ntsc)); + else + saa7185_write_block(sd, init_pal, sizeof(init_pal)); + return 0; +} + +static int saa7185_s_std_output(struct v4l2_subdev *sd, v4l2_std_id std) +{ + struct saa7185 *encoder = to_saa7185(sd); + + if (std & V4L2_STD_NTSC) + saa7185_write_block(sd, init_ntsc, sizeof(init_ntsc)); + else if (std & V4L2_STD_PAL) + saa7185_write_block(sd, init_pal, sizeof(init_pal)); + else + return -EINVAL; + encoder->norm = std; + return 0; +} + +static int saa7185_s_routing(struct v4l2_subdev *sd, const struct v4l2_routing *route) { - struct saa7185 *encoder = i2c_get_clientdata(client); - - switch (cmd) { - case VIDIOC_INT_INIT: - saa7185_write_block(client, init_common, - sizeof(init_common)); - if (encoder->norm & V4L2_STD_NTSC) - saa7185_write_block(client, init_ntsc, - sizeof(init_ntsc)); - else - saa7185_write_block(client, init_pal, - sizeof(init_pal)); + struct saa7185 *encoder = to_saa7185(sd); + + /* RJ: route->input = 0: input is from SA7111 + route->input = 1: input is from ZR36060 */ + + switch (route->input) { + case 0: + /* turn off colorbar */ + saa7185_write(sd, 0x3a, 0x0f); + /* Switch RTCE to 1 */ + saa7185_write(sd, 0x61, (encoder->reg[0x61] & 0xf7) | 0x08); + saa7185_write(sd, 0x6e, 0x01); break; - case VIDIOC_INT_S_STD_OUTPUT: - { - v4l2_std_id *iarg = arg; - - //saa7185_write_block(client, init_common, sizeof(init_common)); - - if (*iarg & V4L2_STD_NTSC) - saa7185_write_block(client, init_ntsc, - sizeof(init_ntsc)); - else if (*iarg & V4L2_STD_PAL) - saa7185_write_block(client, init_pal, - sizeof(init_pal)); - else - return -EINVAL; - encoder->norm = *iarg; + case 1: + /* turn off colorbar */ + saa7185_write(sd, 0x3a, 0x0f); + /* Switch RTCE to 0 */ + saa7185_write(sd, 0x61, (encoder->reg[0x61] & 0xf7) | 0x00); + /* SW: a slight sync problem... */ + saa7185_write(sd, 0x6e, 0x00); break; - } - case VIDIOC_INT_S_VIDEO_ROUTING: - { - struct v4l2_routing *route = arg; - - /* RJ: route->input = 0: input is from SA7111 - route->input = 1: input is from ZR36060 */ - - switch (route->input) { - case 0: - /* turn off colorbar */ - saa7185_write(client, 0x3a, 0x0f); - /* Switch RTCE to 1 */ - saa7185_write(client, 0x61, - (encoder->reg[0x61] & 0xf7) | 0x08); - saa7185_write(client, 0x6e, 0x01); - break; - - case 1: - /* turn off colorbar */ - saa7185_write(client, 0x3a, 0x0f); - /* Switch RTCE to 0 */ - saa7185_write(client, 0x61, - (encoder->reg[0x61] & 0xf7) | 0x00); - /* SW: a slight sync problem... */ - saa7185_write(client, 0x6e, 0x00); - break; - - case 2: - /* turn on colorbar */ - saa7185_write(client, 0x3a, 0x8f); - /* Switch RTCE to 0 */ - saa7185_write(client, 0x61, - (encoder->reg[0x61] & 0xf7) | 0x08); - /* SW: a slight sync problem... */ - saa7185_write(client, 0x6e, 0x01); - break; - - default: - return -EINVAL; - } + case 2: + /* turn on colorbar */ + saa7185_write(sd, 0x3a, 0x8f); + /* Switch RTCE to 0 */ + saa7185_write(sd, 0x61, (encoder->reg[0x61] & 0xf7) | 0x08); + /* SW: a slight sync problem... */ + saa7185_write(sd, 0x6e, 0x01); break; - } default: return -EINVAL; } - return 0; } +static int saa7185_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip) +{ + struct i2c_client *client = v4l2_get_subdevdata(sd); + + return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_SAA7185, 0); +} + +static int saa7185_command(struct i2c_client *client, unsigned cmd, void *arg) +{ + return v4l2_subdev_command(i2c_get_clientdata(client), cmd, arg); +} + /* ----------------------------------------------------------------------- */ -static unsigned short normal_i2c[] = { 0x88 >> 1, I2C_CLIENT_END }; +static const struct v4l2_subdev_core_ops saa7185_core_ops = { + .g_chip_ident = saa7185_g_chip_ident, + .init = saa7185_init, +}; -I2C_CLIENT_INSMOD; +static const struct v4l2_subdev_video_ops saa7185_video_ops = { + .s_std_output = saa7185_s_std_output, + .s_routing = saa7185_s_routing, +}; + +static const struct v4l2_subdev_ops saa7185_ops = { + .core = &saa7185_core_ops, + .video = &saa7185_video_ops, +}; + + +/* ----------------------------------------------------------------------- */ static int saa7185_probe(struct i2c_client *client, const struct i2c_device_id *id) { int i; struct saa7185 *encoder; + struct v4l2_subdev *sd; /* Check if the adapter supports the needed features */ if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) @@ -319,26 +338,28 @@ static int saa7185_probe(struct i2c_client *client, if (encoder == NULL) return -ENOMEM; encoder->norm = V4L2_STD_NTSC; - i2c_set_clientdata(client, encoder); + sd = &encoder->sd; + v4l2_i2c_subdev_init(sd, client, &saa7185_ops); - i = saa7185_write_block(client, init_common, sizeof(init_common)); + i = saa7185_write_block(sd, init_common, sizeof(init_common)); if (i >= 0) - i = saa7185_write_block(client, init_ntsc, sizeof(init_ntsc)); + i = saa7185_write_block(sd, init_ntsc, sizeof(init_ntsc)); if (i < 0) - v4l_dbg(1, debug, client, "init error %d\n", i); + v4l2_dbg(1, debug, sd, "init error %d\n", i); else - v4l_dbg(1, debug, client, "revision 0x%x\n", - saa7185_read(client) >> 5); + v4l2_dbg(1, debug, sd, "revision 0x%x\n", + saa7185_read(sd) >> 5); return 0; } static int saa7185_remove(struct i2c_client *client) { - struct saa7185 *encoder = i2c_get_clientdata(client); - - saa7185_write(client, 0x61, (encoder->reg[0x61]) | 0x40); /* SW: output off is active */ - //saa7185_write(client, 0x3a, (encoder->reg[0x3a]) | 0x80); /* SW: color bar */ + struct v4l2_subdev *sd = i2c_get_clientdata(client); + struct saa7185 *encoder = to_saa7185(sd); + v4l2_device_unregister_subdev(sd); + /* SW: output off is active */ + saa7185_write(sd, 0x61, (encoder->reg[0x61]) | 0x40); kfree(encoder); return 0; } diff --git a/include/media/v4l2-chip-ident.h b/include/media/v4l2-chip-ident.h index f3fdada21963..59106cc68a63 100644 --- a/include/media/v4l2-chip-ident.h +++ b/include/media/v4l2-chip-ident.h @@ -113,6 +113,9 @@ enum { V4L2_IDENT_SAA6752HS = 6752, V4L2_IDENT_SAA6752HS_AC3 = 6753, + /* module saa7185: just ident 7185 */ + V4L2_IDENT_SAA7185 = 7185, + /* module wm8739: just ident 8739 */ V4L2_IDENT_WM8739 = 8739, -- cgit v1.2.3 From 7e5eaadcbd8894b25f715aa03cb632d0df63269c Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Thu, 19 Feb 2009 14:36:53 -0300 Subject: V4L/DVB (10726): vpx3220: convert to v4l2_subdev. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/vpx3220.c | 497 +++++++++++++++++++++------------------- include/media/v4l2-chip-ident.h | 5 + 2 files changed, 271 insertions(+), 231 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/vpx3220.c b/drivers/media/video/vpx3220.c index cd2064e7733b..476a204dcf90 100644 --- a/drivers/media/video/vpx3220.c +++ b/drivers/media/video/vpx3220.c @@ -24,11 +24,10 @@ #include #include #include -#include -#include -#include #include -#include +#include +#include +#include MODULE_DESCRIPTION("vpx3220a/vpx3216b/vpx3214c video decoder driver"); MODULE_AUTHOR("Laurent Pinchart"); @@ -38,14 +37,20 @@ static int debug; module_param(debug, int, 0); MODULE_PARM_DESC(debug, "Debug level (0-1)"); +static unsigned short normal_i2c[] = { 0x86 >> 1, 0x8e >> 1, I2C_CLIENT_END }; + +I2C_CLIENT_INSMOD; + #define VPX_TIMEOUT_COUNT 10 /* ----------------------------------------------------------------------- */ struct vpx3220 { + struct v4l2_subdev sd; unsigned char reg[255]; v4l2_std_id norm; + int ident; int input; int enable; int bright; @@ -54,30 +59,38 @@ struct vpx3220 { int sat; }; +static inline struct vpx3220 *to_vpx3220(struct v4l2_subdev *sd) +{ + return container_of(sd, struct vpx3220, sd); +} + static char *inputs[] = { "internal", "composite", "svideo" }; /* ----------------------------------------------------------------------- */ -static inline int vpx3220_write(struct i2c_client *client, u8 reg, u8 value) +static inline int vpx3220_write(struct v4l2_subdev *sd, u8 reg, u8 value) { + struct i2c_client *client = v4l2_get_subdevdata(sd); struct vpx3220 *decoder = i2c_get_clientdata(client); decoder->reg[reg] = value; return i2c_smbus_write_byte_data(client, reg, value); } -static inline int vpx3220_read(struct i2c_client *client, u8 reg) +static inline int vpx3220_read(struct v4l2_subdev *sd, u8 reg) { + struct i2c_client *client = v4l2_get_subdevdata(sd); + return i2c_smbus_read_byte_data(client, reg); } -static int vpx3220_fp_status(struct i2c_client *client) +static int vpx3220_fp_status(struct v4l2_subdev *sd) { unsigned char status; unsigned int i; for (i = 0; i < VPX_TIMEOUT_COUNT; i++) { - status = vpx3220_read(client, 0x29); + status = vpx3220_read(sd, 0x29); if (!(status & 4)) return 0; @@ -91,57 +104,60 @@ static int vpx3220_fp_status(struct i2c_client *client) return -1; } -static int vpx3220_fp_write(struct i2c_client *client, u8 fpaddr, u16 data) +static int vpx3220_fp_write(struct v4l2_subdev *sd, u8 fpaddr, u16 data) { + struct i2c_client *client = v4l2_get_subdevdata(sd); + /* Write the 16-bit address to the FPWR register */ if (i2c_smbus_write_word_data(client, 0x27, swab16(fpaddr)) == -1) { - v4l_dbg(1, debug, client, "%s: failed\n", __func__); + v4l2_dbg(1, debug, sd, "%s: failed\n", __func__); return -1; } - if (vpx3220_fp_status(client) < 0) + if (vpx3220_fp_status(sd) < 0) return -1; /* Write the 16-bit data to the FPDAT register */ if (i2c_smbus_write_word_data(client, 0x28, swab16(data)) == -1) { - v4l_dbg(1, debug, client, "%s: failed\n", __func__); + v4l2_dbg(1, debug, sd, "%s: failed\n", __func__); return -1; } return 0; } -static u16 vpx3220_fp_read(struct i2c_client *client, u16 fpaddr) +static u16 vpx3220_fp_read(struct v4l2_subdev *sd, u16 fpaddr) { + struct i2c_client *client = v4l2_get_subdevdata(sd); s16 data; /* Write the 16-bit address to the FPRD register */ if (i2c_smbus_write_word_data(client, 0x26, swab16(fpaddr)) == -1) { - v4l_dbg(1, debug, client, "%s: failed\n", __func__); + v4l2_dbg(1, debug, sd, "%s: failed\n", __func__); return -1; } - if (vpx3220_fp_status(client) < 0) + if (vpx3220_fp_status(sd) < 0) return -1; /* Read the 16-bit data from the FPDAT register */ data = i2c_smbus_read_word_data(client, 0x28); if (data == -1) { - v4l_dbg(1, debug, client, "%s: failed\n", __func__); + v4l2_dbg(1, debug, sd, "%s: failed\n", __func__); return -1; } return swab16(data); } -static int vpx3220_write_block(struct i2c_client *client, const u8 *data, unsigned int len) +static int vpx3220_write_block(struct v4l2_subdev *sd, const u8 *data, unsigned int len) { u8 reg; int ret = -1; while (len >= 2) { reg = *data++; - ret = vpx3220_write(client, reg, *data++); + ret = vpx3220_write(sd, reg, *data++); if (ret < 0) break; len -= 2; @@ -150,7 +166,7 @@ static int vpx3220_write_block(struct i2c_client *client, const u8 *data, unsign return ret; } -static int vpx3220_write_fp_block(struct i2c_client *client, +static int vpx3220_write_fp_block(struct v4l2_subdev *sd, const u16 *data, unsigned int len) { u8 reg; @@ -158,7 +174,7 @@ static int vpx3220_write_fp_block(struct i2c_client *client, while (len > 1) { reg = *data++; - ret |= vpx3220_fp_write(client, reg, *data++); + ret |= vpx3220_fp_write(sd, reg, *data++); len -= 2; } @@ -261,272 +277,281 @@ static const unsigned short init_fp[] = { }; -static int vpx3220_command(struct i2c_client *client, unsigned cmd, void *arg) +static int vpx3220_init(struct v4l2_subdev *sd, u32 val) { - struct vpx3220 *decoder = i2c_get_clientdata(client); - - switch (cmd) { - case VIDIOC_INT_INIT: - { - vpx3220_write_block(client, init_common, - sizeof(init_common)); - vpx3220_write_fp_block(client, init_fp, - sizeof(init_fp) >> 1); - if (decoder->norm & V4L2_STD_NTSC) { - vpx3220_write_fp_block(client, init_ntsc, - sizeof(init_ntsc) >> 1); - } else if (decoder->norm & V4L2_STD_PAL) { - vpx3220_write_fp_block(client, init_pal, - sizeof(init_pal) >> 1); - } else if (decoder->norm & V4L2_STD_SECAM) { - vpx3220_write_fp_block(client, init_secam, - sizeof(init_secam) >> 1); - } else { - vpx3220_write_fp_block(client, init_pal, - sizeof(init_pal) >> 1); - } - break; - } + struct vpx3220 *decoder = to_vpx3220(sd); + + vpx3220_write_block(sd, init_common, sizeof(init_common)); + vpx3220_write_fp_block(sd, init_fp, sizeof(init_fp) >> 1); + if (decoder->norm & V4L2_STD_NTSC) + vpx3220_write_fp_block(sd, init_ntsc, sizeof(init_ntsc) >> 1); + else if (decoder->norm & V4L2_STD_PAL) + vpx3220_write_fp_block(sd, init_pal, sizeof(init_pal) >> 1); + else if (decoder->norm & V4L2_STD_SECAM) + vpx3220_write_fp_block(sd, init_secam, sizeof(init_secam) >> 1); + else + vpx3220_write_fp_block(sd, init_pal, sizeof(init_pal) >> 1); + return 0; +} - case VIDIOC_QUERYSTD: - case VIDIOC_INT_G_INPUT_STATUS: - { - int res = V4L2_IN_ST_NO_SIGNAL, status; - v4l2_std_id std = 0; +static int vpx3220_status(struct v4l2_subdev *sd, u32 *pstatus, v4l2_std_id *pstd) +{ + int res = V4L2_IN_ST_NO_SIGNAL, status; + v4l2_std_id std = 0; - v4l_dbg(1, debug, client, "VIDIOC_QUERYSTD/VIDIOC_INT_G_INPUT_STATUS\n"); + v4l2_dbg(1, debug, sd, "VIDIOC_QUERYSTD/VIDIOC_INT_G_INPUT_STATUS\n"); - status = vpx3220_fp_read(client, 0x0f3); + status = vpx3220_fp_read(sd, 0x0f3); - v4l_dbg(1, debug, client, "status: 0x%04x\n", status); + v4l2_dbg(1, debug, sd, "status: 0x%04x\n", status); - if (status < 0) - return status; + if (status < 0) + return status; - if ((status & 0x20) == 0) { - res = 0; + if ((status & 0x20) == 0) { + res = 0; - switch (status & 0x18) { - case 0x00: - case 0x10: - case 0x14: - case 0x18: - std = V4L2_STD_PAL; - break; + switch (status & 0x18) { + case 0x00: + case 0x10: + case 0x14: + case 0x18: + std = V4L2_STD_PAL; + break; - case 0x08: - std = V4L2_STD_SECAM; - break; + case 0x08: + std = V4L2_STD_SECAM; + break; - case 0x04: - case 0x0c: - case 0x1c: - std = V4L2_STD_NTSC; - break; - } + case 0x04: + case 0x0c: + case 0x1c: + std = V4L2_STD_NTSC; + break; } - - if (cmd == VIDIOC_QUERYSTD) - *(v4l2_std_id *)arg = std; - else - *(int *)arg = res; - break; } + if (pstd) + *pstd = std; + if (pstatus) + *pstatus = status; + return 0; +} - case VIDIOC_S_STD: - { - v4l2_std_id *iarg = arg; - int temp_input; - - /* Here we back up the input selection because it gets - overwritten when we fill the registers with the - choosen video norm */ - temp_input = vpx3220_fp_read(client, 0xf2); - - v4l_dbg(1, debug, client, "VIDIOC_S_STD %llx\n", *iarg); - if (*iarg & V4L2_STD_NTSC) { - vpx3220_write_fp_block(client, init_ntsc, - sizeof(init_ntsc) >> 1); - v4l_dbg(1, debug, client, "norm switched to NTSC\n"); - } else if (*iarg & V4L2_STD_PAL) { - vpx3220_write_fp_block(client, init_pal, - sizeof(init_pal) >> 1); - v4l_dbg(1, debug, client, "norm switched to PAL\n"); - } else if (*iarg & V4L2_STD_SECAM) { - vpx3220_write_fp_block(client, init_secam, - sizeof(init_secam) >> 1); - v4l_dbg(1, debug, client, "norm switched to SECAM\n"); - } else { - return -EINVAL; - } +static int vpx3220_querystd(struct v4l2_subdev *sd, v4l2_std_id *std) +{ + return vpx3220_status(sd, NULL, std); +} - decoder->norm = *iarg; +static int vpx3220_g_input_status(struct v4l2_subdev *sd, u32 *status) +{ + return vpx3220_status(sd, status, NULL); +} - /* And here we set the backed up video input again */ - vpx3220_fp_write(client, 0xf2, temp_input | 0x0010); - udelay(10); - break; +static int vpx3220_s_std(struct v4l2_subdev *sd, v4l2_std_id std) +{ + struct vpx3220 *decoder = to_vpx3220(sd); + int temp_input; + + /* Here we back up the input selection because it gets + overwritten when we fill the registers with the + choosen video norm */ + temp_input = vpx3220_fp_read(sd, 0xf2); + + v4l2_dbg(1, debug, sd, "VIDIOC_S_STD %llx\n", std); + if (std & V4L2_STD_NTSC) { + vpx3220_write_fp_block(sd, init_ntsc, sizeof(init_ntsc) >> 1); + v4l2_dbg(1, debug, sd, "norm switched to NTSC\n"); + } else if (std & V4L2_STD_PAL) { + vpx3220_write_fp_block(sd, init_pal, sizeof(init_pal) >> 1); + v4l2_dbg(1, debug, sd, "norm switched to PAL\n"); + } else if (std & V4L2_STD_SECAM) { + vpx3220_write_fp_block(sd, init_secam, sizeof(init_secam) >> 1); + v4l2_dbg(1, debug, sd, "norm switched to SECAM\n"); + } else { + return -EINVAL; } - case VIDIOC_INT_S_VIDEO_ROUTING: - { - struct v4l2_routing *route = arg; - int data; + decoder->norm = std; - /* RJ: *iarg = 0: ST8 (PCTV) input - *iarg = 1: COMPOSITE input - *iarg = 2: SVHS input */ + /* And here we set the backed up video input again */ + vpx3220_fp_write(sd, 0xf2, temp_input | 0x0010); + udelay(10); + return 0; +} - const int input[3][2] = { - {0x0c, 0}, - {0x0d, 0}, - {0x0e, 1} - }; +static int vpx3220_s_routing(struct v4l2_subdev *sd, const struct v4l2_routing *route) +{ + int data; - if (route->input < 0 || route->input > 2) - return -EINVAL; + /* RJ: route->input = 0: ST8 (PCTV) input + route->input = 1: COMPOSITE input + route->input = 2: SVHS input */ - v4l_dbg(1, debug, client, "input switched to %s\n", inputs[route->input]); + const int input[3][2] = { + {0x0c, 0}, + {0x0d, 0}, + {0x0e, 1} + }; - vpx3220_write(client, 0x33, input[route->input][0]); + if (route->input < 0 || route->input > 2) + return -EINVAL; - data = vpx3220_fp_read(client, 0xf2) & ~(0x0020); - if (data < 0) - return data; - /* 0x0010 is required to latch the setting */ - vpx3220_fp_write(client, 0xf2, - data | (input[route->input][1] << 5) | 0x0010); + v4l2_dbg(1, debug, sd, "input switched to %s\n", inputs[route->input]); - udelay(10); - break; - } + vpx3220_write(sd, 0x33, input[route->input][0]); - case VIDIOC_STREAMON: - case VIDIOC_STREAMOFF: - { - int on = cmd == VIDIOC_STREAMON; - v4l_dbg(1, debug, client, "VIDIOC_STREAM%s\n", on ? "ON" : "OFF"); + data = vpx3220_fp_read(sd, 0xf2) & ~(0x0020); + if (data < 0) + return data; + /* 0x0010 is required to latch the setting */ + vpx3220_fp_write(sd, 0xf2, + data | (input[route->input][1] << 5) | 0x0010); - vpx3220_write(client, 0xf2, (on ? 0x1b : 0x00)); - break; - } + udelay(10); + return 0; +} - case VIDIOC_QUERYCTRL: - { - struct v4l2_queryctrl *qc = arg; +static int vpx3220_s_stream(struct v4l2_subdev *sd, int enable) +{ + v4l2_dbg(1, debug, sd, "VIDIOC_STREAM%s\n", enable ? "ON" : "OFF"); - switch (qc->id) { - case V4L2_CID_BRIGHTNESS: - v4l2_ctrl_query_fill(qc, -128, 127, 1, 0); - break; + vpx3220_write(sd, 0xf2, (enable ? 0x1b : 0x00)); + return 0; +} - case V4L2_CID_CONTRAST: - v4l2_ctrl_query_fill(qc, 0, 63, 1, 32); - break; +static int vpx3220_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qc) +{ + switch (qc->id) { + case V4L2_CID_BRIGHTNESS: + v4l2_ctrl_query_fill(qc, -128, 127, 1, 0); + break; - case V4L2_CID_SATURATION: - v4l2_ctrl_query_fill(qc, 0, 4095, 1, 2048); - break; + case V4L2_CID_CONTRAST: + v4l2_ctrl_query_fill(qc, 0, 63, 1, 32); + break; - case V4L2_CID_HUE: - v4l2_ctrl_query_fill(qc, -512, 511, 1, 0); - break; + case V4L2_CID_SATURATION: + v4l2_ctrl_query_fill(qc, 0, 4095, 1, 2048); + break; - default: - return -EINVAL; - } + case V4L2_CID_HUE: + v4l2_ctrl_query_fill(qc, -512, 511, 1, 0); break; + + default: + return -EINVAL; } + return 0; +} - case VIDIOC_G_CTRL: - { - struct v4l2_control *ctrl = arg; +static int vpx3220_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) +{ + struct vpx3220 *decoder = to_vpx3220(sd); - switch (ctrl->id) { - case V4L2_CID_BRIGHTNESS: - ctrl->value = decoder->bright; - break; - case V4L2_CID_CONTRAST: - ctrl->value = decoder->contrast; - break; - case V4L2_CID_SATURATION: - ctrl->value = decoder->sat; - break; - case V4L2_CID_HUE: - ctrl->value = decoder->hue; - break; - default: - return -EINVAL; - } + switch (ctrl->id) { + case V4L2_CID_BRIGHTNESS: + ctrl->value = decoder->bright; + break; + case V4L2_CID_CONTRAST: + ctrl->value = decoder->contrast; break; + case V4L2_CID_SATURATION: + ctrl->value = decoder->sat; + break; + case V4L2_CID_HUE: + ctrl->value = decoder->hue; + break; + default: + return -EINVAL; } + return 0; +} - case VIDIOC_S_CTRL: - { - struct v4l2_control *ctrl = arg; +static int vpx3220_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) +{ + struct vpx3220 *decoder = to_vpx3220(sd); - switch (ctrl->id) { - case V4L2_CID_BRIGHTNESS: - if (decoder->bright != ctrl->value) { - decoder->bright = ctrl->value; - vpx3220_write(client, 0xe6, decoder->bright); - } - break; - case V4L2_CID_CONTRAST: - if (decoder->contrast != ctrl->value) { - /* Bit 7 and 8 is for noise shaping */ - decoder->contrast = ctrl->value; - vpx3220_write(client, 0xe7, - decoder->contrast + 192); - } - break; - case V4L2_CID_SATURATION: - if (decoder->sat != ctrl->value) { - decoder->sat = ctrl->value; - vpx3220_fp_write(client, 0xa0, decoder->sat); - } - break; - case V4L2_CID_HUE: - if (decoder->hue != ctrl->value) { - decoder->hue = ctrl->value; - vpx3220_fp_write(client, 0x1c, decoder->hue); - } - break; - default: - return -EINVAL; + switch (ctrl->id) { + case V4L2_CID_BRIGHTNESS: + if (decoder->bright != ctrl->value) { + decoder->bright = ctrl->value; + vpx3220_write(sd, 0xe6, decoder->bright); + } + break; + case V4L2_CID_CONTRAST: + if (decoder->contrast != ctrl->value) { + /* Bit 7 and 8 is for noise shaping */ + decoder->contrast = ctrl->value; + vpx3220_write(sd, 0xe7, decoder->contrast + 192); + } + break; + case V4L2_CID_SATURATION: + if (decoder->sat != ctrl->value) { + decoder->sat = ctrl->value; + vpx3220_fp_write(sd, 0xa0, decoder->sat); + } + break; + case V4L2_CID_HUE: + if (decoder->hue != ctrl->value) { + decoder->hue = ctrl->value; + vpx3220_fp_write(sd, 0x1c, decoder->hue); } break; - } - default: return -EINVAL; } - return 0; } -static int vpx3220_init_client(struct i2c_client *client) +static int vpx3220_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip) { - vpx3220_write_block(client, init_common, sizeof(init_common)); - vpx3220_write_fp_block(client, init_fp, sizeof(init_fp) >> 1); - /* Default to PAL */ - vpx3220_write_fp_block(client, init_pal, sizeof(init_pal) >> 1); + struct vpx3220 *decoder = to_vpx3220(sd); + struct i2c_client *client = v4l2_get_subdevdata(sd); - return 0; + return v4l2_chip_ident_i2c_client(client, chip, decoder->ident, 0); } +static int vpx3220_command(struct i2c_client *client, unsigned cmd, void *arg) +{ + return v4l2_subdev_command(i2c_get_clientdata(client), cmd, arg); +} + +/* ----------------------------------------------------------------------- */ + +static const struct v4l2_subdev_core_ops vpx3220_core_ops = { + .g_chip_ident = vpx3220_g_chip_ident, + .init = vpx3220_init, + .g_ctrl = vpx3220_g_ctrl, + .s_ctrl = vpx3220_s_ctrl, + .queryctrl = vpx3220_queryctrl, +}; + +static const struct v4l2_subdev_tuner_ops vpx3220_tuner_ops = { + .s_std = vpx3220_s_std, +}; + +static const struct v4l2_subdev_video_ops vpx3220_video_ops = { + .s_routing = vpx3220_s_routing, + .s_stream = vpx3220_s_stream, + .querystd = vpx3220_querystd, + .g_input_status = vpx3220_g_input_status, +}; + +static const struct v4l2_subdev_ops vpx3220_ops = { + .core = &vpx3220_core_ops, + .tuner = &vpx3220_tuner_ops, + .video = &vpx3220_video_ops, +}; + /* ----------------------------------------------------------------------- * Client management code */ -static unsigned short normal_i2c[] = { 0x86 >> 1, 0x8e >> 1, I2C_CLIENT_END }; - -I2C_CLIENT_INSMOD; - static int vpx3220_probe(struct i2c_client *client, const struct i2c_device_id *id) { struct vpx3220 *decoder; + struct v4l2_subdev *sd; const char *name = NULL; u8 ver; u16 pn; @@ -539,6 +564,8 @@ static int vpx3220_probe(struct i2c_client *client, decoder = kzalloc(sizeof(struct vpx3220), GFP_KERNEL); if (decoder == NULL) return -ENOMEM; + sd = &decoder->sd; + v4l2_i2c_subdev_init(sd, client, &vpx3220_ops); decoder->norm = V4L2_STD_PAL; decoder->input = 0; decoder->enable = 1; @@ -546,11 +573,11 @@ static int vpx3220_probe(struct i2c_client *client, decoder->contrast = 32768; decoder->hue = 32768; decoder->sat = 32768; - i2c_set_clientdata(client, decoder); ver = i2c_smbus_read_byte_data(client, 0x00); pn = (i2c_smbus_read_byte_data(client, 0x02) << 8) + i2c_smbus_read_byte_data(client, 0x01); + decoder->ident = V4L2_IDENT_VPX3220A; if (ver == 0xec) { switch (pn) { case 0x4680: @@ -558,26 +585,34 @@ static int vpx3220_probe(struct i2c_client *client, break; case 0x4260: name = "vpx3216b"; + decoder->ident = V4L2_IDENT_VPX3216B; break; case 0x4280: name = "vpx3214c"; + decoder->ident = V4L2_IDENT_VPX3214C; break; } } if (name) - v4l_info(client, "%s found @ 0x%x (%s)\n", name, + v4l2_info(sd, "%s found @ 0x%x (%s)\n", name, client->addr << 1, client->adapter->name); else - v4l_info(client, "chip (%02x:%04x) found @ 0x%x (%s)\n", + v4l2_info(sd, "chip (%02x:%04x) found @ 0x%x (%s)\n", ver, pn, client->addr << 1, client->adapter->name); - vpx3220_init_client(client); + vpx3220_write_block(sd, init_common, sizeof(init_common)); + vpx3220_write_fp_block(sd, init_fp, sizeof(init_fp) >> 1); + /* Default to PAL */ + vpx3220_write_fp_block(sd, init_pal, sizeof(init_pal) >> 1); return 0; } static int vpx3220_remove(struct i2c_client *client) { - kfree(i2c_get_clientdata(client)); + struct v4l2_subdev *sd = i2c_get_clientdata(client); + + v4l2_device_unregister_subdev(sd); + kfree(to_vpx3220(sd)); return 0; } diff --git a/include/media/v4l2-chip-ident.h b/include/media/v4l2-chip-ident.h index 59106cc68a63..f53f1a1b0525 100644 --- a/include/media/v4l2-chip-ident.h +++ b/include/media/v4l2-chip-ident.h @@ -88,6 +88,11 @@ enum { /* module vp27smpx: just ident 2700 */ V4L2_IDENT_VP27SMPX = 2700, + /* module vpx3220: reserved range: 3210-3229 */ + V4L2_IDENT_VPX3214C = 3214, + V4L2_IDENT_VPX3216B = 3216, + V4L2_IDENT_VPX3220A = 3220, + /* module tvp5150 */ V4L2_IDENT_TVP5150 = 5150, -- cgit v1.2.3 From 7d9ef21c2fd4d4d302cd2026c477c058f17d2ba8 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Thu, 19 Feb 2009 14:47:22 -0300 Subject: V4L/DVB (10727): adv7170: convert to v4l2_subdev. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/adv7170.c | 321 +++++++++++++++++++++------------------- include/media/v4l2-chip-ident.h | 6 + 2 files changed, 174 insertions(+), 153 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/adv7170.c b/drivers/media/video/adv7170.c index ebafe78cb4c0..f7120b369ba2 100644 --- a/drivers/media/video/adv7170.c +++ b/drivers/media/video/adv7170.c @@ -34,15 +34,23 @@ #include #include #include -#include -#include -#include +#include +#include +#include #include MODULE_DESCRIPTION("Analog Devices ADV7170 video encoder driver"); MODULE_AUTHOR("Maxim Yevtyushkin"); MODULE_LICENSE("GPL"); +static unsigned short normal_i2c[] = { + 0xd4 >> 1, 0xd6 >> 1, /* adv7170 IDs */ + 0x54 >> 1, 0x56 >> 1, /* adv7171 IDs */ + I2C_CLIENT_END +}; + +I2C_CLIENT_INSMOD; + static int debug; module_param(debug, int, 0); MODULE_PARM_DESC(debug, "Debug level (0-1)"); @@ -50,36 +58,43 @@ MODULE_PARM_DESC(debug, "Debug level (0-1)"); /* ----------------------------------------------------------------------- */ struct adv7170 { + struct v4l2_subdev sd; unsigned char reg[128]; v4l2_std_id norm; int input; - int bright; - int contrast; - int hue; - int sat; }; +static inline struct adv7170 *to_adv7170(struct v4l2_subdev *sd) +{ + return container_of(sd, struct adv7170, sd); +} + static char *inputs[] = { "pass_through", "play_back" }; /* ----------------------------------------------------------------------- */ -static inline int adv7170_write(struct i2c_client *client, u8 reg, u8 value) +static inline int adv7170_write(struct v4l2_subdev *sd, u8 reg, u8 value) { - struct adv7170 *encoder = i2c_get_clientdata(client); + struct i2c_client *client = v4l2_get_subdevdata(sd); + struct adv7170 *encoder = to_adv7170(sd); encoder->reg[reg] = value; return i2c_smbus_write_byte_data(client, reg, value); } -static inline int adv7170_read(struct i2c_client *client, u8 reg) +static inline int adv7170_read(struct v4l2_subdev *sd, u8 reg) { + struct i2c_client *client = v4l2_get_subdevdata(sd); + return i2c_smbus_read_byte_data(client, reg); } -static int adv7170_write_block(struct i2c_client *client, +static int adv7170_write_block(struct v4l2_subdev *sd, const u8 *data, unsigned int len) { + struct i2c_client *client = v4l2_get_subdevdata(sd); + struct adv7170 *encoder = to_adv7170(sd); int ret = -1; u8 reg; @@ -87,7 +102,6 @@ static int adv7170_write_block(struct i2c_client *client, * the adapter understands raw I2C */ if (i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { /* do raw I2C, not smbus compatible */ - struct adv7170 *encoder = i2c_get_clientdata(client); u8 block_data[32]; int block_len; @@ -108,7 +122,7 @@ static int adv7170_write_block(struct i2c_client *client, /* do some slow I2C emulation kind of thing */ while (len >= 2) { reg = *data++; - ret = adv7170_write(client, reg, *data++); + ret = adv7170_write(sd, reg, *data++); if (ret < 0) break; len -= 2; @@ -126,168 +140,165 @@ static int adv7170_write_block(struct i2c_client *client, #define TR1PLAY 0x00 static const unsigned char init_NTSC[] = { - 0x00, 0x10, // MR0 - 0x01, 0x20, // MR1 - 0x02, 0x0e, // MR2 RTC control: bits 2 and 1 - 0x03, 0x80, // MR3 - 0x04, 0x30, // MR4 - 0x05, 0x00, // Reserved - 0x06, 0x00, // Reserved - 0x07, TR0MODE, // TM0 - 0x08, TR1CAPT, // TM1 - 0x09, 0x16, // Fsc0 - 0x0a, 0x7c, // Fsc1 - 0x0b, 0xf0, // Fsc2 - 0x0c, 0x21, // Fsc3 - 0x0d, 0x00, // Subcarrier Phase - 0x0e, 0x00, // Closed Capt. Ext 0 - 0x0f, 0x00, // Closed Capt. Ext 1 - 0x10, 0x00, // Closed Capt. 0 - 0x11, 0x00, // Closed Capt. 1 - 0x12, 0x00, // Pedestal Ctl 0 - 0x13, 0x00, // Pedestal Ctl 1 - 0x14, 0x00, // Pedestal Ctl 2 - 0x15, 0x00, // Pedestal Ctl 3 - 0x16, 0x00, // CGMS_WSS_0 - 0x17, 0x00, // CGMS_WSS_1 - 0x18, 0x00, // CGMS_WSS_2 - 0x19, 0x00, // Teletext Ctl + 0x00, 0x10, /* MR0 */ + 0x01, 0x20, /* MR1 */ + 0x02, 0x0e, /* MR2 RTC control: bits 2 and 1 */ + 0x03, 0x80, /* MR3 */ + 0x04, 0x30, /* MR4 */ + 0x05, 0x00, /* Reserved */ + 0x06, 0x00, /* Reserved */ + 0x07, TR0MODE, /* TM0 */ + 0x08, TR1CAPT, /* TM1 */ + 0x09, 0x16, /* Fsc0 */ + 0x0a, 0x7c, /* Fsc1 */ + 0x0b, 0xf0, /* Fsc2 */ + 0x0c, 0x21, /* Fsc3 */ + 0x0d, 0x00, /* Subcarrier Phase */ + 0x0e, 0x00, /* Closed Capt. Ext 0 */ + 0x0f, 0x00, /* Closed Capt. Ext 1 */ + 0x10, 0x00, /* Closed Capt. 0 */ + 0x11, 0x00, /* Closed Capt. 1 */ + 0x12, 0x00, /* Pedestal Ctl 0 */ + 0x13, 0x00, /* Pedestal Ctl 1 */ + 0x14, 0x00, /* Pedestal Ctl 2 */ + 0x15, 0x00, /* Pedestal Ctl 3 */ + 0x16, 0x00, /* CGMS_WSS_0 */ + 0x17, 0x00, /* CGMS_WSS_1 */ + 0x18, 0x00, /* CGMS_WSS_2 */ + 0x19, 0x00, /* Teletext Ctl */ }; static const unsigned char init_PAL[] = { - 0x00, 0x71, // MR0 - 0x01, 0x20, // MR1 - 0x02, 0x0e, // MR2 RTC control: bits 2 and 1 - 0x03, 0x80, // MR3 - 0x04, 0x30, // MR4 - 0x05, 0x00, // Reserved - 0x06, 0x00, // Reserved - 0x07, TR0MODE, // TM0 - 0x08, TR1CAPT, // TM1 - 0x09, 0xcb, // Fsc0 - 0x0a, 0x8a, // Fsc1 - 0x0b, 0x09, // Fsc2 - 0x0c, 0x2a, // Fsc3 - 0x0d, 0x00, // Subcarrier Phase - 0x0e, 0x00, // Closed Capt. Ext 0 - 0x0f, 0x00, // Closed Capt. Ext 1 - 0x10, 0x00, // Closed Capt. 0 - 0x11, 0x00, // Closed Capt. 1 - 0x12, 0x00, // Pedestal Ctl 0 - 0x13, 0x00, // Pedestal Ctl 1 - 0x14, 0x00, // Pedestal Ctl 2 - 0x15, 0x00, // Pedestal Ctl 3 - 0x16, 0x00, // CGMS_WSS_0 - 0x17, 0x00, // CGMS_WSS_1 - 0x18, 0x00, // CGMS_WSS_2 - 0x19, 0x00, // Teletext Ctl + 0x00, 0x71, /* MR0 */ + 0x01, 0x20, /* MR1 */ + 0x02, 0x0e, /* MR2 RTC control: bits 2 and 1 */ + 0x03, 0x80, /* MR3 */ + 0x04, 0x30, /* MR4 */ + 0x05, 0x00, /* Reserved */ + 0x06, 0x00, /* Reserved */ + 0x07, TR0MODE, /* TM0 */ + 0x08, TR1CAPT, /* TM1 */ + 0x09, 0xcb, /* Fsc0 */ + 0x0a, 0x8a, /* Fsc1 */ + 0x0b, 0x09, /* Fsc2 */ + 0x0c, 0x2a, /* Fsc3 */ + 0x0d, 0x00, /* Subcarrier Phase */ + 0x0e, 0x00, /* Closed Capt. Ext 0 */ + 0x0f, 0x00, /* Closed Capt. Ext 1 */ + 0x10, 0x00, /* Closed Capt. 0 */ + 0x11, 0x00, /* Closed Capt. 1 */ + 0x12, 0x00, /* Pedestal Ctl 0 */ + 0x13, 0x00, /* Pedestal Ctl 1 */ + 0x14, 0x00, /* Pedestal Ctl 2 */ + 0x15, 0x00, /* Pedestal Ctl 3 */ + 0x16, 0x00, /* CGMS_WSS_0 */ + 0x17, 0x00, /* CGMS_WSS_1 */ + 0x18, 0x00, /* CGMS_WSS_2 */ + 0x19, 0x00, /* Teletext Ctl */ }; -static int adv7170_command(struct i2c_client *client, unsigned cmd, void *arg) +static int adv7170_s_std_output(struct v4l2_subdev *sd, v4l2_std_id std) { - struct adv7170 *encoder = i2c_get_clientdata(client); - - switch (cmd) { - case VIDIOC_INT_INIT: -#if 0 - /* This is just for testing!!! */ - adv7170_write_block(client, init_common, - sizeof(init_common)); - adv7170_write(client, 0x07, TR0MODE | TR0RST); - adv7170_write(client, 0x07, TR0MODE); -#endif - break; - - case VIDIOC_INT_S_STD_OUTPUT: - { - v4l2_std_id iarg = *(v4l2_std_id *) arg; - - v4l_dbg(1, debug, client, "set norm %llx\n", iarg); - - if (iarg & V4L2_STD_NTSC) { - adv7170_write_block(client, init_NTSC, - sizeof(init_NTSC)); - if (encoder->input == 0) - adv7170_write(client, 0x02, 0x0e); // Enable genlock - adv7170_write(client, 0x07, TR0MODE | TR0RST); - adv7170_write(client, 0x07, TR0MODE); - } else if (iarg & V4L2_STD_PAL) { - adv7170_write_block(client, init_PAL, - sizeof(init_PAL)); - if (encoder->input == 0) - adv7170_write(client, 0x02, 0x0e); // Enable genlock - adv7170_write(client, 0x07, TR0MODE | TR0RST); - adv7170_write(client, 0x07, TR0MODE); - } else { - v4l_dbg(1, debug, client, "illegal norm: %llx\n", iarg); - return -EINVAL; - } - v4l_dbg(1, debug, client, "switched to %llx\n", iarg); - encoder->norm = iarg; - break; + struct adv7170 *encoder = to_adv7170(sd); + + v4l2_dbg(1, debug, sd, "set norm %llx\n", std); + + if (std & V4L2_STD_NTSC) { + adv7170_write_block(sd, init_NTSC, sizeof(init_NTSC)); + if (encoder->input == 0) + adv7170_write(sd, 0x02, 0x0e); /* Enable genlock */ + adv7170_write(sd, 0x07, TR0MODE | TR0RST); + adv7170_write(sd, 0x07, TR0MODE); + } else if (std & V4L2_STD_PAL) { + adv7170_write_block(sd, init_PAL, sizeof(init_PAL)); + if (encoder->input == 0) + adv7170_write(sd, 0x02, 0x0e); /* Enable genlock */ + adv7170_write(sd, 0x07, TR0MODE | TR0RST); + adv7170_write(sd, 0x07, TR0MODE); + } else { + v4l2_dbg(1, debug, sd, "illegal norm: %llx\n", std); + return -EINVAL; } + v4l2_dbg(1, debug, sd, "switched to %llx\n", std); + encoder->norm = std; + return 0; +} - case VIDIOC_INT_S_VIDEO_ROUTING: - { - struct v4l2_routing *route = arg; +static int adv7170_s_routing(struct v4l2_subdev *sd, const struct v4l2_routing *route) +{ + struct adv7170 *encoder = to_adv7170(sd); - /* RJ: *iarg = 0: input is from decoder - *iarg = 1: input is from ZR36060 - *iarg = 2: color bar */ + /* RJ: route->input = 0: input is from decoder + route->input = 1: input is from ZR36060 + route->input = 2: color bar */ - v4l_dbg(1, debug, client, "set input from %s\n", + v4l2_dbg(1, debug, sd, "set input from %s\n", route->input == 0 ? "decoder" : "ZR36060"); - switch (route->input) { - case 0: - adv7170_write(client, 0x01, 0x20); - adv7170_write(client, 0x08, TR1CAPT); /* TR1 */ - adv7170_write(client, 0x02, 0x0e); // Enable genlock - adv7170_write(client, 0x07, TR0MODE | TR0RST); - adv7170_write(client, 0x07, TR0MODE); - /* udelay(10); */ - break; - - case 1: - adv7170_write(client, 0x01, 0x00); - adv7170_write(client, 0x08, TR1PLAY); /* TR1 */ - adv7170_write(client, 0x02, 0x08); - adv7170_write(client, 0x07, TR0MODE | TR0RST); - adv7170_write(client, 0x07, TR0MODE); - /* udelay(10); */ - break; - - default: - v4l_dbg(1, debug, client, "illegal input: %d\n", route->input); - return -EINVAL; - } - v4l_dbg(1, debug, client, "switched to %s\n", inputs[route->input]); - encoder->input = route->input; + switch (route->input) { + case 0: + adv7170_write(sd, 0x01, 0x20); + adv7170_write(sd, 0x08, TR1CAPT); /* TR1 */ + adv7170_write(sd, 0x02, 0x0e); /* Enable genlock */ + adv7170_write(sd, 0x07, TR0MODE | TR0RST); + adv7170_write(sd, 0x07, TR0MODE); + /* udelay(10); */ + break; + + case 1: + adv7170_write(sd, 0x01, 0x00); + adv7170_write(sd, 0x08, TR1PLAY); /* TR1 */ + adv7170_write(sd, 0x02, 0x08); + adv7170_write(sd, 0x07, TR0MODE | TR0RST); + adv7170_write(sd, 0x07, TR0MODE); + /* udelay(10); */ break; - } default: + v4l2_dbg(1, debug, sd, "illegal input: %d\n", route->input); return -EINVAL; } - + v4l2_dbg(1, debug, sd, "switched to %s\n", inputs[route->input]); + encoder->input = route->input; return 0; } +static int adv7170_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip) +{ + struct i2c_client *client = v4l2_get_subdevdata(sd); + + return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_BT866, 0); +} + +static int adv7170_command(struct i2c_client *client, unsigned cmd, void *arg) +{ + return v4l2_subdev_command(i2c_get_clientdata(client), cmd, arg); +} + /* ----------------------------------------------------------------------- */ -static unsigned short normal_i2c[] = { - 0xd4 >> 1, 0xd6 >> 1, /* adv7170 IDs */ - 0x54 >> 1, 0x56 >> 1, /* adv7171 IDs */ - I2C_CLIENT_END +static const struct v4l2_subdev_core_ops adv7170_core_ops = { + .g_chip_ident = adv7170_g_chip_ident, }; -I2C_CLIENT_INSMOD; +static const struct v4l2_subdev_video_ops adv7170_video_ops = { + .s_std_output = adv7170_s_std_output, + .s_routing = adv7170_s_routing, +}; + +static const struct v4l2_subdev_ops adv7170_ops = { + .core = &adv7170_core_ops, + .video = &adv7170_video_ops, +}; + +/* ----------------------------------------------------------------------- */ static int adv7170_probe(struct i2c_client *client, const struct i2c_device_id *id) { struct adv7170 *encoder; + struct v4l2_subdev *sd; int i; /* Check if the adapter supports the needed features */ @@ -300,25 +311,29 @@ static int adv7170_probe(struct i2c_client *client, encoder = kzalloc(sizeof(struct adv7170), GFP_KERNEL); if (encoder == NULL) return -ENOMEM; + sd = &encoder->sd; + v4l2_i2c_subdev_init(sd, client, &adv7170_ops); encoder->norm = V4L2_STD_NTSC; encoder->input = 0; - i2c_set_clientdata(client, encoder); - i = adv7170_write_block(client, init_NTSC, sizeof(init_NTSC)); + i = adv7170_write_block(sd, init_NTSC, sizeof(init_NTSC)); if (i >= 0) { - i = adv7170_write(client, 0x07, TR0MODE | TR0RST); - i = adv7170_write(client, 0x07, TR0MODE); - i = adv7170_read(client, 0x12); - v4l_dbg(1, debug, client, "revision %d\n", i & 1); + i = adv7170_write(sd, 0x07, TR0MODE | TR0RST); + i = adv7170_write(sd, 0x07, TR0MODE); + i = adv7170_read(sd, 0x12); + v4l2_dbg(1, debug, sd, "revision %d\n", i & 1); } if (i < 0) - v4l_dbg(1, debug, client, "init error 0x%x\n", i); + v4l2_dbg(1, debug, sd, "init error 0x%x\n", i); return 0; } static int adv7170_remove(struct i2c_client *client) { - kfree(i2c_get_clientdata(client)); + struct v4l2_subdev *sd = i2c_get_clientdata(client); + + v4l2_device_unregister_subdev(sd); + kfree(to_adv7170(sd)); return 0; } diff --git a/include/media/v4l2-chip-ident.h b/include/media/v4l2-chip-ident.h index f53f1a1b0525..a5339d8ba9a4 100644 --- a/include/media/v4l2-chip-ident.h +++ b/include/media/v4l2-chip-ident.h @@ -118,6 +118,12 @@ enum { V4L2_IDENT_SAA6752HS = 6752, V4L2_IDENT_SAA6752HS_AC3 = 6753, + /* module adv7170: just ident 7170 */ + V4L2_IDENT_ADV7170 = 7170, + + /* module adv7175: just ident 7175 */ + V4L2_IDENT_ADV7175 = 7175, + /* module saa7185: just ident 7185 */ V4L2_IDENT_SAA7185 = 7185, -- cgit v1.2.3 From 35631dcc7f09522ff3119ba72d1252f80419779a Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Thu, 19 Feb 2009 14:56:37 -0300 Subject: V4L/DVB (10728): adv7175: convert to v4l2-subdev. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/adv7170.c | 2 +- drivers/media/video/adv7175.c | 307 +++++++++++++++++++++++------------------- 2 files changed, 166 insertions(+), 143 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/adv7170.c b/drivers/media/video/adv7170.c index f7120b369ba2..7b10487ae818 100644 --- a/drivers/media/video/adv7170.c +++ b/drivers/media/video/adv7170.c @@ -268,7 +268,7 @@ static int adv7170_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ide { struct i2c_client *client = v4l2_get_subdevdata(sd); - return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_BT866, 0); + return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_ADV7170, 0); } static int adv7170_command(struct i2c_client *client, unsigned cmd, void *arg) diff --git a/drivers/media/video/adv7175.c b/drivers/media/video/adv7175.c index 154dff03a7d8..318c3053633a 100644 --- a/drivers/media/video/adv7175.c +++ b/drivers/media/video/adv7175.c @@ -30,15 +30,26 @@ #include #include #include -#include -#include -#include +#include +#include +#include #include MODULE_DESCRIPTION("Analog Devices ADV7175 video encoder driver"); MODULE_AUTHOR("Dave Perks"); MODULE_LICENSE("GPL"); +#define I2C_ADV7175 0xd4 +#define I2C_ADV7176 0x54 + +static unsigned short normal_i2c[] = { + I2C_ADV7175 >> 1, (I2C_ADV7175 >> 1) + 1, + I2C_ADV7176 >> 1, (I2C_ADV7176 >> 1) + 1, + I2C_CLIENT_END +}; + +I2C_CLIENT_INSMOD; + static int debug; module_param(debug, int, 0); MODULE_PARM_DESC(debug, "Debug level (0-1)"); @@ -46,34 +57,38 @@ MODULE_PARM_DESC(debug, "Debug level (0-1)"); /* ----------------------------------------------------------------------- */ struct adv7175 { + struct v4l2_subdev sd; v4l2_std_id norm; int input; - int bright; - int contrast; - int hue; - int sat; }; -#define I2C_ADV7175 0xd4 -#define I2C_ADV7176 0x54 +static inline struct adv7175 *to_adv7175(struct v4l2_subdev *sd) +{ + return container_of(sd, struct adv7175, sd); +} static char *inputs[] = { "pass_through", "play_back", "color_bar" }; /* ----------------------------------------------------------------------- */ -static inline int adv7175_write(struct i2c_client *client, u8 reg, u8 value) +static inline int adv7175_write(struct v4l2_subdev *sd, u8 reg, u8 value) { + struct i2c_client *client = v4l2_get_subdevdata(sd); + return i2c_smbus_write_byte_data(client, reg, value); } -static inline int adv7175_read(struct i2c_client *client, u8 reg) +static inline int adv7175_read(struct v4l2_subdev *sd, u8 reg) { + struct i2c_client *client = v4l2_get_subdevdata(sd); + return i2c_smbus_read_byte_data(client, reg); } -static int adv7175_write_block(struct i2c_client *client, +static int adv7175_write_block(struct v4l2_subdev *sd, const u8 *data, unsigned int len) { + struct i2c_client *client = v4l2_get_subdevdata(sd); int ret = -1; u8 reg; @@ -101,7 +116,7 @@ static int adv7175_write_block(struct i2c_client *client, /* do some slow I2C emulation kind of thing */ while (len >= 2) { reg = *data++; - ret = adv7175_write(client, reg, *data++); + ret = adv7175_write(sd, reg, *data++); if (ret < 0) break; len -= 2; @@ -111,18 +126,18 @@ static int adv7175_write_block(struct i2c_client *client, return ret; } -static void set_subcarrier_freq(struct i2c_client *client, int pass_through) +static void set_subcarrier_freq(struct v4l2_subdev *sd, int pass_through) { /* for some reason pass_through NTSC needs * a different sub-carrier freq to remain stable. */ if (pass_through) - adv7175_write(client, 0x02, 0x00); + adv7175_write(sd, 0x02, 0x00); else - adv7175_write(client, 0x02, 0x55); + adv7175_write(sd, 0x02, 0x55); - adv7175_write(client, 0x03, 0x55); - adv7175_write(client, 0x04, 0x55); - adv7175_write(client, 0x05, 0x25); + adv7175_write(sd, 0x03, 0x55); + adv7175_write(sd, 0x04, 0x55); + adv7175_write(sd, 0x05, 0x25); } /* ----------------------------------------------------------------------- */ @@ -182,144 +197,148 @@ static const unsigned char init_ntsc[] = { 0x06, 0x1a, /* subc. phase */ }; -static int adv7175_command(struct i2c_client *client, unsigned cmd, void *arg) +static int adv7175_init(struct v4l2_subdev *sd, u32 val) +{ + /* This is just for testing!!! */ + adv7175_write_block(sd, init_common, sizeof(init_common)); + adv7175_write(sd, 0x07, TR0MODE | TR0RST); + adv7175_write(sd, 0x07, TR0MODE); + return 0; +} + +static int adv7175_s_std_output(struct v4l2_subdev *sd, v4l2_std_id std) { - struct adv7175 *encoder = i2c_get_clientdata(client); - - switch (cmd) { - case VIDIOC_INT_INIT: - /* This is just for testing!!! */ - adv7175_write_block(client, init_common, - sizeof(init_common)); - adv7175_write(client, 0x07, TR0MODE | TR0RST); - adv7175_write(client, 0x07, TR0MODE); + struct adv7175 *encoder = to_adv7175(sd); + + if (std & V4L2_STD_NTSC) { + adv7175_write_block(sd, init_ntsc, sizeof(init_ntsc)); + if (encoder->input == 0) + adv7175_write(sd, 0x0d, 0x4f); /* Enable genlock */ + adv7175_write(sd, 0x07, TR0MODE | TR0RST); + adv7175_write(sd, 0x07, TR0MODE); + } else if (std & V4L2_STD_PAL) { + adv7175_write_block(sd, init_pal, sizeof(init_pal)); + if (encoder->input == 0) + adv7175_write(sd, 0x0d, 0x4f); /* Enable genlock */ + adv7175_write(sd, 0x07, TR0MODE | TR0RST); + adv7175_write(sd, 0x07, TR0MODE); + } else if (std & V4L2_STD_SECAM) { + /* This is an attempt to convert + * SECAM->PAL (typically it does not work + * due to genlock: when decoder is in SECAM + * and encoder in in PAL the subcarrier can + * not be syncronized with horizontal + * quency) */ + adv7175_write_block(sd, init_pal, sizeof(init_pal)); + if (encoder->input == 0) + adv7175_write(sd, 0x0d, 0x49); /* Disable genlock */ + adv7175_write(sd, 0x07, TR0MODE | TR0RST); + adv7175_write(sd, 0x07, TR0MODE); + } else { + v4l2_dbg(1, debug, sd, "illegal norm: %llx\n", std); + return -EINVAL; + } + v4l2_dbg(1, debug, sd, "switched to %llx\n", std); + encoder->norm = std; + return 0; +} + +static int adv7175_s_routing(struct v4l2_subdev *sd, const struct v4l2_routing *route) +{ + struct adv7175 *encoder = to_adv7175(sd); + + /* RJ: route->input = 0: input is from decoder + route->input = 1: input is from ZR36060 + route->input = 2: color bar */ + + switch (route->input) { + case 0: + adv7175_write(sd, 0x01, 0x00); + + if (encoder->norm & V4L2_STD_NTSC) + set_subcarrier_freq(sd, 1); + + adv7175_write(sd, 0x0c, TR1CAPT); /* TR1 */ + if (encoder->norm & V4L2_STD_SECAM) + adv7175_write(sd, 0x0d, 0x49); /* Disable genlock */ + else + adv7175_write(sd, 0x0d, 0x4f); /* Enable genlock */ + adv7175_write(sd, 0x07, TR0MODE | TR0RST); + adv7175_write(sd, 0x07, TR0MODE); + /*udelay(10);*/ break; - case VIDIOC_INT_S_STD_OUTPUT: - { - v4l2_std_id iarg = *(v4l2_std_id *) arg; - - if (iarg & V4L2_STD_NTSC) { - adv7175_write_block(client, init_ntsc, - sizeof(init_ntsc)); - if (encoder->input == 0) - adv7175_write(client, 0x0d, 0x4f); // Enable genlock - adv7175_write(client, 0x07, TR0MODE | TR0RST); - adv7175_write(client, 0x07, TR0MODE); - } else if (iarg & V4L2_STD_PAL) { - adv7175_write_block(client, init_pal, - sizeof(init_pal)); - if (encoder->input == 0) - adv7175_write(client, 0x0d, 0x4f); // Enable genlock - adv7175_write(client, 0x07, TR0MODE | TR0RST); - adv7175_write(client, 0x07, TR0MODE); - } else if (iarg & V4L2_STD_SECAM) { - /* This is an attempt to convert - * SECAM->PAL (typically it does not work - * due to genlock: when decoder is in SECAM - * and encoder in in PAL the subcarrier can - * not be syncronized with horizontal - * quency) */ - adv7175_write_block(client, init_pal, - sizeof(init_pal)); - if (encoder->input == 0) - adv7175_write(client, 0x0d, 0x49); // Disable genlock - adv7175_write(client, 0x07, TR0MODE | TR0RST); - adv7175_write(client, 0x07, TR0MODE); - } else { - v4l_dbg(1, debug, client, "illegal norm: %llx\n", iarg); - return -EINVAL; - } - v4l_dbg(1, debug, client, "switched to %llx\n", iarg); - encoder->norm = iarg; + case 1: + adv7175_write(sd, 0x01, 0x00); + + if (encoder->norm & V4L2_STD_NTSC) + set_subcarrier_freq(sd, 0); + + adv7175_write(sd, 0x0c, TR1PLAY); /* TR1 */ + adv7175_write(sd, 0x0d, 0x49); + adv7175_write(sd, 0x07, TR0MODE | TR0RST); + adv7175_write(sd, 0x07, TR0MODE); + /* udelay(10); */ break; - } - case VIDIOC_INT_S_VIDEO_ROUTING: - { - struct v4l2_routing *route = arg; - - /* RJ: *iarg = 0: input is from SAA7110 - *iarg = 1: input is from ZR36060 - *iarg = 2: color bar */ - - switch (route->input) { - case 0: - adv7175_write(client, 0x01, 0x00); - - if (encoder->norm & V4L2_STD_NTSC) - set_subcarrier_freq(client, 1); - - adv7175_write(client, 0x0c, TR1CAPT); /* TR1 */ - if (encoder->norm & V4L2_STD_SECAM) - adv7175_write(client, 0x0d, 0x49); // Disable genlock - else - adv7175_write(client, 0x0d, 0x4f); // Enable genlock - adv7175_write(client, 0x07, TR0MODE | TR0RST); - adv7175_write(client, 0x07, TR0MODE); - //udelay(10); - break; - - case 1: - adv7175_write(client, 0x01, 0x00); - - if (encoder->norm & V4L2_STD_NTSC) - set_subcarrier_freq(client, 0); - - adv7175_write(client, 0x0c, TR1PLAY); /* TR1 */ - adv7175_write(client, 0x0d, 0x49); - adv7175_write(client, 0x07, TR0MODE | TR0RST); - adv7175_write(client, 0x07, TR0MODE); - /* udelay(10); */ - break; - - case 2: - adv7175_write(client, 0x01, 0x80); - - if (encoder->norm & V4L2_STD_NTSC) - set_subcarrier_freq(client, 0); - - adv7175_write(client, 0x0d, 0x49); - adv7175_write(client, 0x07, TR0MODE | TR0RST); - adv7175_write(client, 0x07, TR0MODE); - /* udelay(10); */ - break; - - default: - v4l_dbg(1, debug, client, "illegal input: %d\n", route->input); - return -EINVAL; - } - v4l_dbg(1, debug, client, "switched to %s\n", inputs[route->input]); - encoder->input = route->input; + case 2: + adv7175_write(sd, 0x01, 0x80); + + if (encoder->norm & V4L2_STD_NTSC) + set_subcarrier_freq(sd, 0); + + adv7175_write(sd, 0x0d, 0x49); + adv7175_write(sd, 0x07, TR0MODE | TR0RST); + adv7175_write(sd, 0x07, TR0MODE); + /* udelay(10); */ break; - } default: + v4l2_dbg(1, debug, sd, "illegal input: %d\n", route->input); return -EINVAL; } - + v4l2_dbg(1, debug, sd, "switched to %s\n", inputs[route->input]); + encoder->input = route->input; return 0; } +static int adv7175_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip) +{ + struct i2c_client *client = v4l2_get_subdevdata(sd); + + return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_ADV7175, 0); +} + +static int adv7175_command(struct i2c_client *client, unsigned cmd, void *arg) +{ + return v4l2_subdev_command(i2c_get_clientdata(client), cmd, arg); +} + /* ----------------------------------------------------------------------- */ -/* - * Generic i2c probe - * concerning the addresses: i2c wants 7 bit (without the r/w bit), so '>>1' - */ -static unsigned short normal_i2c[] = { - I2C_ADV7175 >> 1, (I2C_ADV7175 >> 1) + 1, - I2C_ADV7176 >> 1, (I2C_ADV7176 >> 1) + 1, - I2C_CLIENT_END +static const struct v4l2_subdev_core_ops adv7175_core_ops = { + .g_chip_ident = adv7175_g_chip_ident, + .init = adv7175_init, }; -I2C_CLIENT_INSMOD; +static const struct v4l2_subdev_video_ops adv7175_video_ops = { + .s_std_output = adv7175_s_std_output, + .s_routing = adv7175_s_routing, +}; + +static const struct v4l2_subdev_ops adv7175_ops = { + .core = &adv7175_core_ops, + .video = &adv7175_video_ops, +}; + +/* ----------------------------------------------------------------------- */ static int adv7175_probe(struct i2c_client *client, const struct i2c_device_id *id) { int i; struct adv7175 *encoder; + struct v4l2_subdev *sd; /* Check if the adapter supports the needed features */ if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) @@ -331,25 +350,29 @@ static int adv7175_probe(struct i2c_client *client, encoder = kzalloc(sizeof(struct adv7175), GFP_KERNEL); if (encoder == NULL) return -ENOMEM; + sd = &encoder->sd; + v4l2_i2c_subdev_init(sd, client, &adv7175_ops); encoder->norm = V4L2_STD_NTSC; encoder->input = 0; - i2c_set_clientdata(client, encoder); - i = adv7175_write_block(client, init_common, sizeof(init_common)); + i = adv7175_write_block(sd, init_common, sizeof(init_common)); if (i >= 0) { - i = adv7175_write(client, 0x07, TR0MODE | TR0RST); - i = adv7175_write(client, 0x07, TR0MODE); - i = adv7175_read(client, 0x12); - v4l_dbg(1, debug, client, "revision %d\n", i & 1); + i = adv7175_write(sd, 0x07, TR0MODE | TR0RST); + i = adv7175_write(sd, 0x07, TR0MODE); + i = adv7175_read(sd, 0x12); + v4l2_dbg(1, debug, sd, "revision %d\n", i & 1); } if (i < 0) - v4l_dbg(1, debug, client, "init error 0x%x\n", i); + v4l2_dbg(1, debug, sd, "init error 0x%x\n", i); return 0; } static int adv7175_remove(struct i2c_client *client) { - kfree(i2c_get_clientdata(client)); + struct v4l2_subdev *sd = i2c_get_clientdata(client); + + v4l2_device_unregister_subdev(sd); + kfree(to_adv7175(sd)); return 0; } -- cgit v1.2.3 From 0ab6e1c38d80ab586e3a1ca9e71844131d9f51dc Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Thu, 19 Feb 2009 16:18:23 -0300 Subject: V4L/DVB (10729): zoran: convert to v4l2_device/v4l2_subdev. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/zoran/zoran.h | 19 ++- drivers/media/video/zoran/zoran_card.c | 263 ++++++++++--------------------- drivers/media/video/zoran/zoran_device.c | 74 ++++----- drivers/media/video/zoran/zoran_device.h | 13 +- drivers/media/video/zoran/zoran_driver.c | 78 +++------ 5 files changed, 159 insertions(+), 288 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/zoran/zoran.h b/drivers/media/video/zoran/zoran.h index a323eb66e7cf..ab1ced26276d 100644 --- a/drivers/media/video/zoran/zoran.h +++ b/drivers/media/video/zoran/zoran.h @@ -31,6 +31,8 @@ #ifndef _BUZ_H_ #define _BUZ_H_ +#include + struct zoran_requestbuffers { unsigned long count; /* Number of buffers for MJPEG grabbing */ unsigned long size; /* Size PER BUFFER in bytes */ @@ -339,7 +341,12 @@ struct zoran_fh { struct card_info { enum card_type type; char name[32]; - u16 i2c_decoder, i2c_encoder; /* I2C types */ + const char *i2c_decoder; /* i2c decoder device */ + const char *mod_decoder; /* i2c decoder module */ + const unsigned short *addrs_decoder; + const char *i2c_encoder; /* i2c encoder device */ + const char *mod_encoder; /* i2c encoder module */ + const unsigned short *addrs_encoder; u16 video_vfe, video_codec; /* videocodec types */ u16 audio_chip; /* audio type */ @@ -370,14 +377,15 @@ struct card_info { }; struct zoran { + struct v4l2_device v4l2_dev; struct video_device *video_dev; struct i2c_adapter i2c_adapter; /* */ struct i2c_algo_bit_data i2c_algo; /* */ u32 i2cbr; - struct i2c_client *decoder; /* video decoder i2c client */ - struct i2c_client *encoder; /* video encoder i2c client */ + struct v4l2_subdev *decoder; /* video decoder sub-device */ + struct v4l2_subdev *encoder; /* video encoder sub-device */ struct videocodec *codec; /* video codec */ struct videocodec *vfe; /* video front end */ @@ -481,6 +489,11 @@ struct zoran { wait_queue_head_t test_q; }; +static inline struct zoran *to_zoran(struct v4l2_device *v4l2_dev) +{ + return container_of(v4l2_dev, struct zoran, v4l2_dev); +} + /* There was something called _ALPHA_BUZ that used the PCI address instead of * the kernel iomapped address for btread/btwrite. */ #define btwrite(dat,adr) writel((dat), zr->zr36057_mem+(adr)) diff --git a/drivers/media/video/zoran/zoran_card.c b/drivers/media/video/zoran/zoran_card.c index 38166d40c716..0b64612e35b9 100644 --- a/drivers/media/video/zoran/zoran_card.c +++ b/drivers/media/video/zoran/zoran_card.c @@ -331,47 +331,6 @@ avs6eyes_init (struct zoran *zr) } -static char * -i2cid_to_modulename (u16 i2c_id) -{ - char *name = NULL; - - switch (i2c_id) { - case I2C_DRIVERID_SAA7110: - name = "saa7110"; - break; - case I2C_DRIVERID_SAA711X: - name = "saa7115"; - break; - case I2C_DRIVERID_SAA7185B: - name = "saa7185"; - break; - case I2C_DRIVERID_ADV7170: - name = "adv7170"; - break; - case I2C_DRIVERID_ADV7175: - name = "adv7175"; - break; - case I2C_DRIVERID_BT819: - name = "bt819"; - break; - case I2C_DRIVERID_BT856: - name = "bt856"; - break; - case I2C_DRIVERID_BT866: - name = "bt866"; - break; - case I2C_DRIVERID_VPX3220: - name = "vpx3220"; - break; - case I2C_DRIVERID_KS0127: - name = "ks0127"; - break; - } - - return name; -} - static char * codecid_to_modulename (u16 codecid) { @@ -422,11 +381,24 @@ static struct tvnorm f60ccir601_lm33r10 = { 858, 720, 56+54, 788, 525, 480, 16 } static struct tvnorm f50ccir601_avs6eyes = { 864, 720, 74, 804, 625, 576, 18 }; static struct tvnorm f60ccir601_avs6eyes = { 858, 720, 56, 788, 525, 480, 16 }; +static const unsigned short vpx3220_addrs[] = { 0x43, 0x47, I2C_CLIENT_END }; +static const unsigned short saa7110_addrs[] = { 0x4e, 0x4f, I2C_CLIENT_END }; +static const unsigned short saa7111_addrs[] = { 0x25, 0x24, I2C_CLIENT_END }; +static const unsigned short saa7114_addrs[] = { 0x21, 0x20, I2C_CLIENT_END }; +static const unsigned short adv717x_addrs[] = { 0x6a, 0x6b, 0x2a, 0x2b, I2C_CLIENT_END }; +static const unsigned short ks0127_addrs[] = { 0x6c, 0x6d, I2C_CLIENT_END }; +static const unsigned short saa7185_addrs[] = { 0x44, I2C_CLIENT_END }; +static const unsigned short bt819_addrs[] = { 0x45, I2C_CLIENT_END }; +static const unsigned short bt856_addrs[] = { 0x44, I2C_CLIENT_END }; +static const unsigned short bt866_addrs[] = { 0x44, I2C_CLIENT_END }; + static struct card_info zoran_cards[NUM_CARDS] __devinitdata = { { .type = DC10_old, .name = "DC10(old)", - .i2c_decoder = I2C_DRIVERID_VPX3220, + .i2c_decoder = "vpx3220a", + .mod_decoder = "vpx3220", + .addrs_decoder = vpx3220_addrs, .video_codec = CODEC_TYPE_ZR36050, .video_vfe = CODEC_TYPE_ZR36016, @@ -454,8 +426,12 @@ static struct card_info zoran_cards[NUM_CARDS] __devinitdata = { }, { .type = DC10_new, .name = "DC10(new)", - .i2c_decoder = I2C_DRIVERID_SAA7110, - .i2c_encoder = I2C_DRIVERID_ADV7175, + .i2c_decoder = "saa7110", + .mod_decoder = "saa7110", + .addrs_decoder = saa7110_addrs, + .i2c_encoder = "adv7175", + .mod_encoder = "adv7175", + .addrs_encoder = adv717x_addrs, .video_codec = CODEC_TYPE_ZR36060, .inputs = 3, @@ -481,8 +457,12 @@ static struct card_info zoran_cards[NUM_CARDS] __devinitdata = { }, { .type = DC10plus, .name = "DC10plus", - .i2c_decoder = I2C_DRIVERID_SAA7110, - .i2c_encoder = I2C_DRIVERID_ADV7175, + .i2c_decoder = "saa7110", + .mod_decoder = "saa7110", + .addrs_decoder = saa7110_addrs, + .i2c_encoder = "adv7175", + .mod_encoder = "adv7175", + .addrs_encoder = adv717x_addrs, .video_codec = CODEC_TYPE_ZR36060, .inputs = 3, @@ -509,8 +489,12 @@ static struct card_info zoran_cards[NUM_CARDS] __devinitdata = { }, { .type = DC30, .name = "DC30", - .i2c_decoder = I2C_DRIVERID_VPX3220, - .i2c_encoder = I2C_DRIVERID_ADV7175, + .i2c_decoder = "vpx3220a", + .mod_decoder = "vpx3220", + .addrs_decoder = vpx3220_addrs, + .i2c_encoder = "adv7175", + .mod_encoder = "adv7175", + .addrs_encoder = adv717x_addrs, .video_codec = CODEC_TYPE_ZR36050, .video_vfe = CODEC_TYPE_ZR36016, @@ -538,8 +522,12 @@ static struct card_info zoran_cards[NUM_CARDS] __devinitdata = { }, { .type = DC30plus, .name = "DC30plus", - .i2c_decoder = I2C_DRIVERID_VPX3220, - .i2c_encoder = I2C_DRIVERID_ADV7175, + .i2c_decoder = "vpx3220a", + .mod_decoder = "vpx3220", + .addrs_decoder = vpx3220_addrs, + .i2c_encoder = "adv7175", + .mod_encoder = "adv7175", + .addrs_encoder = adv717x_addrs, .video_codec = CODEC_TYPE_ZR36050, .video_vfe = CODEC_TYPE_ZR36016, @@ -567,8 +555,12 @@ static struct card_info zoran_cards[NUM_CARDS] __devinitdata = { }, { .type = LML33, .name = "LML33", - .i2c_decoder = I2C_DRIVERID_BT819, - .i2c_encoder = I2C_DRIVERID_BT856, + .i2c_decoder = "bt819a", + .mod_decoder = "bt819", + .addrs_decoder = bt819_addrs, + .i2c_encoder = "bt856", + .mod_encoder = "bt856", + .addrs_encoder = bt856_addrs, .video_codec = CODEC_TYPE_ZR36060, .inputs = 2, @@ -594,8 +586,12 @@ static struct card_info zoran_cards[NUM_CARDS] __devinitdata = { }, { .type = LML33R10, .name = "LML33R10", - .i2c_decoder = I2C_DRIVERID_SAA711X, - .i2c_encoder = I2C_DRIVERID_ADV7170, + .i2c_decoder = "saa7114", + .mod_decoder = "saa7115", + .addrs_decoder = saa7114_addrs, + .i2c_encoder = "adv7170", + .mod_encoder = "adv7170", + .addrs_encoder = adv717x_addrs, .video_codec = CODEC_TYPE_ZR36060, .inputs = 2, @@ -621,8 +617,12 @@ static struct card_info zoran_cards[NUM_CARDS] __devinitdata = { }, { .type = BUZ, .name = "Buz", - .i2c_decoder = I2C_DRIVERID_SAA711X, - .i2c_encoder = I2C_DRIVERID_SAA7185B, + .i2c_decoder = "saa7111", + .mod_decoder = "saa7115", + .addrs_decoder = saa7111_addrs, + .i2c_encoder = "saa7185", + .mod_encoder = "saa7185", + .addrs_encoder = saa7185_addrs, .video_codec = CODEC_TYPE_ZR36060, .inputs = 2, @@ -650,8 +650,12 @@ static struct card_info zoran_cards[NUM_CARDS] __devinitdata = { .name = "6-Eyes", /* AverMedia chose not to brand the 6-Eyes. Thus it can't be autodetected, and requires card=x. */ - .i2c_decoder = I2C_DRIVERID_KS0127, - .i2c_encoder = I2C_DRIVERID_BT866, + .i2c_decoder = "ks0127", + .mod_decoder = "ks0127", + .addrs_decoder = ks0127_addrs, + .i2c_encoder = "bt866", + .mod_encoder = "bt866", + .addrs_encoder = bt866_addrs, .video_codec = CODEC_TYPE_ZR36060, .inputs = 10, @@ -732,69 +736,6 @@ zoran_i2c_setscl (void *data, btwrite(zr->i2cbr, ZR36057_I2CBR); } -static int -zoran_i2c_client_register (struct i2c_client *client) -{ - struct zoran *zr = (struct zoran *) i2c_get_adapdata(client->adapter); - int res = 0; - - dprintk(2, - KERN_DEBUG "%s: i2c_client_register() - driver id = %d\n", - ZR_DEVNAME(zr), client->driver->id); - - mutex_lock(&zr->resource_lock); - - if (zr->user > 0) { - /* we're already busy, so we keep a reference to - * them... Could do a lot of stuff here, but this - * is easiest. (Did I ever mention I'm a lazy ass?) - */ - res = -EBUSY; - goto clientreg_unlock_and_return; - } - - if (client->driver->id == zr->card.i2c_decoder) - zr->decoder = client; - else if (client->driver->id == zr->card.i2c_encoder) - zr->encoder = client; - else { - res = -ENODEV; - goto clientreg_unlock_and_return; - } - -clientreg_unlock_and_return: - mutex_unlock(&zr->resource_lock); - - return res; -} - -static int -zoran_i2c_client_unregister (struct i2c_client *client) -{ - struct zoran *zr = (struct zoran *) i2c_get_adapdata(client->adapter); - int res = 0; - - dprintk(2, KERN_DEBUG "%s: i2c_client_unregister()\n", ZR_DEVNAME(zr)); - - mutex_lock(&zr->resource_lock); - - if (zr->user > 0) { - res = -EBUSY; - goto clientunreg_unlock_and_return; - } - - /* try to locate it */ - if (client == zr->encoder) { - zr->encoder = NULL; - } else if (client == zr->decoder) { - zr->decoder = NULL; - snprintf(ZR_DEVNAME(zr), sizeof(ZR_DEVNAME(zr)), "MJPEG[%d]", zr->id); - } -clientunreg_unlock_and_return: - mutex_unlock(&zr->resource_lock); - return res; -} - static const struct i2c_algo_bit_data zoran_i2c_bit_data_template = { .setsda = zoran_i2c_setsda, .setscl = zoran_i2c_setscl, @@ -810,13 +751,10 @@ zoran_register_i2c (struct zoran *zr) memcpy(&zr->i2c_algo, &zoran_i2c_bit_data_template, sizeof(struct i2c_algo_bit_data)); zr->i2c_algo.data = zr; - zr->i2c_adapter.class = I2C_CLASS_TV_ANALOG; zr->i2c_adapter.id = I2C_HW_B_ZR36067; - zr->i2c_adapter.client_register = zoran_i2c_client_register; - zr->i2c_adapter.client_unregister = zoran_i2c_client_unregister; strlcpy(zr->i2c_adapter.name, ZR_DEVNAME(zr), sizeof(zr->i2c_adapter.name)); - i2c_set_adapdata(&zr->i2c_adapter, zr); + i2c_set_adapdata(&zr->i2c_adapter, &zr->v4l2_dev); zr->i2c_adapter.algo_data = &zr->i2c_algo; zr->i2c_adapter.dev.parent = &zr->pci_dev->dev; return i2c_bit_add_bus(&zr->i2c_adapter); @@ -1173,8 +1111,8 @@ zr36057_init (struct zoran *zr) if (!pass_through) { struct v4l2_routing route = { 2, 0 }; - decoder_command(zr, VIDIOC_STREAMOFF, 0); - encoder_command(zr, VIDIOC_INT_S_VIDEO_ROUTING, &route); + decoder_call(zr, video, s_stream, 0); + encoder_call(zr, video, s_routing, &route); } zr->zoran_proc = NULL; @@ -1189,7 +1127,8 @@ exit_free: static void __devexit zoran_remove(struct pci_dev *pdev) { - struct zoran *zr = pci_get_drvdata(pdev); + struct v4l2_device *v4l2_dev = dev_get_drvdata(&pdev->dev); + struct zoran *zr = to_zoran(v4l2_dev); if (!zr->initialized) goto exit_free; @@ -1222,7 +1161,7 @@ static void __devexit zoran_remove(struct pci_dev *pdev) pci_disable_device(zr->pci_dev); video_unregister_device(zr->video_dev); exit_free: - pci_set_drvdata(pdev, NULL); + v4l2_device_unregister(&zr->v4l2_dev); kfree(zr); } @@ -1294,7 +1233,7 @@ static int __devinit zoran_probe(struct pci_dev *pdev, struct videocodec_master *master_vfe = NULL; struct videocodec_master *master_codec = NULL; int card_num; - char *i2c_enc_name, *i2c_dec_name, *codec_name, *vfe_name; + char *codec_name, *vfe_name; unsigned int nr; @@ -1315,13 +1254,15 @@ static int __devinit zoran_probe(struct pci_dev *pdev, ZORAN_NAME); return -ENOMEM; } + if (v4l2_device_register(&pdev->dev, &zr->v4l2_dev)) + goto zr_free_mem; zr->pci_dev = pdev; zr->id = nr; snprintf(ZR_DEVNAME(zr), sizeof(ZR_DEVNAME(zr)), "MJPEG[%u]", zr->id); spin_lock_init(&zr->spinlock); mutex_init(&zr->resource_lock); if (pci_enable_device(pdev)) - goto zr_free_mem; + goto zr_unreg; pci_read_config_byte(zr->pci_dev, PCI_CLASS_REVISION, &zr->revision); dprintk(1, @@ -1348,7 +1289,7 @@ static int __devinit zoran_probe(struct pci_dev *pdev, KERN_ERR "%s: It is not possible to auto-detect ZR36057 based cards\n", ZR_DEVNAME(zr)); - goto zr_free_mem; + goto zr_unreg; } card_num = ent->driver_data; @@ -1357,7 +1298,7 @@ static int __devinit zoran_probe(struct pci_dev *pdev, KERN_ERR "%s: Unknown card, try specifying card=X module parameter\n", ZR_DEVNAME(zr)); - goto zr_free_mem; + goto zr_unreg; } dprintk(3, KERN_DEBUG @@ -1370,7 +1311,7 @@ static int __devinit zoran_probe(struct pci_dev *pdev, KERN_ERR "%s: User specified card type %d out of range (0 .. %d)\n", ZR_DEVNAME(zr), card_num, NUM_CARDS - 1); - goto zr_free_mem; + goto zr_unreg; } } @@ -1389,7 +1330,7 @@ static int __devinit zoran_probe(struct pci_dev *pdev, KERN_ERR "%s: %s() - ioremap failed\n", ZR_DEVNAME(zr), __func__); - goto zr_free_mem; + goto zr_unreg; } result = request_irq(zr->pci_dev->irq, zoran_irq, @@ -1432,46 +1373,6 @@ static int __devinit zoran_probe(struct pci_dev *pdev, dprintk(2, KERN_INFO "%s: Initializing i2c bus...\n", ZR_DEVNAME(zr)); - /* i2c decoder */ - if (decoder[zr->id] != -1) { - i2c_dec_name = i2cid_to_modulename(decoder[zr->id]); - zr->card.i2c_decoder = decoder[zr->id]; - } else if (zr->card.i2c_decoder != 0) { - i2c_dec_name = i2cid_to_modulename(zr->card.i2c_decoder); - } else { - i2c_dec_name = NULL; - } - - if (i2c_dec_name) { - result = request_module(i2c_dec_name); - if (result < 0) { - dprintk(1, - KERN_ERR - "%s: failed to load module %s: %d\n", - ZR_DEVNAME(zr), i2c_dec_name, result); - } - } - - /* i2c encoder */ - if (encoder[zr->id] != -1) { - i2c_enc_name = i2cid_to_modulename(encoder[zr->id]); - zr->card.i2c_encoder = encoder[zr->id]; - } else if (zr->card.i2c_encoder != 0) { - i2c_enc_name = i2cid_to_modulename(zr->card.i2c_encoder); - } else { - i2c_enc_name = NULL; - } - - if (i2c_enc_name) { - result = request_module(i2c_enc_name); - if (result < 0) { - dprintk(1, - KERN_ERR - "%s: failed to load module %s: %d\n", - ZR_DEVNAME(zr), i2c_enc_name, result); - } - } - if (zoran_register_i2c(zr) < 0) { dprintk(1, KERN_ERR @@ -1480,6 +1381,14 @@ static int __devinit zoran_probe(struct pci_dev *pdev, goto zr_free_irq; } + zr->decoder = v4l2_i2c_new_probed_subdev(&zr->i2c_adapter, + zr->card.mod_decoder, zr->card.i2c_decoder, zr->card.addrs_decoder); + + if (zr->card.mod_encoder) + zr->encoder = v4l2_i2c_new_probed_subdev(&zr->i2c_adapter, + zr->card.mod_encoder, zr->card.i2c_encoder, + zr->card.addrs_encoder); + dprintk(2, KERN_INFO "%s: Initializing videocodec bus...\n", ZR_DEVNAME(zr)); @@ -1569,8 +1478,6 @@ static int __devinit zoran_probe(struct pci_dev *pdev, zoran_proc_init(zr); - pci_set_drvdata(pdev, zr); - return 0; zr_detach_vfe: @@ -1588,6 +1495,8 @@ zr_free_irq: free_irq(zr->pci_dev->irq, zr); zr_unmap: iounmap(zr->zr36057_mem); +zr_unreg: + v4l2_device_unregister(&zr->v4l2_dev); zr_free_mem: kfree(zr); diff --git a/drivers/media/video/zoran/zoran_device.c b/drivers/media/video/zoran/zoran_device.c index 712599a5ed72..3336611c0cdf 100644 --- a/drivers/media/video/zoran/zoran_device.c +++ b/drivers/media/video/zoran/zoran_device.c @@ -36,15 +36,12 @@ #include #include #include -#include #include #include #include #include #include -#include -#include #include #include @@ -1000,9 +997,9 @@ zr36057_enable_jpg (struct zoran *zr, * the video bus direction set to input. */ set_videobus_dir(zr, 0); - decoder_command(zr, VIDIOC_STREAMON, 0); + decoder_call(zr, video, s_stream, 1); route.input = 0; - encoder_command(zr, VIDIOC_INT_S_VIDEO_ROUTING, &route); + encoder_call(zr, video, s_routing, &route); /* Take the JPEG codec and the VFE out of sleep */ jpeg_codec_sleep(zr, 0); @@ -1048,10 +1045,10 @@ zr36057_enable_jpg (struct zoran *zr, /* In motion decompression mode, the decoder output must be disabled, and * the video bus direction set to output. */ - decoder_command(zr, VIDIOC_STREAMOFF, 0); + decoder_call(zr, video, s_stream, 0); set_videobus_dir(zr, 1); route.input = 1; - encoder_command(zr, VIDIOC_INT_S_VIDEO_ROUTING, &route); + encoder_call(zr, video, s_routing, &route); /* Take the JPEG codec and the VFE out of sleep */ jpeg_codec_sleep(zr, 0); @@ -1095,9 +1092,9 @@ zr36057_enable_jpg (struct zoran *zr, jpeg_codec_sleep(zr, 1); zr36057_adjust_vfe(zr, mode); - decoder_command(zr, VIDIOC_STREAMON, 0); + decoder_call(zr, video, s_stream, 1); route.input = 0; - encoder_command(zr, VIDIOC_INT_S_VIDEO_ROUTING, &route); + encoder_call(zr, video, s_routing, &route); dprintk(2, KERN_INFO "%s: enable_jpg(IDLE)\n", ZR_DEVNAME(zr)); break; @@ -1210,7 +1207,7 @@ static void zoran_restart(struct zoran *zr) int status = 0, mode; if (zr->codec_mode == BUZ_MODE_MOTION_COMPRESS) { - decoder_command(zr, VIDIOC_INT_G_INPUT_STATUS, &status); + decoder_call(zr, video, g_input_status, &status); mode = CODEC_DO_COMPRESSION; } else { status = V4L2_IN_ST_NO_SIGNAL; @@ -1590,14 +1587,14 @@ zoran_init_hardware (struct zoran *zr) route.input = zr->card.input[zr->input].muxsel; - decoder_command(zr, VIDIOC_INT_INIT, NULL); - decoder_command(zr, VIDIOC_S_STD, &zr->norm); - decoder_command(zr, VIDIOC_INT_S_VIDEO_ROUTING, &route); + decoder_call(zr, core, init, 0); + decoder_s_std(zr, zr->norm); + decoder_s_routing(zr, &route); - encoder_command(zr, VIDIOC_INT_INIT, NULL); - encoder_command(zr, VIDIOC_INT_S_STD_OUTPUT, &zr->norm); + encoder_call(zr, core, init, 0); + encoder_call(zr, video, s_std_output, zr->norm); route.input = 0; - encoder_command(zr, VIDIOC_INT_S_VIDEO_ROUTING, &route); + encoder_call(zr, video, s_routing, &route); /* toggle JPEG codec sleep to sync PLL */ jpeg_codec_sleep(zr, 1); @@ -1662,37 +1659,30 @@ zr36057_init_vfe (struct zoran *zr) * Interface to decoder and encoder chips using i2c bus */ -int -decoder_command (struct zoran *zr, - int cmd, - void *data) +int decoder_s_std(struct zoran *zr, v4l2_std_id std) { - if (zr->decoder == NULL) - return -EIO; - - if (zr->card.type == LML33 && - (cmd == VIDIOC_S_STD || cmd == VIDIOC_INT_S_VIDEO_ROUTING)) { - int res; + int res; - // Bt819 needs to reset its FIFO buffer using #FRST pin and - // LML33 card uses GPIO(7) for that. + /* Bt819 needs to reset its FIFO buffer using #FRST pin and + LML33 card uses GPIO(7) for that. */ + if (zr->card.type == LML33) GPIO(zr, 7, 0); - res = zr->decoder->driver->command(zr->decoder, cmd, data); - // Pull #FRST high. - GPIO(zr, 7, 1); - return res; - } else - return zr->decoder->driver->command(zr->decoder, cmd, - data); + res = decoder_call(zr, tuner, s_std, std); + if (zr->card.type == LML33) + GPIO(zr, 7, 1); /* Pull #FRST high. */ + return res; } -int -encoder_command (struct zoran *zr, - int cmd, - void *data) +int decoder_s_routing(struct zoran *zr, struct v4l2_routing *route) { - if (zr->encoder == NULL) - return -1; + int res; - return zr->encoder->driver->command(zr->encoder, cmd, data); + /* Bt819 needs to reset its FIFO buffer using #FRST pin and + LML33 card uses GPIO(7) for that. */ + if (zr->card.type == LML33) + GPIO(zr, 7, 0); + res = decoder_call(zr, video, s_routing, route); + if (zr->card.type == LML33) + GPIO(zr, 7, 1); /* Pull #FRST high. */ + return res; } diff --git a/drivers/media/video/zoran/zoran_device.h b/drivers/media/video/zoran/zoran_device.h index 74c6c8edb7d0..14d4e7aa6cea 100644 --- a/drivers/media/video/zoran/zoran_device.h +++ b/drivers/media/video/zoran/zoran_device.h @@ -87,11 +87,12 @@ extern int jpg_bufsize; extern int pass_through; /* i2c */ -extern int decoder_command(struct zoran *zr, - int cmd, - void *data); -extern int encoder_command(struct zoran *zr, - int cmd, - void *data); +#define decoder_call(zr, o, f, args...) \ + v4l2_subdev_call(zr->decoder, o, f, ##args) +#define encoder_call(zr, o, f, args...) \ + v4l2_subdev_call(zr->encoder, o, f, ##args) + +int decoder_s_std(struct zoran *zr, v4l2_std_id std); +int decoder_s_routing(struct zoran *zr, struct v4l2_routing *route); #endif /* __ZORAN_DEVICE_H__ */ diff --git a/drivers/media/video/zoran/zoran_driver.c b/drivers/media/video/zoran/zoran_driver.c index 611fc7f18e16..b027a68e8c67 100644 --- a/drivers/media/video/zoran/zoran_driver.c +++ b/drivers/media/video/zoran/zoran_driver.c @@ -963,10 +963,6 @@ static int zoran_open(struct file *file) lock_kernel(); - /* see fs/device.c - the kernel already locks during open(), - * so locking ourselves only causes deadlocks */ - /*mutex_lock(&zr->resource_lock);*/ - if (zr->user >= 2048) { dprintk(1, KERN_ERR "%s: too many users (%d) on device\n", ZR_DEVNAME(zr), zr->user); @@ -974,32 +970,6 @@ static int zoran_open(struct file *file) goto fail_unlock; } - if (!zr->decoder) { - dprintk(1, - KERN_ERR "%s: no TV decoder loaded for device!\n", - ZR_DEVNAME(zr)); - res = -EIO; - goto fail_unlock; - } - - if (!try_module_get(zr->decoder->driver->driver.owner)) { - dprintk(1, - KERN_ERR - "%s: failed to grab ownership of video decoder\n", - ZR_DEVNAME(zr)); - res = -EIO; - goto fail_unlock; - } - if (zr->encoder && - !try_module_get(zr->encoder->driver->driver.owner)) { - dprintk(1, - KERN_ERR - "%s: failed to grab ownership of video encoder\n", - ZR_DEVNAME(zr)); - res = -EIO; - goto fail_decoder; - } - /* now, create the open()-specific file_ops struct */ fh = kzalloc(sizeof(struct zoran_fh), GFP_KERNEL); if (!fh) { @@ -1008,7 +978,7 @@ static int zoran_open(struct file *file) "%s: zoran_open() - allocation of zoran_fh failed\n", ZR_DEVNAME(zr)); res = -ENOMEM; - goto fail_encoder; + goto fail_unlock; } /* used to be BUZ_MAX_WIDTH/HEIGHT, but that gives overflows * on norm-change! */ @@ -1047,11 +1017,6 @@ static int zoran_open(struct file *file) fail_fh: kfree(fh); -fail_encoder: - if (zr->encoder) - module_put(zr->encoder->driver->driver.owner); -fail_decoder: - module_put(zr->decoder->driver->driver.owner); fail_unlock: unlock_kernel(); @@ -1104,8 +1069,8 @@ zoran_close(struct file *file) if (!pass_through) { /* Switch to color bar */ struct v4l2_routing route = { 2, 0 }; - decoder_command(zr, VIDIOC_STREAMOFF, 0); - encoder_command(zr, VIDIOC_INT_S_VIDEO_ROUTING, &route); + decoder_call(zr, video, s_stream, 0); + encoder_call(zr, video, s_routing, &route); } } @@ -1113,13 +1078,6 @@ zoran_close(struct file *file) kfree(fh->overlay_mask); kfree(fh); - /* release locks on the i2c modules */ - module_put(zr->decoder->driver->driver.owner); - if (zr->encoder) - module_put(zr->encoder->driver->driver.owner); - - /*mutex_unlock(&zr->resource_lock);*/ - dprintk(4, KERN_INFO "%s: zoran_close() done\n", ZR_DEVNAME(zr)); return 0; @@ -1567,20 +1525,20 @@ zoran_set_norm (struct zoran *zr, int status = 0; v4l2_std_id std = 0; - decoder_command(zr, VIDIOC_QUERYSTD, &std); - decoder_command(zr, VIDIOC_S_STD, &std); + decoder_call(zr, video, querystd, &std); + decoder_s_std(zr, std); /* let changes come into effect */ ssleep(2); - decoder_command(zr, VIDIOC_INT_G_INPUT_STATUS, &status); + decoder_call(zr, video, g_input_status, &status); if (status & V4L2_IN_ST_NO_SIGNAL) { dprintk(1, KERN_ERR "%s: set_norm() - no norm detected\n", ZR_DEVNAME(zr)); /* reset norm */ - decoder_command(zr, VIDIOC_S_STD, &zr->norm); + decoder_s_std(zr, zr->norm); return -EIO; } @@ -1599,8 +1557,8 @@ zoran_set_norm (struct zoran *zr, if (on) zr36057_overlay(zr, 0); - decoder_command(zr, VIDIOC_S_STD, &norm); - encoder_command(zr, VIDIOC_INT_S_STD_OUTPUT, &norm); + decoder_s_std(zr, norm); + encoder_call(zr, video, s_std_output, norm); if (on) zr36057_overlay(zr, 1); @@ -1641,7 +1599,7 @@ zoran_set_input (struct zoran *zr, route.input = zr->card.input[input].muxsel; zr->input = input; - decoder_command(zr, VIDIOC_INT_S_VIDEO_ROUTING, &route); + decoder_s_routing(zr, &route); return 0; } @@ -1886,18 +1844,18 @@ jpgreqbuf_unlock_and_return: goto gstat_unlock_and_return; } - decoder_command(zr, VIDIOC_INT_S_VIDEO_ROUTING, &route); + decoder_s_routing(zr, &route); /* sleep 1 second */ ssleep(1); /* Get status of video decoder */ - decoder_command(zr, VIDIOC_QUERYSTD, &norm); - decoder_command(zr, VIDIOC_INT_G_INPUT_STATUS, &status); + decoder_call(zr, video, querystd, &norm); + decoder_call(zr, video, g_input_status, &status); /* restore previous input and norm */ route.input = zr->card.input[zr->input].muxsel; - decoder_command(zr, VIDIOC_INT_S_VIDEO_ROUTING, &route); + decoder_s_routing(zr, &route); gstat_unlock_and_return: mutex_unlock(&zr->resource_lock); @@ -2836,7 +2794,7 @@ static int zoran_queryctrl(struct file *file, void *__fh, ctrl->id > V4L2_CID_HUE) return -EINVAL; - decoder_command(zr, VIDIOC_QUERYCTRL, ctrl); + decoder_call(zr, core, queryctrl, ctrl); return 0; } @@ -2852,7 +2810,7 @@ static int zoran_g_ctrl(struct file *file, void *__fh, struct v4l2_control *ctrl return -EINVAL; mutex_lock(&zr->resource_lock); - decoder_command(zr, VIDIOC_G_CTRL, ctrl); + decoder_call(zr, core, g_ctrl, ctrl); mutex_unlock(&zr->resource_lock); return 0; @@ -2869,7 +2827,7 @@ static int zoran_s_ctrl(struct file *file, void *__fh, struct v4l2_control *ctrl return -EINVAL; mutex_lock(&zr->resource_lock); - decoder_command(zr, VIDIOC_S_CTRL, ctrl); + decoder_call(zr, core, s_ctrl, ctrl); mutex_unlock(&zr->resource_lock); return 0; @@ -2924,7 +2882,7 @@ static int zoran_enum_input(struct file *file, void *__fh, /* Get status of video decoder */ mutex_lock(&zr->resource_lock); - decoder_command(zr, VIDIOC_INT_G_INPUT_STATUS, &inp->status); + decoder_call(zr, video, g_input_status, &inp->status); mutex_unlock(&zr->resource_lock); return 0; } -- cgit v1.2.3 From 7f6adeaf2d8800b66c5dd6c2cf2622dfdd68bd31 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Thu, 19 Feb 2009 17:31:17 -0300 Subject: V4L/DVB (10730): v4l-dvb: cleanup obsolete references to v4l1 headers. Signed-off-by: Hans Verkuil [mchehab@redhat.com: fix compilation of tea575x-tuner.c] Signed-off-by: Mauro Carvalho Chehab --- drivers/media/common/tuners/mt20xx.c | 2 +- drivers/media/common/tuners/tda8290.c | 2 +- drivers/media/common/tuners/tea5761.c | 2 +- drivers/media/common/tuners/tea5767.c | 2 +- drivers/media/video/ks0127.h | 2 -- drivers/media/video/saa6588.c | 2 +- drivers/media/video/tvaudio.c | 2 +- drivers/media/video/zoran/videocodec.h | 9 ++----- drivers/media/video/zoran/zoran.h | 8 +++++- drivers/media/video/zoran/zoran_card.c | 43 ++++++++------------------------ drivers/media/video/zoran/zoran_device.c | 20 +++++++-------- drivers/media/video/zoran/zoran_device.h | 2 +- drivers/media/video/zoran/zoran_driver.c | 40 ++++++++++++++--------------- drivers/media/video/zoran/zoran_procfs.c | 2 +- drivers/media/video/zoran/zr36016.c | 5 ---- drivers/media/video/zoran/zr36050.c | 4 --- drivers/media/video/zoran/zr36060.c | 4 --- 17 files changed, 56 insertions(+), 95 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/common/tuners/mt20xx.c b/drivers/media/common/tuners/mt20xx.c index 35b763a16d53..44608ad4e2d2 100644 --- a/drivers/media/common/tuners/mt20xx.c +++ b/drivers/media/common/tuners/mt20xx.c @@ -6,7 +6,7 @@ */ #include #include -#include +#include #include "tuner-i2c.h" #include "mt20xx.h" diff --git a/drivers/media/common/tuners/tda8290.c b/drivers/media/common/tuners/tda8290.c index 39697fa59256..a88e67632c52 100644 --- a/drivers/media/common/tuners/tda8290.c +++ b/drivers/media/common/tuners/tda8290.c @@ -22,7 +22,7 @@ #include #include -#include +#include #include "tuner-i2c.h" #include "tda8290.h" #include "tda827x.h" diff --git a/drivers/media/common/tuners/tea5761.c b/drivers/media/common/tuners/tea5761.c index b23dadeecd05..60ed872f3d44 100644 --- a/drivers/media/common/tuners/tea5761.c +++ b/drivers/media/common/tuners/tea5761.c @@ -9,7 +9,7 @@ #include #include -#include +#include #include #include "tuner-i2c.h" #include "tea5761.h" diff --git a/drivers/media/common/tuners/tea5767.c b/drivers/media/common/tuners/tea5767.c index 1f5646334a8f..223a226d20a1 100644 --- a/drivers/media/common/tuners/tea5767.c +++ b/drivers/media/common/tuners/tea5767.c @@ -12,7 +12,7 @@ #include #include -#include +#include #include "tuner-i2c.h" #include "tea5767.h" diff --git a/drivers/media/video/ks0127.h b/drivers/media/video/ks0127.h index 1ec578833aea..cb8abd5403b3 100644 --- a/drivers/media/video/ks0127.h +++ b/drivers/media/video/ks0127.h @@ -24,8 +24,6 @@ #ifndef KS0127_H #define KS0127_H -#include - /* input channels */ #define KS_INPUT_COMPOSITE_1 0 #define KS_INPUT_COMPOSITE_2 1 diff --git a/drivers/media/video/saa6588.c b/drivers/media/video/saa6588.c index 258b7b2a1e99..0067b281d503 100644 --- a/drivers/media/video/saa6588.c +++ b/drivers/media/video/saa6588.c @@ -23,7 +23,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/drivers/media/video/tvaudio.c b/drivers/media/video/tvaudio.c index 0eb3b1694287..e8ab28532d94 100644 --- a/drivers/media/video/tvaudio.c +++ b/drivers/media/video/tvaudio.c @@ -26,7 +26,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/drivers/media/video/zoran/videocodec.h b/drivers/media/video/zoran/videocodec.h index 97a3bbeda505..5c27b251354e 100644 --- a/drivers/media/video/zoran/videocodec.h +++ b/drivers/media/video/zoran/videocodec.h @@ -97,7 +97,7 @@ available) - it returns 0 if the mode is possible set_size -> this fn-ref. sets the norm and image size for compression/decompression (returns 0 on success) - the norm param is defined in videodev.h (VIDEO_MODE_*) + the norm param is defined in videodev2.h (V4L2_STD_*) additional setup may be available, too - but the codec should work with some default values even without this @@ -144,9 +144,8 @@ M zr36055[1] 0001 0000c001 00000000 (zr36050[1]) #ifndef __LINUX_VIDEOCODEC_H #define __LINUX_VIDEOCODEC_H -#include +#include -//should be in videodev.h ??? (VID_DO_....) #define CODEC_DO_COMPRESSION 0 #define CODEC_DO_EXPANSION 1 @@ -237,10 +236,6 @@ struct vfe_settings { __u32 width, height; /* Area to capture */ __u16 decimation; /* Decimation divider */ __u16 flags; /* Flags for capture */ -/* flags are the same as in struct video_capture - see videodev.h: -#define VIDEO_CAPTURE_ODD 0 -#define VIDEO_CAPTURE_EVEN 1 -*/ __u16 quality; /* quality of the video */ }; diff --git a/drivers/media/video/zoran/zoran.h b/drivers/media/video/zoran/zoran.h index ab1ced26276d..8beada9613f6 100644 --- a/drivers/media/video/zoran/zoran.h +++ b/drivers/media/video/zoran/zoran.h @@ -408,7 +408,13 @@ struct zoran { /* Video for Linux parameters */ int input; /* card's norm and input - norm=VIDEO_MODE_* */ v4l2_std_id norm; - struct video_buffer buffer; /* Current buffer params */ + + /* Current buffer params */ + void *vbuf_base; + int vbuf_height, vbuf_width; + int vbuf_depth; + int vbuf_bytesperline; + struct zoran_overlay_settings overlay_settings; u32 *overlay_mask; /* overlay mask */ enum zoran_lock_activity overlay_active; /* feature currently in use? */ diff --git a/drivers/media/video/zoran/zoran_card.c b/drivers/media/video/zoran/zoran_card.c index 0b64612e35b9..665a5e370a84 100644 --- a/drivers/media/video/zoran/zoran_card.c +++ b/drivers/media/video/zoran/zoran_card.c @@ -38,7 +38,7 @@ #include #include #include -#include +#include #include #include #include @@ -47,8 +47,6 @@ #include #include -#include -#include #include #include @@ -108,23 +106,6 @@ static int video_nr[BUZ_MAX] = { [0 ... (BUZ_MAX-1)] = -1 }; module_param_array(video_nr, int, NULL, 0444); MODULE_PARM_DESC(video_nr, "Video device number (-1=Auto)"); -/* - Number and size of grab buffers for Video 4 Linux - The vast majority of applications should not need more than 2, - the very popular BTTV driver actually does ONLY have 2. - Time sensitive applications might need more, the maximum - is VIDEO_MAX_FRAME (defined in ). - - The size is set so that the maximum possible request - can be satisfied. Decrease it, if bigphys_area alloc'd - memory is low. If you don't have the bigphys_area patch, - set it to 128 KB. Will you allow only to grab small - images with V4L, but that's better than nothing. - - v4l_bufsize has to be given in KB ! - -*/ - int v4l_nbufs = 4; int v4l_bufsize = 810; /* Everybody should be able to work with this setting */ module_param(v4l_nbufs, int, 0644); @@ -1036,20 +1017,19 @@ zr36057_init (struct zoran *zr) zr->jpg_buffers.allocated = 0; zr->v4l_buffers.allocated = 0; - zr->buffer.base = (void *) vidmem; - zr->buffer.width = 0; - zr->buffer.height = 0; - zr->buffer.depth = 0; - zr->buffer.bytesperline = 0; + zr->vbuf_base = (void *) vidmem; + zr->vbuf_width = 0; + zr->vbuf_height = 0; + zr->vbuf_depth = 0; + zr->vbuf_bytesperline = 0; /* Avoid nonsense settings from user for default input/norm */ - if (default_norm < VIDEO_MODE_PAL && - default_norm > VIDEO_MODE_SECAM) - default_norm = VIDEO_MODE_PAL; - if (default_norm == VIDEO_MODE_PAL) { + if (default_norm < 0 && default_norm > 2) + default_norm = 0; + if (default_norm == 0) { zr->norm = V4L2_STD_PAL; zr->timing = zr->card.tvn[0]; - } else if (default_norm == VIDEO_MODE_NTSC) { + } else if (default_norm == 1) { zr->norm = V4L2_STD_NTSC; zr->timing = zr->card.tvn[1]; } else { @@ -1547,9 +1527,6 @@ static int __init zoran_init(void) ZORAN_NAME, vidmem); } - /* random nonsense */ - dprintk(6, KERN_DEBUG "Jotti is een held!\n"); - /* some mainboards might not do PCI-PCI data transfer well */ if (pci_pci_problems & (PCIPCI_FAIL|PCIAGP_FAIL|PCIPCI_ALIMAGIK)) { dprintk(1, diff --git a/drivers/media/video/zoran/zoran_device.c b/drivers/media/video/zoran/zoran_device.c index 3336611c0cdf..49e91b2ed552 100644 --- a/drivers/media/video/zoran/zoran_device.c +++ b/drivers/media/video/zoran/zoran_device.c @@ -488,11 +488,11 @@ zr36057_overlay (struct zoran *zr, * All error messages are internal driver checking only! */ /* video display top and bottom registers */ - reg = (long) zr->buffer.base + + reg = (long) zr->vbuf_base + zr->overlay_settings.x * ((zr->overlay_settings.format->depth + 7) / 8) + zr->overlay_settings.y * - zr->buffer.bytesperline; + zr->vbuf_bytesperline; btwrite(reg, ZR36057_VDTR); if (reg & 3) dprintk(1, @@ -500,15 +500,15 @@ zr36057_overlay (struct zoran *zr, "%s: zr36057_overlay() - video_address not aligned\n", ZR_DEVNAME(zr)); if (zr->overlay_settings.height > BUZ_MAX_HEIGHT / 2) - reg += zr->buffer.bytesperline; + reg += zr->vbuf_bytesperline; btwrite(reg, ZR36057_VDBR); /* video stride, status, and frame grab register */ - reg = zr->buffer.bytesperline - + reg = zr->vbuf_bytesperline - zr->overlay_settings.width * ((zr->overlay_settings.format->depth + 7) / 8); if (zr->overlay_settings.height > BUZ_MAX_HEIGHT / 2) - reg += zr->buffer.bytesperline; + reg += zr->vbuf_bytesperline; if (reg & 3) dprintk(1, KERN_ERR @@ -537,7 +537,7 @@ zr36057_overlay (struct zoran *zr, void write_overlay_mask (struct file *file, - struct video_clip *vp, + struct v4l2_clip *vp, int count) { struct zoran_fh *fh = file->private_data; @@ -554,10 +554,10 @@ write_overlay_mask (struct file *file, for (i = 0; i < count; ++i) { /* pick up local copy of clip */ - x = vp[i].x; - y = vp[i].y; - width = vp[i].width; - height = vp[i].height; + x = vp[i].c.left; + y = vp[i].c.top; + width = vp[i].c.width; + height = vp[i].c.height; /* trim clips that extend beyond the window */ if (x < 0) { diff --git a/drivers/media/video/zoran/zoran_device.h b/drivers/media/video/zoran/zoran_device.h index 14d4e7aa6cea..3520bd54c8bd 100644 --- a/drivers/media/video/zoran/zoran_device.h +++ b/drivers/media/video/zoran/zoran_device.h @@ -55,7 +55,7 @@ extern int jpeg_codec_reset(struct zoran *zr); extern void zr36057_overlay(struct zoran *zr, int on); extern void write_overlay_mask(struct file *file, - struct video_clip *vp, + struct v4l2_clip *vp, int count); extern void zr36057_set_memgrab(struct zoran *zr, int mode); diff --git a/drivers/media/video/zoran/zoran_driver.c b/drivers/media/video/zoran/zoran_driver.c index b027a68e8c67..c6da45b41643 100644 --- a/drivers/media/video/zoran/zoran_driver.c +++ b/drivers/media/video/zoran/zoran_driver.c @@ -59,7 +59,7 @@ #include -#include +#include #include #include #include "videocodec.h" @@ -69,8 +69,6 @@ #include #include -#include -#include #include #include "zoran.h" #include "zoran_device.h" @@ -1170,12 +1168,12 @@ setup_fbuffer (struct file *file, return -EINVAL; } - zr->buffer.base = (void *) ((unsigned long) base & ~3); - zr->buffer.height = height; - zr->buffer.width = width; - zr->buffer.depth = fmt->depth; + zr->vbuf_base = (void *) ((unsigned long) base & ~3); + zr->vbuf_height = height; + zr->vbuf_width = width; + zr->vbuf_depth = fmt->depth; zr->overlay_settings.format = fmt; - zr->buffer.bytesperline = bytesperline; + zr->vbuf_bytesperline = bytesperline; /* The user should set new window parameters */ zr->overlay_settings.is_set = 0; @@ -1190,17 +1188,17 @@ setup_window (struct file *file, int y, int width, int height, - struct video_clip __user *clips, + struct v4l2_clip __user *clips, int clipcount, void __user *bitmap) { struct zoran_fh *fh = file->private_data; struct zoran *zr = fh->zr; - struct video_clip *vcp = NULL; + struct v4l2_clip *vcp = NULL; int on, end; - if (!zr->buffer.base) { + if (!zr->vbuf_base) { dprintk(1, KERN_ERR "%s: setup_window() - frame buffer has to be set first\n", @@ -1220,13 +1218,13 @@ setup_window (struct file *file, * The video front end needs 4-byte alinged line sizes, we correct that * silently here if necessary */ - if (zr->buffer.depth == 15 || zr->buffer.depth == 16) { + if (zr->vbuf_depth == 15 || zr->vbuf_depth == 16) { end = (x + width) & ~1; /* round down */ x = (x + 1) & ~1; /* round up */ width = end - x; } - if (zr->buffer.depth == 24) { + if (zr->vbuf_depth == 24) { end = (x + width) & ~3; /* round down */ x = (x + 3) & ~3; /* round up */ width = end - x; @@ -1281,7 +1279,7 @@ setup_window (struct file *file, } } else if (clipcount > 0) { /* write our own bitmap from the clips */ - vcp = vmalloc(sizeof(struct video_clip) * (clipcount + 4)); + vcp = vmalloc(sizeof(struct v4l2_clip) * (clipcount + 4)); if (vcp == NULL) { dprintk(1, KERN_ERR @@ -1290,7 +1288,7 @@ setup_window (struct file *file, return -ENOMEM; } if (copy_from_user - (vcp, clips, sizeof(struct video_clip) * clipcount)) { + (vcp, clips, sizeof(struct v4l2_clip) * clipcount)) { vfree(vcp); return -EFAULT; } @@ -1349,7 +1347,7 @@ setup_overlay (struct file *file, zr36057_overlay(zr, 0); zr->overlay_mask = NULL; } else { - if (!zr->buffer.base || !fh->overlay_settings.is_set) { + if (!zr->vbuf_base || !fh->overlay_settings.is_set) { dprintk(1, KERN_ERR "%s: setup_overlay() - buffer or window not set\n", @@ -2200,7 +2198,7 @@ static int zoran_s_fmt_vid_overlay(struct file *file, void *__fh, fmt->fmt.win.w.top, fmt->fmt.win.w.width, fmt->fmt.win.w.height, - (struct video_clip __user *) + (struct v4l2_clip __user *) fmt->fmt.win.clips, fmt->fmt.win.clipcount, fmt->fmt.win.bitmap); @@ -2357,12 +2355,12 @@ static int zoran_g_fbuf(struct file *file, void *__fh, memset(fb, 0, sizeof(*fb)); mutex_lock(&zr->resource_lock); - fb->base = zr->buffer.base; - fb->fmt.width = zr->buffer.width; - fb->fmt.height = zr->buffer.height; + fb->base = zr->vbuf_base; + fb->fmt.width = zr->vbuf_width; + fb->fmt.height = zr->vbuf_height; if (zr->overlay_settings.format) fb->fmt.pixelformat = fh->overlay_settings.format->fourcc; - fb->fmt.bytesperline = zr->buffer.bytesperline; + fb->fmt.bytesperline = zr->vbuf_bytesperline; mutex_unlock(&zr->resource_lock); fb->fmt.colorspace = V4L2_COLORSPACE_SRGB; fb->fmt.field = V4L2_FIELD_INTERLACED; diff --git a/drivers/media/video/zoran/zoran_procfs.c b/drivers/media/video/zoran/zoran_procfs.c index 870bc5a70e3f..f1423b777db1 100644 --- a/drivers/media/video/zoran/zoran_procfs.c +++ b/drivers/media/video/zoran/zoran_procfs.c @@ -36,7 +36,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/drivers/media/video/zoran/zr36016.c b/drivers/media/video/zoran/zr36016.c index 00d132bcd1e4..21c088ea9046 100644 --- a/drivers/media/video/zoran/zr36016.c +++ b/drivers/media/video/zoran/zr36016.c @@ -34,15 +34,10 @@ #include #include -/* includes for structures and defines regarding video - #include */ - /* I/O commands, error codes */ #include -//#include /* v4l API */ -#include /* headerfile of this module */ #include"zr36016.h" diff --git a/drivers/media/video/zoran/zr36050.c b/drivers/media/video/zoran/zr36050.c index cf8b271a1c8f..639dd87c663f 100644 --- a/drivers/media/video/zoran/zr36050.c +++ b/drivers/media/video/zoran/zr36050.c @@ -34,12 +34,8 @@ #include #include -/* includes for structures and defines regarding video - #include */ - /* I/O commands, error codes */ #include -//#include /* headerfile of this module */ #include "zr36050.h" diff --git a/drivers/media/video/zoran/zr36060.c b/drivers/media/video/zoran/zr36060.c index 8e74054d5ef1..008746ff7746 100644 --- a/drivers/media/video/zoran/zr36060.c +++ b/drivers/media/video/zoran/zr36060.c @@ -34,12 +34,8 @@ #include #include -/* includes for structures and defines regarding video - #include */ - /* I/O commands, error codes */ #include -//#include /* headerfile of this module */ #include "zr36060.h" -- cgit v1.2.3 From 2d26698e859994d4febb2d27b055bdc37d8e368e Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Thu, 19 Feb 2009 17:41:19 -0300 Subject: V4L/DVB (10731): zoran i2c modules: remove i2c autoprobing support. Zoran doesn't do autoprobing anymore, so remove support for this from the i2c modules. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/adv7170.c | 16 +--------------- drivers/media/video/adv7175.c | 16 +--------------- drivers/media/video/bt819.c | 12 +----------- drivers/media/video/bt856.c | 12 +----------- drivers/media/video/bt866.c | 18 +----------------- drivers/media/video/ks0127.c | 24 ++---------------------- drivers/media/video/saa7110.c | 12 +----------- drivers/media/video/saa7127.c | 1 - drivers/media/video/saa7185.c | 12 +----------- drivers/media/video/vpx3220.c | 12 +----------- 10 files changed, 10 insertions(+), 125 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/adv7170.c b/drivers/media/video/adv7170.c index 7b10487ae818..43fd1d24cdeb 100644 --- a/drivers/media/video/adv7170.c +++ b/drivers/media/video/adv7170.c @@ -37,19 +37,12 @@ #include #include #include -#include +#include MODULE_DESCRIPTION("Analog Devices ADV7170 video encoder driver"); MODULE_AUTHOR("Maxim Yevtyushkin"); MODULE_LICENSE("GPL"); -static unsigned short normal_i2c[] = { - 0xd4 >> 1, 0xd6 >> 1, /* adv7170 IDs */ - 0x54 >> 1, 0x56 >> 1, /* adv7171 IDs */ - I2C_CLIENT_END -}; - -I2C_CLIENT_INSMOD; static int debug; module_param(debug, int, 0); @@ -271,11 +264,6 @@ static int adv7170_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ide return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_ADV7170, 0); } -static int adv7170_command(struct i2c_client *client, unsigned cmd, void *arg) -{ - return v4l2_subdev_command(i2c_get_clientdata(client), cmd, arg); -} - /* ----------------------------------------------------------------------- */ static const struct v4l2_subdev_core_ops adv7170_core_ops = { @@ -348,8 +336,6 @@ MODULE_DEVICE_TABLE(i2c, adv7170_id); static struct v4l2_i2c_driver_data v4l2_i2c_data = { .name = "adv7170", - .driverid = I2C_DRIVERID_ADV7170, - .command = adv7170_command, .probe = adv7170_probe, .remove = adv7170_remove, .id_table = adv7170_id, diff --git a/drivers/media/video/adv7175.c b/drivers/media/video/adv7175.c index 318c3053633a..709e044f007d 100644 --- a/drivers/media/video/adv7175.c +++ b/drivers/media/video/adv7175.c @@ -33,7 +33,7 @@ #include #include #include -#include +#include MODULE_DESCRIPTION("Analog Devices ADV7175 video encoder driver"); MODULE_AUTHOR("Dave Perks"); @@ -42,13 +42,6 @@ MODULE_LICENSE("GPL"); #define I2C_ADV7175 0xd4 #define I2C_ADV7176 0x54 -static unsigned short normal_i2c[] = { - I2C_ADV7175 >> 1, (I2C_ADV7175 >> 1) + 1, - I2C_ADV7176 >> 1, (I2C_ADV7176 >> 1) + 1, - I2C_CLIENT_END -}; - -I2C_CLIENT_INSMOD; static int debug; module_param(debug, int, 0); @@ -309,11 +302,6 @@ static int adv7175_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ide return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_ADV7175, 0); } -static int adv7175_command(struct i2c_client *client, unsigned cmd, void *arg) -{ - return v4l2_subdev_command(i2c_get_clientdata(client), cmd, arg); -} - /* ----------------------------------------------------------------------- */ static const struct v4l2_subdev_core_ops adv7175_core_ops = { @@ -387,8 +375,6 @@ MODULE_DEVICE_TABLE(i2c, adv7175_id); static struct v4l2_i2c_driver_data v4l2_i2c_data = { .name = "adv7175", - .driverid = I2C_DRIVERID_ADV7175, - .command = adv7175_command, .probe = adv7175_probe, .remove = adv7175_remove, .id_table = adv7175_id, diff --git a/drivers/media/video/bt819.c b/drivers/media/video/bt819.c index 821af1269293..f2ebf8441aa0 100644 --- a/drivers/media/video/bt819.c +++ b/drivers/media/video/bt819.c @@ -38,7 +38,7 @@ #include #include #include -#include +#include MODULE_DESCRIPTION("Brooktree-819 video decoder driver"); MODULE_AUTHOR("Mike Bernson & Dave Perks"); @@ -48,9 +48,6 @@ static int debug; module_param(debug, int, 0); MODULE_PARM_DESC(debug, "Debug level (0-1)"); -static unsigned short normal_i2c[] = { 0x8a >> 1, I2C_CLIENT_END }; - -I2C_CLIENT_INSMOD; /* ----------------------------------------------------------------------- */ @@ -428,11 +425,6 @@ static int bt819_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident return v4l2_chip_ident_i2c_client(client, chip, decoder->ident, 0); } -static int bt819_command(struct i2c_client *client, unsigned cmd, void *arg) -{ - return v4l2_subdev_command(i2c_get_clientdata(client), cmd, arg); -} - /* ----------------------------------------------------------------------- */ static const struct v4l2_subdev_core_ops bt819_core_ops = { @@ -537,8 +529,6 @@ MODULE_DEVICE_TABLE(i2c, bt819_id); static struct v4l2_i2c_driver_data v4l2_i2c_data = { .name = "bt819", - .driverid = I2C_DRIVERID_BT819, - .command = bt819_command, .probe = bt819_probe, .remove = bt819_remove, .id_table = bt819_id, diff --git a/drivers/media/video/bt856.c b/drivers/media/video/bt856.c index 182da6ab3845..af3c7a885d50 100644 --- a/drivers/media/video/bt856.c +++ b/drivers/media/video/bt856.c @@ -37,7 +37,7 @@ #include #include #include -#include +#include MODULE_DESCRIPTION("Brooktree-856A video encoder driver"); MODULE_AUTHOR("Mike Bernson & Dave Perks"); @@ -47,9 +47,6 @@ static int debug; module_param(debug, int, 0); MODULE_PARM_DESC(debug, "Debug level (0-1)"); -static unsigned short normal_i2c[] = { 0x88 >> 1, I2C_CLIENT_END }; - -I2C_CLIENT_INSMOD; /* ----------------------------------------------------------------------- */ @@ -187,11 +184,6 @@ static int bt856_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_BT856, 0); } -static int bt856_command(struct i2c_client *client, unsigned cmd, void *arg) -{ - return v4l2_subdev_command(i2c_get_clientdata(client), cmd, arg); -} - /* ----------------------------------------------------------------------- */ static const struct v4l2_subdev_core_ops bt856_core_ops = { @@ -270,8 +262,6 @@ MODULE_DEVICE_TABLE(i2c, bt856_id); static struct v4l2_i2c_driver_data v4l2_i2c_data = { .name = "bt856", - .driverid = I2C_DRIVERID_BT856, - .command = bt856_command, .probe = bt856_probe, .remove = bt856_remove, .id_table = bt856_id, diff --git a/drivers/media/video/bt866.c b/drivers/media/video/bt866.c index 18d383877ece..0a32221fa3f9 100644 --- a/drivers/media/video/bt866.c +++ b/drivers/media/video/bt866.c @@ -37,7 +37,7 @@ #include #include #include -#include +#include MODULE_DESCRIPTION("Brooktree-866 video encoder driver"); MODULE_AUTHOR("Mike Bernson & Dave Perks"); @@ -47,9 +47,6 @@ static int debug; module_param(debug, int, 0); MODULE_PARM_DESC(debug, "Debug level (0-1)"); -static unsigned short normal_i2c[] = { 0x88 >> 1, I2C_CLIENT_END }; - -I2C_CLIENT_INSMOD; /* ----------------------------------------------------------------------- */ @@ -185,11 +182,6 @@ static int bt866_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_BT866, 0); } -static int bt866_command(struct i2c_client *client, unsigned cmd, void *arg) -{ - return v4l2_subdev_command(i2c_get_clientdata(client), cmd, arg); -} - /* ----------------------------------------------------------------------- */ static const struct v4l2_subdev_core_ops bt866_core_ops = { @@ -232,11 +224,6 @@ static int bt866_remove(struct i2c_client *client) return 0; } -static int bt866_legacy_probe(struct i2c_adapter *adapter) -{ - return adapter->id == I2C_HW_B_ZR36067; -} - static const struct i2c_device_id bt866_id[] = { { "bt866", 0 }, { } @@ -245,10 +232,7 @@ MODULE_DEVICE_TABLE(i2c, bt866_id); static struct v4l2_i2c_driver_data v4l2_i2c_data = { .name = "bt866", - .driverid = I2C_DRIVERID_BT866, - .command = bt866_command, .probe = bt866_probe, .remove = bt866_remove, - .legacy_probe = bt866_legacy_probe, .id_table = bt866_id, }; diff --git a/drivers/media/video/ks0127.c b/drivers/media/video/ks0127.c index 07c79250f8fd..678c4e23f0e8 100644 --- a/drivers/media/video/ks0127.c +++ b/drivers/media/video/ks0127.c @@ -42,24 +42,17 @@ #include #include #include -#include +#include #include "ks0127.h" MODULE_DESCRIPTION("KS0127 video decoder driver"); MODULE_AUTHOR("Ryan Drake"); MODULE_LICENSE("GPL"); -/* Addresses to scan */ +/* Addresses */ #define I2C_KS0127_ADDON 0xD8 #define I2C_KS0127_ONBOARD 0xDA -static unsigned short normal_i2c[] = { - I2C_KS0127_ADDON >> 1, - I2C_KS0127_ONBOARD >> 1, - I2C_CLIENT_END -}; - -I2C_CLIENT_INSMOD; /* ks0127 control registers */ #define KS_STAT 0x00 @@ -650,11 +643,6 @@ static int ks0127_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_iden return v4l2_chip_ident_i2c_client(client, chip, ks->ident, 0); } -static int ks0127_command(struct i2c_client *client, unsigned cmd, void *arg) -{ - return v4l2_subdev_command(i2c_get_clientdata(client), cmd, arg); -} - /* ----------------------------------------------------------------------- */ static const struct v4l2_subdev_core_ops ks0127_core_ops = { @@ -717,11 +705,6 @@ static int ks0127_remove(struct i2c_client *client) return 0; } -static int ks0127_legacy_probe(struct i2c_adapter *adapter) -{ - return adapter->id == I2C_HW_B_ZR36067; -} - static const struct i2c_device_id ks0127_id[] = { { "ks0127", 0 }, { "ks0127b", 0 }, @@ -732,10 +715,7 @@ MODULE_DEVICE_TABLE(i2c, ks0127_id); static struct v4l2_i2c_driver_data v4l2_i2c_data = { .name = "ks0127", - .driverid = I2C_DRIVERID_KS0127, - .command = ks0127_command, .probe = ks0127_probe, .remove = ks0127_remove, - .legacy_probe = ks0127_legacy_probe, .id_table = ks0127_id, }; diff --git a/drivers/media/video/saa7110.c b/drivers/media/video/saa7110.c index ea16e3cf1793..977de63fded0 100644 --- a/drivers/media/video/saa7110.c +++ b/drivers/media/video/saa7110.c @@ -36,15 +36,12 @@ #include #include #include -#include +#include MODULE_DESCRIPTION("Philips SAA7110 video decoder driver"); MODULE_AUTHOR("Pauline Middelink"); MODULE_LICENSE("GPL"); -static unsigned short normal_i2c[] = { 0x9c >> 1, 0x9e >> 1, I2C_CLIENT_END }; - -I2C_CLIENT_INSMOD; static int debug; module_param(debug, int, 0); @@ -410,11 +407,6 @@ static int saa7110_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ide return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_SAA7110, 0); } -static int saa7110_command(struct i2c_client *client, unsigned cmd, void *arg) -{ - return v4l2_subdev_command(i2c_get_clientdata(client), cmd, arg); -} - /* ----------------------------------------------------------------------- */ static const struct v4l2_subdev_core_ops saa7110_core_ops = { @@ -518,8 +510,6 @@ MODULE_DEVICE_TABLE(i2c, saa7110_id); static struct v4l2_i2c_driver_data v4l2_i2c_data = { .name = "saa7110", - .driverid = I2C_DRIVERID_SAA7110, - .command = saa7110_command, .probe = saa7110_probe, .remove = saa7110_remove, .id_table = saa7110_id, diff --git a/drivers/media/video/saa7127.c b/drivers/media/video/saa7127.c index 05221d47dd4c..128bb8b8dbbf 100644 --- a/drivers/media/video/saa7127.c +++ b/drivers/media/video/saa7127.c @@ -810,7 +810,6 @@ MODULE_DEVICE_TABLE(i2c, saa7127_id); static struct v4l2_i2c_driver_data v4l2_i2c_data = { .name = "saa7127", - .driverid = I2C_DRIVERID_SAA7127, .probe = saa7127_probe, .remove = saa7127_remove, .id_table = saa7127_id, diff --git a/drivers/media/video/saa7185.c b/drivers/media/video/saa7185.c index b4eb66253bc2..75747b104d07 100644 --- a/drivers/media/video/saa7185.c +++ b/drivers/media/video/saa7185.c @@ -33,7 +33,7 @@ #include #include #include -#include +#include MODULE_DESCRIPTION("Philips SAA7185 video encoder driver"); MODULE_AUTHOR("Dave Perks"); @@ -43,9 +43,6 @@ static int debug; module_param(debug, int, 0); MODULE_PARM_DESC(debug, "Debug level (0-1)"); -static unsigned short normal_i2c[] = { 0x88 >> 1, I2C_CLIENT_END }; - -I2C_CLIENT_INSMOD; /* ----------------------------------------------------------------------- */ @@ -295,11 +292,6 @@ static int saa7185_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ide return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_SAA7185, 0); } -static int saa7185_command(struct i2c_client *client, unsigned cmd, void *arg) -{ - return v4l2_subdev_command(i2c_get_clientdata(client), cmd, arg); -} - /* ----------------------------------------------------------------------- */ static const struct v4l2_subdev_core_ops saa7185_core_ops = { @@ -374,8 +366,6 @@ MODULE_DEVICE_TABLE(i2c, saa7185_id); static struct v4l2_i2c_driver_data v4l2_i2c_data = { .name = "saa7185", - .driverid = I2C_DRIVERID_SAA7185B, - .command = saa7185_command, .probe = saa7185_probe, .remove = saa7185_remove, .id_table = saa7185_id, diff --git a/drivers/media/video/vpx3220.c b/drivers/media/video/vpx3220.c index 476a204dcf90..ed50b912d8a0 100644 --- a/drivers/media/video/vpx3220.c +++ b/drivers/media/video/vpx3220.c @@ -27,7 +27,7 @@ #include #include #include -#include +#include MODULE_DESCRIPTION("vpx3220a/vpx3216b/vpx3214c video decoder driver"); MODULE_AUTHOR("Laurent Pinchart"); @@ -37,9 +37,6 @@ static int debug; module_param(debug, int, 0); MODULE_PARM_DESC(debug, "Debug level (0-1)"); -static unsigned short normal_i2c[] = { 0x86 >> 1, 0x8e >> 1, I2C_CLIENT_END }; - -I2C_CLIENT_INSMOD; #define VPX_TIMEOUT_COUNT 10 @@ -511,11 +508,6 @@ static int vpx3220_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ide return v4l2_chip_ident_i2c_client(client, chip, decoder->ident, 0); } -static int vpx3220_command(struct i2c_client *client, unsigned cmd, void *arg) -{ - return v4l2_subdev_command(i2c_get_clientdata(client), cmd, arg); -} - /* ----------------------------------------------------------------------- */ static const struct v4l2_subdev_core_ops vpx3220_core_ops = { @@ -626,8 +618,6 @@ MODULE_DEVICE_TABLE(i2c, vpx3220_id); static struct v4l2_i2c_driver_data v4l2_i2c_data = { .name = "vpx3220", - .driverid = I2C_DRIVERID_VPX3220, - .command = vpx3220_command, .probe = vpx3220_probe, .remove = vpx3220_remove, .id_table = vpx3220_id, -- cgit v1.2.3 From 27f79525738ef626dfd4df5798bfb86ad5d6d98e Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 20 Feb 2009 07:34:28 -0300 Subject: V4L/DVB (10732): zoran: s_jpegcomp should return a proper result, not 0. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/zoran/zoran_driver.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/zoran/zoran_driver.c b/drivers/media/video/zoran/zoran_driver.c index c6da45b41643..daad93728cf9 100644 --- a/drivers/media/video/zoran/zoran_driver.c +++ b/drivers/media/video/zoran/zoran_driver.c @@ -3119,7 +3119,7 @@ static int zoran_s_jpegcomp(struct file *file, void *__fh, sjpegc_unlock_and_return: mutex_unlock(&zr->resource_lock); - return 0; + return res; } static unsigned int -- cgit v1.2.3 From e686e73ca7e6b157c8a4877c5dc9655b20c4967a Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 20 Feb 2009 15:06:59 -0300 Subject: V4L/DVB (10733): zoran: increase bufsize to a value suitable for 768x576. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/zoran/zoran_card.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/zoran/zoran_card.c b/drivers/media/video/zoran/zoran_card.c index 665a5e370a84..3ffdbe34ecc1 100644 --- a/drivers/media/video/zoran/zoran_card.c +++ b/drivers/media/video/zoran/zoran_card.c @@ -107,7 +107,7 @@ module_param_array(video_nr, int, NULL, 0444); MODULE_PARM_DESC(video_nr, "Video device number (-1=Auto)"); int v4l_nbufs = 4; -int v4l_bufsize = 810; /* Everybody should be able to work with this setting */ +int v4l_bufsize = 864; /* Everybody should be able to work with this setting */ module_param(v4l_nbufs, int, 0644); MODULE_PARM_DESC(v4l_nbufs, "Maximum number of V4L buffers to use"); module_param(v4l_bufsize, int, 0644); -- cgit v1.2.3 From 770060385a1694a8d909e7872c4ce0703da2b069 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 26 Feb 2009 21:22:18 -0300 Subject: V4L/DVB (10738): Get rid of video_decoder.h header were uneeded Now, just a few modules are still dependent of this legacy header: $ grep -l DECODER_ `find linux/drivers/media/ -name '*.[ch]' -exec grep -l video_decoder '{}' \;` linux/drivers/media/video/v4l2-ioctl.c linux/drivers/media/video/indycam.c linux/drivers/media/video/saa7191.c linux/drivers/media/video/vino.c Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/tvp5150.c | 1 - drivers/media/video/usbvision/usbvision-core.c | 1 - drivers/media/video/usbvision/usbvision-video.c | 1 - 3 files changed, 3 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/tvp5150.c b/drivers/media/video/tvp5150.c index 6b600bed445f..9ee55f26c4f9 100644 --- a/drivers/media/video/tvp5150.c +++ b/drivers/media/video/tvp5150.c @@ -8,7 +8,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/media/video/usbvision/usbvision-core.c b/drivers/media/video/usbvision/usbvision-core.c index eadebb91b092..71cb4aabdf7d 100644 --- a/drivers/media/video/usbvision/usbvision-core.c +++ b/drivers/media/video/usbvision/usbvision-core.c @@ -36,7 +36,6 @@ #include #include #include -#include #include #include diff --git a/drivers/media/video/usbvision/usbvision-video.c b/drivers/media/video/usbvision/usbvision-video.c index cfa184d63c65..33d79a5dad0f 100644 --- a/drivers/media/video/usbvision/usbvision-video.c +++ b/drivers/media/video/usbvision/usbvision-video.c @@ -59,7 +59,6 @@ #include #include #include -#include #include #include -- cgit v1.2.3 From 812c582390f2c6b81c0400d1286a7bce39d161d0 Mon Sep 17 00:00:00 2001 From: Douglas Schilling Landgraf Date: Wed, 25 Feb 2009 16:52:31 -0300 Subject: V4L/DVB (10739): em28xx-cards: remove incorrect entry Removed EM2821_BOARD_PROLINK_PLAYTV_USB2 entry. This entry has a incorrect tuner set. Signed-off-by: Douglas Schilling Landgraf Signed-off-by: Mauro Carvalho Chehab --- Documentation/video4linux/CARDLIST.em28xx | 1 - drivers/media/video/em28xx/em28xx-cards.c | 20 -------------------- drivers/media/video/em28xx/em28xx.h | 1 - 3 files changed, 22 deletions(-) (limited to 'drivers/media/video') diff --git a/Documentation/video4linux/CARDLIST.em28xx b/Documentation/video4linux/CARDLIST.em28xx index 77874bd20550..dafbd955ee1b 100644 --- a/Documentation/video4linux/CARDLIST.em28xx +++ b/Documentation/video4linux/CARDLIST.em28xx @@ -30,7 +30,6 @@ 30 -> Videology 20K14XUSB USB2.0 (em2820/em2840) 31 -> Usbgear VD204v9 (em2821) 32 -> Supercomp USB 2.0 TV (em2821) - 33 -> SIIG AVTuner-PVR/Prolink PlayTV USB 2.0 (em2821) 34 -> Terratec Cinergy A Hybrid XS (em2860) [0ccd:004f] 35 -> Typhoon DVD Maker (em2860) 36 -> NetGMBH Cam (em2860) diff --git a/drivers/media/video/em28xx/em28xx-cards.c b/drivers/media/video/em28xx/em28xx-cards.c index 2b27460dae35..e263ab0f4ee4 100644 --- a/drivers/media/video/em28xx/em28xx-cards.c +++ b/drivers/media/video/em28xx/em28xx-cards.c @@ -369,26 +369,6 @@ struct em28xx_board em28xx_boards[] = { .amux = EM28XX_AMUX_VIDEO, } }, }, - [EM2821_BOARD_PROLINK_PLAYTV_USB2] = { - .name = "SIIG AVTuner-PVR/Prolink PlayTV USB 2.0", - .valid = EM28XX_BOARD_NOT_VALIDATED, - .tuner_type = TUNER_LG_PAL_NEW_TAPC, /* unknown? */ - .tda9887_conf = TDA9887_PRESENT, /* unknown? */ - .decoder = EM28XX_SAA711X, - .input = { { - .type = EM28XX_VMUX_TELEVISION, - .vmux = SAA7115_COMPOSITE2, - .amux = EM28XX_AMUX_LINE_IN, - }, { - .type = EM28XX_VMUX_COMPOSITE1, - .vmux = SAA7115_COMPOSITE0, - .amux = EM28XX_AMUX_LINE_IN, - }, { - .type = EM28XX_VMUX_SVIDEO, - .vmux = SAA7115_SVIDEO3, - .amux = EM28XX_AMUX_LINE_IN, - } }, - }, [EM2821_BOARD_SUPERCOMP_USB_2] = { .name = "Supercomp USB 2.0 TV", .valid = EM28XX_BOARD_NOT_VALIDATED, diff --git a/drivers/media/video/em28xx/em28xx.h b/drivers/media/video/em28xx/em28xx.h index 89a793cb8ca4..57a4084f9b5e 100644 --- a/drivers/media/video/em28xx/em28xx.h +++ b/drivers/media/video/em28xx/em28xx.h @@ -70,7 +70,6 @@ #define EM2820_BOARD_VIDEOLOGY_20K14XUSB 30 #define EM2821_BOARD_USBGEAR_VD204 31 #define EM2821_BOARD_SUPERCOMP_USB_2 32 -#define EM2821_BOARD_PROLINK_PLAYTV_USB2 33 #define EM2860_BOARD_TERRATEC_HYBRID_XS 34 #define EM2860_BOARD_TYPHOON_DVD_MAKER 35 #define EM2860_BOARD_NETGMBH_CAM 36 -- cgit v1.2.3 From 1f372a930c85270b4435b508b3e029021b1c5b62 Mon Sep 17 00:00:00 2001 From: Douglas Schilling Landgraf Date: Wed, 25 Feb 2009 16:54:31 -0300 Subject: V4L/DVB (10740): em28xx-cards: Add SIIG AVTuner-PVR board Added SIIG AVTuner-PVR to the right entry. Signed-off-by: Douglas Schilling Landgraf Signed-off-by: Mauro Carvalho Chehab --- Documentation/video4linux/CARDLIST.em28xx | 2 +- drivers/media/video/em28xx/em28xx-cards.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/media/video') diff --git a/Documentation/video4linux/CARDLIST.em28xx b/Documentation/video4linux/CARDLIST.em28xx index dafbd955ee1b..5707c6fbf89f 100644 --- a/Documentation/video4linux/CARDLIST.em28xx +++ b/Documentation/video4linux/CARDLIST.em28xx @@ -12,7 +12,7 @@ 11 -> Terratec Hybrid XS (em2880) [0ccd:0042] 12 -> Kworld PVR TV 2800 RF (em2820/em2840) 13 -> Terratec Prodigy XS (em2880) [0ccd:0047] - 14 -> Pixelview Prolink PlayTV USB 2.0 (em2820/em2840) + 14 -> SIIG AVTuner-PVR / Pixelview Prolink PlayTV USB 2.0 (em2820/em2840) 15 -> V-Gear PocketTV (em2800) 16 -> Hauppauge WinTV HVR 950 (em2883) [2040:6513,2040:6517,2040:651b] 17 -> Pinnacle PCTV HD Pro Stick (em2880) [2304:0227] diff --git a/drivers/media/video/em28xx/em28xx-cards.c b/drivers/media/video/em28xx/em28xx-cards.c index e263ab0f4ee4..226dc154aaf0 100644 --- a/drivers/media/video/em28xx/em28xx-cards.c +++ b/drivers/media/video/em28xx/em28xx-cards.c @@ -951,7 +951,7 @@ struct em28xx_board em28xx_boards[] = { } }, }, [EM2820_BOARD_PROLINK_PLAYTV_USB2] = { - .name = "Pixelview Prolink PlayTV USB 2.0", + .name = "SIIG AVTuner-PVR / Pixelview Prolink PlayTV USB 2.0", .has_snapshot_button = 1, .tda9887_conf = TDA9887_PRESENT, .tuner_type = TUNER_YMEC_TVF_5533MF, -- cgit v1.2.3 From ac40d9e09825c62b77e8b11b3ed201f390550351 Mon Sep 17 00:00:00 2001 From: Douglas Schilling Landgraf Date: Wed, 25 Feb 2009 16:55:48 -0300 Subject: V4L/DVB (10741): em28xx: Add Kaiser Baas Video to DVD maker support Added usb vendor/product id for Kaiser Baas Video to DVD maker. Thanks to Trevor Campbell for providing all data and tests needed to add this card to em28xx driver. Signed-off-by: Douglas Schilling Landgraf Signed-off-by: Mauro Carvalho Chehab --- Documentation/video4linux/CARDLIST.em28xx | 2 +- drivers/media/video/em28xx/em28xx-cards.c | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers/media/video') diff --git a/Documentation/video4linux/CARDLIST.em28xx b/Documentation/video4linux/CARDLIST.em28xx index 5707c6fbf89f..78d0a6eed571 100644 --- a/Documentation/video4linux/CARDLIST.em28xx +++ b/Documentation/video4linux/CARDLIST.em28xx @@ -7,7 +7,7 @@ 6 -> Terratec Cinergy 200 USB (em2800) 7 -> Leadtek Winfast USB II (em2800) [0413:6023] 8 -> Kworld USB2800 (em2800) - 9 -> Pinnacle Dazzle DVC 90/DVC 100/DVC 101/DVC 107 (em2820/em2840) [2304:0207,2304:021a] + 9 -> Pinnacle Dazzle DVC 90/100/101/107 / Kaiser Baas Video to DVD maker (em2820/em2840) [1b80:e302,2304:0207,2304:021a] 10 -> Hauppauge WinTV HVR 900 (em2880) [2040:6500] 11 -> Terratec Hybrid XS (em2880) [0ccd:0042] 12 -> Kworld PVR TV 2800 RF (em2820/em2840) diff --git a/drivers/media/video/em28xx/em28xx-cards.c b/drivers/media/video/em28xx/em28xx-cards.c index 226dc154aaf0..f7c817765752 100644 --- a/drivers/media/video/em28xx/em28xx-cards.c +++ b/drivers/media/video/em28xx/em28xx-cards.c @@ -896,7 +896,7 @@ struct em28xx_board em28xx_boards[] = { } }, }, [EM2820_BOARD_PINNACLE_DVC_90] = { - .name = "Pinnacle Dazzle DVC 90/DVC 100/DVC 101/DVC 107", + .name = "Pinnacle Dazzle DVC 90/100/101/107 / Kaiser Baas Video to DVD maker", .tuner_type = TUNER_ABSENT, /* capture only board */ .decoder = EM28XX_SAA711X, .input = { { @@ -1345,6 +1345,8 @@ struct usb_device_id em28xx_id_table[] = { .driver_info = EM2800_BOARD_GRABBEEX_USB2800 }, { USB_DEVICE(0xeb1a, 0xe357), .driver_info = EM2870_BOARD_KWORLD_355U }, + { USB_DEVICE(0x1b80, 0xe302), + .driver_info = EM2820_BOARD_PINNACLE_DVC_90 }, /* Kaiser Baas Video to DVD maker */ { USB_DEVICE(0x0ccd, 0x0036), .driver_info = EM2820_BOARD_TERRATEC_CINERGY_250 }, { USB_DEVICE(0x0ccd, 0x004c), -- cgit v1.2.3 From 1a2670465ec94029e5df62e3decca9e2f7aea075 Mon Sep 17 00:00:00 2001 From: Andy Walls Date: Sat, 14 Feb 2009 02:32:39 -0300 Subject: V4L/DVB (10755): cx18: Convert the integrated A/V decoder core interface to a v4l2_subdev This is the next step in converting the cx18 driver to use the v4l2_device/ v4l2_subdevice framework. This is a straightforward conversion of the cx18_av_*[ch] files. It compiles, but leaves the driver in an unlinkable state at the moment. Note, the cx18 integrated A/V digitizer will now make a host match at address 1, as far as v4l2-dbg is concerned. That means it identifies itself as a separate "chip", and acts as an alias to the integrated A/V decoder registers that are also available with the host match at address 0. Signed-off-by: Andy Walls [mchehab@redhat.com: fix merge conflicts due to the removal of v4l2_ctrl_query_fill_std()] Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx18/cx18-av-core.c | 583 ++++++++++++++++++-------------- drivers/media/video/cx18/cx18-av-core.h | 13 +- 2 files changed, 336 insertions(+), 260 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/cx18/cx18-av-core.c b/drivers/media/video/cx18/cx18-av-core.c index fc576cf1a8b5..9b30f77b5205 100644 --- a/drivers/media/video/cx18/cx18-av-core.c +++ b/drivers/media/video/cx18/cx18-av-core.c @@ -22,8 +22,10 @@ * 02110-1301, USA. */ +#include #include "cx18-driver.h" #include "cx18-io.h" +#include "cx18-cards.h" int cx18_av_write(struct cx18 *cx, u16 addr, u8 value) { @@ -97,15 +99,6 @@ int cx18_av_and_or4(struct cx18 *cx, u16 addr, u32 and_mask, or_value); } -/* ----------------------------------------------------------------------- */ - -static int set_input(struct cx18 *cx, enum cx18_av_video_input vid_input, - enum cx18_av_audio_input aud_input); -static void log_audio_status(struct cx18 *cx); -static void log_video_status(struct cx18 *cx); - -/* ----------------------------------------------------------------------- */ - static void cx18_av_initialize(struct cx18 *cx) { struct cx18_av_state *state = &cx->av_state; @@ -200,7 +193,26 @@ static void cx18_av_initialize(struct cx18 *cx) state->default_volume = ((state->default_volume / 2) + 23) << 9; } -/* ----------------------------------------------------------------------- */ +static int cx18_av_reset(struct v4l2_subdev *sd, u32 val) +{ + struct cx18 *cx = v4l2_get_subdevdata(sd); + + cx18_av_initialize(cx); + return 0; +} + +static int cx18_av_init_hardware(struct v4l2_subdev *sd, u32 val) +{ + struct cx18_av_state *state = to_cx18_av_state(sd); + struct cx18 *cx = v4l2_get_subdevdata(sd); + + if (!state->is_initialized) { + /* initialize on first use */ + state->is_initialized = 1; + cx18_av_initialize(cx); + } + return 0; +} void cx18_av_std_setup(struct cx18 *cx) { @@ -362,7 +374,18 @@ void cx18_av_std_setup(struct cx18 *cx) cx18_av_write(cx, 0x47f, state->slicer_line_delay); } -/* ----------------------------------------------------------------------- */ +static int cx18_av_decode_vbi_line(struct v4l2_subdev *sd, + struct v4l2_decode_vbi_line *vbi_line) +{ + struct cx18 *cx = v4l2_get_subdevdata(sd); + return cx18_av_vbi(cx, VIDIOC_INT_DECODE_VBI_LINE, vbi_line); +} + +static int cx18_av_s_clock_freq(struct v4l2_subdev *sd, u32 freq) +{ + struct cx18 *cx = v4l2_get_subdevdata(sd); + return cx18_av_audio(cx, VIDIOC_INT_AUDIO_CLOCK_FREQ, &freq); +} static void input_change(struct cx18 *cx) { @@ -409,6 +432,14 @@ static void input_change(struct cx18 *cx) } } +static int cx18_av_s_frequency(struct v4l2_subdev *sd, + struct v4l2_frequency *freq) +{ + struct cx18 *cx = v4l2_get_subdevdata(sd); + input_change(cx); + return 0; +} + static int set_input(struct cx18 *cx, enum cx18_av_video_input vid_input, enum cx18_av_audio_input aud_input) { @@ -488,14 +519,118 @@ static int set_input(struct cx18 *cx, enum cx18_av_video_input vid_input, return 0; } -/* ----------------------------------------------------------------------- */ +static int cx18_av_s_video_routing(struct v4l2_subdev *sd, + const struct v4l2_routing *route) +{ + struct cx18_av_state *state = to_cx18_av_state(sd); + struct cx18 *cx = v4l2_get_subdevdata(sd); + return set_input(cx, route->input, state->aud_input); +} -static int set_v4lstd(struct cx18 *cx) +static int cx18_av_s_audio_routing(struct v4l2_subdev *sd, + const struct v4l2_routing *route) { - struct cx18_av_state *state = &cx->av_state; + struct cx18_av_state *state = to_cx18_av_state(sd); + struct cx18 *cx = v4l2_get_subdevdata(sd); + return set_input(cx, state->vid_input, route->input); +} + +static int cx18_av_g_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt) +{ + struct cx18_av_state *state = to_cx18_av_state(sd); + struct cx18 *cx = v4l2_get_subdevdata(sd); + u8 vpres; + u8 mode; + int val = 0; + + if (state->radio) + return 0; + + vpres = cx18_av_read(cx, 0x40e) & 0x20; + vt->signal = vpres ? 0xffff : 0x0; + + vt->capability |= + V4L2_TUNER_CAP_STEREO | V4L2_TUNER_CAP_LANG1 | + V4L2_TUNER_CAP_LANG2 | V4L2_TUNER_CAP_SAP; + + mode = cx18_av_read(cx, 0x804); + + /* get rxsubchans and audmode */ + if ((mode & 0xf) == 1) + val |= V4L2_TUNER_SUB_STEREO; + else + val |= V4L2_TUNER_SUB_MONO; + + if (mode == 2 || mode == 4) + val = V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_LANG2; + + if (mode & 0x10) + val |= V4L2_TUNER_SUB_SAP; + + vt->rxsubchans = val; + vt->audmode = state->audmode; + return 0; +} + +static int cx18_av_s_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt) +{ + struct cx18_av_state *state = to_cx18_av_state(sd); + struct cx18 *cx = v4l2_get_subdevdata(sd); + u8 v; + + if (state->radio) + return 0; + + v = cx18_av_read(cx, 0x809); + v &= ~0xf; + + switch (vt->audmode) { + case V4L2_TUNER_MODE_MONO: + /* mono -> mono + stereo -> mono + bilingual -> lang1 */ + break; + case V4L2_TUNER_MODE_STEREO: + case V4L2_TUNER_MODE_LANG1: + /* mono -> mono + stereo -> stereo + bilingual -> lang1 */ + v |= 0x4; + break; + case V4L2_TUNER_MODE_LANG1_LANG2: + /* mono -> mono + stereo -> stereo + bilingual -> lang1/lang2 */ + v |= 0x7; + break; + case V4L2_TUNER_MODE_LANG2: + /* mono -> mono + stereo -> stereo + bilingual -> lang2 */ + v |= 0x1; + break; + default: + return -EINVAL; + } + cx18_av_write_expect(cx, 0x809, v, v, 0xff); + state->audmode = vt->audmode; + return 0; +} + +static int cx18_av_s_std(struct v4l2_subdev *sd, v4l2_std_id norm) +{ + struct cx18_av_state *state = to_cx18_av_state(sd); + struct cx18 *cx = v4l2_get_subdevdata(sd); + u8 fmt = 0; /* zero is autodetect */ u8 pal_m = 0; + if (state->radio == 0 && state->std == norm) + return 0; + + state->radio = 0; + state->std = norm; + /* First tests should be against specific std */ if (state->std == V4L2_STD_NTSC_M_JP) { fmt = 0x2; @@ -538,10 +673,17 @@ static int set_v4lstd(struct cx18 *cx) return 0; } -/* ----------------------------------------------------------------------- */ +static int cx18_av_s_radio(struct v4l2_subdev *sd) +{ + struct cx18_av_state *state = to_cx18_av_state(sd); + state->radio = 1; + return 0; +} -static int set_v4lctrl(struct cx18 *cx, struct v4l2_control *ctrl) +static int cx18_av_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) { + struct cx18 *cx = v4l2_get_subdevdata(sd); + switch (ctrl->id) { case V4L2_CID_BRIGHTNESS: if (ctrl->value < 0 || ctrl->value > 255) { @@ -593,12 +735,13 @@ static int set_v4lctrl(struct cx18 *cx, struct v4l2_control *ctrl) default: return -EINVAL; } - return 0; } -static int get_v4lctrl(struct cx18 *cx, struct v4l2_control *ctrl) +static int cx18_av_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) { + struct cx18 *cx = v4l2_get_subdevdata(sd); + switch (ctrl->id) { case V4L2_CID_BRIGHTNESS: ctrl->value = (s8)cx18_av_read(cx, 0x414) + 128; @@ -621,27 +764,59 @@ static int get_v4lctrl(struct cx18 *cx, struct v4l2_control *ctrl) default: return -EINVAL; } - return 0; } -/* ----------------------------------------------------------------------- */ +static int cx18_av_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qc) +{ + struct cx18_av_state *state = to_cx18_av_state(sd); + + switch (qc->id) { + case V4L2_CID_BRIGHTNESS: + return v4l2_ctrl_query_fill(qc, 0, 255, 1, 128); + case V4L2_CID_CONTRAST: + case V4L2_CID_SATURATION: + return v4l2_ctrl_query_fill(qc, 0, 127, 1, 64); + case V4L2_CID_HUE: + return v4l2_ctrl_query_fill(qc, -128, 127, 1, 0); + default: + break; + } + + switch (qc->id) { + case V4L2_CID_AUDIO_VOLUME: + return v4l2_ctrl_query_fill(qc, 0, 65535, + 65535 / 100, state->default_volume); + case V4L2_CID_AUDIO_MUTE: + return v4l2_ctrl_query_fill(qc, 0, 1, 1, 0); + case V4L2_CID_AUDIO_BALANCE: + case V4L2_CID_AUDIO_BASS: + case V4L2_CID_AUDIO_TREBLE: + return v4l2_ctrl_query_fill(qc, 0, 65535, 65535 / 100, 32768); + default: + return -EINVAL; + } + return -EINVAL; +} -static int get_v4lfmt(struct cx18 *cx, struct v4l2_format *fmt) +static int cx18_av_g_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt) { + struct cx18 *cx = v4l2_get_subdevdata(sd); + switch (fmt->type) { case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE: return cx18_av_vbi(cx, VIDIOC_G_FMT, fmt); default: return -EINVAL; } - return 0; } -static int set_v4lfmt(struct cx18 *cx, struct v4l2_format *fmt) +static int cx18_av_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt) { - struct cx18_av_state *state = &cx->av_state; + struct cx18_av_state *state = to_cx18_av_state(sd); + struct cx18 *cx = v4l2_get_subdevdata(sd); + struct v4l2_pix_format *pix; int HSC, VSC, Vsrc, Hsrc, filter, Vlines; int is_50Hz = !(state->std & V4L2_STD_525_60); @@ -701,252 +876,24 @@ static int set_v4lfmt(struct cx18 *cx, struct v4l2_format *fmt) default: return -EINVAL; } - return 0; } -/* ----------------------------------------------------------------------- */ - -static int valid_av_cmd(unsigned int cmd) +static int cx18_av_s_stream(struct v4l2_subdev *sd, int enable) { - switch (cmd) { - /* All commands supported by cx18_av_cmd() */ - case VIDIOC_INT_DECODE_VBI_LINE: - case VIDIOC_INT_AUDIO_CLOCK_FREQ: - case VIDIOC_STREAMON: - case VIDIOC_STREAMOFF: - case VIDIOC_LOG_STATUS: - case VIDIOC_G_CTRL: - case VIDIOC_S_CTRL: - case VIDIOC_QUERYCTRL: - case VIDIOC_G_STD: - case VIDIOC_S_STD: - case AUDC_SET_RADIO: - case VIDIOC_INT_G_VIDEO_ROUTING: - case VIDIOC_INT_S_VIDEO_ROUTING: - case VIDIOC_INT_G_AUDIO_ROUTING: - case VIDIOC_INT_S_AUDIO_ROUTING: - case VIDIOC_S_FREQUENCY: - case VIDIOC_G_TUNER: - case VIDIOC_S_TUNER: - case VIDIOC_G_FMT: - case VIDIOC_S_FMT: - case VIDIOC_INT_RESET: - return 1; - default: - return 0; - } - return 0; -} - -int cx18_av_cmd(struct cx18 *cx, unsigned int cmd, void *arg) -{ - struct cx18_av_state *state = &cx->av_state; - struct v4l2_tuner *vt = arg; - struct v4l2_routing *route = arg; - - if (!state->is_initialized && valid_av_cmd(cmd)) { - CX18_DEBUG_INFO("cmd %08x triggered fw load\n", cmd); - /* initialize on first use */ - state->is_initialized = 1; - cx18_av_initialize(cx); - } - - switch (cmd) { - case VIDIOC_INT_DECODE_VBI_LINE: - return cx18_av_vbi(cx, cmd, arg); - - case VIDIOC_INT_AUDIO_CLOCK_FREQ: - return cx18_av_audio(cx, cmd, arg); + struct cx18 *cx = v4l2_get_subdevdata(sd); - case VIDIOC_STREAMON: - CX18_DEBUG_INFO("enable output\n"); + CX18_DEBUG_INFO("%s output\n", enable ? "enable" : "disable"); + if (enable) { cx18_av_write(cx, 0x115, 0x8c); cx18_av_write(cx, 0x116, 0x07); - break; - - case VIDIOC_STREAMOFF: - CX18_DEBUG_INFO("disable output\n"); + } else { cx18_av_write(cx, 0x115, 0x00); cx18_av_write(cx, 0x116, 0x00); - break; - - case VIDIOC_LOG_STATUS: - log_video_status(cx); - log_audio_status(cx); - break; - - case VIDIOC_G_CTRL: - return get_v4lctrl(cx, (struct v4l2_control *)arg); - - case VIDIOC_S_CTRL: - return set_v4lctrl(cx, (struct v4l2_control *)arg); - - case VIDIOC_QUERYCTRL: - { - struct v4l2_queryctrl *qc = arg; - - switch (qc->id) { - case V4L2_CID_BRIGHTNESS: - return v4l2_ctrl_query_fill(qc, 0, 255, 1, 128); - case V4L2_CID_CONTRAST: - case V4L2_CID_SATURATION: - return v4l2_ctrl_query_fill(qc, 0, 127, 1, 64); - case V4L2_CID_HUE: - return v4l2_ctrl_query_fill(qc, -128, 127, 1, 0); - default: - break; - } - - switch (qc->id) { - case V4L2_CID_AUDIO_VOLUME: - return v4l2_ctrl_query_fill(qc, 0, 65535, - 65535 / 100, state->default_volume); - case V4L2_CID_AUDIO_MUTE: - return v4l2_ctrl_query_fill(qc, 0, 1, 1, 0); - case V4L2_CID_AUDIO_BALANCE: - case V4L2_CID_AUDIO_BASS: - case V4L2_CID_AUDIO_TREBLE: - return v4l2_ctrl_query_fill(qc, 0, 65535, 65535 / 100, 32768); - default: - return -EINVAL; - } - return -EINVAL; - } - - case VIDIOC_G_STD: - *(v4l2_std_id *)arg = state->std; - break; - - case VIDIOC_S_STD: - if (state->radio == 0 && state->std == *(v4l2_std_id *)arg) - return 0; - state->radio = 0; - state->std = *(v4l2_std_id *)arg; - return set_v4lstd(cx); - - case AUDC_SET_RADIO: - state->radio = 1; - break; - - case VIDIOC_INT_G_VIDEO_ROUTING: - route->input = state->vid_input; - route->output = 0; - break; - - case VIDIOC_INT_S_VIDEO_ROUTING: - return set_input(cx, route->input, state->aud_input); - - case VIDIOC_INT_G_AUDIO_ROUTING: - route->input = state->aud_input; - route->output = 0; - break; - - case VIDIOC_INT_S_AUDIO_ROUTING: - return set_input(cx, state->vid_input, route->input); - - case VIDIOC_S_FREQUENCY: - input_change(cx); - break; - - case VIDIOC_G_TUNER: - { - u8 vpres = cx18_av_read(cx, 0x40e) & 0x20; - u8 mode; - int val = 0; - - if (state->radio) - break; - - vt->signal = vpres ? 0xffff : 0x0; - - vt->capability |= - V4L2_TUNER_CAP_STEREO | V4L2_TUNER_CAP_LANG1 | - V4L2_TUNER_CAP_LANG2 | V4L2_TUNER_CAP_SAP; - - mode = cx18_av_read(cx, 0x804); - - /* get rxsubchans and audmode */ - if ((mode & 0xf) == 1) - val |= V4L2_TUNER_SUB_STEREO; - else - val |= V4L2_TUNER_SUB_MONO; - - if (mode == 2 || mode == 4) - val = V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_LANG2; - - if (mode & 0x10) - val |= V4L2_TUNER_SUB_SAP; - - vt->rxsubchans = val; - vt->audmode = state->audmode; - break; } - - case VIDIOC_S_TUNER: - { - u8 v; - - if (state->radio) - break; - - v = cx18_av_read(cx, 0x809); - v &= ~0xf; - - switch (vt->audmode) { - case V4L2_TUNER_MODE_MONO: - /* mono -> mono - stereo -> mono - bilingual -> lang1 */ - break; - case V4L2_TUNER_MODE_STEREO: - case V4L2_TUNER_MODE_LANG1: - /* mono -> mono - stereo -> stereo - bilingual -> lang1 */ - v |= 0x4; - break; - case V4L2_TUNER_MODE_LANG1_LANG2: - /* mono -> mono - stereo -> stereo - bilingual -> lang1/lang2 */ - v |= 0x7; - break; - case V4L2_TUNER_MODE_LANG2: - /* mono -> mono - stereo -> stereo - bilingual -> lang2 */ - v |= 0x1; - break; - default: - return -EINVAL; - } - cx18_av_write_expect(cx, 0x809, v, v, 0xff); - state->audmode = vt->audmode; - break; - } - - case VIDIOC_G_FMT: - return get_v4lfmt(cx, (struct v4l2_format *)arg); - - case VIDIOC_S_FMT: - return set_v4lfmt(cx, (struct v4l2_format *)arg); - - case VIDIOC_INT_RESET: - cx18_av_initialize(cx); - break; - - default: - return -EINVAL; - } - return 0; } -/* ----------------------------------------------------------------------- */ - -/* ----------------------------------------------------------------------- */ - static void log_video_status(struct cx18 *cx) { static const char *const fmt_strs[] = { @@ -984,8 +931,6 @@ static void log_video_status(struct cx18 *cx) CX18_INFO("Specified audioclock freq: %d Hz\n", state->audclk_freq); } -/* ----------------------------------------------------------------------- */ - static void log_audio_status(struct cx18 *cx) { struct cx18_av_state *state = &cx->av_state; @@ -1133,3 +1078,123 @@ static void log_audio_status(struct cx18 *cx) CX18_INFO("Selected 45 MHz format: %s\n", p); } } + +static int cx18_av_log_status(struct v4l2_subdev *sd) +{ + struct cx18 *cx = v4l2_get_subdevdata(sd); + log_video_status(cx); + log_audio_status(cx); + return 0; +} + +static inline int cx18_av_dbg_match(const struct v4l2_dbg_match *match) +{ + return match->type == V4L2_CHIP_MATCH_HOST && match->addr == 1; +} + +static int cx18_av_g_chip_ident(struct v4l2_subdev *sd, + struct v4l2_dbg_chip_ident *chip) +{ + if (cx18_av_dbg_match(&chip->match)) { + /* + * Nothing else is going to claim to be this combination, + * and the real host chip revision will be returned by a host + * match on address 0. + */ + chip->ident = V4L2_IDENT_CX25843; + chip->revision = V4L2_IDENT_CX23418; /* Why not */ + } + return 0; +} + +#ifdef CONFIG_VIDEO_ADV_DEBUG +static int cx18_av_g_register(struct v4l2_subdev *sd, + struct v4l2_dbg_register *reg) +{ + struct cx18 *cx = v4l2_get_subdevdata(sd); + + if (!cx18_av_dbg_match(®->match)) + return -EINVAL; + if ((reg->reg & 0x3) != 0) + return -EINVAL; + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; + reg->size = 4; + reg->val = cx18_av_read4(cx, reg->reg & 0x00000ffc); + return 0; +} + +static int cx18_av_s_register(struct v4l2_subdev *sd, + struct v4l2_dbg_register *reg) +{ + struct cx18 *cx = v4l2_get_subdevdata(sd); + + if (!cx18_av_dbg_match(®->match)) + return -EINVAL; + if ((reg->reg & 0x3) != 0) + return -EINVAL; + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; + cx18_av_write4(cx, reg->reg & 0x00000ffc, reg->val); + return 0; +} +#endif + +static const struct v4l2_subdev_core_ops cx18_av_general_ops = { + .g_chip_ident = cx18_av_g_chip_ident, + .log_status = cx18_av_log_status, + .init = cx18_av_init_hardware, + .reset = cx18_av_reset, + .queryctrl = cx18_av_queryctrl, + .g_ctrl = cx18_av_g_ctrl, + .s_ctrl = cx18_av_s_ctrl, +#ifdef CONFIG_VIDEO_ADV_DEBUG + .g_register = cx18_av_g_register, + .s_register = cx18_av_s_register, +#endif +}; + +static const struct v4l2_subdev_tuner_ops cx18_av_tuner_ops = { + .s_radio = cx18_av_s_radio, + .s_frequency = cx18_av_s_frequency, + .g_tuner = cx18_av_g_tuner, + .s_tuner = cx18_av_s_tuner, + .s_std = cx18_av_s_std, +}; + +static const struct v4l2_subdev_audio_ops cx18_av_audio_ops = { + .s_clock_freq = cx18_av_s_clock_freq, + .s_routing = cx18_av_s_audio_routing, +}; + +static const struct v4l2_subdev_video_ops cx18_av_video_ops = { + .s_routing = cx18_av_s_video_routing, + .decode_vbi_line = cx18_av_decode_vbi_line, + .s_stream = cx18_av_s_stream, + .g_fmt = cx18_av_g_fmt, + .s_fmt = cx18_av_s_fmt, +}; + +static const struct v4l2_subdev_ops cx18_av_ops = { + .core = &cx18_av_general_ops, + .tuner = &cx18_av_tuner_ops, + .audio = &cx18_av_audio_ops, + .video = &cx18_av_video_ops, +}; + +int cx18_av_init(struct cx18 *cx) +{ + struct v4l2_subdev *sd = &cx->av_state.sd; + + v4l2_subdev_init(sd, &cx18_av_ops); + v4l2_set_subdevdata(sd, cx); + snprintf(sd->name, sizeof(sd->name), + "%s-internal A/V decoder", cx->v4l2_dev.name); + sd->grp_id = CX18_HW_CX23418; + return v4l2_device_register_subdev(&cx->v4l2_dev, sd); +} + +void cx18_av_fini(struct cx18 *cx) +{ + v4l2_device_unregister_subdev(&cx->av_state.sd); +} diff --git a/drivers/media/video/cx18/cx18-av-core.h b/drivers/media/video/cx18/cx18-av-core.h index d83760cae540..025100aee4b8 100644 --- a/drivers/media/video/cx18/cx18-av-core.h +++ b/drivers/media/video/cx18/cx18-av-core.h @@ -25,6 +25,8 @@ #ifndef _CX18_AV_CORE_H_ #define _CX18_AV_CORE_H_ +#include + struct cx18; enum cx18_av_video_input { @@ -73,6 +75,7 @@ enum cx18_av_audio_input { }; struct cx18_av_state { + struct v4l2_subdev sd; int radio; v4l2_std_id std; enum cx18_av_video_input vid_input; @@ -315,6 +318,11 @@ struct cx18_av_state { #define CXADEC_SELECT_AUDIO_STANDARD_FM 0xF9 /* FM radio */ #define CXADEC_SELECT_AUDIO_STANDARD_AUTO 0xFF /* Auto detect */ +static inline struct cx18_av_state *to_cx18_av_state(struct v4l2_subdev *sd) +{ + return container_of(sd, struct cx18_av_state, sd); +} + /* ----------------------------------------------------------------------- */ /* cx18_av-core.c */ int cx18_av_write(struct cx18 *cx, u16 addr, u8 value); @@ -327,9 +335,12 @@ u8 cx18_av_read(struct cx18 *cx, u16 addr); u32 cx18_av_read4(struct cx18 *cx, u16 addr); int cx18_av_and_or(struct cx18 *cx, u16 addr, unsigned mask, u8 value); int cx18_av_and_or4(struct cx18 *cx, u16 addr, u32 mask, u32 value); -int cx18_av_cmd(struct cx18 *cx, unsigned int cmd, void *arg); void cx18_av_std_setup(struct cx18 *cx); +int cx18_av_cmd(struct cx18 *cx, int cmd, void *arg); /* FIXME - Remove */ +int cx18_av_init(struct cx18 *cx); +void cx18_av_fini(struct cx18 *cx); + /* ----------------------------------------------------------------------- */ /* cx18_av-firmware.c */ int cx18_av_loadfw(struct cx18 *cx); -- cgit v1.2.3 From 5811cf99df2e3c102055be3ea77508e56c9f77c6 Mon Sep 17 00:00:00 2001 From: Andy Walls Date: Sat, 14 Feb 2009 17:08:37 -0300 Subject: V4L/DVB (10756): cx18: Slim down instance handling, build names from v4l2_device.name Convert card instance handling to a lighter weight mechanism like ivtv. Also convert name strings and debug messages to use v4l2_device.name. Signed-off-by: Andy Walls Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx18/cx18-driver.c | 107 ++++++++++++-------------------- drivers/media/video/cx18/cx18-driver.h | 27 ++++---- drivers/media/video/cx18/cx18-fileops.c | 35 ++--------- drivers/media/video/cx18/cx18-i2c.c | 2 +- drivers/media/video/cx18/cx18-ioctl.c | 10 ++- drivers/media/video/cx18/cx18-streams.c | 9 +-- 6 files changed, 71 insertions(+), 119 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/cx18/cx18-driver.c b/drivers/media/video/cx18/cx18-driver.c index 2a45bbc757e8..f69e688ab6f4 100644 --- a/drivers/media/video/cx18/cx18-driver.c +++ b/drivers/media/video/cx18/cx18-driver.c @@ -39,10 +39,6 @@ #include - -/* var to keep track of the number of array elements in use */ -int cx18_cards_active; - /* If you have already X v4l cards, then set this to X. This way the device numbers stay matched. Example: you have a WinTV card without radio and a Compro H900 with. Normally this would give a @@ -50,12 +46,6 @@ int cx18_cards_active; setting this to 1 you ensure that radio0 is now also radio1. */ int cx18_first_minor; -/* Master variable for all cx18 info */ -struct cx18 *cx18_cards[CX18_MAX_CARDS]; - -/* Protects cx18_cards_active */ -DEFINE_SPINLOCK(cx18_cards_lock); - /* add your revision and whatnot here */ static struct pci_device_id cx18_pci_tbl[] __devinitdata = { {PCI_VENDOR_ID_CX, PCI_DEVICE_ID_CX23418, @@ -65,6 +55,8 @@ static struct pci_device_id cx18_pci_tbl[] __devinitdata = { MODULE_DEVICE_TABLE(pci, cx18_pci_tbl); +static atomic_t cx18_instance = ATOMIC_INIT(0); + /* Parameter declarations */ static int cardtype[CX18_MAX_CARDS]; static int tuner[CX18_MAX_CARDS] = { -1, -1, -1, -1, -1, -1, -1, -1, @@ -491,9 +483,9 @@ static void cx18_process_options(struct cx18 *cx) cx->stream_buf_size[i] *= 1024; /* convert from kB to bytes */ } - cx->options.cardtype = cardtype[cx->num]; - cx->options.tuner = tuner[cx->num]; - cx->options.radio = radio[cx->num]; + cx->options.cardtype = cardtype[cx->instance]; + cx->options.tuner = tuner[cx->instance]; + cx->options.radio = radio[cx->instance]; cx->std = cx18_parse_std(cx); if (cx->options.cardtype == -1) { @@ -550,7 +542,7 @@ done: } /* Precondition: the cx18 structure has been memset to 0. Only - the dev and num fields have been filled in. + the dev and instance fields have been filled in. No assumptions on the card type may be made here (see cx18_init_struct2 for that). */ @@ -567,7 +559,7 @@ static int __devinit cx18_init_struct1(struct cx18 *cx) mutex_init(&cx->epu2apu_mb_lock); mutex_init(&cx->epu2cpu_mb_lock); - cx->work_queue = create_singlethread_workqueue(cx->name); + cx->work_queue = create_singlethread_workqueue(cx->v4l2_dev.name); if (cx->work_queue == NULL) { CX18_ERR("Unable to create work hander thread\n"); return -ENOMEM; @@ -647,15 +639,16 @@ static int cx18_setup_pci(struct cx18 *cx, struct pci_dev *pci_dev, CX18_DEBUG_INFO("Enabling pci device\n"); if (pci_enable_device(pci_dev)) { - CX18_ERR("Can't enable device %d!\n", cx->num); + CX18_ERR("Can't enable device %d!\n", cx->instance); return -EIO; } if (pci_set_dma_mask(pci_dev, 0xffffffff)) { - CX18_ERR("No suitable DMA available on card %d.\n", cx->num); + CX18_ERR("No suitable DMA available, card %d\n", cx->instance); return -EIO; } if (!request_mem_region(cx->base_addr, CX18_MEM_SIZE, "cx18 encoder")) { - CX18_ERR("Cannot request encoder memory region on card %d.\n", cx->num); + CX18_ERR("Cannot request encoder memory region, card %d\n", + cx->instance); return -EIO; } @@ -741,44 +734,42 @@ static int __devinit cx18_probe(struct pci_dev *pci_dev, u32 devtype; struct cx18 *cx; - spin_lock(&cx18_cards_lock); - - /* Make sure we've got a place for this card */ - if (cx18_cards_active == CX18_MAX_CARDS) { - printk(KERN_ERR "cx18: Maximum number of cards detected (%d).\n", - cx18_cards_active); - spin_unlock(&cx18_cards_lock); + /* FIXME - module parameter arrays constrain max instances */ + i = atomic_inc_return(&cx18_instance) - 1; + if (i >= CX18_MAX_CARDS) { + printk(KERN_ERR "cx18: cannot manage card %d, driver has a " + "limit of 0 - %d\n", i, CX18_MAX_CARDS - 1); return -ENOMEM; } cx = kzalloc(sizeof(struct cx18), GFP_ATOMIC); - if (!cx) { - spin_unlock(&cx18_cards_lock); + if (cx == NULL) { + printk(KERN_ERR "cx18: cannot manage card %d, out of memory\n", + i); return -ENOMEM; } - cx18_cards[cx18_cards_active] = cx; - cx->num = cx18_cards_active++; - snprintf(cx->name, sizeof(cx->name), "cx18-%d", cx->num); - CX18_INFO("Initializing card #%d\n", cx->num); - - spin_unlock(&cx18_cards_lock); - cx->pci_dev = pci_dev; + cx->instance = i; + retval = v4l2_device_register(&pci_dev->dev, &cx->v4l2_dev); if (retval) { - CX18_ERR("Call to v4l2_device_register() failed\n"); - goto err; + printk(KERN_ERR "cx18: v4l2_device_register of card %d failed" + "\n", cx->instance); + kfree(cx); + return retval; } - CX18_DEBUG_INFO("registered v4l2_device name: %s\n", cx->v4l2_dev.name); + snprintf(cx->v4l2_dev.name, sizeof(cx->v4l2_dev.name), "cx18-%d", + cx->instance); + CX18_INFO("Initializing card %d\n", cx->instance); cx18_process_options(cx); if (cx->options.cardtype == -1) { retval = -ENODEV; - goto unregister_v4l2; + goto err; } if (cx18_init_struct1(cx)) { retval = -ENOMEM; - goto unregister_v4l2; + goto err; } CX18_DEBUG_INFO("base addr: 0x%08x\n", cx->base_addr); @@ -829,8 +820,6 @@ static int __devinit cx18_probe(struct pci_dev *pci_dev, goto free_map; } - CX18_DEBUG_INFO("Active card count: %d.\n", cx18_cards_active); - if (cx->card->hw_all & CX18_HW_TVEEPROM) { /* Based on the model number the cardtype may be changed. The PCI IDs are not always reliable. */ @@ -847,7 +836,8 @@ static int __devinit cx18_probe(struct pci_dev *pci_dev, /* Register IRQ */ retval = request_irq(cx->pci_dev->irq, cx18_irq_handler, - IRQF_SHARED | IRQF_DISABLED, cx->name, (void *)cx); + IRQF_SHARED | IRQF_DISABLED, + cx->v4l2_dev.name, (void *)cx); if (retval) { CX18_ERR("Failed to register irq %d\n", retval); goto free_i2c; @@ -933,8 +923,7 @@ static int __devinit cx18_probe(struct pci_dev *pci_dev, goto free_streams; } - CX18_INFO("Initialized card #%d: %s\n", cx->num, cx->card_name); - + CX18_INFO("Initialized card: %s\n", cx->card_name); return 0; free_streams: @@ -949,18 +938,13 @@ free_mem: release_mem_region(cx->base_addr, CX18_MEM_SIZE); free_workqueue: destroy_workqueue(cx->work_queue); -unregister_v4l2: - v4l2_device_unregister(&cx->v4l2_dev); err: if (retval == 0) retval = -ENODEV; CX18_ERR("Error %d on initialization\n", retval); - i = cx->num; - spin_lock(&cx18_cards_lock); - kfree(cx18_cards[i]); - cx18_cards[i] = NULL; - spin_unlock(&cx18_cards_lock); + v4l2_device_unregister(&cx->v4l2_dev); + kfree(cx); return retval; } @@ -1069,9 +1053,9 @@ static void cx18_cancel_epu_work_orders(struct cx18 *cx) static void cx18_remove(struct pci_dev *pci_dev) { struct v4l2_device *v4l2_dev = pci_get_drvdata(pci_dev); - struct cx18 *cx = container_of(v4l2_dev, struct cx18, v4l2_dev); + struct cx18 *cx = to_cx18(v4l2_dev); - CX18_DEBUG_INFO("Removing Card #%d\n", cx->num); + CX18_DEBUG_INFO("Removing Card\n"); /* Stop all captures */ CX18_DEBUG_INFO("Stopping all streams\n"); @@ -1099,10 +1083,12 @@ static void cx18_remove(struct pci_dev *pci_dev) release_mem_region(cx->base_addr, CX18_MEM_SIZE); pci_disable_device(cx->pci_dev); + /* FIXME - we leak cx->vbi.sliced_mpeg_data[i] allocations */ - v4l2_device_unregister(v4l2_dev); + CX18_INFO("Removed %s\n", cx->card_name); - CX18_INFO("Removed %s, card #%d\n", cx->card_name, cx->num); + v4l2_device_unregister(v4l2_dev); + kfree(cx); } /* define a pci_driver for card detection */ @@ -1117,8 +1103,6 @@ static int module_start(void) { printk(KERN_INFO "cx18: Start initialization, version %s\n", CX18_VERSION); - memset(cx18_cards, 0, sizeof(cx18_cards)); - /* Validate parameters */ if (cx18_first_minor < 0 || cx18_first_minor >= CX18_MAX_CARDS) { printk(KERN_ERR "cx18: Exiting, cx18_first_minor must be between 0 and %d\n", @@ -1141,16 +1125,7 @@ static int module_start(void) static void module_cleanup(void) { - int i; - pci_unregister_driver(&cx18_pci_driver); - - for (i = 0; i < cx18_cards_active; i++) { - if (cx18_cards[i] == NULL) - continue; - kfree(cx18_cards[i]); - } - } module_init(module_start); diff --git a/drivers/media/video/cx18/cx18-driver.h b/drivers/media/video/cx18/cx18-driver.h index 7fc914c521f7..def82bd1078a 100644 --- a/drivers/media/video/cx18/cx18-driver.h +++ b/drivers/media/video/cx18/cx18-driver.h @@ -144,12 +144,12 @@ /* Flag to turn on high volume debugging */ #define CX18_DBGFLG_HIGHVOL (1 << 8) -/* NOTE: extra space before comma in 'cx->num , ## args' is required for +/* NOTE: extra space before comma in 'fmt , ## args' is required for gcc-2.95, otherwise it won't compile. */ #define CX18_DEBUG(x, type, fmt, args...) \ do { \ if ((x) & cx18_debug) \ - printk(KERN_INFO "cx18-%d " type ": " fmt, cx->num , ## args); \ + v4l2_info(&cx->v4l2_dev, " " type ": " fmt , ## args); \ } while (0) #define CX18_DEBUG_WARN(fmt, args...) CX18_DEBUG(CX18_DBGFLG_WARN, "warning", fmt , ## args) #define CX18_DEBUG_INFO(fmt, args...) CX18_DEBUG(CX18_DBGFLG_INFO, "info", fmt , ## args) @@ -163,7 +163,7 @@ #define CX18_DEBUG_HIGH_VOL(x, type, fmt, args...) \ do { \ if (((x) & cx18_debug) && (cx18_debug & CX18_DBGFLG_HIGHVOL)) \ - printk(KERN_INFO "cx18%d " type ": " fmt, cx->num , ## args); \ + v4l2_info(&cx->v4l2_dev, " " type ": " fmt , ## args); \ } while (0) #define CX18_DEBUG_HI_WARN(fmt, args...) CX18_DEBUG_HIGH_VOL(CX18_DBGFLG_WARN, "warning", fmt , ## args) #define CX18_DEBUG_HI_INFO(fmt, args...) CX18_DEBUG_HIGH_VOL(CX18_DBGFLG_INFO, "info", fmt , ## args) @@ -175,9 +175,9 @@ #define CX18_DEBUG_HI_IRQ(fmt, args...) CX18_DEBUG_HIGH_VOL(CX18_DBGFLG_IRQ, "irq", fmt , ## args) /* Standard kernel messages */ -#define CX18_ERR(fmt, args...) printk(KERN_ERR "cx18-%d: " fmt, cx->num , ## args) -#define CX18_WARN(fmt, args...) printk(KERN_WARNING "cx18-%d: " fmt, cx->num , ## args) -#define CX18_INFO(fmt, args...) printk(KERN_INFO "cx18-%d: " fmt, cx->num , ## args) +#define CX18_ERR(fmt, args...) v4l2_err(&cx->v4l2_dev, fmt , ## args) +#define CX18_WARN(fmt, args...) v4l2_warn(&cx->v4l2_dev, fmt , ## args) +#define CX18_INFO(fmt, args...) v4l2_info(&cx->v4l2_dev, fmt , ## args) /* Values for CX18_API_DEC_PLAYBACK_SPEED mpeg_frame_type_mask parameter: */ #define MPEG_FRAME_TYPE_IFRAME 1 @@ -445,8 +445,7 @@ struct cx18_i2c_algo_callback_data { /* Struct to hold info about cx18 cards */ struct cx18 { - int num; /* board number, -1 during init! */ - char name[8]; /* board name for printk and interrupts (e.g. 'cx180') */ + int instance; struct pci_dev *pci_dev; struct v4l2_device v4l2_dev; @@ -455,8 +454,8 @@ struct cx18 { const struct cx18_card_tuner_i2c *card_i2c; /* i2c addresses to probe for tuner */ u8 is_50hz; u8 is_60hz; - u8 is_out_50hz; - u8 is_out_60hz; + u8 is_out_50hz; /* FIXME - remove, we don't have an output decoder */ + u8 is_out_60hz; /* FIXME - remove, we don't have an output decoder */ u8 nof_inputs; /* number of video inputs */ u8 nof_audio_inputs; /* number of audio inputs */ u16 buffer_id; /* buffer ID counter */ @@ -547,11 +546,13 @@ struct cx18 { v4l2_std_id tuner_std; /* The norm of the tuner (fixed) */ }; +static inline struct cx18 *to_cx18(struct v4l2_device *v4l2_dev) +{ + return container_of(v4l2_dev, struct cx18, v4l2_dev); +} + /* Globals */ -extern struct cx18 *cx18_cards[]; -extern int cx18_cards_active; extern int cx18_first_minor; -extern spinlock_t cx18_cards_lock; /*==============Prototypes==================*/ diff --git a/drivers/media/video/cx18/cx18-fileops.c b/drivers/media/video/cx18/cx18-fileops.c index 68dd50ac4bfe..757982ea3766 100644 --- a/drivers/media/video/cx18/cx18-fileops.c +++ b/drivers/media/video/cx18/cx18-fileops.c @@ -682,38 +682,15 @@ static int cx18_serialized_open(struct cx18_stream *s, struct file *filp) int cx18_v4l2_open(struct file *filp) { - int res, x, y = 0; - struct cx18 *cx = NULL; - struct cx18_stream *s = NULL; - int minor = video_devdata(filp)->minor; - - /* Find which card this open was on */ - spin_lock(&cx18_cards_lock); - for (x = 0; cx == NULL && x < cx18_cards_active; x++) { - /* find out which stream this open was on */ - for (y = 0; y < CX18_MAX_STREAMS; y++) { - if (cx18_cards[x] == NULL) - continue; - s = &cx18_cards[x]->streams[y]; - if (s->video_dev && s->video_dev->minor == minor) { - cx = cx18_cards[x]; - break; - } - } - } - spin_unlock(&cx18_cards_lock); - - if (cx == NULL) { - /* Couldn't find a device registered - on that minor, shouldn't happen! */ - printk(KERN_WARNING "No cx18 device found on minor %d\n", - minor); - return -ENXIO; - } + int res; + struct video_device *video_dev = video_devdata(filp); + struct cx18_stream *s = video_get_drvdata(video_dev); + struct cx18 *cx = s->cx;; mutex_lock(&cx->serialize_lock); if (cx18_init_on_first_open(cx)) { - CX18_ERR("Failed to initialize on minor %d\n", minor); + CX18_ERR("Failed to initialize on minor %d\n", + video_dev->minor); mutex_unlock(&cx->serialize_lock); return -ENXIO; } diff --git a/drivers/media/video/cx18/cx18-i2c.c b/drivers/media/video/cx18/cx18-i2c.c index 200d9257a926..db2c3e6997d0 100644 --- a/drivers/media/video/cx18/cx18-i2c.c +++ b/drivers/media/video/cx18/cx18-i2c.c @@ -358,7 +358,7 @@ int init_cx18_i2c(struct cx18 *cx) cx->i2c_adap[i].algo_data = &cx->i2c_algo[i]; sprintf(cx->i2c_adap[i].name + strlen(cx->i2c_adap[i].name), - " #%d-%d", cx->num, i); + " #%d-%d", cx->instance, i); i2c_set_adapdata(&cx->i2c_adap[i], cx); memcpy(&cx->i2c_client[i], &cx18_i2c_client_template, diff --git a/drivers/media/video/cx18/cx18-ioctl.c b/drivers/media/video/cx18/cx18-ioctl.c index 5c8e9cb244f9..3277b3d3ceae 100644 --- a/drivers/media/video/cx18/cx18-ioctl.c +++ b/drivers/media/video/cx18/cx18-ioctl.c @@ -387,20 +387,17 @@ static int cx18_g_chip_ident(struct file *file, void *fh, static int cx18_cxc(struct cx18 *cx, unsigned int cmd, void *arg) { struct v4l2_dbg_register *regs = arg; - unsigned long flags; if (!capable(CAP_SYS_ADMIN)) return -EPERM; if (regs->reg >= CX18_MEM_OFFSET + CX18_MEM_SIZE) return -EINVAL; - spin_lock_irqsave(&cx18_cards_lock, flags); regs->size = 4; if (cmd == VIDIOC_DBG_G_REGISTER) regs->val = cx18_read_enc(cx, regs->reg); else cx18_write_enc(cx, regs->val, regs->reg); - spin_unlock_irqrestore(&cx18_cards_lock, flags); return 0; } @@ -847,7 +844,7 @@ static int cx18_log_status(struct file *file, void *fh) int i; CX18_INFO("================= START STATUS CARD #%d " - "=================\n", cx->num); + "=================\n", cx->instance); CX18_INFO("Version: %s Card: %s\n", CX18_VERSION, cx->card_name); if (cx->hw_flags & CX18_HW_TVEEPROM) { struct tveeprom tv; @@ -865,7 +862,7 @@ static int cx18_log_status(struct file *file, void *fh) mutex_unlock(&cx->gpio_lock); CX18_INFO("Tuner: %s\n", test_bit(CX18_F_I_RADIO_USER, &cx->i_flags) ? "Radio" : "TV"); - cx2341x_log_status(&cx->params, cx->name); + cx2341x_log_status(&cx->params, cx->v4l2_dev.name); CX18_INFO("Status flags: 0x%08lx\n", cx->i_flags); for (i = 0; i < CX18_MAX_STREAMS; i++) { struct cx18_stream *s = &cx->streams[i]; @@ -880,7 +877,8 @@ static int cx18_log_status(struct file *file, void *fh) CX18_INFO("Read MPEG/VBI: %lld/%lld bytes\n", (long long)cx->mpg_data_received, (long long)cx->vbi_data_inserted); - CX18_INFO("================== END STATUS CARD #%d ==================\n", cx->num); + CX18_INFO("================== END STATUS CARD #%d " + "==================\n", cx->instance); return 0; } diff --git a/drivers/media/video/cx18/cx18-streams.c b/drivers/media/video/cx18/cx18-streams.c index 778aa0c0f9b5..eff4a14d0152 100644 --- a/drivers/media/video/cx18/cx18-streams.c +++ b/drivers/media/video/cx18/cx18-streams.c @@ -130,7 +130,7 @@ static int cx18_prep_dev(struct cx18 *cx, int type) struct cx18_stream *s = &cx->streams[type]; u32 cap = cx->v4l2_cap; int num_offset = cx18_stream_info[type].num_offset; - int num = cx->num + cx18_first_minor + num_offset; + int num = cx->instance + cx18_first_minor + num_offset; /* These four fields are always initialized. If video_dev == NULL, then this stream is not in use. In that case no other fields but these @@ -170,11 +170,11 @@ static int cx18_prep_dev(struct cx18 *cx, int type) return -ENOMEM; } - snprintf(s->video_dev->name, sizeof(s->video_dev->name), "cx18-%d", - cx->num); + snprintf(s->video_dev->name, sizeof(s->video_dev->name), "%s %s", + cx->v4l2_dev.name, s->name); s->video_dev->num = num; - s->video_dev->parent = &cx->pci_dev->dev; + s->video_dev->v4l2_dev = &cx->v4l2_dev; s->video_dev->fops = &cx18_v4l2_enc_fops; s->video_dev->release = video_device_release; s->video_dev->tvnorms = V4L2_STD_ALL; @@ -239,6 +239,7 @@ static int cx18_reg_dev(struct cx18 *cx, int type) num = s_mpg->video_dev->num + cx18_stream_info[type].num_offset; } + video_set_drvdata(s->video_dev, s); /* Register device. First try the desired minor, then any free one. */ ret = video_register_device(s->video_dev, vfl_type, num); -- cgit v1.2.3 From fa3e70360c86480acbaa54c9791e843196327a66 Mon Sep 17 00:00:00 2001 From: Andy Walls Date: Mon, 16 Feb 2009 02:23:25 -0300 Subject: V4L/DVB (10757): cx18, v4l2-chip-ident: Finish conversion of AV decoder core to v4l2_subdev Added a new chip identifer to v4l2-chip-ident for the integrated A/V broadcast decoder core internal to the CX23418. Completed separation and encapsulation of the A/V decoder core interface as a v4l2_subdevice. The cx18 driver now compiles and links again. Signed-off-by: Andy Walls Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx18/cx18-av-core.c | 85 +++++++++++++++++++++++--------- drivers/media/video/cx18/cx18-av-core.h | 10 ++-- drivers/media/video/cx18/cx18-controls.c | 8 +-- drivers/media/video/cx18/cx18-driver.c | 18 ++++--- drivers/media/video/cx18/cx18-driver.h | 1 + drivers/media/video/cx18/cx18-firmware.c | 18 ------- drivers/media/video/cx18/cx18-i2c.c | 4 +- drivers/media/video/cx18/cx18-ioctl.c | 14 +++--- drivers/media/video/cx18/cx18-streams.c | 2 +- drivers/media/video/cx18/cx18-vbi.c | 2 +- drivers/media/video/cx18/cx18-video.c | 2 +- include/media/v4l2-chip-ident.h | 3 +- 12 files changed, 100 insertions(+), 67 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/cx18/cx18-av-core.c b/drivers/media/video/cx18/cx18-av-core.c index 9b30f77b5205..f9bb77a25ee9 100644 --- a/drivers/media/video/cx18/cx18-av-core.c +++ b/drivers/media/video/cx18/cx18-av-core.c @@ -201,15 +201,45 @@ static int cx18_av_reset(struct v4l2_subdev *sd, u32 val) return 0; } -static int cx18_av_init_hardware(struct v4l2_subdev *sd, u32 val) +static int cx18_av_init(struct v4l2_subdev *sd, u32 val) { struct cx18_av_state *state = to_cx18_av_state(sd); struct cx18 *cx = v4l2_get_subdevdata(sd); - if (!state->is_initialized) { - /* initialize on first use */ - state->is_initialized = 1; - cx18_av_initialize(cx); + switch (val) { + case CX18_AV_INIT_PLLS: + /* + * The crystal freq used in calculations in this driver will be + * 28.636360 MHz. + * Aim to run the PLLs' VCOs near 400 MHz to minimze errors. + */ + + /* + * VDCLK Integer = 0x0f, Post Divider = 0x04 + * AIMCLK Integer = 0x0e, Post Divider = 0x16 + */ + cx18_av_write4(cx, CXADEC_PLL_CTRL1, 0x160e040f); + + /* VDCLK Fraction = 0x2be2fe */ + /* xtal * 0xf.15f17f0/4 = 108 MHz: 432 MHz before post divide */ + cx18_av_write4(cx, CXADEC_VID_PLL_FRAC, 0x002be2fe); + + /* AIMCLK Fraction = 0x05227ad */ + /* xtal * 0xe.2913d68/0x16 = 48000 * 384: 406 MHz pre post-div*/ + cx18_av_write4(cx, CXADEC_AUX_PLL_FRAC, 0x005227ad); + + /* SA_MCLK_SEL=1, SA_MCLK_DIV=0x16 */ + cx18_av_write(cx, CXADEC_I2S_MCLK, 0x56); + break; + + case CX18_AV_INIT_NORMAL: + default: + if (!state->is_initialized) { + /* initialize on first use */ + state->is_initialized = 1; + cx18_av_initialize(cx); + } + break; } return 0; } @@ -1095,14 +1125,11 @@ static inline int cx18_av_dbg_match(const struct v4l2_dbg_match *match) static int cx18_av_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip) { + struct cx18_av_state *state = to_cx18_av_state(sd); + if (cx18_av_dbg_match(&chip->match)) { - /* - * Nothing else is going to claim to be this combination, - * and the real host chip revision will be returned by a host - * match on address 0. - */ - chip->ident = V4L2_IDENT_CX25843; - chip->revision = V4L2_IDENT_CX23418; /* Why not */ + chip->ident = state->id; + chip->revision = state->rev; } return 0; } @@ -1143,7 +1170,7 @@ static int cx18_av_s_register(struct v4l2_subdev *sd, static const struct v4l2_subdev_core_ops cx18_av_general_ops = { .g_chip_ident = cx18_av_g_chip_ident, .log_status = cx18_av_log_status, - .init = cx18_av_init_hardware, + .init = cx18_av_init, .reset = cx18_av_reset, .queryctrl = cx18_av_queryctrl, .g_ctrl = cx18_av_g_ctrl, @@ -1182,19 +1209,31 @@ static const struct v4l2_subdev_ops cx18_av_ops = { .video = &cx18_av_video_ops, }; -int cx18_av_init(struct cx18 *cx) +int cx18_av_probe(struct cx18 *cx, struct v4l2_subdev **sd) { - struct v4l2_subdev *sd = &cx->av_state.sd; - - v4l2_subdev_init(sd, &cx18_av_ops); - v4l2_set_subdevdata(sd, cx); - snprintf(sd->name, sizeof(sd->name), - "%s-internal A/V decoder", cx->v4l2_dev.name); - sd->grp_id = CX18_HW_CX23418; - return v4l2_device_register_subdev(&cx->v4l2_dev, sd); + struct cx18_av_state *state = &cx->av_state; + + state->rev = cx18_av_read4(cx, CXADEC_CHIP_CTRL) & 0xffff; + state->id = ((state->rev >> 4) == CXADEC_CHIP_TYPE_MAKO) + ? V4L2_IDENT_CX23418_843 : V4L2_IDENT_UNKNOWN; + + state->vid_input = CX18_AV_COMPOSITE7; + state->aud_input = CX18_AV_AUDIO8; + state->audclk_freq = 48000; + state->audmode = V4L2_TUNER_MODE_LANG1; + state->slicer_line_delay = 0; + state->slicer_line_offset = (10 + state->slicer_line_delay - 2); + + *sd = &state->sd; + v4l2_subdev_init(*sd, &cx18_av_ops); + v4l2_set_subdevdata(*sd, cx); + snprintf((*sd)->name, sizeof((*sd)->name), + "%s internal A/V decoder", cx->v4l2_dev.name); + (*sd)->grp_id = CX18_HW_CX23418; + return v4l2_device_register_subdev(&cx->v4l2_dev, *sd); } -void cx18_av_fini(struct cx18 *cx) +void cx18_av_exit(struct cx18 *cx, struct v4l2_subdev *sd) { v4l2_device_unregister_subdev(&cx->av_state.sd); } diff --git a/drivers/media/video/cx18/cx18-av-core.h b/drivers/media/video/cx18/cx18-av-core.h index 025100aee4b8..90bdca960292 100644 --- a/drivers/media/video/cx18/cx18-av-core.h +++ b/drivers/media/video/cx18/cx18-av-core.h @@ -323,6 +323,11 @@ static inline struct cx18_av_state *to_cx18_av_state(struct v4l2_subdev *sd) return container_of(sd, struct cx18_av_state, sd); } +enum cx18_av_subdev_init_arg { + CX18_AV_INIT_NORMAL = 0, + CX18_AV_INIT_PLLS = 1, +}; + /* ----------------------------------------------------------------------- */ /* cx18_av-core.c */ int cx18_av_write(struct cx18 *cx, u16 addr, u8 value); @@ -337,9 +342,8 @@ int cx18_av_and_or(struct cx18 *cx, u16 addr, unsigned mask, u8 value); int cx18_av_and_or4(struct cx18 *cx, u16 addr, u32 mask, u32 value); void cx18_av_std_setup(struct cx18 *cx); -int cx18_av_cmd(struct cx18 *cx, int cmd, void *arg); /* FIXME - Remove */ -int cx18_av_init(struct cx18 *cx); -void cx18_av_fini(struct cx18 *cx); +int cx18_av_probe(struct cx18 *cx, struct v4l2_subdev **sd); +void cx18_av_exit(struct cx18 *cx, struct v4l2_subdev *sd); /* ----------------------------------------------------------------------- */ /* cx18_av-firmware.c */ diff --git a/drivers/media/video/cx18/cx18-controls.c b/drivers/media/video/cx18/cx18-controls.c index 10a4e07b7aca..9505c417371d 100644 --- a/drivers/media/video/cx18/cx18-controls.c +++ b/drivers/media/video/cx18/cx18-controls.c @@ -67,7 +67,7 @@ int cx18_queryctrl(struct file *file, void *fh, struct v4l2_queryctrl *qctrl) case V4L2_CID_HUE: case V4L2_CID_SATURATION: case V4L2_CID_CONTRAST: - if (cx18_av_cmd(cx, VIDIOC_QUERYCTRL, qctrl)) + if (v4l2_subdev_call(cx->sd_av, core, queryctrl, qctrl)) qctrl->flags |= V4L2_CTRL_FLAG_DISABLED; return 0; @@ -126,7 +126,7 @@ static int cx18_s_ctrl(struct cx18 *cx, struct v4l2_control *vctrl) case V4L2_CID_HUE: case V4L2_CID_SATURATION: case V4L2_CID_CONTRAST: - return cx18_av_cmd(cx, VIDIOC_S_CTRL, vctrl); + return v4l2_subdev_call(cx->sd_av, core, s_ctrl, vctrl); case V4L2_CID_AUDIO_VOLUME: case V4L2_CID_AUDIO_MUTE: @@ -151,7 +151,7 @@ static int cx18_g_ctrl(struct cx18 *cx, struct v4l2_control *vctrl) case V4L2_CID_HUE: case V4L2_CID_SATURATION: case V4L2_CID_CONTRAST: - return cx18_av_cmd(cx, VIDIOC_G_CTRL, vctrl); + return v4l2_subdev_call(cx->sd_av, core, g_ctrl, vctrl); case V4L2_CID_AUDIO_VOLUME: case V4L2_CID_AUDIO_MUTE: @@ -278,7 +278,7 @@ int cx18_s_ext_ctrls(struct file *file, void *fh, struct v4l2_ext_controls *c) fmt.fmt.pix.width = cx->params.width / (is_mpeg1 ? 2 : 1); fmt.fmt.pix.height = cx->params.height; - cx18_av_cmd(cx, VIDIOC_S_FMT, &fmt); + v4l2_subdev_call(cx->sd_av, video, s_fmt, &fmt); } priv.cx = cx; priv.s = &cx->streams[id->type]; diff --git a/drivers/media/video/cx18/cx18-driver.c b/drivers/media/video/cx18/cx18-driver.c index f69e688ab6f4..f5a41dd663dc 100644 --- a/drivers/media/video/cx18/cx18-driver.c +++ b/drivers/media/video/cx18/cx18-driver.c @@ -621,13 +621,6 @@ static void __devinit cx18_init_struct2(struct cx18 *cx) i = 0; cx->active_input = i; cx->audio_input = cx->card->video_inputs[i].audio_index; - cx->av_state.vid_input = CX18_AV_COMPOSITE7; - cx->av_state.aud_input = CX18_AV_AUDIO8; - cx->av_state.audclk_freq = 48000; - cx->av_state.audmode = V4L2_TUNER_MODE_LANG1; - cx->av_state.slicer_line_delay = 0; - cx->av_state.slicer_line_offset = - (10 + cx->av_state.slicer_line_delay - 2); } static int cx18_setup_pci(struct cx18 *cx, struct pci_dev *pci_dev, @@ -812,6 +805,14 @@ static int __devinit cx18_probe(struct pci_dev *pci_dev, cx18_gpio_init(cx); + retval = cx18_av_probe(cx, &cx->sd_av); + if (retval) { + CX18_ERR("Could not register A/V decoder subdevice\n"); + goto free_map; + } + /* Initialize the A/V decoder PLLs to sane defaults */ + v4l2_subdev_call(cx->sd_av, core, init, (u32) CX18_AV_INIT_PLLS); + /* active i2c */ CX18_DEBUG_INFO("activating i2c...\n"); retval = init_cx18_i2c(cx); @@ -1020,6 +1021,9 @@ int cx18_init_on_first_open(struct cx18 *cx) cx18_vapi(cx, CX18_APU_RESETAI, 0); cx18_vapi(cx, CX18_APU_STOP, 1, CX18_APU_ENCODING_METHOD_MPEG); + /* Init the A/V decoder, if it hasn't been already */ + v4l2_subdev_call(cx->sd_av, core, init, (u32) CX18_AV_INIT_NORMAL); + vf.tuner = 0; vf.type = V4L2_TUNER_ANALOG_TV; vf.frequency = 6400; /* the tuner 'baseline' frequency */ diff --git a/drivers/media/video/cx18/cx18-driver.h b/drivers/media/video/cx18/cx18-driver.h index def82bd1078a..4b50878fc265 100644 --- a/drivers/media/video/cx18/cx18-driver.h +++ b/drivers/media/video/cx18/cx18-driver.h @@ -448,6 +448,7 @@ struct cx18 { int instance; struct pci_dev *pci_dev; struct v4l2_device v4l2_dev; + struct v4l2_subdev *sd_av; const struct cx18_card *card; /* card information */ const char *card_name; /* full name of the card */ diff --git a/drivers/media/video/cx18/cx18-firmware.c b/drivers/media/video/cx18/cx18-firmware.c index aa89bee65af0..83cd559cc609 100644 --- a/drivers/media/video/cx18/cx18-firmware.c +++ b/drivers/media/video/cx18/cx18-firmware.c @@ -26,7 +26,6 @@ #include "cx18-irq.h" #include "cx18-firmware.h" #include "cx18-cards.h" -#include "cx18-av-core.h" #include #define CX18_PROC_SOFT_RESET 0xc70010 @@ -286,23 +285,6 @@ void cx18_init_power(struct cx18 *cx, int lowpwr) cx18_write_reg(cx, 0x2BE2FE, CX18_MPEG_CLOCK_PLL_FRAC); cx18_write_reg(cx, 8, CX18_MPEG_CLOCK_PLL_POST); - /* - * VDCLK Integer = 0x0f, Post Divider = 0x04 - * AIMCLK Integer = 0x0e, Post Divider = 0x16 - */ - cx18_av_write4(cx, CXADEC_PLL_CTRL1, 0x160e040f); - - /* VDCLK Fraction = 0x2be2fe */ - /* xtal * 0xf.15f17f0/4 = 108 MHz: 432 MHz before post divide */ - cx18_av_write4(cx, CXADEC_VID_PLL_FRAC, 0x002be2fe); - - /* AIMCLK Fraction = 0x05227ad */ - /* xtal * 0xe.2913d68/0x16 = 48000 * 384: 406 MHz before post-divide */ - cx18_av_write4(cx, CXADEC_AUX_PLL_FRAC, 0x005227ad); - - /* SA_MCLK_SEL=1, SA_MCLK_DIV=0x16 */ - cx18_av_write(cx, CXADEC_I2S_MCLK, 0x56); - /* Defaults */ /* APU = SC or SC/2 = 125/62.5 */ /* EPU = SC = 125 */ diff --git a/drivers/media/video/cx18/cx18-i2c.c b/drivers/media/video/cx18/cx18-i2c.c index db2c3e6997d0..db7b55281f50 100644 --- a/drivers/media/video/cx18/cx18-i2c.c +++ b/drivers/media/video/cx18/cx18-i2c.c @@ -304,7 +304,7 @@ int cx18_i2c_hw(struct cx18 *cx, u32 hw, unsigned int cmd, void *arg) return cx18_gpio(cx, cmd, arg); if (hw == CX18_HW_CX23418) - return cx18_av_cmd(cx, cmd, arg); + return v4l2_subdev_command(cx->sd_av, cmd, arg); addr = cx18_i2c_hw_addr(cx, hw); if (addr < 0) { @@ -322,7 +322,7 @@ void cx18_call_i2c_clients(struct cx18 *cx, unsigned int cmd, void *arg) CX18_ERR("adapter is not set\n"); return; } - cx18_av_cmd(cx, cmd, arg); + v4l2_subdev_command(cx->sd_av, cmd, arg); i2c_clients_command(&cx->i2c_adap[0], cmd, arg); i2c_clients_command(&cx->i2c_adap[1], cmd, arg); if (cx->hw_flags & CX18_HW_GPIO) diff --git a/drivers/media/video/cx18/cx18-ioctl.c b/drivers/media/video/cx18/cx18-ioctl.c index 3277b3d3ceae..0ddf4dd55308 100644 --- a/drivers/media/video/cx18/cx18-ioctl.c +++ b/drivers/media/video/cx18/cx18-ioctl.c @@ -208,7 +208,7 @@ static int cx18_g_fmt_sliced_vbi_cap(struct file *file, void *fh, * digitizer/slicer. Note, cx18_av_vbi() wipes the passed in * fmt->fmt.sliced under valid calling conditions */ - if (cx18_av_cmd(cx, VIDIOC_G_FMT, fmt)) + if (v4l2_subdev_call(cx->sd_av, video, g_fmt, fmt)) return -EINVAL; /* Ensure V4L2 spec compliant output */ @@ -295,7 +295,7 @@ static int cx18_s_fmt_vid_cap(struct file *file, void *fh, cx->params.width = w; cx->params.height = h; - cx18_av_cmd(cx, VIDIOC_S_FMT, fmt); + v4l2_subdev_call(cx->sd_av, video, s_fmt, fmt); return cx18_g_fmt_vid_cap(file, fh, fmt); } @@ -322,7 +322,7 @@ static int cx18_s_fmt_vbi_cap(struct file *file, void *fh, * Note cx18_av_vbi_wipes out alot of the passed in fmt under valid * calling conditions */ - ret = cx18_av_cmd(cx, VIDIOC_S_FMT, fmt); + ret = v4l2_subdev_call(cx->sd_av, video, s_fmt, fmt); if (ret) return ret; @@ -359,7 +359,7 @@ static int cx18_s_fmt_sliced_vbi_cap(struct file *file, void *fh, * Note, cx18_av_vbi() wipes some "impossible" service lines in the * passed in fmt->fmt.sliced under valid calling conditions */ - ret = cx18_av_cmd(cx, VIDIOC_S_FMT, fmt); + ret = v4l2_subdev_call(cx->sd_av, video, s_fmt, fmt); if (ret) return ret; /* Store our current v4l2 sliced VBI settings */ @@ -516,7 +516,8 @@ static int cx18_s_crop(struct file *file, void *fh, struct v4l2_crop *crop) if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) return -EINVAL; - return cx18_av_cmd(cx, VIDIOC_S_CROP, crop); + CX18_DEBUG_WARN("VIDIOC_S_CROP not implemented\n"); + return -EINVAL; } static int cx18_g_crop(struct file *file, void *fh, struct v4l2_crop *crop) @@ -525,7 +526,8 @@ static int cx18_g_crop(struct file *file, void *fh, struct v4l2_crop *crop) if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) return -EINVAL; - return cx18_av_cmd(cx, VIDIOC_G_CROP, crop); + CX18_DEBUG_WARN("VIDIOC_G_CROP not implemented\n"); + return -EINVAL; } static int cx18_enum_fmt_vid_cap(struct file *file, void *fh, diff --git a/drivers/media/video/cx18/cx18-streams.c b/drivers/media/video/cx18/cx18-streams.c index eff4a14d0152..1d17884b3b0d 100644 --- a/drivers/media/video/cx18/cx18-streams.c +++ b/drivers/media/video/cx18/cx18-streams.c @@ -348,7 +348,7 @@ static void cx18_vbi_setup(struct cx18_stream *s) } /* setup VBI registers */ - cx18_av_cmd(cx, VIDIOC_S_FMT, &cx->vbi.in); + v4l2_subdev_call(cx->sd_av, video, s_fmt, &cx->vbi.in); /* * Send the CX18_CPU_SET_RAW_VBI_PARAM API command to setup Encoder Raw diff --git a/drivers/media/video/cx18/cx18-vbi.c b/drivers/media/video/cx18/cx18-vbi.c index 8e6f4d4aff9a..91c21dce607f 100644 --- a/drivers/media/video/cx18/cx18-vbi.c +++ b/drivers/media/video/cx18/cx18-vbi.c @@ -154,7 +154,7 @@ static u32 compress_sliced_buf(struct cx18 *cx, u32 line, u8 *buf, if (p[0] != 0xff || p[1] || p[2] || p[3] != eav) continue; vbi.p = p + 4; - cx18_av_cmd(cx, VIDIOC_INT_DECODE_VBI_LINE, &vbi); + v4l2_subdev_call(cx->sd_av, video, decode_vbi_line, &vbi); if (vbi.type) { cx->vbi.sliced_data[line].id = vbi.type; cx->vbi.sliced_data[line].field = vbi.is_second_field; diff --git a/drivers/media/video/cx18/cx18-video.c b/drivers/media/video/cx18/cx18-video.c index 2e5c41939330..fabacb0f87c6 100644 --- a/drivers/media/video/cx18/cx18-video.c +++ b/drivers/media/video/cx18/cx18-video.c @@ -32,7 +32,7 @@ void cx18_video_set_io(struct cx18 *cx) route.input = cx->card->video_inputs[inp].video_input; route.output = 0; - cx18_av_cmd(cx, VIDIOC_INT_S_VIDEO_ROUTING, &route); + v4l2_subdev_call(cx->sd_av, video, s_routing, &route); type = cx->card->video_inputs[inp].video_type; diff --git a/include/media/v4l2-chip-ident.h b/include/media/v4l2-chip-ident.h index a5339d8ba9a4..70117e748f20 100644 --- a/include/media/v4l2-chip-ident.h +++ b/include/media/v4l2-chip-ident.h @@ -64,7 +64,8 @@ enum { /* module saa7146: reserved range 300-309 */ V4L2_IDENT_SAA7146 = 300, - /* Conexant MPEG encoder/decoders: reserved range 410-420 */ + /* Conexant MPEG encoder/decoders: reserved range 400-420 */ + V4L2_IDENT_CX23418_843 = 403, /* Integrated A/V Decoder on the '418 */ V4L2_IDENT_CX23415 = 415, V4L2_IDENT_CX23416 = 416, V4L2_IDENT_CX23418 = 418, -- cgit v1.2.3 From ff2a20018094c593a35f4887bbdabf8926ddb6e6 Mon Sep 17 00:00:00 2001 From: Andy Walls Date: Fri, 20 Feb 2009 23:52:13 -0300 Subject: V4L/DVB (10758): cx18: Convert I2C devices to v4l2_subdevices This is a major perturbation to cx18 I2C device handling to convert it to the v4l2_device/subdeivce framework. This change breaks GPIO audio multiplexer control for the time being. It will be fixed in a coming change. Signed-off-by: Andy Walls Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx18/cx18-audio.c | 50 ++---- drivers/media/video/cx18/cx18-audio.h | 2 - drivers/media/video/cx18/cx18-av-core.c | 15 +- drivers/media/video/cx18/cx18-av-core.h | 2 +- drivers/media/video/cx18/cx18-cards.c | 32 ++-- drivers/media/video/cx18/cx18-cards.h | 14 +- drivers/media/video/cx18/cx18-controls.c | 15 +- drivers/media/video/cx18/cx18-driver.c | 86 +++++----- drivers/media/video/cx18/cx18-driver.h | 24 ++- drivers/media/video/cx18/cx18-fileops.c | 6 +- drivers/media/video/cx18/cx18-i2c.c | 284 ++++++++----------------------- drivers/media/video/cx18/cx18-i2c.h | 5 +- drivers/media/video/cx18/cx18-ioctl.c | 78 ++++++--- 13 files changed, 250 insertions(+), 363 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/cx18/cx18-audio.c b/drivers/media/video/cx18/cx18-audio.c index d19bd778c6ac..ccd170887b89 100644 --- a/drivers/media/video/cx18/cx18-audio.c +++ b/drivers/media/video/cx18/cx18-audio.c @@ -23,9 +23,7 @@ #include "cx18-driver.h" #include "cx18-io.h" -#include "cx18-i2c.h" #include "cx18-cards.h" -#include "cx18-audio.h" #define CX18_AUDIO_ENABLE 0xc72014 @@ -33,54 +31,32 @@ settings. */ int cx18_audio_set_io(struct cx18 *cx) { + const struct cx18_card_audio_input *in; struct v4l2_routing route; - u32 audio_input; u32 val; - int mux_input; int err; /* Determine which input to use */ - if (test_bit(CX18_F_I_RADIO_USER, &cx->i_flags)) { - audio_input = cx->card->radio_input.audio_input; - mux_input = cx->card->radio_input.muxer_input; - } else { - audio_input = - cx->card->audio_inputs[cx->audio_input].audio_input; - mux_input = - cx->card->audio_inputs[cx->audio_input].muxer_input; - } + if (test_bit(CX18_F_I_RADIO_USER, &cx->i_flags)) + in = &cx->card->radio_input; + else + in = &cx->card->audio_inputs[cx->audio_input]; /* handle muxer chips */ - route.input = mux_input; + route.input = in->muxer_input; route.output = 0; - cx18_i2c_hw(cx, cx->card->hw_muxer, VIDIOC_INT_S_AUDIO_ROUTING, &route); + v4l2_subdev_call(cx->sd_extmux, audio, s_routing, &route); - route.input = audio_input; - err = cx18_i2c_hw(cx, cx->card->hw_audio_ctrl, - VIDIOC_INT_S_AUDIO_ROUTING, &route); + route.input = in->audio_input; + err = cx18_call_hw_err(cx, cx->card->hw_audio_ctrl, + audio, s_routing, &route); if (err) return err; + /* FIXME - this internal mux should be abstracted to a subdev */ val = cx18_read_reg(cx, CX18_AUDIO_ENABLE) & ~0x30; - val |= (audio_input > CX18_AV_AUDIO_SERIAL2) ? 0x20 : - (audio_input << 4); + val |= (in->audio_input > CX18_AV_AUDIO_SERIAL2) ? 0x20 : + (in->audio_input << 4); cx18_write_reg_expect(cx, val | 0xb00, CX18_AUDIO_ENABLE, val, 0x30); return 0; } - -void cx18_audio_set_route(struct cx18 *cx, struct v4l2_routing *route) -{ - cx18_i2c_hw(cx, cx->card->hw_audio_ctrl, - VIDIOC_INT_S_AUDIO_ROUTING, route); -} - -void cx18_audio_set_audio_clock_freq(struct cx18 *cx, u8 freq) -{ - static u32 freqs[3] = { 44100, 48000, 32000 }; - - /* The audio clock of the digitizer must match the codec sample - rate otherwise you get some very strange effects. */ - if (freq > 2) - return; - cx18_call_i2c_clients(cx, VIDIOC_INT_AUDIO_CLOCK_FREQ, &freqs[freq]); -} diff --git a/drivers/media/video/cx18/cx18-audio.h b/drivers/media/video/cx18/cx18-audio.h index cb569a69379c..2731d29b0ab9 100644 --- a/drivers/media/video/cx18/cx18-audio.h +++ b/drivers/media/video/cx18/cx18-audio.h @@ -22,5 +22,3 @@ */ int cx18_audio_set_io(struct cx18 *cx); -void cx18_audio_set_route(struct cx18 *cx, struct v4l2_routing *route); -void cx18_audio_set_audio_clock_freq(struct cx18 *cx, u8 freq); diff --git a/drivers/media/video/cx18/cx18-av-core.c b/drivers/media/video/cx18/cx18-av-core.c index f9bb77a25ee9..2128070154d3 100644 --- a/drivers/media/video/cx18/cx18-av-core.c +++ b/drivers/media/video/cx18/cx18-av-core.c @@ -1209,9 +1209,10 @@ static const struct v4l2_subdev_ops cx18_av_ops = { .video = &cx18_av_video_ops, }; -int cx18_av_probe(struct cx18 *cx, struct v4l2_subdev **sd) +int cx18_av_probe(struct cx18 *cx) { struct cx18_av_state *state = &cx->av_state; + struct v4l2_subdev *sd; state->rev = cx18_av_read4(cx, CXADEC_CHIP_CTRL) & 0xffff; state->id = ((state->rev >> 4) == CXADEC_CHIP_TYPE_MAKO) @@ -1224,13 +1225,13 @@ int cx18_av_probe(struct cx18 *cx, struct v4l2_subdev **sd) state->slicer_line_delay = 0; state->slicer_line_offset = (10 + state->slicer_line_delay - 2); - *sd = &state->sd; - v4l2_subdev_init(*sd, &cx18_av_ops); - v4l2_set_subdevdata(*sd, cx); - snprintf((*sd)->name, sizeof((*sd)->name), + sd = &state->sd; + v4l2_subdev_init(sd, &cx18_av_ops); + v4l2_set_subdevdata(sd, cx); + snprintf(sd->name, sizeof(sd->name), "%s internal A/V decoder", cx->v4l2_dev.name); - (*sd)->grp_id = CX18_HW_CX23418; - return v4l2_device_register_subdev(&cx->v4l2_dev, *sd); + sd->grp_id = CX18_HW_418_AV; + return v4l2_device_register_subdev(&cx->v4l2_dev, sd); } void cx18_av_exit(struct cx18 *cx, struct v4l2_subdev *sd) diff --git a/drivers/media/video/cx18/cx18-av-core.h b/drivers/media/video/cx18/cx18-av-core.h index 90bdca960292..cd9c0e70f1fc 100644 --- a/drivers/media/video/cx18/cx18-av-core.h +++ b/drivers/media/video/cx18/cx18-av-core.h @@ -342,7 +342,7 @@ int cx18_av_and_or(struct cx18 *cx, u16 addr, unsigned mask, u8 value); int cx18_av_and_or4(struct cx18 *cx, u16 addr, u32 mask, u32 value); void cx18_av_std_setup(struct cx18 *cx); -int cx18_av_probe(struct cx18 *cx, struct v4l2_subdev **sd); +int cx18_av_probe(struct cx18 *cx); void cx18_av_exit(struct cx18 *cx, struct v4l2_subdev *sd); /* ----------------------------------------------------------------------- */ diff --git a/drivers/media/video/cx18/cx18-cards.c b/drivers/media/video/cx18/cx18-cards.c index 6e2105ac2bc4..6644534db564 100644 --- a/drivers/media/video/cx18/cx18-cards.c +++ b/drivers/media/video/cx18/cx18-cards.c @@ -53,9 +53,9 @@ static const struct cx18_card cx18_card_hvr1600_esmt = { .name = "Hauppauge HVR-1600", .comment = "Simultaneous Digital and Analog TV capture supported\n", .v4l2_capabilities = CX18_CAP_ENCODER, - .hw_audio_ctrl = CX18_HW_CX23418, + .hw_audio_ctrl = CX18_HW_418_AV, .hw_muxer = CX18_HW_CS5345, - .hw_all = CX18_HW_TVEEPROM | CX18_HW_TUNER | + .hw_all = CX18_HW_TVEEPROM | CX18_HW_418_AV | CX18_HW_TUNER | CX18_HW_CS5345 | CX18_HW_DVB, .video_inputs = { { CX18_CARD_INPUT_VID_TUNER, 0, CX18_AV_COMPOSITE7 }, @@ -99,9 +99,9 @@ static const struct cx18_card cx18_card_hvr1600_samsung = { .name = "Hauppauge HVR-1600 (Preproduction)", .comment = "Simultaneous Digital and Analog TV capture supported\n", .v4l2_capabilities = CX18_CAP_ENCODER, - .hw_audio_ctrl = CX18_HW_CX23418, + .hw_audio_ctrl = CX18_HW_418_AV, .hw_muxer = CX18_HW_CS5345, - .hw_all = CX18_HW_TVEEPROM | CX18_HW_TUNER | + .hw_all = CX18_HW_TVEEPROM | CX18_HW_418_AV | CX18_HW_TUNER | CX18_HW_CS5345 | CX18_HW_DVB, .video_inputs = { { CX18_CARD_INPUT_VID_TUNER, 0, CX18_AV_COMPOSITE7 }, @@ -154,8 +154,8 @@ static const struct cx18_card cx18_card_h900 = { .name = "Compro VideoMate H900", .comment = "Analog TV capture supported\n", .v4l2_capabilities = CX18_CAP_ENCODER, - .hw_audio_ctrl = CX18_HW_CX23418, - .hw_all = CX18_HW_TUNER, + .hw_audio_ctrl = CX18_HW_418_AV, + .hw_all = CX18_HW_418_AV | CX18_HW_TUNER, .video_inputs = { { CX18_CARD_INPUT_VID_TUNER, 0, CX18_AV_COMPOSITE2 }, { CX18_CARD_INPUT_SVIDEO1, 1, @@ -201,8 +201,8 @@ static const struct cx18_card cx18_card_mpc718 = { .name = "Yuan MPC718", .comment = "Analog video capture works; some audio line in may not.\n", .v4l2_capabilities = CX18_CAP_ENCODER, - .hw_audio_ctrl = CX18_HW_CX23418, - .hw_all = CX18_HW_TUNER, + .hw_audio_ctrl = CX18_HW_418_AV, + .hw_all = CX18_HW_418_AV | CX18_HW_TUNER, .video_inputs = { { CX18_CARD_INPUT_VID_TUNER, 0, CX18_AV_COMPOSITE2 }, { CX18_CARD_INPUT_SVIDEO1, 1, @@ -251,9 +251,9 @@ static const struct cx18_card cx18_card_cnxt_raptor_pal = { .name = "Conexant Raptor PAL/SECAM", .comment = "Analog TV capture supported\n", .v4l2_capabilities = CX18_CAP_ENCODER, - .hw_audio_ctrl = CX18_HW_CX23418, - .hw_muxer = CX18_HW_GPIO, - .hw_all = CX18_HW_TUNER | CX18_HW_GPIO, + .hw_audio_ctrl = CX18_HW_418_AV, + .hw_muxer = CX18_HW_GPIO_AUDIO_MUX, + .hw_all = CX18_HW_418_AV | CX18_HW_TUNER | CX18_HW_GPIO_AUDIO_MUX, .video_inputs = { { CX18_CARD_INPUT_VID_TUNER, 0, CX18_AV_COMPOSITE2 }, { CX18_CARD_INPUT_SVIDEO1, 1, @@ -306,8 +306,8 @@ static const struct cx18_card cx18_card_toshiba_qosmio_dvbt = { .comment = "Experimenters and photos needed for device to work well.\n" "\tTo help, mail the ivtv-devel list (www.ivtvdriver.org).\n", .v4l2_capabilities = CX18_CAP_ENCODER, - .hw_audio_ctrl = CX18_HW_CX23418, - .hw_all = CX18_HW_TUNER, + .hw_audio_ctrl = CX18_HW_418_AV, + .hw_all = CX18_HW_418_AV | CX18_HW_TUNER, .video_inputs = { { CX18_CARD_INPUT_VID_TUNER, 0, CX18_AV_COMPOSITE6 }, { CX18_CARD_INPUT_SVIDEO1, 1, @@ -350,9 +350,9 @@ static const struct cx18_card cx18_card_leadtek_pvr2100 = { .comment = "Experimenters and photos needed for device to work well.\n" "\tTo help, mail the ivtv-devel list (www.ivtvdriver.org).\n", .v4l2_capabilities = CX18_CAP_ENCODER, - .hw_audio_ctrl = CX18_HW_CX23418, - .hw_muxer = CX18_HW_GPIO, - .hw_all = CX18_HW_TUNER | CX18_HW_GPIO, + .hw_audio_ctrl = CX18_HW_418_AV, + .hw_muxer = CX18_HW_GPIO_AUDIO_MUX, + .hw_all = CX18_HW_418_AV | CX18_HW_TUNER | CX18_HW_GPIO_AUDIO_MUX, .video_inputs = { { CX18_CARD_INPUT_VID_TUNER, 0, CX18_AV_COMPOSITE2 }, { CX18_CARD_INPUT_SVIDEO1, 1, diff --git a/drivers/media/video/cx18/cx18-cards.h b/drivers/media/video/cx18/cx18-cards.h index f8ee29f102d4..bd7f9556f18c 100644 --- a/drivers/media/video/cx18/cx18-cards.h +++ b/drivers/media/video/cx18/cx18-cards.h @@ -22,12 +22,12 @@ */ /* hardware flags */ -#define CX18_HW_TUNER (1 << 0) -#define CX18_HW_TVEEPROM (1 << 1) -#define CX18_HW_CS5345 (1 << 2) -#define CX18_HW_GPIO (1 << 3) -#define CX18_HW_CX23418 (1 << 4) -#define CX18_HW_DVB (1 << 5) +#define CX18_HW_TUNER (1 << 0) +#define CX18_HW_TVEEPROM (1 << 1) +#define CX18_HW_CS5345 (1 << 2) +#define CX18_HW_DVB (1 << 3) +#define CX18_HW_418_AV (1 << 4) +#define CX18_HW_GPIO_AUDIO_MUX (1 << 5) /* video inputs */ #define CX18_CARD_INPUT_VID_TUNER 1 @@ -121,7 +121,7 @@ struct cx18_card { char *comment; u32 v4l2_capabilities; u32 hw_audio_ctrl; /* hardware used for the V4L2 controls (only - 1 dev allowed) */ + 1 dev allowed currently) */ u32 hw_muxer; /* hardware used to multiplex audio input */ u32 hw_all; /* all hardware used by the board */ struct cx18_card_video_input video_inputs[CX18_CARD_MAX_VIDEO_INPUTS]; diff --git a/drivers/media/video/cx18/cx18-controls.c b/drivers/media/video/cx18/cx18-controls.c index 9505c417371d..e5604c2328ad 100644 --- a/drivers/media/video/cx18/cx18-controls.c +++ b/drivers/media/video/cx18/cx18-controls.c @@ -77,7 +77,7 @@ int cx18_queryctrl(struct file *file, void *fh, struct v4l2_queryctrl *qctrl) case V4L2_CID_AUDIO_BASS: case V4L2_CID_AUDIO_TREBLE: case V4L2_CID_AUDIO_LOUDNESS: - if (cx18_i2c_hw(cx, cx->card->hw_audio_ctrl, VIDIOC_QUERYCTRL, qctrl)) + if (v4l2_subdev_call(cx->sd_av, core, queryctrl, qctrl)) qctrl->flags |= V4L2_CTRL_FLAG_DISABLED; return 0; @@ -134,7 +134,7 @@ static int cx18_s_ctrl(struct cx18 *cx, struct v4l2_control *vctrl) case V4L2_CID_AUDIO_BASS: case V4L2_CID_AUDIO_TREBLE: case V4L2_CID_AUDIO_LOUDNESS: - return cx18_i2c_hw(cx, cx->card->hw_audio_ctrl, VIDIOC_S_CTRL, vctrl); + return v4l2_subdev_call(cx->sd_av, core, s_ctrl, vctrl); default: CX18_DEBUG_IOCTL("invalid control 0x%x\n", vctrl->id); @@ -159,7 +159,8 @@ static int cx18_g_ctrl(struct cx18 *cx, struct v4l2_control *vctrl) case V4L2_CID_AUDIO_BASS: case V4L2_CID_AUDIO_TREBLE: case V4L2_CID_AUDIO_LOUDNESS: - return cx18_i2c_hw(cx, cx->card->hw_audio_ctrl, VIDIOC_G_CTRL, vctrl); + return v4l2_subdev_call(cx->sd_av, core, g_ctrl, vctrl); + default: CX18_DEBUG_IOCTL("invalid control 0x%x\n", vctrl->id); return -EINVAL; @@ -260,10 +261,12 @@ int cx18_s_ext_ctrls(struct file *file, void *fh, struct v4l2_ext_controls *c) return err; } if (c->ctrl_class == V4L2_CTRL_CLASS_MPEG) { + static u32 freqs[3] = { 44100, 48000, 32000 }; struct cx18_api_func_private priv; struct cx2341x_mpeg_params p = cx->params; int err = cx2341x_ext_ctrls(&p, atomic_read(&cx->ana_capturing), c, VIDIOC_S_EXT_CTRLS); + unsigned int idx; if (err) return err; @@ -287,7 +290,11 @@ int cx18_s_ext_ctrls(struct file *file, void *fh, struct v4l2_ext_controls *c) err = cx18_setup_vbi_fmt(cx, p.stream_vbi_fmt); cx->params = p; cx->dualwatch_stereo_mode = p.audio_properties & 0x0300; - cx18_audio_set_audio_clock_freq(cx, p.audio_properties & 0x03); + idx = p.audio_properties & 0x03; + /* The audio clock of the digitizer must match the codec sample + rate otherwise you get some very strange effects. */ + if (idx < sizeof(freqs)) + cx18_call_all(cx, audio, s_clock_freq, freqs[idx]); return err; } return -EINVAL; diff --git a/drivers/media/video/cx18/cx18-driver.c b/drivers/media/video/cx18/cx18-driver.c index f5a41dd663dc..edbb83c4c564 100644 --- a/drivers/media/video/cx18/cx18-driver.c +++ b/drivers/media/video/cx18/cx18-driver.c @@ -269,11 +269,16 @@ static void cx18_iounmap(struct cx18 *cx) /* Hauppauge card? get values from tveeprom */ void cx18_read_eeprom(struct cx18 *cx, struct tveeprom *tv) { + struct i2c_client c; u8 eedata[256]; - cx->i2c_client[0].addr = 0xA0 >> 1; - tveeprom_read(&cx->i2c_client[0], eedata, sizeof(eedata)); - tveeprom_hauppauge_analog(&cx->i2c_client[0], tv, eedata); + strncpy(c.name, "cx18 tveeprom tmp", sizeof(c.name)); + c.name[sizeof(c.name)-1] = '\0'; + c.adapter = &cx->i2c_adap[0]; + c.addr = 0xA0 >> 1; + + tveeprom_read(&c, eedata, sizeof(eedata)); + tveeprom_hauppauge_analog(&c, tv, eedata); } static void cx18_process_eeprom(struct cx18 *cx) @@ -553,8 +558,6 @@ static int __devinit cx18_init_struct1(struct cx18 *cx) cx->base_addr = pci_resource_start(cx->pci_dev, 0); mutex_init(&cx->serialize_lock); - mutex_init(&cx->i2c_bus_lock[0]); - mutex_init(&cx->i2c_bus_lock[1]); mutex_init(&cx->gpio_lock); mutex_init(&cx->epu2apu_mb_lock); mutex_init(&cx->epu2cpu_mb_lock); @@ -669,54 +672,41 @@ static int cx18_setup_pci(struct cx18 *cx, struct pci_dev *pci_dev, return 0; } -#ifdef MODULE -static u32 cx18_request_module(struct cx18 *cx, u32 hw, - const char *name, u32 id) -{ - if ((hw & id) == 0) - return hw; - if (request_module("%s", name) != 0) { - CX18_ERR("Failed to load module %s\n", name); - return hw & ~id; - } - CX18_DEBUG_INFO("Loaded module %s\n", name); - return hw; -} -#endif - -static void cx18_load_and_init_modules(struct cx18 *cx) +static void cx18_init_subdevs(struct cx18 *cx) { u32 hw = cx->card->hw_all; + u32 device; int i; -#ifdef MODULE - /* load modules */ -#ifdef CONFIG_MEDIA_TUNER_MODULE - hw = cx18_request_module(cx, hw, "tuner", CX18_HW_TUNER); -#endif -#ifdef CONFIG_VIDEO_CS5345_MODULE - hw = cx18_request_module(cx, hw, "cs5345", CX18_HW_CS5345); -#endif -#endif - - /* check which i2c devices are actually found */ - for (i = 0; i < 32; i++) { - u32 device = 1 << i; + for (i = 0, device = 1; i < 32; i++, device <<= 1) { if (!(device & hw)) continue; - if (device == CX18_HW_GPIO || device == CX18_HW_TVEEPROM || - device == CX18_HW_CX23418 || device == CX18_HW_DVB) { - /* These 'devices' do not use i2c probing */ + + switch (device) { + case CX18_HW_GPIO_AUDIO_MUX: + case CX18_HW_DVB: + case CX18_HW_TVEEPROM: + /* These subordinate devices do not use probing */ cx->hw_flags |= device; - continue; - } - cx18_i2c_register(cx, i); - if (cx18_i2c_hw_addr(cx, device) > 0) + break; + case CX18_HW_418_AV: + /* The A/V decoder gets probed earlier to set PLLs */ + /* Just note that the card uses it (i.e. has analog) */ cx->hw_flags |= device; + break; + default: + if (cx18_i2c_register(cx, i) == 0) + cx->hw_flags |= device; + break; + } } - hw = cx->hw_flags; + if (cx->hw_flags & CX18_HW_418_AV) + cx->sd_av = cx18_find_hw(cx, CX18_HW_418_AV); + + if (cx->card->hw_muxer != 0) + cx->sd_extmux = cx18_find_hw(cx, cx->card->hw_muxer); } static int __devinit cx18_probe(struct pci_dev *pci_dev, @@ -803,15 +793,17 @@ static int __devinit cx18_probe(struct pci_dev *pci_dev, cx->scb = (struct cx18_scb __iomem *)(cx->enc_mem + SCB_OFFSET); cx18_init_scb(cx); + /* Initialize GPIO early so I2C device resets can be performed */ cx18_gpio_init(cx); - retval = cx18_av_probe(cx, &cx->sd_av); + /* Initialize integrated A/V decoder early to set PLLs, just in case */ + retval = cx18_av_probe(cx); if (retval) { CX18_ERR("Could not register A/V decoder subdevice\n"); goto free_map; } /* Initialize the A/V decoder PLLs to sane defaults */ - v4l2_subdev_call(cx->sd_av, core, init, (u32) CX18_AV_INIT_PLLS); + cx18_call_hw(cx, CX18_HW_418_AV, core, init, (u32) CX18_AV_INIT_PLLS); /* active i2c */ CX18_DEBUG_INFO("activating i2c...\n"); @@ -873,7 +865,7 @@ static int __devinit cx18_probe(struct pci_dev *pci_dev, initialization. */ cx18_init_struct2(cx); - cx18_load_and_init_modules(cx); + cx18_init_subdevs(cx); if (cx->std & V4L2_STD_525_60) { cx->is_60hz = 1; @@ -895,7 +887,7 @@ static int __devinit cx18_probe(struct pci_dev *pci_dev, setup.mode_mask = T_ANALOG_TV; /* matches TV tuners */ setup.tuner_callback = (setup.type == TUNER_XC2028) ? cx18_reset_tuner_gpio : NULL; - cx18_call_i2c_clients(cx, TUNER_SET_TYPE_ADDR, &setup); + cx18_call_all(cx, tuner, s_type_addr, &setup); if (setup.type == TUNER_XC2028) { static struct xc2028_ctrl ctrl = { .fname = XC2028_DEFAULT_FIRMWARE, @@ -905,7 +897,7 @@ static int __devinit cx18_probe(struct pci_dev *pci_dev, .tuner = cx->options.tuner, .priv = &ctrl, }; - cx18_call_i2c_clients(cx, TUNER_SET_CONFIG, &cfg); + cx18_call_all(cx, tuner, s_config, &cfg); } } diff --git a/drivers/media/video/cx18/cx18-driver.h b/drivers/media/video/cx18/cx18-driver.h index 4b50878fc265..b81106d682ae 100644 --- a/drivers/media/video/cx18/cx18-driver.h +++ b/drivers/media/video/cx18/cx18-driver.h @@ -448,7 +448,8 @@ struct cx18 { int instance; struct pci_dev *pci_dev; struct v4l2_device v4l2_dev; - struct v4l2_subdev *sd_av; + struct v4l2_subdev *sd_av; /* A/V decoder/digitizer sub-device */ + struct v4l2_subdev *sd_extmux; /* External audio multiplexer sub-dev */ const struct cx18_card *card; /* card information */ const char *card_name; /* full name of the card */ @@ -528,9 +529,6 @@ struct cx18 { struct i2c_adapter i2c_adap[2]; struct i2c_algo_bit_data i2c_algo[2]; struct cx18_i2c_algo_callback_data i2c_algo_cb_data[2]; - struct i2c_client i2c_client[2]; - struct mutex i2c_bus_lock[2]; - struct i2c_client *i2c_clients[I2C_CLIENTS_MAX]; /* gpio */ u32 gpio_dir; @@ -573,4 +571,22 @@ static inline int cx18_raw_vbi(const struct cx18 *cx) return cx->vbi.in.type == V4L2_BUF_TYPE_VBI_CAPTURE; } +/* Call the specified callback for all subdevs with a grp_id bit matching the + * mask in hw (if 0, then match them all). Ignore any errors. */ +#define cx18_call_hw(cx, hw, o, f, args...) \ + __v4l2_device_call_subdevs(&(cx)->v4l2_dev, \ + !(hw) || (sd->grp_id & (hw)), o, f , ##args) + +#define cx18_call_all(cx, o, f, args...) cx18_call_hw(cx, 0, o, f , ##args) + +/* Call the specified callback for all subdevs with a grp_id bit matching the + * mask in hw (if 0, then match them all). If the callback returns an error + * other than 0 or -ENOIOCTLCMD, then return with that error code. */ +#define cx18_call_hw_err(cx, hw, o, f, args...) \ + __v4l2_device_call_subdevs_until_err( \ + &(cx)->v4l2_dev, !(hw) || (sd->grp_id & (hw)), o, f , ##args) + +#define cx18_call_all_err(cx, o, f, args...) \ + cx18_call_hw_err(cx, 0, o, f , ##args) + #endif /* CX18_DRIVER_H */ diff --git a/drivers/media/video/cx18/cx18-fileops.c b/drivers/media/video/cx18/cx18-fileops.c index 757982ea3766..4d7d6d5a7f86 100644 --- a/drivers/media/video/cx18/cx18-fileops.c +++ b/drivers/media/video/cx18/cx18-fileops.c @@ -136,7 +136,7 @@ static void cx18_dualwatch(struct cx18 *cx) new_stereo_mode = cx->params.audio_properties & stereo_mask; memset(&vt, 0, sizeof(vt)); - cx18_call_i2c_clients(cx, VIDIOC_G_TUNER, &vt); + cx18_call_all(cx, tuner, g_tuner, &vt); if (vt.audmode == V4L2_TUNER_MODE_LANG1_LANG2 && (vt.rxsubchans & V4L2_TUNER_SUB_LANG2)) new_stereo_mode = dual; @@ -608,7 +608,7 @@ int cx18_v4l2_close(struct file *filp) /* Mark that the radio is no longer in use */ clear_bit(CX18_F_I_RADIO_USER, &cx->i_flags); /* Switch tuner to TV */ - cx18_call_i2c_clients(cx, VIDIOC_S_STD, &cx->std); + cx18_call_all(cx, tuner, s_std, cx->std); /* Select correct audio input (i.e. TV tuner or Line in) */ cx18_audio_set_io(cx); if (atomic_read(&cx->ana_capturing) > 0) { @@ -671,7 +671,7 @@ static int cx18_serialized_open(struct cx18_stream *s, struct file *filp) /* We have the radio */ cx18_mute(cx); /* Switch tuner to radio */ - cx18_call_i2c_clients(cx, AUDC_SET_RADIO, NULL); + cx18_call_all(cx, tuner, s_radio); /* Select the correct audio input (i.e. radio tuner) */ cx18_audio_set_io(cx); /* Done! Unmute and continue. */ diff --git a/drivers/media/video/cx18/cx18-i2c.c b/drivers/media/video/cx18/cx18-i2c.c index db7b55281f50..6357dc44ab5b 100644 --- a/drivers/media/video/cx18/cx18-i2c.c +++ b/drivers/media/video/cx18/cx18-i2c.c @@ -42,32 +42,35 @@ #define CX18_CS5345_I2C_ADDR 0x4c -/* This array should match the CX18_HW_ defines */ -static const u8 hw_driverids[] = { - I2C_DRIVERID_TUNER, - I2C_DRIVERID_TVEEPROM, - I2C_DRIVERID_CS5345, - 0, /* CX18_HW_GPIO dummy driver ID */ - 0 /* CX18_HW_CX23418 dummy driver ID */ -}; - /* This array should match the CX18_HW_ defines */ static const u8 hw_addrs[] = { - 0, - 0, - CX18_CS5345_I2C_ADDR, - 0, /* CX18_HW_GPIO dummy driver ID */ - 0, /* CX18_HW_CX23418 dummy driver ID */ + 0, /* CX18_HW_TUNER */ + 0, /* CX18_HW_TVEEPROM */ + CX18_CS5345_I2C_ADDR, /* CX18_HW_CS5345 */ + 0, /* CX18_HW_DVB */ + 0, /* CX18_HW_418_AV */ + 0, /* CX18_HW_GPIO_AUDIO_MUX */ }; /* This array should match the CX18_HW_ defines */ /* This might well become a card-specific array */ static const u8 hw_bus[] = { - 0, - 0, - 0, - 0, /* CX18_HW_GPIO dummy driver ID */ - 0, /* CX18_HW_CX23418 dummy driver ID */ + 1, /* CX18_HW_TUNER */ + 0, /* CX18_HW_TVEEPROM */ + 0, /* CX18_HW_CS5345 */ + 0, /* CX18_HW_DVB */ + 0, /* CX18_HW_418_AV */ + 0, /* CX18_HW_GPIO_AUDIO_MUX */ +}; + +/* This array should match the CX18_HW_ defines */ +static const char * const hw_modules[] = { + "tuner", /* CX18_HW_TUNER */ + NULL, /* CX18_HW_TVEEPROM */ + "cs5345", /* CX18_HW_CS5345 */ + NULL, /* CX18_HW_DVB */ + NULL, /* CX18_HW_418_AV */ + NULL, /* CX18_HW_GPIO_AUDIO_MUX */ }; /* This array should match the CX18_HW_ defines */ @@ -75,83 +78,66 @@ static const char * const hw_devicenames[] = { "tuner", "tveeprom", "cs5345", - "gpio", - "cx23418", + "cx23418_DTV", + "cx23418_AV", + "gpio_audio_mux", }; int cx18_i2c_register(struct cx18 *cx, unsigned idx) { - struct i2c_board_info info; - struct i2c_client *c; - u8 id, bus; - int i; - - CX18_DEBUG_I2C("i2c client register\n"); - if (idx >= ARRAY_SIZE(hw_driverids) || hw_driverids[idx] == 0) + struct v4l2_subdev *sd; + int bus = hw_bus[idx]; + struct i2c_adapter *adap = &cx->i2c_adap[bus]; + const char *mod = hw_modules[idx]; + const char *type = hw_devicenames[idx]; + u32 hw = 1 << idx; + + if (idx >= ARRAY_SIZE(hw_addrs)) return -1; - id = hw_driverids[idx]; - bus = hw_bus[idx]; - memset(&info, 0, sizeof(info)); - strlcpy(info.type, hw_devicenames[idx], sizeof(info.type)); - info.addr = hw_addrs[idx]; - for (i = 0; i < I2C_CLIENTS_MAX; i++) - if (cx->i2c_clients[i] == NULL) - break; - - if (i == I2C_CLIENTS_MAX) { - CX18_ERR("insufficient room for new I2C client!\n"); - return -ENOMEM; - } - if (id != I2C_DRIVERID_TUNER) { - c = i2c_new_device(&cx->i2c_adap[bus], &info); - if (c->driver == NULL) - i2c_unregister_device(c); - else - cx->i2c_clients[i] = c; - return cx->i2c_clients[i] ? 0 : -ENODEV; + if (hw == CX18_HW_TUNER) { + /* special tuner group handling */ + sd = v4l2_i2c_new_probed_subdev(adap, mod, type, + cx->card_i2c->radio); + if (sd != NULL) + sd->grp_id = hw; + sd = v4l2_i2c_new_probed_subdev(adap, mod, type, + cx->card_i2c->demod); + if (sd != NULL) + sd->grp_id = hw; + sd = v4l2_i2c_new_probed_subdev(adap, mod, type, + cx->card_i2c->tv); + if (sd != NULL) + sd->grp_id = hw; + return sd != NULL ? 0 : -1; } - /* special tuner handling */ - c = i2c_new_probed_device(&cx->i2c_adap[1], &info, cx->card_i2c->radio); - if (c && c->driver == NULL) - i2c_unregister_device(c); - else if (c) - cx->i2c_clients[i++] = c; - c = i2c_new_probed_device(&cx->i2c_adap[1], &info, cx->card_i2c->demod); - if (c && c->driver == NULL) - i2c_unregister_device(c); - else if (c) - cx->i2c_clients[i++] = c; - c = i2c_new_probed_device(&cx->i2c_adap[1], &info, cx->card_i2c->tv); - if (c && c->driver == NULL) - i2c_unregister_device(c); - else if (c) - cx->i2c_clients[i++] = c; - return 0; -} + /* Is it not an I2C device or one we do not wish to register? */ + if (!hw_addrs[idx]) + return -1; -static int attach_inform(struct i2c_client *client) -{ - return 0; + /* It's an I2C device other than an analog tuner */ + sd = v4l2_i2c_new_subdev(adap, mod, type, hw_addrs[idx]); + if (sd != NULL) + sd->grp_id = hw; + return sd != NULL ? 0 : -1; } -static int detach_inform(struct i2c_client *client) +/* Find the first member of the subdev group id in hw */ +struct v4l2_subdev *cx18_find_hw(struct cx18 *cx, u32 hw) { - int i; - struct cx18 *cx = (struct cx18 *)i2c_get_adapdata(client->adapter); + struct v4l2_subdev *result = NULL; + struct v4l2_subdev *sd; - CX18_DEBUG_I2C("i2c client detach\n"); - for (i = 0; i < I2C_CLIENTS_MAX; i++) { - if (cx->i2c_clients[i] == client) { - cx->i2c_clients[i] = NULL; + spin_lock(&cx->v4l2_dev.lock); + v4l2_device_for_each_subdev(sd, &cx->v4l2_dev) { + if (sd->grp_id == hw) { + result = sd; break; } } - CX18_DEBUG_I2C("i2c detach [client=%s,%s]\n", - client->name, (i < I2C_CLIENTS_MAX) ? "ok" : "failed"); - - return 0; + spin_unlock(&cx->v4l2_dev.lock); + return result; } static void cx18_setscl(void *data, int state) @@ -204,8 +190,6 @@ static struct i2c_adapter cx18_i2c_adap_template = { .id = I2C_HW_B_CX2341X, .algo = NULL, /* set by i2c-algo-bit */ .algo_data = NULL, /* filled from template */ - .client_register = attach_inform, - .client_unregister = detach_inform, .owner = THIS_MODULE, }; @@ -221,151 +205,27 @@ static struct i2c_algo_bit_data cx18_i2c_algo_template = { .timeout = CX18_ALGO_BIT_TIMEOUT*HZ /* jiffies */ }; -static struct i2c_client cx18_i2c_client_template = { - .name = "cx18 internal", -}; - -int cx18_call_i2c_client(struct cx18 *cx, int addr, unsigned cmd, void *arg) -{ - struct i2c_client *client; - int retval; - int i; - - CX18_DEBUG_I2C("call_i2c_client addr=%02x\n", addr); - for (i = 0; i < I2C_CLIENTS_MAX; i++) { - client = cx->i2c_clients[i]; - if (client == NULL || client->driver == NULL || - client->driver->command == NULL) - continue; - if (addr == client->addr) { - retval = client->driver->command(client, cmd, arg); - return retval; - } - } - if (cmd != VIDIOC_DBG_G_CHIP_IDENT) - CX18_ERR("i2c addr 0x%02x not found for cmd 0x%x!\n", - addr, cmd); - return -ENODEV; -} - -/* Find the i2c device based on the driver ID and return - its i2c address or -ENODEV if no matching device was found. */ -static int cx18_i2c_id_addr(struct cx18 *cx, u32 id) -{ - struct i2c_client *client; - int retval = -ENODEV; - int i; - - for (i = 0; i < I2C_CLIENTS_MAX; i++) { - client = cx->i2c_clients[i]; - if (client == NULL || client->driver == NULL) - continue; - if (id == client->driver->id) { - retval = client->addr; - break; - } - } - return retval; -} - -/* Find the i2c device name matching the CX18_HW_ flag */ -static const char *cx18_i2c_hw_name(u32 hw) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(hw_driverids); i++) - if (1 << i == hw) - return hw_devicenames[i]; - return "unknown device"; -} - -/* Find the i2c device matching the CX18_HW_ flag and return - its i2c address or -ENODEV if no matching device was found. */ -int cx18_i2c_hw_addr(struct cx18 *cx, u32 hw) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(hw_driverids); i++) - if (1 << i == hw) - return cx18_i2c_id_addr(cx, hw_driverids[i]); - return -ENODEV; -} - -/* Calls i2c device based on CX18_HW_ flag. If hw == 0, then do nothing. - If hw == CX18_HW_GPIO then call the gpio handler. */ -int cx18_i2c_hw(struct cx18 *cx, u32 hw, unsigned int cmd, void *arg) -{ - int addr; - - if (hw == 0) - return 0; - - if (hw == CX18_HW_GPIO) - return cx18_gpio(cx, cmd, arg); - - if (hw == CX18_HW_CX23418) - return v4l2_subdev_command(cx->sd_av, cmd, arg); - - addr = cx18_i2c_hw_addr(cx, hw); - if (addr < 0) { - CX18_ERR("i2c hardware 0x%08x (%s) not found for cmd 0x%x!\n", - hw, cx18_i2c_hw_name(hw), cmd); - return addr; - } - return cx18_call_i2c_client(cx, addr, cmd, arg); -} - -/* broadcast cmd for all I2C clients and for the gpio subsystem */ -void cx18_call_i2c_clients(struct cx18 *cx, unsigned int cmd, void *arg) -{ - if (cx->i2c_adap[0].algo == NULL || cx->i2c_adap[1].algo == NULL) { - CX18_ERR("adapter is not set\n"); - return; - } - v4l2_subdev_command(cx->sd_av, cmd, arg); - i2c_clients_command(&cx->i2c_adap[0], cmd, arg); - i2c_clients_command(&cx->i2c_adap[1], cmd, arg); - if (cx->hw_flags & CX18_HW_GPIO) - cx18_gpio(cx, cmd, arg); -} - /* init + register i2c algo-bit adapter */ int init_cx18_i2c(struct cx18 *cx) { int i; CX18_DEBUG_I2C("i2c init\n"); - /* Sanity checks for the I2C hardware arrays. They must be the - * same size and GPIO/CX23418 must be the last entries. - */ - if (ARRAY_SIZE(hw_driverids) != ARRAY_SIZE(hw_addrs) || - ARRAY_SIZE(hw_devicenames) != ARRAY_SIZE(hw_addrs) || - CX18_HW_GPIO != (1 << (ARRAY_SIZE(hw_addrs) - 2)) || - CX18_HW_CX23418 != (1 << (ARRAY_SIZE(hw_addrs) - 1)) || - hw_driverids[ARRAY_SIZE(hw_addrs) - 1]) { - CX18_ERR("Mismatched I2C hardware arrays\n"); - return -ENODEV; - } - for (i = 0; i < 2; i++) { - memcpy(&cx->i2c_adap[i], &cx18_i2c_adap_template, - sizeof(struct i2c_adapter)); + /* Setup algorithm for adapter */ memcpy(&cx->i2c_algo[i], &cx18_i2c_algo_template, sizeof(struct i2c_algo_bit_data)); cx->i2c_algo_cb_data[i].cx = cx; cx->i2c_algo_cb_data[i].bus_index = i; cx->i2c_algo[i].data = &cx->i2c_algo_cb_data[i]; - cx->i2c_adap[i].algo_data = &cx->i2c_algo[i]; + /* Setup adapter */ + memcpy(&cx->i2c_adap[i], &cx18_i2c_adap_template, + sizeof(struct i2c_adapter)); + cx->i2c_adap[i].algo_data = &cx->i2c_algo[i]; sprintf(cx->i2c_adap[i].name + strlen(cx->i2c_adap[i].name), " #%d-%d", cx->instance, i); - i2c_set_adapdata(&cx->i2c_adap[i], cx); - - memcpy(&cx->i2c_client[i], &cx18_i2c_client_template, - sizeof(struct i2c_client)); - sprintf(cx->i2c_client[i].name + - strlen(cx->i2c_client[i].name), "%d", i); - cx->i2c_client[i].adapter = &cx->i2c_adap[i]; + i2c_set_adapdata(&cx->i2c_adap[i], &cx->v4l2_dev); cx->i2c_adap[i].dev.parent = &cx->pci_dev->dev; } diff --git a/drivers/media/video/cx18/cx18-i2c.h b/drivers/media/video/cx18/cx18-i2c.h index 4869739013bd..bdfd1921e300 100644 --- a/drivers/media/video/cx18/cx18-i2c.h +++ b/drivers/media/video/cx18/cx18-i2c.h @@ -21,11 +21,8 @@ * 02111-1307 USA */ -int cx18_i2c_hw_addr(struct cx18 *cx, u32 hw); -int cx18_i2c_hw(struct cx18 *cx, u32 hw, unsigned int cmd, void *arg); -int cx18_call_i2c_client(struct cx18 *cx, int addr, unsigned cmd, void *arg); -void cx18_call_i2c_clients(struct cx18 *cx, unsigned int cmd, void *arg); int cx18_i2c_register(struct cx18 *cx, unsigned idx); +struct v4l2_subdev *cx18_find_hw(struct cx18 *cx, u32 hw); /* init + register i2c algo-bit adapter */ int init_cx18_i2c(struct cx18 *cx); diff --git a/drivers/media/video/cx18/cx18-ioctl.c b/drivers/media/video/cx18/cx18-ioctl.c index 0ddf4dd55308..13ebd4a70f0d 100644 --- a/drivers/media/video/cx18/cx18-ioctl.c +++ b/drivers/media/video/cx18/cx18-ioctl.c @@ -372,15 +372,52 @@ static int cx18_g_chip_ident(struct file *file, void *fh, struct v4l2_dbg_chip_ident *chip) { struct cx18 *cx = ((struct cx18_open_id *)fh)->cx; + int err = 0; chip->ident = V4L2_IDENT_NONE; chip->revision = 0; - if (v4l2_chip_match_host(&chip->match)) { - chip->ident = V4L2_IDENT_CX23418; - return 0; + switch (chip->match.type) { + case V4L2_CHIP_MATCH_HOST: + switch (chip->match.addr) { + case 0: + chip->ident = V4L2_IDENT_CX23418; + chip->revision = cx18_read_reg(cx, 0xC72028); + break; + case 1: + /* + * The A/V decoder is always present, but in the rare + * case that the card doesn't have analog, we don't + * use it. We find it w/o using the cx->sd_av pointer + */ + cx18_call_hw(cx, CX18_HW_418_AV, + core, g_chip_ident, chip); + break; + default: + /* + * Could return ident = V4L2_IDENT_UNKNOWN if we had + * other host chips at higher addresses, but we don't + */ + err = -EINVAL; /* per V4L2 spec */ + break; + } + break; + case V4L2_CHIP_MATCH_I2C_DRIVER: + /* If needed, returns V4L2_IDENT_AMBIGUOUS without extra work */ + cx18_call_all(cx, core, g_chip_ident, chip); + break; + case V4L2_CHIP_MATCH_I2C_ADDR: + /* + * We could return V4L2_IDENT_UNKNOWN, but we don't do the work + * to look if a chip is at the address with no driver. That's a + * dangerous thing to do with EEPROMs anyway. + */ + cx18_call_all(cx, core, g_chip_ident, chip); + break; + default: + err = -EINVAL; + break; } - cx18_call_i2c_clients(cx, VIDIOC_DBG_G_CHIP_IDENT, chip); - return 0; + return err; } #ifdef CONFIG_VIDEO_ADV_DEBUG @@ -394,10 +431,10 @@ static int cx18_cxc(struct cx18 *cx, unsigned int cmd, void *arg) return -EINVAL; regs->size = 4; - if (cmd == VIDIOC_DBG_G_REGISTER) - regs->val = cx18_read_enc(cx, regs->reg); - else + if (cmd == VIDIOC_DBG_S_REGISTER) cx18_write_enc(cx, regs->val, regs->reg); + else + regs->val = cx18_read_enc(cx, regs->reg); return 0; } @@ -408,7 +445,8 @@ static int cx18_g_register(struct file *file, void *fh, if (v4l2_chip_match_host(®->match)) return cx18_cxc(cx, VIDIOC_DBG_G_REGISTER, reg); - cx18_call_i2c_clients(cx, VIDIOC_DBG_G_REGISTER, reg); + /* FIXME - errors shouldn't be ignored */ + cx18_call_all(cx, core, g_register, reg); return 0; } @@ -419,7 +457,8 @@ static int cx18_s_register(struct file *file, void *fh, if (v4l2_chip_match_host(®->match)) return cx18_cxc(cx, VIDIOC_DBG_S_REGISTER, reg); - cx18_call_i2c_clients(cx, VIDIOC_DBG_S_REGISTER, reg); + /* FIXME - errors shouldn't be ignored */ + cx18_call_all(cx, core, s_register, reg); return 0; } #endif @@ -598,7 +637,7 @@ static int cx18_g_frequency(struct file *file, void *fh, if (vf->tuner != 0) return -EINVAL; - cx18_call_i2c_clients(cx, VIDIOC_G_FREQUENCY, vf); + cx18_call_all(cx, tuner, g_frequency, vf); return 0; } @@ -617,7 +656,7 @@ int cx18_s_frequency(struct file *file, void *fh, struct v4l2_frequency *vf) cx18_mute(cx); CX18_DEBUG_INFO("v4l2 ioctl: set frequency %d\n", vf->frequency); - cx18_call_i2c_clients(cx, VIDIOC_S_FREQUENCY, vf); + cx18_call_all(cx, tuner, s_frequency, vf); cx18_unmute(cx); return 0; } @@ -666,7 +705,7 @@ int cx18_s_std(struct file *file, void *fh, v4l2_std_id *std) (unsigned long long) cx->std); /* Tuner */ - cx18_call_i2c_clients(cx, VIDIOC_S_STD, &cx->std); + cx18_call_all(cx, tuner, s_std, cx->std); return 0; } @@ -683,9 +722,7 @@ static int cx18_s_tuner(struct file *file, void *fh, struct v4l2_tuner *vt) if (vt->index != 0) return -EINVAL; - /* Setting tuner can only set audio mode */ - cx18_call_i2c_clients(cx, VIDIOC_S_TUNER, vt); - + cx18_call_all(cx, tuner, s_tuner, vt); return 0; } @@ -696,7 +733,7 @@ static int cx18_g_tuner(struct file *file, void *fh, struct v4l2_tuner *vt) if (vt->index != 0) return -EINVAL; - cx18_call_i2c_clients(cx, VIDIOC_G_TUNER, vt); + cx18_call_all(cx, tuner, g_tuner, vt); if (test_bit(CX18_F_I_RADIO_USER, &cx->i_flags)) { strlcpy(vt->name, "cx18 Radio Tuner", sizeof(vt->name)); @@ -853,7 +890,7 @@ static int cx18_log_status(struct file *file, void *fh) cx18_read_eeprom(cx, &tv); } - cx18_call_i2c_clients(cx, VIDIOC_LOG_STATUS, NULL); + cx18_call_all(cx, core, log_status); cx18_get_input(cx, cx->active_input, &vidin); cx18_get_audio_input(cx, cx->audio_input, &audin); CX18_INFO("Video Input: %s\n", vidin.name); @@ -894,7 +931,8 @@ static long cx18_default(struct file *file, void *fh, int cmd, void *arg) CX18_DEBUG_IOCTL("VIDIOC_INT_S_AUDIO_ROUTING(%d, %d)\n", route->input, route->output); - cx18_audio_set_route(cx, route); + cx18_call_hw(cx, cx->card->hw_audio_ctrl, audio, s_routing, + route); break; } @@ -922,6 +960,8 @@ long cx18_v4l2_ioctl(struct file *filp, unsigned int cmd, mutex_lock(&cx->serialize_lock); + /* FIXME - consolidate v4l2_prio_check()'s here */ + if (cx18_debug & CX18_DBGFLG_IOCTL) vfd->debug = V4L2_DEBUG_IOCTL | V4L2_DEBUG_IOCTL_ARG; res = video_ioctl2(filp, cmd, arg); -- cgit v1.2.3 From eefe1010a4657959588afc7fb3551cfa4e8bb4a7 Mon Sep 17 00:00:00 2001 From: Andy Walls Date: Sat, 21 Feb 2009 18:42:49 -0300 Subject: V4L/DVB (10759): cx18: Convert GPIO connected functions to act as v4l2_subdevices Convert GPIO line functions, such a audio routing and device resets, to v4l2_subdevices. This essentially completes the conversion of cx18 to the v4l2_device/v4l2_subdevice framework. No regression testing has taken place as of yet. Also an ivtv legacy bug with GPIO mux routing and going to/from radio mode was commented, but not fixed. Signed-off-by: Andy Walls Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx18/cx18-cards.c | 19 +- drivers/media/video/cx18/cx18-cards.h | 3 +- drivers/media/video/cx18/cx18-controls.c | 2 - drivers/media/video/cx18/cx18-driver.c | 22 ++- drivers/media/video/cx18/cx18-driver.h | 4 +- drivers/media/video/cx18/cx18-gpio.c | 319 ++++++++++++++++++++++--------- drivers/media/video/cx18/cx18-gpio.h | 10 +- drivers/media/video/cx18/cx18-i2c.c | 16 +- drivers/media/video/cx18/cx18-ioctl.c | 3 +- drivers/media/video/cx18/cx18-streams.c | 1 - drivers/media/video/cx18/cx18-vbi.c | 1 - drivers/media/video/cx18/cx18-video.c | 1 - 12 files changed, 278 insertions(+), 123 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/cx18/cx18-cards.c b/drivers/media/video/cx18/cx18-cards.c index 6644534db564..9bc221837847 100644 --- a/drivers/media/video/cx18/cx18-cards.c +++ b/drivers/media/video/cx18/cx18-cards.c @@ -56,7 +56,7 @@ static const struct cx18_card cx18_card_hvr1600_esmt = { .hw_audio_ctrl = CX18_HW_418_AV, .hw_muxer = CX18_HW_CS5345, .hw_all = CX18_HW_TVEEPROM | CX18_HW_418_AV | CX18_HW_TUNER | - CX18_HW_CS5345 | CX18_HW_DVB, + CX18_HW_CS5345 | CX18_HW_DVB | CX18_HW_GPIO_RESET_CTRL, .video_inputs = { { CX18_CARD_INPUT_VID_TUNER, 0, CX18_AV_COMPOSITE7 }, { CX18_CARD_INPUT_SVIDEO1, 1, CX18_AV_SVIDEO1 }, @@ -102,7 +102,7 @@ static const struct cx18_card cx18_card_hvr1600_samsung = { .hw_audio_ctrl = CX18_HW_418_AV, .hw_muxer = CX18_HW_CS5345, .hw_all = CX18_HW_TVEEPROM | CX18_HW_418_AV | CX18_HW_TUNER | - CX18_HW_CS5345 | CX18_HW_DVB, + CX18_HW_CS5345 | CX18_HW_DVB | CX18_HW_GPIO_RESET_CTRL, .video_inputs = { { CX18_CARD_INPUT_VID_TUNER, 0, CX18_AV_COMPOSITE7 }, { CX18_CARD_INPUT_SVIDEO1, 1, CX18_AV_SVIDEO1 }, @@ -155,7 +155,7 @@ static const struct cx18_card cx18_card_h900 = { .comment = "Analog TV capture supported\n", .v4l2_capabilities = CX18_CAP_ENCODER, .hw_audio_ctrl = CX18_HW_418_AV, - .hw_all = CX18_HW_418_AV | CX18_HW_TUNER, + .hw_all = CX18_HW_418_AV | CX18_HW_TUNER | CX18_HW_GPIO_RESET_CTRL, .video_inputs = { { CX18_CARD_INPUT_VID_TUNER, 0, CX18_AV_COMPOSITE2 }, { CX18_CARD_INPUT_SVIDEO1, 1, @@ -202,7 +202,7 @@ static const struct cx18_card cx18_card_mpc718 = { .comment = "Analog video capture works; some audio line in may not.\n", .v4l2_capabilities = CX18_CAP_ENCODER, .hw_audio_ctrl = CX18_HW_418_AV, - .hw_all = CX18_HW_418_AV | CX18_HW_TUNER, + .hw_all = CX18_HW_418_AV | CX18_HW_TUNER | CX18_HW_GPIO_RESET_CTRL, .video_inputs = { { CX18_CARD_INPUT_VID_TUNER, 0, CX18_AV_COMPOSITE2 }, { CX18_CARD_INPUT_SVIDEO1, 1, @@ -252,8 +252,8 @@ static const struct cx18_card cx18_card_cnxt_raptor_pal = { .comment = "Analog TV capture supported\n", .v4l2_capabilities = CX18_CAP_ENCODER, .hw_audio_ctrl = CX18_HW_418_AV, - .hw_muxer = CX18_HW_GPIO_AUDIO_MUX, - .hw_all = CX18_HW_418_AV | CX18_HW_TUNER | CX18_HW_GPIO_AUDIO_MUX, + .hw_muxer = CX18_HW_GPIO_MUX, + .hw_all = CX18_HW_418_AV | CX18_HW_TUNER | CX18_HW_GPIO_MUX, .video_inputs = { { CX18_CARD_INPUT_VID_TUNER, 0, CX18_AV_COMPOSITE2 }, { CX18_CARD_INPUT_SVIDEO1, 1, @@ -307,7 +307,7 @@ static const struct cx18_card cx18_card_toshiba_qosmio_dvbt = { "\tTo help, mail the ivtv-devel list (www.ivtvdriver.org).\n", .v4l2_capabilities = CX18_CAP_ENCODER, .hw_audio_ctrl = CX18_HW_418_AV, - .hw_all = CX18_HW_418_AV | CX18_HW_TUNER, + .hw_all = CX18_HW_418_AV | CX18_HW_TUNER | CX18_HW_GPIO_RESET_CTRL, .video_inputs = { { CX18_CARD_INPUT_VID_TUNER, 0, CX18_AV_COMPOSITE6 }, { CX18_CARD_INPUT_SVIDEO1, 1, @@ -351,8 +351,9 @@ static const struct cx18_card cx18_card_leadtek_pvr2100 = { "\tTo help, mail the ivtv-devel list (www.ivtvdriver.org).\n", .v4l2_capabilities = CX18_CAP_ENCODER, .hw_audio_ctrl = CX18_HW_418_AV, - .hw_muxer = CX18_HW_GPIO_AUDIO_MUX, - .hw_all = CX18_HW_418_AV | CX18_HW_TUNER | CX18_HW_GPIO_AUDIO_MUX, + .hw_muxer = CX18_HW_GPIO_MUX, + .hw_all = CX18_HW_418_AV | CX18_HW_TUNER | CX18_HW_GPIO_MUX | + CX18_HW_GPIO_RESET_CTRL, .video_inputs = { { CX18_CARD_INPUT_VID_TUNER, 0, CX18_AV_COMPOSITE2 }, { CX18_CARD_INPUT_SVIDEO1, 1, diff --git a/drivers/media/video/cx18/cx18-cards.h b/drivers/media/video/cx18/cx18-cards.h index bd7f9556f18c..3c552b6b7c4d 100644 --- a/drivers/media/video/cx18/cx18-cards.h +++ b/drivers/media/video/cx18/cx18-cards.h @@ -27,7 +27,8 @@ #define CX18_HW_CS5345 (1 << 2) #define CX18_HW_DVB (1 << 3) #define CX18_HW_418_AV (1 << 4) -#define CX18_HW_GPIO_AUDIO_MUX (1 << 5) +#define CX18_HW_GPIO_MUX (1 << 5) +#define CX18_HW_GPIO_RESET_CTRL (1 << 6) /* video inputs */ #define CX18_CARD_INPUT_VID_TUNER 1 diff --git a/drivers/media/video/cx18/cx18-controls.c b/drivers/media/video/cx18/cx18-controls.c index e5604c2328ad..925e01fdbaa6 100644 --- a/drivers/media/video/cx18/cx18-controls.c +++ b/drivers/media/video/cx18/cx18-controls.c @@ -22,11 +22,9 @@ */ #include "cx18-driver.h" -#include "cx18-av-core.h" #include "cx18-cards.h" #include "cx18-ioctl.h" #include "cx18-audio.h" -#include "cx18-i2c.h" #include "cx18-mailbox.h" #include "cx18-controls.h" diff --git a/drivers/media/video/cx18/cx18-driver.c b/drivers/media/video/cx18/cx18-driver.c index edbb83c4c564..79b3bf5bcec1 100644 --- a/drivers/media/video/cx18/cx18-driver.c +++ b/drivers/media/video/cx18/cx18-driver.c @@ -684,7 +684,6 @@ static void cx18_init_subdevs(struct cx18 *cx) continue; switch (device) { - case CX18_HW_GPIO_AUDIO_MUX: case CX18_HW_DVB: case CX18_HW_TVEEPROM: /* These subordinate devices do not use probing */ @@ -695,6 +694,16 @@ static void cx18_init_subdevs(struct cx18 *cx) /* Just note that the card uses it (i.e. has analog) */ cx->hw_flags |= device; break; + case CX18_HW_GPIO_RESET_CTRL: + /* + * The Reset Controller gets probed and added to + * hw_flags earlier for i2c adapter/bus initialization + */ + break; + case CX18_HW_GPIO_MUX: + if (cx18_gpio_register(cx, device) == 0) + cx->hw_flags |= device; + break; default: if (cx18_i2c_register(cx, i) == 0) cx->hw_flags |= device; @@ -793,7 +802,6 @@ static int __devinit cx18_probe(struct pci_dev *pci_dev, cx->scb = (struct cx18_scb __iomem *)(cx->enc_mem + SCB_OFFSET); cx18_init_scb(cx); - /* Initialize GPIO early so I2C device resets can be performed */ cx18_gpio_init(cx); /* Initialize integrated A/V decoder early to set PLLs, just in case */ @@ -802,9 +810,17 @@ static int __devinit cx18_probe(struct pci_dev *pci_dev, CX18_ERR("Could not register A/V decoder subdevice\n"); goto free_map; } - /* Initialize the A/V decoder PLLs to sane defaults */ cx18_call_hw(cx, CX18_HW_418_AV, core, init, (u32) CX18_AV_INIT_PLLS); + /* Initialize GPIO Reset Controller to do chip resets during i2c init */ + if (cx->card->hw_all & CX18_HW_GPIO_RESET_CTRL) { + if (cx18_gpio_register(cx, CX18_HW_GPIO_RESET_CTRL) != 0) + CX18_WARN("Could not register GPIO reset controller" + "subdevice; proceeding anyway.\n"); + else + cx->hw_flags |= CX18_HW_GPIO_RESET_CTRL; + } + /* active i2c */ CX18_DEBUG_INFO("activating i2c...\n"); retval = init_cx18_i2c(cx); diff --git a/drivers/media/video/cx18/cx18-driver.h b/drivers/media/video/cx18/cx18-driver.h index b81106d682ae..9ee608063b49 100644 --- a/drivers/media/video/cx18/cx18-driver.h +++ b/drivers/media/video/cx18/cx18-driver.h @@ -449,7 +449,7 @@ struct cx18 { struct pci_dev *pci_dev; struct v4l2_device v4l2_dev; struct v4l2_subdev *sd_av; /* A/V decoder/digitizer sub-device */ - struct v4l2_subdev *sd_extmux; /* External audio multiplexer sub-dev */ + struct v4l2_subdev *sd_extmux; /* External multiplexer sub-dev */ const struct cx18_card *card; /* card information */ const char *card_name; /* full name of the card */ @@ -534,6 +534,8 @@ struct cx18 { u32 gpio_dir; u32 gpio_val; struct mutex gpio_lock; + struct v4l2_subdev sd_gpiomux; + struct v4l2_subdev sd_resetctrl; /* v4l2 and User settings */ diff --git a/drivers/media/video/cx18/cx18-gpio.c b/drivers/media/video/cx18/cx18-gpio.c index 1a99329f33cb..dcc19b1c541d 100644 --- a/drivers/media/video/cx18/cx18-gpio.c +++ b/drivers/media/video/cx18/cx18-gpio.c @@ -46,6 +46,9 @@ * gpio13: cs5345 reset pin */ +/* + * File scope utility functions + */ static void gpio_write(struct cx18 *cx) { u32 dir_lo = cx->gpio_dir & 0xffff; @@ -63,73 +66,201 @@ static void gpio_write(struct cx18 *cx) CX18_REG_GPIO_OUT2, val_hi, dir_hi); } -void cx18_reset_i2c_slaves_gpio(struct cx18 *cx) +static void gpio_update(struct cx18 *cx, u32 mask, u32 data) { - const struct cx18_gpio_i2c_slave_reset *p; + if (mask == 0) + return; - p = &cx->card->gpio_i2c_slave_reset; + mutex_lock(&cx->gpio_lock); + cx->gpio_val = (cx->gpio_val & ~mask) | (data & mask); + gpio_write(cx); + mutex_unlock(&cx->gpio_lock); +} + +static void gpio_reset_seq(struct cx18 *cx, u32 active_lo, u32 active_hi, + unsigned int assert_msecs, + unsigned int recovery_msecs) +{ + u32 mask; - if ((p->active_lo_mask | p->active_hi_mask) == 0) + mask = active_lo | active_hi; + if (mask == 0) return; - /* Assuming that the masks are a subset of the bits in gpio_dir */ + /* + * Assuming that active_hi and active_lo are a subsets of the bits in + * gpio_dir. Also assumes that active_lo and active_hi don't overlap + * in any bit position + */ /* Assert */ - mutex_lock(&cx->gpio_lock); - cx->gpio_val = - (cx->gpio_val | p->active_hi_mask) & ~(p->active_lo_mask); - gpio_write(cx); - schedule_timeout_uninterruptible(msecs_to_jiffies(p->msecs_asserted)); + gpio_update(cx, mask, ~active_lo); + schedule_timeout_uninterruptible(msecs_to_jiffies(assert_msecs)); /* Deassert */ - cx->gpio_val = - (cx->gpio_val | p->active_lo_mask) & ~(p->active_hi_mask); - gpio_write(cx); - schedule_timeout_uninterruptible(msecs_to_jiffies(p->msecs_recovery)); + gpio_update(cx, mask, ~active_hi); + schedule_timeout_uninterruptible(msecs_to_jiffies(recovery_msecs)); +} + +/* + * GPIO Multiplexer - logical device + */ +static int gpiomux_log_status(struct v4l2_subdev *sd) +{ + struct cx18 *cx = v4l2_get_subdevdata(sd); + + mutex_lock(&cx->gpio_lock); + CX18_INFO("GPIO: direction 0x%08x, value 0x%08x\n", + cx->gpio_dir, cx->gpio_val); mutex_unlock(&cx->gpio_lock); + return 0; } -void cx18_reset_ir_gpio(void *data) +static int gpiomux_s_radio(struct v4l2_subdev *sd) { - struct cx18 *cx = ((struct cx18_i2c_algo_callback_data *)data)->cx; - const struct cx18_gpio_i2c_slave_reset *p; + struct cx18 *cx = v4l2_get_subdevdata(sd); - p = &cx->card->gpio_i2c_slave_reset; + /* + * FIXME - work out the cx->active/audio_input mess - this is + * intended to handle the switch to radio mode and set the + * audio routing, but we need to update the state in cx + */ + gpio_update(cx, cx->card->gpio_audio_input.mask, + cx->card->gpio_audio_input.radio); + return 0; +} - if (p->ir_reset_mask == 0) - return; +static int gpiomux_s_std(struct v4l2_subdev *sd, v4l2_std_id norm) +{ + struct cx18 *cx = v4l2_get_subdevdata(sd); + u32 data; - CX18_DEBUG_INFO("Resetting IR microcontroller\n"); + switch (cx->card->audio_inputs[cx->audio_input].muxer_input) { + case 1: + data = cx->card->gpio_audio_input.linein; + break; + case 0: + data = cx->card->gpio_audio_input.tuner; + break; + default: + /* + * FIXME - work out the cx->active/audio_input mess - this is + * intended to handle the switch from radio mode and set the + * audio routing, but we need to update the state in cx + */ + data = cx->card->gpio_audio_input.tuner; + break; + } + gpio_update(cx, cx->card->gpio_audio_input.mask, data); + return 0; +} - /* - Assert timing for the Z8F0811 on HVR-1600 boards: - 1. Assert RESET for min of 4 clock cycles at 18.432 MHz to initiate - 2. Reset then takes 66 WDT cycles at 10 kHz + 16 xtal clock cycles - (6,601,085 nanoseconds ~= 7 milliseconds) - 3. DBG pin must be high before chip exits reset for normal operation. - DBG is open drain and hopefully pulled high since we don't - normally drive it (GPIO 1?) for the HVR-1600 - 4. Z8F0811 won't exit reset until RESET is deasserted - */ - mutex_lock(&cx->gpio_lock); - cx->gpio_val = cx->gpio_val & ~p->ir_reset_mask; - gpio_write(cx); - mutex_unlock(&cx->gpio_lock); - schedule_timeout_uninterruptible(msecs_to_jiffies(p->msecs_asserted)); +static int gpiomux_s_audio_routing(struct v4l2_subdev *sd, + const struct v4l2_routing *route) +{ + struct cx18 *cx = v4l2_get_subdevdata(sd); + u32 data; + + switch (route->input) { + case 0: + data = cx->card->gpio_audio_input.tuner; + break; + case 1: + data = cx->card->gpio_audio_input.linein; + break; + case 2: + data = cx->card->gpio_audio_input.radio; + break; + default: + return -EINVAL; + } + gpio_update(cx, cx->card->gpio_audio_input.mask, data); + return 0; +} + +static const struct v4l2_subdev_core_ops gpiomux_core_ops = { + .log_status = gpiomux_log_status, +}; + +static const struct v4l2_subdev_tuner_ops gpiomux_tuner_ops = { + .s_std = gpiomux_s_std, + .s_radio = gpiomux_s_radio, +}; + +static const struct v4l2_subdev_audio_ops gpiomux_audio_ops = { + .s_routing = gpiomux_s_audio_routing, +}; + +static const struct v4l2_subdev_ops gpiomux_ops = { + .core = &gpiomux_core_ops, + .tuner = &gpiomux_tuner_ops, + .audio = &gpiomux_audio_ops, +}; + +/* + * GPIO Reset Controller - logical device + */ +static int resetctrl_log_status(struct v4l2_subdev *sd) +{ + struct cx18 *cx = v4l2_get_subdevdata(sd); - /* - Zilog comes out of reset, loads reset vector address and executes - from there. Required recovery delay unknown. - */ mutex_lock(&cx->gpio_lock); - cx->gpio_val = cx->gpio_val | p->ir_reset_mask; - gpio_write(cx); + CX18_INFO("GPIO: direction 0x%08x, value 0x%08x\n", + cx->gpio_dir, cx->gpio_val); mutex_unlock(&cx->gpio_lock); - schedule_timeout_uninterruptible(msecs_to_jiffies(p->msecs_recovery)); + return 0; } -EXPORT_SYMBOL(cx18_reset_ir_gpio); -/* This symbol is exported for use by an infrared module for the IR-blaster */ +static int resetctrl_reset(struct v4l2_subdev *sd, u32 val) +{ + struct cx18 *cx = v4l2_get_subdevdata(sd); + const struct cx18_gpio_i2c_slave_reset *p; + + p = &cx->card->gpio_i2c_slave_reset; + switch (val) { + case CX18_GPIO_RESET_I2C: + gpio_reset_seq(cx, p->active_lo_mask, p->active_hi_mask, + p->msecs_asserted, p->msecs_recovery); + break; + case CX18_GPIO_RESET_Z8F0811: + /* + * Assert timing for the Z8F0811 on HVR-1600 boards: + * 1. Assert RESET for min of 4 clock cycles at 18.432 MHz to + * initiate + * 2. Reset then takes 66 WDT cycles at 10 kHz + 16 xtal clock + * cycles (6,601,085 nanoseconds ~= 7 milliseconds) + * 3. DBG pin must be high before chip exits reset for normal + * operation. DBG is open drain and hopefully pulled high + * since we don't normally drive it (GPIO 1?) for the + * HVR-1600 + * 4. Z8F0811 won't exit reset until RESET is deasserted + * 5. Zilog comes out of reset, loads reset vector address and + * executes from there. Required recovery delay unknown. + */ + gpio_reset_seq(cx, p->ir_reset_mask, 0, + p->msecs_asserted, p->msecs_recovery); + break; + case CX18_GPIO_RESET_XC2028: + if (cx->card->tuners[0].tuner == TUNER_XC2028) + gpio_reset_seq(cx, (1 << cx->card->xceive_pin), 0, + 1, 1); + break; + } + return 0; +} + +static const struct v4l2_subdev_core_ops resetctrl_core_ops = { + .log_status = resetctrl_log_status, + .reset = resetctrl_reset, +}; + +static const struct v4l2_subdev_ops resetctrl_ops = { + .core = &resetctrl_core_ops, +}; + +/* + * External entry points + */ void cx18_gpio_init(struct cx18 *cx) { mutex_lock(&cx->gpio_lock); @@ -156,6 +287,49 @@ void cx18_gpio_init(struct cx18 *cx) mutex_unlock(&cx->gpio_lock); } +int cx18_gpio_register(struct cx18 *cx, u32 hw) +{ + struct v4l2_subdev *sd; + const struct v4l2_subdev_ops *ops; + char *str; + + switch (hw) { + case CX18_HW_GPIO_MUX: + sd = &cx->sd_gpiomux; + ops = &gpiomux_ops; + str = "gpio mux"; + break; + case CX18_HW_GPIO_RESET_CTRL: + sd = &cx->sd_resetctrl; + ops = &resetctrl_ops; + str = "gpio reset ctrl"; + break; + default: + return -EINVAL; + } + + v4l2_subdev_init(sd, ops); + v4l2_set_subdevdata(sd, cx); + snprintf(sd->name, sizeof(sd->name), "%s %s", cx->v4l2_dev.name, str); + sd->grp_id = hw; + return v4l2_device_register_subdev(&cx->v4l2_dev, sd); +} + +void cx18_reset_ir_gpio(void *data) +{ + struct cx18 *cx = to_cx18((struct v4l2_device *)data); + + if (cx->card->gpio_i2c_slave_reset.ir_reset_mask == 0) + return; + + CX18_DEBUG_INFO("Resetting IR microcontroller\n"); + + v4l2_subdev_call(&cx->sd_resetctrl, + core, reset, CX18_GPIO_RESET_Z8F0811); +} +EXPORT_SYMBOL(cx18_reset_ir_gpio); +/* This symbol is exported for use by lirc_pvr150 for the IR-blaster */ + /* Xceive tuner reset function */ int cx18_reset_tuner_gpio(void *dev, int component, int cmd, int value) { @@ -163,56 +337,11 @@ int cx18_reset_tuner_gpio(void *dev, int component, int cmd, int value) struct cx18_i2c_algo_callback_data *cb_data = algo->data; struct cx18 *cx = cb_data->cx; - if (cmd != XC2028_TUNER_RESET) + if (cmd != XC2028_TUNER_RESET || + cx->card->tuners[0].tuner != TUNER_XC2028) return 0; - CX18_DEBUG_INFO("Resetting tuner\n"); - mutex_lock(&cx->gpio_lock); - cx->gpio_val &= ~(1 << cx->card->xceive_pin); - gpio_write(cx); - mutex_unlock(&cx->gpio_lock); - schedule_timeout_interruptible(msecs_to_jiffies(1)); - - mutex_lock(&cx->gpio_lock); - cx->gpio_val |= 1 << cx->card->xceive_pin; - gpio_write(cx); - mutex_unlock(&cx->gpio_lock); - schedule_timeout_interruptible(msecs_to_jiffies(1)); - return 0; -} - -int cx18_gpio(struct cx18 *cx, unsigned int command, void *arg) -{ - struct v4l2_routing *route = arg; - u32 mask, data; - - switch (command) { - case VIDIOC_INT_S_AUDIO_ROUTING: - if (route->input > 2) - return -EINVAL; - mask = cx->card->gpio_audio_input.mask; - switch (route->input) { - case 0: - data = cx->card->gpio_audio_input.tuner; - break; - case 1: - data = cx->card->gpio_audio_input.linein; - break; - case 2: - default: - data = cx->card->gpio_audio_input.radio; - break; - } - break; - - default: - return -EINVAL; - } - if (mask) { - mutex_lock(&cx->gpio_lock); - cx->gpio_val = (cx->gpio_val & ~mask) | (data & mask); - gpio_write(cx); - mutex_unlock(&cx->gpio_lock); - } - return 0; + CX18_DEBUG_INFO("Resetting XCeive tuner\n"); + return v4l2_subdev_call(&cx->sd_resetctrl, + core, reset, CX18_GPIO_RESET_XC2028); } diff --git a/drivers/media/video/cx18/cx18-gpio.h b/drivers/media/video/cx18/cx18-gpio.h index 39ffccc19d8a..f9a5ca3566af 100644 --- a/drivers/media/video/cx18/cx18-gpio.h +++ b/drivers/media/video/cx18/cx18-gpio.h @@ -22,7 +22,13 @@ */ void cx18_gpio_init(struct cx18 *cx); -void cx18_reset_i2c_slaves_gpio(struct cx18 *cx); +int cx18_gpio_register(struct cx18 *cx, u32 hw); + +enum cx18_gpio_reset_type { + CX18_GPIO_RESET_I2C = 0, + CX18_GPIO_RESET_Z8F0811 = 1, + CX18_GPIO_RESET_XC2028 = 2, +}; + void cx18_reset_ir_gpio(void *data); int cx18_reset_tuner_gpio(void *dev, int component, int cmd, int value); -int cx18_gpio(struct cx18 *cx, unsigned int command, void *arg); diff --git a/drivers/media/video/cx18/cx18-i2c.c b/drivers/media/video/cx18/cx18-i2c.c index 6357dc44ab5b..d092643faf46 100644 --- a/drivers/media/video/cx18/cx18-i2c.c +++ b/drivers/media/video/cx18/cx18-i2c.c @@ -26,7 +26,6 @@ #include "cx18-io.h" #include "cx18-cards.h" #include "cx18-gpio.h" -#include "cx18-av-core.h" #include "cx18-i2c.h" #include "cx18-irq.h" @@ -49,7 +48,8 @@ static const u8 hw_addrs[] = { CX18_CS5345_I2C_ADDR, /* CX18_HW_CS5345 */ 0, /* CX18_HW_DVB */ 0, /* CX18_HW_418_AV */ - 0, /* CX18_HW_GPIO_AUDIO_MUX */ + 0, /* CX18_HW_GPIO_MUX */ + 0, /* CX18_HW_GPIO_RESET_CTRL */ }; /* This array should match the CX18_HW_ defines */ @@ -60,7 +60,8 @@ static const u8 hw_bus[] = { 0, /* CX18_HW_CS5345 */ 0, /* CX18_HW_DVB */ 0, /* CX18_HW_418_AV */ - 0, /* CX18_HW_GPIO_AUDIO_MUX */ + 0, /* CX18_HW_GPIO_MUX */ + 0, /* CX18_HW_GPIO_RESET_CTRL */ }; /* This array should match the CX18_HW_ defines */ @@ -70,7 +71,8 @@ static const char * const hw_modules[] = { "cs5345", /* CX18_HW_CS5345 */ NULL, /* CX18_HW_DVB */ NULL, /* CX18_HW_418_AV */ - NULL, /* CX18_HW_GPIO_AUDIO_MUX */ + NULL, /* CX18_HW_GPIO_MUX */ + NULL, /* CX18_HW_GPIO_RESET_CTRL */ }; /* This array should match the CX18_HW_ defines */ @@ -80,7 +82,8 @@ static const char * const hw_devicenames[] = { "cs5345", "cx23418_DTV", "cx23418_AV", - "gpio_audio_mux", + "gpio_mux", + "gpio_reset_ctrl", }; int cx18_i2c_register(struct cx18 *cx, unsigned idx) @@ -262,7 +265,8 @@ int init_cx18_i2c(struct cx18 *cx) cx18_setscl(&cx->i2c_algo_cb_data[1], 1); cx18_setsda(&cx->i2c_algo_cb_data[1], 1); - cx18_reset_i2c_slaves_gpio(cx); + cx18_call_hw(cx, CX18_HW_GPIO_RESET_CTRL, + core, reset, (u32) CX18_GPIO_RESET_I2C); return i2c_bit_add_bus(&cx->i2c_adap[0]) || i2c_bit_add_bus(&cx->i2c_adap[1]); diff --git a/drivers/media/video/cx18/cx18-ioctl.c b/drivers/media/video/cx18/cx18-ioctl.c index 13ebd4a70f0d..e4c9e3d8bacd 100644 --- a/drivers/media/video/cx18/cx18-ioctl.c +++ b/drivers/media/video/cx18/cx18-ioctl.c @@ -940,7 +940,8 @@ static long cx18_default(struct file *file, void *fh, int cmd, void *arg) u32 val = *(u32 *)arg; if ((val == 0) || (val & 0x01)) - cx18_reset_ir_gpio(&cx->i2c_algo_cb_data[0]); + cx18_call_hw(cx, CX18_HW_GPIO_RESET_CTRL, core, reset, + (u32) CX18_GPIO_RESET_Z8F0811); break; } diff --git a/drivers/media/video/cx18/cx18-streams.c b/drivers/media/video/cx18/cx18-streams.c index 1d17884b3b0d..ce65cc6c86e8 100644 --- a/drivers/media/video/cx18/cx18-streams.c +++ b/drivers/media/video/cx18/cx18-streams.c @@ -32,7 +32,6 @@ #include "cx18-streams.h" #include "cx18-cards.h" #include "cx18-scb.h" -#include "cx18-av-core.h" #include "cx18-dvb.h" #define CX18_DSP0_INTERRUPT_MASK 0xd0004C diff --git a/drivers/media/video/cx18/cx18-vbi.c b/drivers/media/video/cx18/cx18-vbi.c index 91c21dce607f..a81fe2e985f2 100644 --- a/drivers/media/video/cx18/cx18-vbi.c +++ b/drivers/media/video/cx18/cx18-vbi.c @@ -25,7 +25,6 @@ #include "cx18-vbi.h" #include "cx18-ioctl.h" #include "cx18-queue.h" -#include "cx18-av-core.h" /* * Raster Reference/Protection (RP) bytes, used in Start/End Active diff --git a/drivers/media/video/cx18/cx18-video.c b/drivers/media/video/cx18/cx18-video.c index fabacb0f87c6..6fdadedf17a8 100644 --- a/drivers/media/video/cx18/cx18-video.c +++ b/drivers/media/video/cx18/cx18-video.c @@ -21,7 +21,6 @@ #include "cx18-driver.h" #include "cx18-video.h" -#include "cx18-av-core.h" #include "cx18-cards.h" void cx18_video_set_io(struct cx18 *cx) -- cgit v1.2.3 From 6da6bf5e43f409672f5525657ff59282e160c59f Mon Sep 17 00:00:00 2001 From: Andy Walls Date: Sat, 21 Feb 2009 19:53:54 -0300 Subject: V4L/DVB (10760): cx18: Fix a memory leak of buffers used for sliced VBI insertion We leaked buffers every time a device was removed, if the user had enabled sliced VBI insertion into the MPEG stream. MythTV uses that. Signed-off-by: Andy Walls Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx18/cx18-driver.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/cx18/cx18-driver.c b/drivers/media/video/cx18/cx18-driver.c index 79b3bf5bcec1..544abbfb843e 100644 --- a/drivers/media/video/cx18/cx18-driver.c +++ b/drivers/media/video/cx18/cx18-driver.c @@ -1066,6 +1066,7 @@ static void cx18_remove(struct pci_dev *pci_dev) { struct v4l2_device *v4l2_dev = pci_get_drvdata(pci_dev); struct cx18 *cx = to_cx18(v4l2_dev); + int i; CX18_DEBUG_INFO("Removing Card\n"); @@ -1095,7 +1096,10 @@ static void cx18_remove(struct pci_dev *pci_dev) release_mem_region(cx->base_addr, CX18_MEM_SIZE); pci_disable_device(cx->pci_dev); - /* FIXME - we leak cx->vbi.sliced_mpeg_data[i] allocations */ + + if (cx->vbi.sliced_mpeg_data[0] != NULL) + for (i = 0; i < CX18_VBI_FRAMES; i++) + kfree(cx->vbi.sliced_mpeg_data[i]); CX18_INFO("Removed %s\n", cx->card_name); -- cgit v1.2.3 From 6246d4e1b30aa9404d2603dc09a823aba36d9c13 Mon Sep 17 00:00:00 2001 From: Andy Walls Date: Sat, 21 Feb 2009 22:27:37 -0300 Subject: V4L/DVB (10761): cx18: Change log lines for internal subdevs and fix tveeprom reads Give messages originating from internal subdevs a header using the subdev's name. Fixed an uninitialized variable problem with reading the EEPROM, noticed from log output. Got rid of the unused cx18_av_exit() function. Signed-off-by: Andy Walls Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx18/cx18-av-core.c | 142 +++++++++++++++------------- drivers/media/video/cx18/cx18-av-core.h | 1 - drivers/media/video/cx18/cx18-av-firmware.c | 7 +- drivers/media/video/cx18/cx18-driver.c | 1 + drivers/media/video/cx18/cx18-driver.h | 49 ++++++++++ drivers/media/video/cx18/cx18-gpio.c | 12 +-- 6 files changed, 135 insertions(+), 77 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/cx18/cx18-av-core.c b/drivers/media/video/cx18/cx18-av-core.c index 2128070154d3..cf256a999bd4 100644 --- a/drivers/media/video/cx18/cx18-av-core.c +++ b/drivers/media/video/cx18/cx18-av-core.c @@ -247,6 +247,7 @@ static int cx18_av_init(struct v4l2_subdev *sd, u32 val) void cx18_av_std_setup(struct cx18 *cx) { struct cx18_av_state *state = &cx->av_state; + struct v4l2_subdev *sd = &state->sd; v4l2_std_id std = state->std; int hblank, hactive, burst, vblank, vactive, sc; int vblank656, src_decimation; @@ -334,33 +335,35 @@ void cx18_av_std_setup(struct cx18 *cx) pll_int = cx18_av_read(cx, 0x108); pll_frac = cx18_av_read4(cx, 0x10c) & 0x1ffffff; pll_post = cx18_av_read(cx, 0x109); - CX18_DEBUG_INFO("PLL regs = int: %u, frac: %u, post: %u\n", - pll_int, pll_frac, pll_post); + CX18_DEBUG_INFO_DEV(sd, "PLL regs = int: %u, frac: %u, post: %u\n", + pll_int, pll_frac, pll_post); if (pll_post) { int fin, fsc, pll; pll = (28636360L * ((((u64)pll_int) << 25) + pll_frac)) >> 25; pll /= pll_post; - CX18_DEBUG_INFO("PLL = %d.%06d MHz\n", - pll / 1000000, pll % 1000000); - CX18_DEBUG_INFO("PLL/8 = %d.%06d MHz\n", - pll / 8000000, (pll / 8) % 1000000); + CX18_DEBUG_INFO_DEV(sd, "PLL = %d.%06d MHz\n", + pll / 1000000, pll % 1000000); + CX18_DEBUG_INFO_DEV(sd, "PLL/8 = %d.%06d MHz\n", + pll / 8000000, (pll / 8) % 1000000); fin = ((u64)src_decimation * pll) >> 12; - CX18_DEBUG_INFO("ADC Sampling freq = %d.%06d MHz\n", - fin / 1000000, fin % 1000000); + CX18_DEBUG_INFO_DEV(sd, "ADC Sampling freq = %d.%06d MHz\n", + fin / 1000000, fin % 1000000); fsc = (((u64)sc) * pll) >> 24L; - CX18_DEBUG_INFO("Chroma sub-carrier freq = %d.%06d MHz\n", - fsc / 1000000, fsc % 1000000); - - CX18_DEBUG_INFO("hblank %i, hactive %i, " - "vblank %i , vactive %i, vblank656 %i, src_dec %i," - "burst 0x%02x, luma_lpf %i, uv_lpf %i, comb 0x%02x," - " sc 0x%06x\n", - hblank, hactive, vblank, vactive, vblank656, - src_decimation, burst, luma_lpf, uv_lpf, comb, sc); + CX18_DEBUG_INFO_DEV(sd, + "Chroma sub-carrier freq = %d.%06d MHz\n", + fsc / 1000000, fsc % 1000000); + + CX18_DEBUG_INFO_DEV(sd, "hblank %i, hactive %i, vblank %i, " + "vactive %i, vblank656 %i, src_dec %i, " + "burst 0x%02x, luma_lpf %i, uv_lpf %i, " + "comb 0x%02x, sc 0x%06x\n", + hblank, hactive, vblank, vactive, vblank656, + src_decimation, burst, luma_lpf, uv_lpf, + comb, sc); } /* Sets horizontal blanking delay and active lines */ @@ -474,13 +477,14 @@ static int set_input(struct cx18 *cx, enum cx18_av_video_input vid_input, enum cx18_av_audio_input aud_input) { struct cx18_av_state *state = &cx->av_state; + struct v4l2_subdev *sd = &state->sd; u8 is_composite = (vid_input >= CX18_AV_COMPOSITE1 && vid_input <= CX18_AV_COMPOSITE8); u8 reg; u8 v; - CX18_DEBUG_INFO("decoder set video input %d, audio input %d\n", - vid_input, aud_input); + CX18_DEBUG_INFO_DEV(sd, "decoder set video input %d, audio input %d\n", + vid_input, aud_input); if (is_composite) { reg = 0xf0 + (vid_input - CX18_AV_COMPOSITE1); @@ -493,8 +497,8 @@ static int set_input(struct cx18 *cx, enum cx18_av_video_input vid_input, luma > CX18_AV_SVIDEO_LUMA8 || chroma < CX18_AV_SVIDEO_CHROMA4 || chroma > CX18_AV_SVIDEO_CHROMA8) { - CX18_ERR("0x%04x is not a valid video input!\n", - vid_input); + CX18_ERR_DEV(sd, "0x%04x is not a valid video input!\n", + vid_input); return -EINVAL; } reg = 0xf0 + ((luma - CX18_AV_SVIDEO_LUMA1) >> 4); @@ -519,7 +523,8 @@ static int set_input(struct cx18 *cx, enum cx18_av_video_input vid_input, case CX18_AV_AUDIO8: reg &= ~0xc0; reg |= 0x40; break; default: - CX18_ERR("0x%04x is not a valid audio input!\n", aud_input); + CX18_ERR_DEV(sd, "0x%04x is not a valid audio input!\n", + aud_input); return -EINVAL; } @@ -685,7 +690,7 @@ static int cx18_av_s_std(struct v4l2_subdev *sd, v4l2_std_id norm) fmt = 0xc; } - CX18_DEBUG_INFO("changing video std to fmt %i\n", fmt); + CX18_DEBUG_INFO_DEV(sd, "changing video std to fmt %i\n", fmt); /* Follow step 9 of section 3.16 in the cx18_av datasheet. Without this PAL may display a vertical ghosting effect. @@ -717,8 +722,8 @@ static int cx18_av_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) switch (ctrl->id) { case V4L2_CID_BRIGHTNESS: if (ctrl->value < 0 || ctrl->value > 255) { - CX18_ERR("invalid brightness setting %d\n", - ctrl->value); + CX18_ERR_DEV(sd, "invalid brightness setting %d\n", + ctrl->value); return -ERANGE; } @@ -727,8 +732,8 @@ static int cx18_av_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) case V4L2_CID_CONTRAST: if (ctrl->value < 0 || ctrl->value > 127) { - CX18_ERR("invalid contrast setting %d\n", - ctrl->value); + CX18_ERR_DEV(sd, "invalid contrast setting %d\n", + ctrl->value); return -ERANGE; } @@ -737,8 +742,8 @@ static int cx18_av_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) case V4L2_CID_SATURATION: if (ctrl->value < 0 || ctrl->value > 127) { - CX18_ERR("invalid saturation setting %d\n", - ctrl->value); + CX18_ERR_DEV(sd, "invalid saturation setting %d\n", + ctrl->value); return -ERANGE; } @@ -748,7 +753,8 @@ static int cx18_av_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) case V4L2_CID_HUE: if (ctrl->value < -128 || ctrl->value > 127) { - CX18_ERR("invalid hue setting %d\n", ctrl->value); + CX18_ERR_DEV(sd, "invalid hue setting %d\n", + ctrl->value); return -ERANGE; } @@ -865,8 +871,8 @@ static int cx18_av_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt) if ((pix->width * 16 < Hsrc) || (Hsrc < pix->width) || (Vlines * 8 < Vsrc) || (Vsrc < Vlines)) { - CX18_ERR("%dx%d is not a valid size!\n", - pix->width, pix->height); + CX18_ERR_DEV(sd, "%dx%d is not a valid size!\n", + pix->width, pix->height); return -ERANGE; } @@ -883,8 +889,9 @@ static int cx18_av_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt) else filter = 3; - CX18_DEBUG_INFO("decoder set size %dx%d -> scale %ux%u\n", - pix->width, pix->height, HSC, VSC); + CX18_DEBUG_INFO_DEV(sd, + "decoder set size %dx%d -> scale %ux%u\n", + pix->width, pix->height, HSC, VSC); /* HSCALE=HSC */ cx18_av_write(cx, 0x418, HSC & 0xff); @@ -913,7 +920,7 @@ static int cx18_av_s_stream(struct v4l2_subdev *sd, int enable) { struct cx18 *cx = v4l2_get_subdevdata(sd); - CX18_DEBUG_INFO("%s output\n", enable ? "enable" : "disable"); + CX18_DEBUG_INFO_DEV(sd, "%s output\n", enable ? "enable" : "disable"); if (enable) { cx18_av_write(cx, 0x115, 0x8c); cx18_av_write(cx, 0x116, 0x07); @@ -936,34 +943,40 @@ static void log_video_status(struct cx18 *cx) }; struct cx18_av_state *state = &cx->av_state; + struct v4l2_subdev *sd = &state->sd; u8 vidfmt_sel = cx18_av_read(cx, 0x400) & 0xf; u8 gen_stat1 = cx18_av_read(cx, 0x40d); u8 gen_stat2 = cx18_av_read(cx, 0x40e); int vid_input = state->vid_input; - CX18_INFO("Video signal: %spresent\n", - (gen_stat2 & 0x20) ? "" : "not "); - CX18_INFO("Detected format: %s\n", - fmt_strs[gen_stat1 & 0xf]); + CX18_INFO_DEV(sd, "Video signal: %spresent\n", + (gen_stat2 & 0x20) ? "" : "not "); + CX18_INFO_DEV(sd, "Detected format: %s\n", + fmt_strs[gen_stat1 & 0xf]); - CX18_INFO("Specified standard: %s\n", - vidfmt_sel ? fmt_strs[vidfmt_sel] : "automatic detection"); + CX18_INFO_DEV(sd, "Specified standard: %s\n", + vidfmt_sel ? fmt_strs[vidfmt_sel] + : "automatic detection"); if (vid_input >= CX18_AV_COMPOSITE1 && vid_input <= CX18_AV_COMPOSITE8) { - CX18_INFO("Specified video input: Composite %d\n", - vid_input - CX18_AV_COMPOSITE1 + 1); + CX18_INFO_DEV(sd, "Specified video input: Composite %d\n", + vid_input - CX18_AV_COMPOSITE1 + 1); } else { - CX18_INFO("Specified video input: S-Video (Luma In%d, Chroma In%d)\n", - (vid_input & 0xf0) >> 4, (vid_input & 0xf00) >> 8); + CX18_INFO_DEV(sd, "Specified video input: " + "S-Video (Luma In%d, Chroma In%d)\n", + (vid_input & 0xf0) >> 4, + (vid_input & 0xf00) >> 8); } - CX18_INFO("Specified audioclock freq: %d Hz\n", state->audclk_freq); + CX18_INFO_DEV(sd, "Specified audioclock freq: %d Hz\n", + state->audclk_freq); } static void log_audio_status(struct cx18 *cx) { struct cx18_av_state *state = &cx->av_state; + struct v4l2_subdev *sd = &state->sd; u8 download_ctl = cx18_av_read(cx, 0x803); u8 mod_det_stat0 = cx18_av_read(cx, 0x804); u8 mod_det_stat1 = cx18_av_read(cx, 0x805); @@ -986,7 +999,7 @@ static void log_audio_status(struct cx18 *cx) case 0xfe: p = "forced mode"; break; default: p = "not defined"; break; } - CX18_INFO("Detected audio mode: %s\n", p); + CX18_INFO_DEV(sd, "Detected audio mode: %s\n", p); switch (mod_det_stat1) { case 0x00: p = "not defined"; break; @@ -1011,11 +1024,11 @@ static void log_audio_status(struct cx18 *cx) case 0xff: p = "no detected audio standard"; break; default: p = "not defined"; break; } - CX18_INFO("Detected audio standard: %s\n", p); - CX18_INFO("Audio muted: %s\n", - (mute_ctl & 0x2) ? "yes" : "no"); - CX18_INFO("Audio microcontroller: %s\n", - (download_ctl & 0x10) ? "running" : "stopped"); + CX18_INFO_DEV(sd, "Detected audio standard: %s\n", p); + CX18_INFO_DEV(sd, "Audio muted: %s\n", + (mute_ctl & 0x2) ? "yes" : "no"); + CX18_INFO_DEV(sd, "Audio microcontroller: %s\n", + (download_ctl & 0x10) ? "running" : "stopped"); switch (audio_config >> 4) { case 0x00: p = "undefined"; break; @@ -1036,7 +1049,7 @@ static void log_audio_status(struct cx18 *cx) case 0x0f: p = "automatic detection"; break; default: p = "undefined"; break; } - CX18_INFO("Configured audio standard: %s\n", p); + CX18_INFO_DEV(sd, "Configured audio standard: %s\n", p); if ((audio_config >> 4) < 0xF) { switch (audio_config & 0xF) { @@ -1050,7 +1063,7 @@ static void log_audio_status(struct cx18 *cx) case 0x07: p = "DUAL3 (AB)"; break; default: p = "undefined"; } - CX18_INFO("Configured audio mode: %s\n", p); + CX18_INFO_DEV(sd, "Configured audio mode: %s\n", p); } else { switch (audio_config & 0xF) { case 0x00: p = "BG"; break; @@ -1068,14 +1081,14 @@ static void log_audio_status(struct cx18 *cx) case 0x0f: p = "automatic standard and mode detection"; break; default: p = "undefined"; break; } - CX18_INFO("Configured audio system: %s\n", p); + CX18_INFO_DEV(sd, "Configured audio system: %s\n", p); } if (aud_input) - CX18_INFO("Specified audio input: Tuner (In%d)\n", - aud_input); + CX18_INFO_DEV(sd, "Specified audio input: Tuner (In%d)\n", + aud_input); else - CX18_INFO("Specified audio input: External\n"); + CX18_INFO_DEV(sd, "Specified audio input: External\n"); switch (pref_mode & 0xf) { case 0: p = "mono/language A"; break; @@ -1088,14 +1101,14 @@ static void log_audio_status(struct cx18 *cx) case 7: p = "language AB"; break; default: p = "undefined"; break; } - CX18_INFO("Preferred audio mode: %s\n", p); + CX18_INFO_DEV(sd, "Preferred audio mode: %s\n", p); if ((audio_config & 0xf) == 0xf) { switch ((afc0 >> 3) & 0x1) { case 0: p = "system DK"; break; case 1: p = "system L"; break; } - CX18_INFO("Selected 65 MHz format: %s\n", p); + CX18_INFO_DEV(sd, "Selected 65 MHz format: %s\n", p); switch (afc0 & 0x7) { case 0: p = "Chroma"; break; @@ -1105,7 +1118,7 @@ static void log_audio_status(struct cx18 *cx) case 4: p = "autodetect"; break; default: p = "undefined"; break; } - CX18_INFO("Selected 45 MHz format: %s\n", p); + CX18_INFO_DEV(sd, "Selected 45 MHz format: %s\n", p); } } @@ -1229,12 +1242,7 @@ int cx18_av_probe(struct cx18 *cx) v4l2_subdev_init(sd, &cx18_av_ops); v4l2_set_subdevdata(sd, cx); snprintf(sd->name, sizeof(sd->name), - "%s internal A/V decoder", cx->v4l2_dev.name); + "%s %03x", cx->v4l2_dev.name, (state->rev >> 4)); sd->grp_id = CX18_HW_418_AV; return v4l2_device_register_subdev(&cx->v4l2_dev, sd); } - -void cx18_av_exit(struct cx18 *cx, struct v4l2_subdev *sd) -{ - v4l2_device_unregister_subdev(&cx->av_state.sd); -} diff --git a/drivers/media/video/cx18/cx18-av-core.h b/drivers/media/video/cx18/cx18-av-core.h index cd9c0e70f1fc..fd0df4151211 100644 --- a/drivers/media/video/cx18/cx18-av-core.h +++ b/drivers/media/video/cx18/cx18-av-core.h @@ -343,7 +343,6 @@ int cx18_av_and_or4(struct cx18 *cx, u16 addr, u32 mask, u32 value); void cx18_av_std_setup(struct cx18 *cx); int cx18_av_probe(struct cx18 *cx); -void cx18_av_exit(struct cx18 *cx, struct v4l2_subdev *sd); /* ----------------------------------------------------------------------- */ /* cx18_av-firmware.c */ diff --git a/drivers/media/video/cx18/cx18-av-firmware.c b/drivers/media/video/cx18/cx18-av-firmware.c index 940ea9352115..49a55cc8d839 100644 --- a/drivers/media/video/cx18/cx18-av-firmware.c +++ b/drivers/media/video/cx18/cx18-av-firmware.c @@ -29,6 +29,7 @@ int cx18_av_loadfw(struct cx18 *cx) { + struct v4l2_subdev *sd = &cx->av_state.sd; const struct firmware *fw = NULL; u32 size; u32 v; @@ -37,7 +38,7 @@ int cx18_av_loadfw(struct cx18 *cx) int retries1 = 0; if (request_firmware(&fw, FWFILE, &cx->pci_dev->dev) != 0) { - CX18_ERR("unable to open firmware %s\n", FWFILE); + CX18_ERR_DEV(sd, "unable to open firmware %s\n", FWFILE); return -EINVAL; } @@ -88,7 +89,7 @@ int cx18_av_loadfw(struct cx18 *cx) retries1++; } if (retries1 >= 5) { - CX18_ERR("unable to load firmware %s\n", FWFILE); + CX18_ERR_DEV(sd, "unable to load firmware %s\n", FWFILE); release_firmware(fw); return -EIO; } @@ -143,6 +144,6 @@ int cx18_av_loadfw(struct cx18 *cx) release_firmware(fw); - CX18_INFO("loaded %s firmware (%d bytes)\n", FWFILE, size); + CX18_INFO_DEV(sd, "loaded %s firmware (%d bytes)\n", FWFILE, size); return 0; } diff --git a/drivers/media/video/cx18/cx18-driver.c b/drivers/media/video/cx18/cx18-driver.c index 544abbfb843e..fcc40bf37f2f 100644 --- a/drivers/media/video/cx18/cx18-driver.c +++ b/drivers/media/video/cx18/cx18-driver.c @@ -272,6 +272,7 @@ void cx18_read_eeprom(struct cx18 *cx, struct tveeprom *tv) struct i2c_client c; u8 eedata[256]; + memset(&c, 0, sizeof(c)); strncpy(c.name, "cx18 tveeprom tmp", sizeof(c.name)); c.name[sizeof(c.name)-1] = '\0'; c.adapter = &cx->i2c_adap[0]; diff --git a/drivers/media/video/cx18/cx18-driver.h b/drivers/media/video/cx18/cx18-driver.h index 9ee608063b49..5e1ae91d5325 100644 --- a/drivers/media/video/cx18/cx18-driver.h +++ b/drivers/media/video/cx18/cx18-driver.h @@ -179,6 +179,55 @@ #define CX18_WARN(fmt, args...) v4l2_warn(&cx->v4l2_dev, fmt , ## args) #define CX18_INFO(fmt, args...) v4l2_info(&cx->v4l2_dev, fmt , ## args) +/* Messages for internal subdevs to use */ +#define CX18_DEBUG_DEV(x, dev, type, fmt, args...) \ + do { \ + if ((x) & cx18_debug) \ + v4l2_info(dev, " " type ": " fmt , ## args); \ + } while (0) +#define CX18_DEBUG_WARN_DEV(dev, fmt, args...) \ + CX18_DEBUG_DEV(CX18_DBGFLG_WARN, dev, "warning", fmt , ## args) +#define CX18_DEBUG_INFO_DEV(dev, fmt, args...) \ + CX18_DEBUG_DEV(CX18_DBGFLG_INFO, dev, "info", fmt , ## args) +#define CX18_DEBUG_API_DEV(dev, fmt, args...) \ + CX18_DEBUG_DEV(CX18_DBGFLG_API, dev, "api", fmt , ## args) +#define CX18_DEBUG_DMA_DEV(dev, fmt, args...) \ + CX18_DEBUG_DEV(CX18_DBGFLG_DMA, dev, "dma", fmt , ## args) +#define CX18_DEBUG_IOCTL_DEV(dev, fmt, args...) \ + CX18_DEBUG_DEV(CX18_DBGFLG_IOCTL, dev, "ioctl", fmt , ## args) +#define CX18_DEBUG_FILE_DEV(dev, fmt, args...) \ + CX18_DEBUG_DEV(CX18_DBGFLG_FILE, dev, "file", fmt , ## args) +#define CX18_DEBUG_I2C_DEV(dev, fmt, args...) \ + CX18_DEBUG_DEV(CX18_DBGFLG_I2C, dev, "i2c", fmt , ## args) +#define CX18_DEBUG_IRQ_DEV(dev, fmt, args...) \ + CX18_DEBUG_DEV(CX18_DBGFLG_IRQ, dev, "irq", fmt , ## args) + +#define CX18_DEBUG_HIGH_VOL_DEV(x, dev, type, fmt, args...) \ + do { \ + if (((x) & cx18_debug) && (cx18_debug & CX18_DBGFLG_HIGHVOL)) \ + v4l2_info(dev, " " type ": " fmt , ## args); \ + } while (0) +#define CX18_DEBUG_HI_WARN_DEV(dev, fmt, args...) \ + CX18_DEBUG_HIGH_VOL_DEV(CX18_DBGFLG_WARN, dev, "warning", fmt , ## args) +#define CX18_DEBUG_HI_INFO_DEV(dev, fmt, args...) \ + CX18_DEBUG_HIGH_VOL_DEV(CX18_DBGFLG_INFO, dev, "info", fmt , ## args) +#define CX18_DEBUG_HI_API_DEV(dev, fmt, args...) \ + CX18_DEBUG_HIGH_VOL_DEV(CX18_DBGFLG_API, dev, "api", fmt , ## args) +#define CX18_DEBUG_HI_DMA_DEV(dev, fmt, args...) \ + CX18_DEBUG_HIGH_VOL_DEV(CX18_DBGFLG_DMA, dev, "dma", fmt , ## args) +#define CX18_DEBUG_HI_IOCTL_DEV(dev, fmt, args...) \ + CX18_DEBUG_HIGH_VOL_DEV(CX18_DBGFLG_IOCTL, dev, "ioctl", fmt , ## args) +#define CX18_DEBUG_HI_FILE_DEV(dev, fmt, args...) \ + CX18_DEBUG_HIGH_VOL_DEV(CX18_DBGFLG_FILE, dev, "file", fmt , ## args) +#define CX18_DEBUG_HI_I2C_DEV(dev, fmt, args...) \ + CX18_DEBUG_HIGH_VOL_DEV(CX18_DBGFLG_I2C, dev, "i2c", fmt , ## args) +#define CX18_DEBUG_HI_IRQ_DEV(dev, fmt, args...) \ + CX18_DEBUG_HIGH_VOL_DEV(CX18_DBGFLG_IRQ, dev, "irq", fmt , ## args) + +#define CX18_ERR_DEV(dev, fmt, args...) v4l2_err(dev, fmt , ## args) +#define CX18_WARN_DEV(dev, fmt, args...) v4l2_warn(dev, fmt , ## args) +#define CX18_INFO_DEV(dev, fmt, args...) v4l2_info(dev, fmt , ## args) + /* Values for CX18_API_DEC_PLAYBACK_SPEED mpeg_frame_type_mask parameter: */ #define MPEG_FRAME_TYPE_IFRAME 1 #define MPEG_FRAME_TYPE_IFRAME_PFRAME 3 diff --git a/drivers/media/video/cx18/cx18-gpio.c b/drivers/media/video/cx18/cx18-gpio.c index dcc19b1c541d..5518d1424f8f 100644 --- a/drivers/media/video/cx18/cx18-gpio.c +++ b/drivers/media/video/cx18/cx18-gpio.c @@ -110,8 +110,8 @@ static int gpiomux_log_status(struct v4l2_subdev *sd) struct cx18 *cx = v4l2_get_subdevdata(sd); mutex_lock(&cx->gpio_lock); - CX18_INFO("GPIO: direction 0x%08x, value 0x%08x\n", - cx->gpio_dir, cx->gpio_val); + CX18_INFO_DEV(sd, "GPIO: direction 0x%08x, value 0x%08x\n", + cx->gpio_dir, cx->gpio_val); mutex_unlock(&cx->gpio_lock); return 0; } @@ -205,8 +205,8 @@ static int resetctrl_log_status(struct v4l2_subdev *sd) struct cx18 *cx = v4l2_get_subdevdata(sd); mutex_lock(&cx->gpio_lock); - CX18_INFO("GPIO: direction 0x%08x, value 0x%08x\n", - cx->gpio_dir, cx->gpio_val); + CX18_INFO_DEV(sd, "GPIO: direction 0x%08x, value 0x%08x\n", + cx->gpio_dir, cx->gpio_val); mutex_unlock(&cx->gpio_lock); return 0; } @@ -297,12 +297,12 @@ int cx18_gpio_register(struct cx18 *cx, u32 hw) case CX18_HW_GPIO_MUX: sd = &cx->sd_gpiomux; ops = &gpiomux_ops; - str = "gpio mux"; + str = "gpio-mux"; break; case CX18_HW_GPIO_RESET_CTRL: sd = &cx->sd_resetctrl; ops = &resetctrl_ops; - str = "gpio reset ctrl"; + str = "gpio-reset-ctrl"; break; default: return -EINVAL; -- cgit v1.2.3 From 8d037ed14d1be0eff67fed0f9b1b333b0d52ec78 Mon Sep 17 00:00:00 2001 From: Andy Walls Date: Sat, 21 Feb 2009 22:35:11 -0300 Subject: V4L/DVB (10762): cx18: Get rid of unused variables related to video output Remove variables that were holdovers from ivtv for supporting the CX23415 MPEG decoder output. Signed-off-by: Andy Walls Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx18/cx18-driver.c | 8 +++----- drivers/media/video/cx18/cx18-driver.h | 3 --- 2 files changed, 3 insertions(+), 8 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/cx18/cx18-driver.c b/drivers/media/video/cx18/cx18-driver.c index fcc40bf37f2f..f3b0c946d45d 100644 --- a/drivers/media/video/cx18/cx18-driver.c +++ b/drivers/media/video/cx18/cx18-driver.c @@ -884,13 +884,11 @@ static int __devinit cx18_probe(struct pci_dev *pci_dev, cx18_init_subdevs(cx); - if (cx->std & V4L2_STD_525_60) { + if (cx->std & V4L2_STD_525_60) cx->is_60hz = 1; - cx->is_out_60hz = 1; - } else { + else cx->is_50hz = 1; - cx->is_out_50hz = 1; - } + cx->params.video_gop_size = cx->is_60hz ? 15 : 12; if (cx->options.radio > 0) diff --git a/drivers/media/video/cx18/cx18-driver.h b/drivers/media/video/cx18/cx18-driver.h index 5e1ae91d5325..ece4f281ef42 100644 --- a/drivers/media/video/cx18/cx18-driver.h +++ b/drivers/media/video/cx18/cx18-driver.h @@ -505,8 +505,6 @@ struct cx18 { const struct cx18_card_tuner_i2c *card_i2c; /* i2c addresses to probe for tuner */ u8 is_50hz; u8 is_60hz; - u8 is_out_50hz; /* FIXME - remove, we don't have an output decoder */ - u8 is_out_60hz; /* FIXME - remove, we don't have an output decoder */ u8 nof_inputs; /* number of video inputs */ u8 nof_audio_inputs; /* number of audio inputs */ u16 buffer_id; /* buffer ID counter */ @@ -591,7 +589,6 @@ struct cx18 { /* codec settings */ u32 audio_input; u32 active_input; - u32 active_output; v4l2_std_id std; v4l2_std_id tuner_std; /* The norm of the tuner (fixed) */ }; -- cgit v1.2.3 From f85953d324dea12ca9c8bcd5bb0a7c22da690a9f Mon Sep 17 00:00:00 2001 From: Andy Walls Date: Sat, 21 Feb 2009 22:40:52 -0300 Subject: V4L/DVB (10763): cx18: Increment version number due to significant changes for v4l2_subdevs Driver is now at version 1.1.0. Signed-off-by: Andy Walls Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx18/cx18-version.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/cx18/cx18-version.h b/drivers/media/video/cx18/cx18-version.h index 84c0ff13b607..bd9bd44da791 100644 --- a/drivers/media/video/cx18/cx18-version.h +++ b/drivers/media/video/cx18/cx18-version.h @@ -24,8 +24,8 @@ #define CX18_DRIVER_NAME "cx18" #define CX18_DRIVER_VERSION_MAJOR 1 -#define CX18_DRIVER_VERSION_MINOR 0 -#define CX18_DRIVER_VERSION_PATCHLEVEL 4 +#define CX18_DRIVER_VERSION_MINOR 1 +#define CX18_DRIVER_VERSION_PATCHLEVEL 0 #define CX18_VERSION __stringify(CX18_DRIVER_VERSION_MAJOR) "." __stringify(CX18_DRIVER_VERSION_MINOR) "." __stringify(CX18_DRIVER_VERSION_PATCHLEVEL) #define CX18_DRIVER_VERSION KERNEL_VERSION(CX18_DRIVER_VERSION_MAJOR, \ -- cgit v1.2.3 From 006e7179577b40be0b97a93c11def536a64abac0 Mon Sep 17 00:00:00 2001 From: Andy Walls Date: Sat, 21 Feb 2009 22:44:50 -0300 Subject: V4L/DVB (10764): cx18: Disable AC3 controls as the firmware doesn't support AC3 Signed-off-by: Andy Walls Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx18/cx18-driver.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/cx18/cx18-driver.c b/drivers/media/video/cx18/cx18-driver.c index f3b0c946d45d..0d24e2297457 100644 --- a/drivers/media/video/cx18/cx18-driver.c +++ b/drivers/media/video/cx18/cx18-driver.c @@ -587,7 +587,7 @@ static int __devinit cx18_init_struct1(struct cx18 *cx) (cx->params.video_median_filter_type << 2); cx->params.port = CX2341X_PORT_MEMORY; cx->params.capabilities = - CX2341X_CAP_HAS_TS | CX2341X_CAP_HAS_AC3 | CX2341X_CAP_HAS_SLICED_VBI; + CX2341X_CAP_HAS_TS | CX2341X_CAP_HAS_SLICED_VBI; init_waitqueue_head(&cx->cap_w); init_waitqueue_head(&cx->mb_apu_waitq); init_waitqueue_head(&cx->mb_cpu_waitq); -- cgit v1.2.3 From 85f8841e8a17367a85a60b6d30eff7858d9d1598 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 27 Feb 2009 09:32:31 -0300 Subject: V4L/DVB (10769): Update dependencies of the modules converted to V4L2 Several modules were converted to V4L2 API. Update their dependencies on Kconfig. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/Kconfig | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig index bb7df8c18b03..6c26618b8869 100644 --- a/drivers/media/video/Kconfig +++ b/drivers/media/video/Kconfig @@ -253,7 +253,7 @@ comment "Video decoders" config VIDEO_BT819 tristate "BT819A VideoStream decoder" - depends on VIDEO_V4L1 && I2C + depends on VIDEO_V4L2 && I2C ---help--- Support for BT819A video decoder. @@ -262,7 +262,7 @@ config VIDEO_BT819 config VIDEO_BT856 tristate "BT856 VideoStream decoder" - depends on VIDEO_V4L1 && I2C + depends on VIDEO_V4L2 && I2C ---help--- Support for BT856 video decoder. @@ -271,7 +271,7 @@ config VIDEO_BT856 config VIDEO_BT866 tristate "BT866 VideoStream decoder" - depends on VIDEO_V4L1 && I2C + depends on VIDEO_V4L2 && I2C ---help--- Support for BT866 video decoder. @@ -280,7 +280,7 @@ config VIDEO_BT866 config VIDEO_KS0127 tristate "KS0127 video decoder" - depends on VIDEO_V4L1 && I2C + depends on VIDEO_V4L2 && I2C ---help--- Support for KS0127 video decoder. @@ -363,7 +363,7 @@ config VIDEO_TVP5150 config VIDEO_VPX3220 tristate "vpx3220a, vpx3216b & vpx3214c video decoders" - depends on VIDEO_V4L1 && I2C + depends on VIDEO_V4L2 && I2C ---help--- Support for VPX322x video decoders. @@ -401,7 +401,7 @@ config VIDEO_SAA7127 config VIDEO_SAA7185 tristate "Philips SAA7185 video encoder" - depends on VIDEO_V4L1 && I2C + depends on VIDEO_V4L2 && I2C ---help--- Support for the Philips SAA7185 video encoder. @@ -410,7 +410,7 @@ config VIDEO_SAA7185 config VIDEO_ADV7170 tristate "Analog Devices ADV7170 video encoder" - depends on VIDEO_V4L1 && I2C + depends on VIDEO_V4L2 && I2C ---help--- Support for the Analog Devices ADV7170 video encoder driver @@ -419,7 +419,7 @@ config VIDEO_ADV7170 config VIDEO_ADV7175 tristate "Analog Devices ADV7175 video encoder" - depends on VIDEO_V4L1 && I2C + depends on VIDEO_V4L2 && I2C ---help--- Support for the Analog Devices ADV7175 video encoder driver -- cgit v1.2.3 From 253bae5748010e218539603f1ec18f7fc6a03002 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Sat, 28 Feb 2009 08:09:24 -0300 Subject: V4L/DVB (10787): gspca - mars: Bad webcam register values tied to saturation. Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/mars.c | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/gspca/mars.c b/drivers/media/video/gspca/mars.c index 7f605ce3a7e5..ce065d363e8a 100644 --- a/drivers/media/video/gspca/mars.c +++ b/drivers/media/video/gspca/mars.c @@ -69,10 +69,10 @@ static struct ctrl sd_ctrls[] = { .id = V4L2_CID_SATURATION, .type = V4L2_CTRL_TYPE_INTEGER, .name = "Color", - .minimum = 0, - .maximum = 220, + .minimum = 1, + .maximum = 255, .step = 1, -#define COLOR_DEF 190 +#define COLOR_DEF 200 .default_value = COLOR_DEF, }, .set = sd_setcolors, @@ -191,7 +191,7 @@ static int sd_start(struct gspca_dev *gspca_dev) struct sd *sd = (struct sd *) gspca_dev; int err_code; u8 *data; - int i, val; + int i; data = gspca_dev->usb_buf; @@ -247,9 +247,11 @@ static int sd_start(struct gspca_dev *gspca_dev) data[0] = 0x5e; /* address */ data[1] = 0; /* reg 94, Y Gain (auto) */ /*jfm: from win trace*/ - val = sd->colors * 0x40 + 0x400; - data[2] = val; /* reg 0x5f/0x60 (LE) = saturation */ - data[3] = val >> 8; + /* reg 0x5f/0x60 (LE) = saturation */ + /* h (60): xxxx x100 + * l (5f): xxxx x000 */ + data[2] = sd->colors << 3; + data[3] = ((sd->colors >> 2) & 0xf8) | 0x04; data[4] = sd->brightness; /* reg 0x61 = brightness */ data[5] = 0x00; @@ -365,10 +367,11 @@ static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val) sd->colors = val; if (gspca_dev->streaming) { - val = val * 0x40 + 0x400; + + /* see sd_start */ gspca_dev->usb_buf[0] = 0x5f; - gspca_dev->usb_buf[1] = val; - gspca_dev->usb_buf[2] = val >> 8; + gspca_dev->usb_buf[1] = sd->colors << 3; + gspca_dev->usb_buf[2] = ((sd->colors >> 2) & 0xf8) | 0x04; reg_w(gspca_dev, 3); } return 0; -- cgit v1.2.3 From f985c7006756cb7da452815d4bf040c02decd044 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Sat, 28 Feb 2009 08:23:25 -0300 Subject: V4L/DVB (10788): gspca - vc032x: Bad matrix for sensor mi1310_soc. Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/vc032x.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/gspca/vc032x.c b/drivers/media/video/gspca/vc032x.c index 9f3d9f104e6e..ca96cbc98794 100644 --- a/drivers/media/video/gspca/vc032x.c +++ b/drivers/media/video/gspca/vc032x.c @@ -2277,7 +2277,7 @@ static int sd_start(struct gspca_dev *gspca_dev) break; case SENSOR_MI1310_SOC: GammaT = mi1320_gamma; - MatrixT = mi0360_matrix; + MatrixT = mi1320_matrix; switch (mode) { case 1: init = mi1310_socinitQVGA_JPG; /* 320x240 */ -- cgit v1.2.3 From 428c8d19167c4597adf4d164262c68befafde9bf Mon Sep 17 00:00:00 2001 From: Trent Piepho Date: Tue, 3 Mar 2009 18:51:52 -0300 Subject: V4L/DVB (10791): videodev: not possible to register NULL video_device video_register_device_index() checks if it was passed a NULL video_device pointer (which isn't allowed) _after_ it has already dereferenced it with video_get_drvdata(vdev). The checks are clearly pointless and can be removed, as the function would have crashed before reaching them if vdev ever was NULL. Signed-off-by: Trent Piepho Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/v4l2-dev.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/v4l2-dev.c b/drivers/media/video/v4l2-dev.c index 922b39e79b8e..231f5dbb18b4 100644 --- a/drivers/media/video/v4l2-dev.c +++ b/drivers/media/video/v4l2-dev.c @@ -366,12 +366,11 @@ int video_register_device_index(struct video_device *vdev, int type, int nr, /* A minor value of -1 marks this video device as never having been registered */ - if (vdev) - vdev->minor = -1; + vdev->minor = -1; /* the release callback MUST be present */ - WARN_ON(!vdev || !vdev->release); - if (!vdev || !vdev->release) + WARN_ON(!vdev->release); + if (!vdev->release) return -EINVAL; /* Part 1: check device type */ -- cgit v1.2.3 From 86b5aeacabb4451655c528c41d45ca05b753f72c Mon Sep 17 00:00:00 2001 From: Trent Piepho Date: Tue, 3 Mar 2009 18:52:57 -0300 Subject: V4L/DVB (10792): cx88: remove unnecessary forward declaration of cx88_core A recent patch added a forward declaration of cx88_core right before the main definition of that structure, which is obviously unneeded. Signed-off-by: Trent Piepho Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx88/cx88.h | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/cx88/cx88.h b/drivers/media/video/cx88/cx88.h index 6025fdd23344..3542061c7329 100644 --- a/drivers/media/video/cx88/cx88.h +++ b/drivers/media/video/cx88/cx88.h @@ -302,7 +302,6 @@ struct cx88_dmaqueue { struct btcx_riscmem stopper; u32 count; }; -struct cx88_core; struct cx88_core { struct list_head devlist; -- cgit v1.2.3 From 9cfb6a3f1b16e82fab97831265858aa2d1983883 Mon Sep 17 00:00:00 2001 From: Trent Piepho Date: Tue, 3 Mar 2009 20:44:45 -0300 Subject: V4L/DVB (10794): v4l2: Move code to zero querybuf output struct to v4l2_ioctl For VIDIOC_QUERYBUF only the first two fields, size and type, are used as input. The rest can be filled in by the driver as output. Most drivers do not actually use all the field and unused ones should be zeroed out. Some drivers have code to do this and some drivers should but don't. So put some zero out code in v4l2_ioctl so that all drivers using that system get it. The drivers that have zeroing code get that code removed. Some drivers checked that the type field was valid, but v4l2_ioctl already does this so those checks can be removed as well. Signed-off-by: Trent Piepho Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/meye.c | 4 ---- drivers/media/video/stk-webcam.c | 8 +------- drivers/media/video/usbvision/usbvision-video.c | 3 --- drivers/media/video/v4l2-ioctl.c | 5 +++++ drivers/media/video/zoran/zoran_driver.c | 7 +------ 5 files changed, 7 insertions(+), 20 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/meye.c b/drivers/media/video/meye.c index b76e33d5c867..163fb2b329df 100644 --- a/drivers/media/video/meye.c +++ b/drivers/media/video/meye.c @@ -1446,10 +1446,6 @@ static int vidioc_querybuf(struct file *file, void *fh, struct v4l2_buffer *buf) if (index < 0 || index >= gbuffers) return -EINVAL; - memset(buf, 0, sizeof(*buf)); - - buf->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - buf->index = index; buf->bytesused = meye.grab_buffer[index].size; buf->flags = V4L2_BUF_FLAG_MAPPED; diff --git a/drivers/media/video/stk-webcam.c b/drivers/media/video/stk-webcam.c index 26378cf390fc..686720d8bfed 100644 --- a/drivers/media/video/stk-webcam.c +++ b/drivers/media/video/stk-webcam.c @@ -1139,16 +1139,10 @@ static int stk_vidioc_reqbufs(struct file *filp, static int stk_vidioc_querybuf(struct file *filp, void *priv, struct v4l2_buffer *buf) { - int index; struct stk_camera *dev = priv; struct stk_sio_buffer *sbuf; - if (buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - return -EINVAL; - - index = buf->index; - - if (index < 0 || index >= dev->n_sbufs) + if (buf->index < 0 || buf->index >= dev->n_sbufs) return -EINVAL; sbuf = dev->sio_bufs + buf->index; *buf = sbuf->v4lbuf; diff --git a/drivers/media/video/usbvision/usbvision-video.c b/drivers/media/video/usbvision/usbvision-video.c index 33d79a5dad0f..863fcb31622f 100644 --- a/drivers/media/video/usbvision/usbvision-video.c +++ b/drivers/media/video/usbvision/usbvision-video.c @@ -788,9 +788,6 @@ static int vidioc_querybuf (struct file *file, /* FIXME : must control that buffers are mapped (VIDIOC_REQBUFS has been called) */ - if(vb->type != V4L2_CAP_VIDEO_CAPTURE) { - return -EINVAL; - } if(vb->index>=usbvision->num_frames) { return -EINVAL; } diff --git a/drivers/media/video/v4l2-ioctl.c b/drivers/media/video/v4l2-ioctl.c index 20a571f21577..175688e9489f 100644 --- a/drivers/media/video/v4l2-ioctl.c +++ b/drivers/media/video/v4l2-ioctl.c @@ -969,6 +969,11 @@ static long __video_do_ioctl(struct file *file, if (ret) break; + /* Zero out all fields starting with bytesysed, which is + * everything but index and type. */ + memset(0, &p->bytesused, + sizeof(*p) - offsetof(typeof(*p), bytesused)); + ret = ops->vidioc_querybuf(file, fh, p); if (!ret) dbgbuf(cmd, vfd, p); diff --git a/drivers/media/video/zoran/zoran_driver.c b/drivers/media/video/zoran/zoran_driver.c index daad93728cf9..5dcd56c9b947 100644 --- a/drivers/media/video/zoran/zoran_driver.c +++ b/drivers/media/video/zoran/zoran_driver.c @@ -2498,12 +2498,7 @@ static int zoran_querybuf(struct file *file, void *__fh, struct v4l2_buffer *buf { struct zoran_fh *fh = __fh; struct zoran *zr = fh->zr; - __u32 type = buf->type; - int index = buf->index, res; - - memset(buf, 0, sizeof(*buf)); - buf->type = type; - buf->index = index; + int res; mutex_lock(&zr->resource_lock); res = zoran_v4l2_buffer_status(file, buf, buf->index); -- cgit v1.2.3 From c253a17126d6e841720d5926c6d426745693676b Mon Sep 17 00:00:00 2001 From: Abylay Ospan Date: Tue, 3 Mar 2009 10:55:38 -0300 Subject: V4L/DVB (10796): Add init code for NetUP Dual DVB-S2 CI card Add init code for NetUP Dual DVB-S2 CI card The card based on cx23885 PCI-e bridge, CiMax SP2 Common Interface chips, STM lnbh24 LNB power chip, stv6110 tuners and stv0900 demodulator. Signed-off-by: Abylay Ospan Signed-off-by: Igor M. Liplianin Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx23885/netup-init.c | 125 +++++++++++++++++++++++++++++++ drivers/media/video/cx23885/netup-init.h | 25 +++++++ 2 files changed, 150 insertions(+) create mode 100644 drivers/media/video/cx23885/netup-init.c create mode 100644 drivers/media/video/cx23885/netup-init.h (limited to 'drivers/media/video') diff --git a/drivers/media/video/cx23885/netup-init.c b/drivers/media/video/cx23885/netup-init.c new file mode 100644 index 000000000000..f4893e69cd89 --- /dev/null +++ b/drivers/media/video/cx23885/netup-init.c @@ -0,0 +1,125 @@ +/* + * netup-init.c + * + * NetUP Dual DVB-S2 CI driver + * + * Copyright (C) 2009 NetUP Inc. + * Copyright (C) 2009 Igor M. Liplianin + * Copyright (C) 2009 Abylay Ospan + * + * 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. + */ + +#include "cx23885.h" + +static void i2c_av_write(struct i2c_adapter *i2c, u16 reg, u8 val) +{ + int ret; + u8 buf[3]; + struct i2c_msg msg = { + .addr = 0x88 >> 1, + .flags = 0, + .buf = buf, + .len = 3 + }; + + buf[0] = reg >> 8; + buf[1] = reg & 0xff; + buf[2] = val; + + ret = i2c_transfer(i2c, &msg, 1); + + if (ret != 1) + printk(KERN_ERR "%s: i2c write error!\n", __func__); +} + +static void i2c_av_write4(struct i2c_adapter *i2c, u16 reg, u32 val) +{ + int ret; + u8 buf[6]; + struct i2c_msg msg = { + .addr = 0x88 >> 1, + .flags = 0, + .buf = buf, + .len = 6 + }; + + buf[0] = reg >> 8; + buf[1] = reg & 0xff; + buf[2] = val & 0xff; + buf[3] = (val >> 8) & 0xff; + buf[4] = (val >> 16) & 0xff; + buf[5] = val >> 24; + + ret = i2c_transfer(i2c, &msg, 1); + + if (ret != 1) + printk(KERN_ERR "%s: i2c write error!\n", __func__); +} + +static u8 i2c_av_read(struct i2c_adapter *i2c, u16 reg) +{ + int ret; + u8 buf[2]; + struct i2c_msg msg = { + .addr = 0x88 >> 1, + .flags = 0, + .buf = buf, + .len = 2 + }; + + buf[0] = reg >> 8; + buf[1] = reg & 0xff; + + ret = i2c_transfer(i2c, &msg, 1); + + if (ret != 1) + printk(KERN_ERR "%s: i2c write error!\n", __func__); + + msg.flags = I2C_M_RD; + msg.len = 1; + + ret = i2c_transfer(i2c, &msg, 1); + + if (ret != 1) + printk(KERN_ERR "%s: i2c read error!\n", __func__); + + return buf[0]; +} + +static void i2c_av_and_or(struct i2c_adapter *i2c, u16 reg, unsigned and_mask, + u8 or_value) +{ + i2c_av_write(i2c, reg, (i2c_av_read(i2c, reg) & and_mask) | or_value); +} +/* set 27MHz on AUX_CLK */ +void netup_initialize(struct cx23885_dev *dev) +{ + struct cx23885_i2c *i2c_bus = &dev->i2c_bus[2]; + struct i2c_adapter *i2c = &i2c_bus->i2c_adap; + + /* Stop microcontroller */ + i2c_av_and_or(i2c, 0x803, ~0x10, 0x00); + + /* Aux PLL frac for 27 MHz */ + i2c_av_write4(i2c, 0x114, 0xea0eb3); + + /* Aux PLL int for 27 MHz */ + i2c_av_write4(i2c, 0x110, 0x090319); + + /* start microcontroller */ + i2c_av_and_or(i2c, 0x803, ~0x10, 0x10); +} diff --git a/drivers/media/video/cx23885/netup-init.h b/drivers/media/video/cx23885/netup-init.h new file mode 100644 index 000000000000..d26ae4b1590e --- /dev/null +++ b/drivers/media/video/cx23885/netup-init.h @@ -0,0 +1,25 @@ +/* + * netup-init.h + * + * NetUP Dual DVB-S2 CI driver + * + * Copyright (C) 2009 NetUP Inc. + * Copyright (C) 2009 Igor M. Liplianin + * Copyright (C) 2009 Abylay Ospan + * + * 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. + */ +extern void netup_initialize(struct cx23885_dev *dev); -- cgit v1.2.3 From b45c0551f94dbc160e94f48a034a51312acec81d Mon Sep 17 00:00:00 2001 From: Abylay Ospan Date: Tue, 3 Mar 2009 11:00:18 -0300 Subject: V4L/DVB (10797): Add EEPROM code for NetUP Dual DVB-S2 CI card. Signed-off-by: Abylay Ospan Signed-off-by: Igor M. Liplianin Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx23885/netup-eeprom.c | 107 +++++++++++++++++++++++++++++ drivers/media/video/cx23885/netup-eeprom.h | 42 +++++++++++ 2 files changed, 149 insertions(+) create mode 100644 drivers/media/video/cx23885/netup-eeprom.c create mode 100644 drivers/media/video/cx23885/netup-eeprom.h (limited to 'drivers/media/video') diff --git a/drivers/media/video/cx23885/netup-eeprom.c b/drivers/media/video/cx23885/netup-eeprom.c new file mode 100644 index 000000000000..042bbbbd48f8 --- /dev/null +++ b/drivers/media/video/cx23885/netup-eeprom.c @@ -0,0 +1,107 @@ + +/* + * netup-eeprom.c + * + * 24LC02 EEPROM driver in conjunction with NetUP Dual DVB-S2 CI card + * + * Copyright (C) 2009 NetUP Inc. + * Copyright (C) 2009 Abylay Ospan + * + * 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. + */ + +# +#include "cx23885.h" +#include "netup-eeprom.h" + +#define EEPROM_I2C_ADDR 0x50 + +int netup_eeprom_read(struct i2c_adapter *i2c_adap, u8 addr) +{ + int ret; + unsigned char buf[2]; + + /* Read from EEPROM */ + struct i2c_msg msg[] = { + { + .addr = EEPROM_I2C_ADDR, + .flags = 0, + .buf = &buf[0], + .len = 1 + }, { + .addr = EEPROM_I2C_ADDR, + .flags = I2C_M_RD, + .buf = &buf[1], + .len = 1 + } + + }; + + buf[0] = addr; + buf[1] = 0x0; + + ret = i2c_transfer(i2c_adap, msg, 2); + + if (ret != 2) { + printk(KERN_ERR "eeprom i2c read error, status=%d\n", ret); + return -1; + } + + return buf[1]; +}; + +int netup_eeprom_write(struct i2c_adapter *i2c_adap, u8 addr, u8 data) +{ + int ret; + unsigned char bufw[2]; + + /* Write into EEPROM */ + struct i2c_msg msg[] = { + { + .addr = EEPROM_I2C_ADDR, + .flags = 0, + .buf = &bufw[0], + .len = 2 + } + }; + + bufw[0] = addr; + bufw[1] = data; + + ret = i2c_transfer(i2c_adap, msg, 1); + + if (ret != 1) { + printk(KERN_ERR "eeprom i2c write error, status=%d\n", ret); + return -1; + } + + mdelay(10); /* prophylactic delay, datasheet write cycle time = 5 ms */ + return 0; +}; + +void netup_get_card_info(struct i2c_adapter *i2c_adap, + struct netup_card_info *cinfo) +{ + int i, j; + + cinfo->rev = netup_eeprom_read(i2c_adap, 13); + + for (i = 0, j = 0; i < 6; i++, j++) + cinfo->port[0].mac[j] = netup_eeprom_read(i2c_adap, i); + + for (i = 6, j = 0; i < 12; i++, j++) + cinfo->port[1].mac[j] = netup_eeprom_read(i2c_adap, i); +}; diff --git a/drivers/media/video/cx23885/netup-eeprom.h b/drivers/media/video/cx23885/netup-eeprom.h new file mode 100644 index 000000000000..13926e18feba --- /dev/null +++ b/drivers/media/video/cx23885/netup-eeprom.h @@ -0,0 +1,42 @@ +/* + * netup-eeprom.h + * + * 24LC02 EEPROM driver in conjunction with NetUP Dual DVB-S2 CI card + * + * Copyright (C) 2009 NetUP Inc. + * Copyright (C) 2009 Abylay Ospan + * + * 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 NETUP_EEPROM_H +#define NETUP_EEPROM_H + +struct netup_port_info { + u8 mac[6];/* card MAC address */ +}; + +struct netup_card_info { + struct netup_port_info port[2];/* ports - 1,2 */ + u8 rev;/* card revision */ +}; + +extern int netup_eeprom_read(struct i2c_adapter *i2c_adap, u8 addr); +extern int netup_eeprom_write(struct i2c_adapter *i2c_adap, u8 addr, u8 data); +extern void netup_get_card_info(struct i2c_adapter *i2c_adap, + struct netup_card_info *cinfo); + +#endif -- cgit v1.2.3 From c184dcd282337c09695a4c1761d7ac77fdc8fb7d Mon Sep 17 00:00:00 2001 From: Abylay Ospan Date: Tue, 3 Mar 2009 11:06:00 -0300 Subject: V4L/DVB (10798): Add CIMax(R) SP2 Common Interface code for NetUP Dual DVB-S2 CI card Add CIMax2 Common Interface code for NetUP Dual DVB-S2 CI card. SmarDTV CIMax(R) SP2 is Dual CableCARD, DVB Common Interface and OpenCable Hardware Controller. Signed-off-by: Abylay Ospan Signed-off-by: Igor M. Liplianin Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx23885/cimax2.c | 472 +++++++++++++++++++++++++++++++++++ drivers/media/video/cx23885/cimax2.h | 47 ++++ 2 files changed, 519 insertions(+) create mode 100644 drivers/media/video/cx23885/cimax2.c create mode 100644 drivers/media/video/cx23885/cimax2.h (limited to 'drivers/media/video') diff --git a/drivers/media/video/cx23885/cimax2.c b/drivers/media/video/cx23885/cimax2.c new file mode 100644 index 000000000000..2105c2e4cf46 --- /dev/null +++ b/drivers/media/video/cx23885/cimax2.c @@ -0,0 +1,472 @@ +/* + * cimax2.c + * + * CIMax2(R) SP2 driver in conjunction with NetUp Dual DVB-S2 CI card + * + * Copyright (C) 2009 NetUP Inc. + * Copyright (C) 2009 Igor M. Liplianin + * Copyright (C) 2009 Abylay Ospan + * + * 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. + */ + +#include "cx23885.h" +#include "dvb_ca_en50221.h" +/**** Bit definitions for MC417_RWD and MC417_OEN registers *** + bits 31-16 ++-----------+ +| Reserved | ++-----------+ + bit 15 bit 14 bit 13 bit 12 bit 11 bit 10 bit 9 bit 8 ++-------+-------+-------+-------+-------+-------+-------+-------+ +| WR# | RD# | | ACK# | ADHI | ADLO | CS1# | CS0# | ++-------+-------+-------+-------+-------+-------+-------+-------+ + bit 7 bit 6 bit 5 bit 4 bit 3 bit 2 bit 1 bit 0 ++-------+-------+-------+-------+-------+-------+-------+-------+ +| DATA7| DATA6| DATA5| DATA4| DATA3| DATA2| DATA1| DATA0| ++-------+-------+-------+-------+-------+-------+-------+-------+ +***/ +/* MC417 */ +#define NETUP_DATA 0x000000ff +#define NETUP_WR 0x00008000 +#define NETUP_RD 0x00004000 +#define NETUP_ACK 0x00001000 +#define NETUP_ADHI 0x00000800 +#define NETUP_ADLO 0x00000400 +#define NETUP_CS1 0x00000200 +#define NETUP_CS0 0x00000100 +#define NETUP_EN_ALL 0x00001000 +#define NETUP_CTRL_OFF (NETUP_CS1 | NETUP_CS0 | NETUP_WR | NETUP_RD) +#define NETUP_CI_CTL 0x04 +#define NETUP_CI_RD 1 + + +static unsigned int ci_dbg; +module_param(ci_dbg, int, 0644); +MODULE_PARM_DESC(ci_dbg, "Enable CI debugging"); + +#define ci_dbg_print(args...) \ + do { \ + if (ci_dbg) \ + printk(KERN_DEBUG args); \ + } while (0) + +/* stores all private variables for communication with CI */ +struct netup_ci_state { + struct dvb_ca_en50221 ca; + struct mutex ca_mutex; + struct i2c_adapter *i2c_adap; + u8 ci_i2c_addr; + int status; + struct work_struct work; + void *priv; +}; + +struct mutex gpio_mutex;/* Two CiMax's uses same GPIO lines */ + +int netup_read_i2c(struct i2c_adapter *i2c_adap, u8 addr, u8 reg, + u8 *buf, int len) +{ + int ret; + struct i2c_msg msg[] = { + { + .addr = addr, + .flags = 0, + .buf = ®, + .len = 1 + }, { + .addr = addr, + .flags = I2C_M_RD, + .buf = buf, + .len = len + } + }; + + ret = i2c_transfer(i2c_adap, msg, 2); + + if (ret != 2) { + ci_dbg_print("%s: i2c read error, Reg = 0x%02x, Status = %d\n", + __func__, reg, ret); + + return -1; + } + + ci_dbg_print("%s: i2c read Addr=0x%04x, Reg = 0x%02x, data = %02x\n", + __func__, addr, reg, buf[0]); + + return 0; +} + +int netup_write_i2c(struct i2c_adapter *i2c_adap, u8 addr, u8 reg, + u8 *buf, int len) +{ + int ret; + u8 buffer[len + 1]; + + struct i2c_msg msg = { + .addr = addr, + .flags = 0, + .buf = &buffer[0], + .len = len + 1 + }; + + buffer[0] = reg; + memcpy(&buffer[1], buf, len); + + ret = i2c_transfer(i2c_adap, &msg, 1); + + if (ret != 1) { + ci_dbg_print("%s: i2c write error, Reg=[0x%02x], Status=%d\n", + __func__, reg, ret); + return -1; + } + + return 0; +} + +int netup_ci_get_mem(struct cx23885_dev *dev) +{ + int mem; + unsigned long timeout = jiffies + msecs_to_jiffies(1); + + for (;;) { + mem = cx_read(MC417_RWD); + if ((mem & NETUP_ACK) == 0) + break; + if (time_after(jiffies, timeout)) + break; + udelay(1); + } + + cx_set(MC417_RWD, NETUP_CTRL_OFF); + + return mem & 0xff; +} + +int netup_ci_op_cam(struct dvb_ca_en50221 *en50221, int slot, + u8 flag, u8 read, u8 addr, u8 data) +{ + struct netup_ci_state *state = en50221->data; + struct cx23885_tsport *port = state->priv; + struct cx23885_dev *dev = port->dev; + + u8 store; + int mem; + int ret; + + if (0 != slot) + return -EINVAL; + + ret = netup_read_i2c(state->i2c_adap, state->ci_i2c_addr, + 0, &store, 1); + if (ret != 0) + return ret; + + store &= ~0x0c; + store |= flag; + + ret = netup_write_i2c(state->i2c_adap, state->ci_i2c_addr, + 0, &store, 1); + if (ret != 0) + return ret; + + mutex_lock(&gpio_mutex); + + /* write addr */ + cx_write(MC417_OEN, NETUP_EN_ALL); + cx_write(MC417_RWD, NETUP_CTRL_OFF | + NETUP_ADLO | (0xff & addr)); + cx_clear(MC417_RWD, NETUP_ADLO); + cx_write(MC417_RWD, NETUP_CTRL_OFF | + NETUP_ADHI | (0xff & (addr >> 8))); + cx_clear(MC417_RWD, NETUP_ADHI); + + if (read) /* data in */ + cx_write(MC417_OEN, NETUP_EN_ALL | NETUP_DATA); + else /* data out */ + cx_write(MC417_RWD, NETUP_CTRL_OFF | data); + + /* choose chip */ + cx_clear(MC417_RWD, + (state->ci_i2c_addr == 0x40) ? NETUP_CS0 : NETUP_CS1); + /* read/write */ + cx_clear(MC417_RWD, (read) ? NETUP_RD : NETUP_WR); + mem = netup_ci_get_mem(dev); + + mutex_unlock(&gpio_mutex); + + if (!read) + if (mem < 0) + return -EREMOTEIO; + + ci_dbg_print("%s: %s: addr=[0x%02x], %s=%x\n", __func__, + (read) ? "read" : "write", addr, + (flag == NETUP_CI_CTL) ? "ctl" : "mem", + (read) ? mem : data); + + if (read) + return mem; + + return 0; +} + +int netup_ci_read_attribute_mem(struct dvb_ca_en50221 *en50221, + int slot, int addr) +{ + return netup_ci_op_cam(en50221, slot, 0, NETUP_CI_RD, addr, 0); +} + +int netup_ci_write_attribute_mem(struct dvb_ca_en50221 *en50221, + int slot, int addr, u8 data) +{ + return netup_ci_op_cam(en50221, slot, 0, 0, addr, data); +} + +int netup_ci_read_cam_ctl(struct dvb_ca_en50221 *en50221, int slot, u8 addr) +{ + return netup_ci_op_cam(en50221, slot, NETUP_CI_CTL, + NETUP_CI_RD, addr, 0); +} + +int netup_ci_write_cam_ctl(struct dvb_ca_en50221 *en50221, int slot, + u8 addr, u8 data) +{ + return netup_ci_op_cam(en50221, slot, NETUP_CI_CTL, 0, addr, data); +} + +int netup_ci_slot_reset(struct dvb_ca_en50221 *en50221, int slot) +{ + struct netup_ci_state *state = en50221->data; + u8 buf = 0x80; + int ret; + + if (0 != slot) + return -EINVAL; + + udelay(500); + ret = netup_write_i2c(state->i2c_adap, state->ci_i2c_addr, + 0, &buf, 1); + + if (ret != 0) + return ret; + + udelay(500); + + buf = 0x00; + ret = netup_write_i2c(state->i2c_adap, state->ci_i2c_addr, + 0, &buf, 1); + + msleep(1000); + dvb_ca_en50221_camready_irq(&state->ca, 0); + + return 0; + +} + +int netup_ci_slot_shutdown(struct dvb_ca_en50221 *en50221, int slot) +{ + /* not implemented */ + return 0; +} + +int netup_ci_slot_ts_ctl(struct dvb_ca_en50221 *en50221, int slot) +{ + struct netup_ci_state *state = en50221->data; + u8 buf = 0x60; + + if (0 != slot) + return -EINVAL; + + return netup_write_i2c(state->i2c_adap, state->ci_i2c_addr, + 0, &buf, 1); +} + +/* work handler */ +static void netup_read_ci_status(struct work_struct *work) +{ + struct netup_ci_state *state = + container_of(work, struct netup_ci_state, work); + u8 buf[33]; + int ret; + + ret = netup_read_i2c(state->i2c_adap, state->ci_i2c_addr, + 0, &buf[0], 33); + + if (ret != 0) + return; + + ci_dbg_print("%s: Slot Status Addr=[0x%04x], Reg=[0x%02x], data=%02x, " + "TS config = %02x\n", __func__, state->ci_i2c_addr, 0, buf[0], + buf[32]); + + if (buf[0] && 1) + state->status = DVB_CA_EN50221_POLL_CAM_PRESENT | + DVB_CA_EN50221_POLL_CAM_READY; + else + state->status = 0; +} + +/* CI irq handler */ +int netup_ci_slot_status(struct cx23885_dev *dev, u32 pci_status) +{ + struct cx23885_tsport *port = NULL; + struct netup_ci_state *state = NULL; + + if (pci_status & PCI_MSK_GPIO0) + port = &dev->ts1; + else if (pci_status & PCI_MSK_GPIO1) + port = &dev->ts2; + else /* who calls ? */ + return 0; + + state = port->port_priv; + + schedule_work(&state->work); + + return 1; +} + +int netup_poll_ci_slot_status(struct dvb_ca_en50221 *en50221, int slot, int open) +{ + struct netup_ci_state *state = en50221->data; + + if (0 != slot) + return -EINVAL; + + return state->status; +} + +int netup_ci_init(struct cx23885_tsport *port) +{ + struct netup_ci_state *state; + u8 cimax_init[34] = { + 0x00, /* module A control*/ + 0x00, /* auto select mask high A */ + 0x00, /* auto select mask low A */ + 0x00, /* auto select pattern high A */ + 0x00, /* auto select pattern low A */ + 0x44, /* memory access time A */ + 0x00, /* invert input A */ + 0x00, /* RFU */ + 0x00, /* RFU */ + 0x00, /* module B control*/ + 0x00, /* auto select mask high B */ + 0x00, /* auto select mask low B */ + 0x00, /* auto select pattern high B */ + 0x00, /* auto select pattern low B */ + 0x44, /* memory access time B */ + 0x00, /* invert input B */ + 0x00, /* RFU */ + 0x00, /* RFU */ + 0x00, /* auto select mask high Ext */ + 0x00, /* auto select mask low Ext */ + 0x00, /* auto select pattern high Ext */ + 0x00, /* auto select pattern low Ext */ + 0x00, /* RFU */ + 0x02, /* destination - module A */ + 0x01, /* power on (use it like store place) */ + 0x00, /* RFU */ + 0x00, /* int status read only */ + 0x01, /* all int unmasked */ + 0x04, /* int config */ + 0x00, /* USCG1 */ + 0x04, /* ack active low */ + 0x00, /* LOCK = 0 */ + 0x33, /* serial mode, rising in, rising out, MSB first*/ + 0x31, /* syncronization */ + }; + int ret; + + ci_dbg_print("%s\n", __func__); + state = kzalloc(sizeof(struct netup_ci_state), GFP_KERNEL); + if (!state) { + ci_dbg_print("%s: Unable create CI structure!\n", __func__); + ret = -ENOMEM; + goto err; + } + + port->port_priv = state; + + switch (port->nr) { + case 1: + state->ci_i2c_addr = 0x40; + mutex_init(&gpio_mutex); + break; + case 2: + state->ci_i2c_addr = 0x41; + break; + } + + state->i2c_adap = &port->dev->i2c_bus[0].i2c_adap; + state->ca.owner = THIS_MODULE; + state->ca.read_attribute_mem = netup_ci_read_attribute_mem; + state->ca.write_attribute_mem = netup_ci_write_attribute_mem; + state->ca.read_cam_control = netup_ci_read_cam_ctl; + state->ca.write_cam_control = netup_ci_write_cam_ctl; + state->ca.slot_reset = netup_ci_slot_reset; + state->ca.slot_shutdown = netup_ci_slot_shutdown; + state->ca.slot_ts_enable = netup_ci_slot_ts_ctl; + state->ca.poll_slot_status = netup_poll_ci_slot_status; + state->ca.data = state; + state->priv = port; + + ret = netup_write_i2c(state->i2c_adap, state->ci_i2c_addr, + 0, &cimax_init[0], 34); + /* lock registers */ + ret |= netup_write_i2c(state->i2c_adap, state->ci_i2c_addr, + 0x1f, &cimax_init[0x18], 1); + /* power on slots */ + ret |= netup_write_i2c(state->i2c_adap, state->ci_i2c_addr, + 0x18, &cimax_init[0x18], 1); + + if (0 != ret) + goto err; + + ret = dvb_ca_en50221_init(&port->frontends.adapter, + &state->ca, + /* flags */ 0, + /* n_slots */ 1); + if (0 != ret) + goto err; + + INIT_WORK(&state->work, netup_read_ci_status); + + ci_dbg_print("%s: CI initialized!\n", __func__); + + return 0; +err: + ci_dbg_print("%s: Cannot initialize CI: Error %d.\n", __func__, ret); + kfree(state); + return ret; +} + +void netup_ci_exit(struct cx23885_tsport *port) +{ + struct netup_ci_state *state; + + if (NULL == port) + return; + + state = (struct netup_ci_state *)port->port_priv; + if (NULL == state) + return; + + if (NULL == state->ca.data) + return; + + dvb_ca_en50221_release(&state->ca); + kfree(state); +} diff --git a/drivers/media/video/cx23885/cimax2.h b/drivers/media/video/cx23885/cimax2.h new file mode 100644 index 000000000000..518744a4c8a5 --- /dev/null +++ b/drivers/media/video/cx23885/cimax2.h @@ -0,0 +1,47 @@ +/* + * cimax2.h + * + * CIMax(R) SP2 driver in conjunction with NetUp Dual DVB-S2 CI card + * + * Copyright (C) 2009 NetUP Inc. + * Copyright (C) 2009 Igor M. Liplianin + * Copyright (C) 2009 Abylay Ospan + * + * 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 CIMAX2_H +#define CIMAX2_H +#include "dvb_ca_en50221.h" + +extern int netup_ci_read_attribute_mem(struct dvb_ca_en50221 *en50221, + int slot, int addr); +extern int netup_ci_write_attribute_mem(struct dvb_ca_en50221 *en50221, + int slot, int addr, u8 data); +extern int netup_ci_read_cam_ctl(struct dvb_ca_en50221 *en50221, + int slot, u8 addr); +extern int netup_ci_write_cam_ctl(struct dvb_ca_en50221 *en50221, + int slot, u8 addr, u8 data); +extern int netup_ci_slot_reset(struct dvb_ca_en50221 *en50221, int slot); +extern int netup_ci_slot_shutdown(struct dvb_ca_en50221 *en50221, int slot); +extern int netup_ci_slot_ts_ctl(struct dvb_ca_en50221 *en50221, int slot); +extern int netup_ci_slot_status(struct cx23885_dev *dev, u32 pci_status); +extern int netup_poll_ci_slot_status(struct dvb_ca_en50221 *en50221, + int slot, int open); +extern int netup_ci_init(struct cx23885_tsport *port); +extern void netup_ci_exit(struct cx23885_tsport *port); + +#endif -- cgit v1.2.3 From 5a23b0762c9095e137ce9a559cc7c37b2f8fd083 Mon Sep 17 00:00:00 2001 From: "Igor M. Liplianin" Date: Tue, 3 Mar 2009 12:06:09 -0300 Subject: V4L/DVB (10805): Add support for NetUP Dual DVB-S2 CI card Add support for NetUP Dual DVB-S2 CI card The card based on cx23885 PCI-e bridge, CiMax SP2 Common Interface chips, STM lnbh24 LNB power chip, stv6110 tuners and stv0900 demodulator. http://www.linuxtv.org/wiki/index.php/NetUP_Dual_DVB_S2_CI Signed-off-by: Igor M. Liplianin Signed-off-by: Mauro Carvalho Chehab --- Documentation/video4linux/CARDLIST.cx23885 | 1 + drivers/media/video/cx23885/Kconfig | 1 + drivers/media/video/cx23885/Makefile | 4 +- drivers/media/video/cx23885/cx23885-cards.c | 53 ++++++++++++++ drivers/media/video/cx23885/cx23885-core.c | 20 +++++- drivers/media/video/cx23885/cx23885-dvb.c | 106 +++++++++++++++++++++++++++- drivers/media/video/cx23885/cx23885-reg.h | 2 + drivers/media/video/cx23885/cx23885.h | 3 + 8 files changed, 187 insertions(+), 3 deletions(-) (limited to 'drivers/media/video') diff --git a/Documentation/video4linux/CARDLIST.cx23885 b/Documentation/video4linux/CARDLIST.cx23885 index 5937ff958f04..91aa3c0f0dd2 100644 --- a/Documentation/video4linux/CARDLIST.cx23885 +++ b/Documentation/video4linux/CARDLIST.cx23885 @@ -15,3 +15,4 @@ 14 -> TurboSight TBS 6920 [6920:8888] 15 -> TeVii S470 [d470:9022] 16 -> DVBWorld DVB-S2 2005 [0001:2005] + 17 -> NetUP Dual DVB-S2 CI [1b55:2a2c] diff --git a/drivers/media/video/cx23885/Kconfig b/drivers/media/video/cx23885/Kconfig index 00f1e2e8889e..b62f16d507d8 100644 --- a/drivers/media/video/cx23885/Kconfig +++ b/drivers/media/video/cx23885/Kconfig @@ -16,6 +16,7 @@ config VIDEO_CX23885 select DVB_LGDT330X if !DVB_FE_CUSTOMISE select DVB_ZL10353 if !DVB_FE_CUSTOMISE select DVB_TDA10048 if !DVB_FE_CUSTOMIZE + select DVB_LNBP21 if !DVB_FE_CUSTOMIZE select MEDIA_TUNER_MT2131 if !MEDIA_TUNER_CUSTOMIZE select MEDIA_TUNER_XC2028 if !DVB_FE_CUSTOMIZE select MEDIA_TUNER_TDA8290 if !DVB_FE_CUSTOMIZE diff --git a/drivers/media/video/cx23885/Makefile b/drivers/media/video/cx23885/Makefile index 29c23b44c13c..ab8ea35c9bfb 100644 --- a/drivers/media/video/cx23885/Makefile +++ b/drivers/media/video/cx23885/Makefile @@ -1,4 +1,6 @@ -cx23885-objs := cx23885-cards.o cx23885-video.o cx23885-vbi.o cx23885-core.o cx23885-i2c.o cx23885-dvb.o cx23885-417.o +cx23885-objs := cx23885-cards.o cx23885-video.o cx23885-vbi.o \ + cx23885-core.o cx23885-i2c.o cx23885-dvb.o cx23885-417.o \ + netup-init.o cimax2.o netup-eeprom.o obj-$(CONFIG_VIDEO_CX23885) += cx23885.o diff --git a/drivers/media/video/cx23885/cx23885-cards.c b/drivers/media/video/cx23885/cx23885-cards.c index 7ff339a2e3f2..08cd793cd151 100644 --- a/drivers/media/video/cx23885/cx23885-cards.c +++ b/drivers/media/video/cx23885/cx23885-cards.c @@ -27,6 +27,7 @@ #include "cx23885.h" #include "tuner-xc2028.h" +#include "netup-init.h" /* ------------------------------------------------------------------ */ /* board config info */ @@ -174,6 +175,12 @@ struct cx23885_board cx23885_boards[] = { .name = "DVBWorld DVB-S2 2005", .portb = CX23885_MPEG_DVB, }, + [CX23885_BOARD_NETUP_DUAL_DVBS2_CI] = { + .cimax = 1, + .name = "NetUP Dual DVB-S2 CI", + .portb = CX23885_MPEG_DVB, + .portc = CX23885_MPEG_DVB, + }, }; const unsigned int cx23885_bcount = ARRAY_SIZE(cx23885_boards); @@ -269,6 +276,10 @@ struct cx23885_subid cx23885_subids[] = { .subvendor = 0x0001, .subdevice = 0x2005, .card = CX23885_BOARD_DVBWORLD_2005, + }, { + .subvendor = 0x1b55, + .subdevice = 0x2a2c, + .card = CX23885_BOARD_NETUP_DUAL_DVBS2_CI, }, }; const unsigned int cx23885_idcount = ARRAY_SIZE(cx23885_subids); @@ -582,6 +593,32 @@ void cx23885_gpio_setup(struct cx23885_dev *dev) cx_write(MC417_OEN, 0x00001000); cx_write(MC417_RWD, 0x00001800); break; + case CX23885_BOARD_NETUP_DUAL_DVBS2_CI: + /* GPIO-0 INTA from CiMax1 + GPIO-1 INTB from CiMax2 + GPIO-2 reset chips + GPIO-3 to GPIO-10 data/addr for CA + GPIO-11 ~CS0 to CiMax1 + GPIO-12 ~CS1 to CiMax2 + GPIO-13 ADL0 load LSB addr + GPIO-14 ADL1 load MSB addr + GPIO-15 ~RDY from CiMax + GPIO-17 ~RD to CiMax + GPIO-18 ~WR to CiMax + */ + cx_set(GP0_IO, 0x00040000); /* GPIO as out */ + /* GPIO1 and GPIO2 as INTA and INTB from CiMaxes, reset low */ + cx_clear(GP0_IO, 0x00030004); + mdelay(100);/* reset delay */ + cx_set(GP0_IO, 0x00040004); /* GPIO as out, reset high */ + cx_write(MC417_CTL, 0x00000037);/* enable GPIO3-18 pins */ + /* GPIO-15 IN as ~ACK, rest as OUT */ + cx_write(MC417_OEN, 0x00001000); + /* ~RD, ~WR high; ADL0, ADL1 low; ~CS0, ~CS1 high */ + cx_write(MC417_RWD, 0x0000c300); + /* enable irq */ + cx_write(GPIO_ISM, 0x00000000);/* INTERRUPTS active low*/ + break; } } @@ -669,6 +706,14 @@ void cx23885_card_setup(struct cx23885_dev *dev) ts1->ts_clk_en_val = 0x1; /* Enable TS_CLK */ ts1->src_sel_val = CX23885_SRC_SEL_PARALLEL_MPEG_VIDEO; break; + case CX23885_BOARD_NETUP_DUAL_DVBS2_CI: + ts1->gen_ctrl_val = 0xc; /* Serial bus + punctured clock */ + ts1->ts_clk_en_val = 0x1; /* Enable TS_CLK */ + ts1->src_sel_val = CX23885_SRC_SEL_PARALLEL_MPEG_VIDEO; + ts2->gen_ctrl_val = 0xc; /* Serial bus + punctured clock */ + ts2->ts_clk_en_val = 0x1; /* Enable TS_CLK */ + ts2->src_sel_val = CX23885_SRC_SEL_PARALLEL_MPEG_VIDEO; + break; case CX23885_BOARD_HAUPPAUGE_HVR1250: case CX23885_BOARD_HAUPPAUGE_HVR1500: case CX23885_BOARD_HAUPPAUGE_HVR1500Q: @@ -693,9 +738,17 @@ void cx23885_card_setup(struct cx23885_dev *dev) case CX23885_BOARD_HAUPPAUGE_HVR1700: case CX23885_BOARD_LEADTEK_WINFAST_PXDVR3200_H: case CX23885_BOARD_COMPRO_VIDEOMATE_E650F: + case CX23885_BOARD_NETUP_DUAL_DVBS2_CI: request_module("cx25840"); break; } + + /* AUX-PLL 27MHz CLK */ + switch (dev->board) { + case CX23885_BOARD_NETUP_DUAL_DVBS2_CI: + netup_initialize(dev); + break; + } } /* ------------------------------------------------------------------ */ diff --git a/drivers/media/video/cx23885/cx23885-core.c b/drivers/media/video/cx23885/cx23885-core.c index 8f6fb2add7de..1b401457d42e 100644 --- a/drivers/media/video/cx23885/cx23885-core.c +++ b/drivers/media/video/cx23885/cx23885-core.c @@ -31,6 +31,7 @@ #include #include "cx23885.h" +#include "cimax2.h" MODULE_DESCRIPTION("Driver for cx23885 based TV cards"); MODULE_AUTHOR("Steven Toth "); @@ -791,6 +792,8 @@ static int cx23885_dev_setup(struct cx23885_dev *dev) dev->pci_bus = dev->pci->bus->number; dev->pci_slot = PCI_SLOT(dev->pci->devfn); dev->pci_irqmask = 0x001f00; + if (cx23885_boards[dev->board].cimax > 0) + dev->pci_irqmask |= 0x01800000; /* for CiMaxes */ /* External Master 1 Bus */ dev->i2c_bus[0].nr = 0; @@ -1643,7 +1646,9 @@ static irqreturn_t cx23885_irq(int irq, void *dev_id) (pci_status & PCI_MSK_VID_B) || (pci_status & PCI_MSK_VID_A) || (pci_status & PCI_MSK_AUD_INT) || - (pci_status & PCI_MSK_AUD_EXT)) { + (pci_status & PCI_MSK_AUD_EXT) || + (pci_status & PCI_MSK_GPIO0) || + (pci_status & PCI_MSK_GPIO1)) { if (pci_status & PCI_MSK_RISC_RD) dprintk(7, " (PCI_MSK_RISC_RD 0x%08x)\n", @@ -1685,8 +1690,19 @@ static irqreturn_t cx23885_irq(int irq, void *dev_id) dprintk(7, " (PCI_MSK_AUD_EXT 0x%08x)\n", PCI_MSK_AUD_EXT); + if (pci_status & PCI_MSK_GPIO0) + dprintk(7, " (PCI_MSK_GPIO0 0x%08x)\n", + PCI_MSK_GPIO0); + + if (pci_status & PCI_MSK_GPIO1) + dprintk(7, " (PCI_MSK_GPIO1 0x%08x)\n", + PCI_MSK_GPIO1); } + if ((pci_status & PCI_MSK_GPIO0) || (pci_status & PCI_MSK_GPIO1)) + /* handled += cx23885_irq_gpio(dev, pci_status); */ + handled += netup_ci_slot_status(dev, pci_status); + if (ts1_status) { if (cx23885_boards[dev->board].portb == CX23885_MPEG_DVB) handled += cx23885_irq_ts(ts1, ts1_status); @@ -1759,6 +1775,8 @@ static int __devinit cx23885_initdev(struct pci_dev *pci_dev, } pci_set_drvdata(pci_dev, dev); + cx_set(PCI_INT_MSK, 0x01800000); /* for NetUP */ + return 0; fail_irq: diff --git a/drivers/media/video/cx23885/cx23885-dvb.c b/drivers/media/video/cx23885/cx23885-dvb.c index 14a6540b826c..9a0bc6e84a95 100644 --- a/drivers/media/video/cx23885/cx23885-dvb.c +++ b/drivers/media/video/cx23885/cx23885-dvb.c @@ -30,6 +30,7 @@ #include "cx23885.h" #include +#include "dvb_ca_en50221.h" #include "s5h1409.h" #include "s5h1411.h" #include "mt2131.h" @@ -43,7 +44,13 @@ #include "dib7000p.h" #include "dibx000_common.h" #include "zl10353.h" +#include "stv0900.h" +#include "stv6110.h" +#include "lnbh24.h" #include "cx24116.h" +#include "cimax2.h" +#include "netup-eeprom.h" +#include "netup-init.h" static unsigned int debug; @@ -309,6 +316,31 @@ static struct zl10353_config dvico_fusionhdtv_xc3028 = { .no_tuner = 1, }; +static struct stv0900_config netup_stv0900_config = { + .demod_address = 0x68, + .xtal = 27000000, + .clkmode = 3,/* 0-CLKI, 2-XTALI, else AUTO */ + .diseqc_mode = 2,/* 2/3 PWM */ + .path1_mode = 2,/*Serial continues clock */ + .path2_mode = 2,/*Serial continues clock */ + .tun1_maddress = 0,/* 0x60 */ + .tun2_maddress = 3,/* 0x63 */ + .tun1_adc = 1,/* 1 Vpp */ + .tun2_adc = 1,/* 1 Vpp */ +}; + +static struct stv6110_config netup_stv6110_tunerconfig_a = { + .i2c_address = 0x60, + .mclk = 27000000, + .iq_wiring = 0, +}; + +static struct stv6110_config netup_stv6110_tunerconfig_b = { + .i2c_address = 0x63, + .mclk = 27000000, + .iq_wiring = 1, +}; + static int tbs_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage) { struct cx23885_tsport *port = fe->dvb->priv; @@ -340,6 +372,7 @@ static int dvb_register(struct cx23885_tsport *port) struct cx23885_dev *dev = port->dev; struct cx23885_i2c *i2c_bus = NULL; struct videobuf_dvb_frontend *fe0; + int ret; /* Get the first frontend */ fe0 = videobuf_dvb_get_frontend(&port->frontends, 1); @@ -580,6 +613,51 @@ static int dvb_register(struct cx23885_tsport *port) &dvbworld_cx24116_config, &i2c_bus->i2c_adap); break; + case CX23885_BOARD_NETUP_DUAL_DVBS2_CI: + i2c_bus = &dev->i2c_bus[0]; + switch (port->nr) { + /* port B */ + case 1: + fe0->dvb.frontend = dvb_attach(stv0900_attach, + &netup_stv0900_config, + &i2c_bus->i2c_adap, 0); + if (fe0->dvb.frontend != NULL) { + if (dvb_attach(stv6110_attach, + fe0->dvb.frontend, + &netup_stv6110_tunerconfig_a, + &i2c_bus->i2c_adap)) { + if (!dvb_attach(lnbh24_attach, + fe0->dvb.frontend, + &i2c_bus->i2c_adap, + LNBH24_PCL, 0, 0x09)) + printk(KERN_ERR + "No LNBH24 found!\n"); + + } + } + break; + /* port C */ + case 2: + fe0->dvb.frontend = dvb_attach(stv0900_attach, + &netup_stv0900_config, + &i2c_bus->i2c_adap, 1); + if (fe0->dvb.frontend != NULL) { + if (dvb_attach(stv6110_attach, + fe0->dvb.frontend, + &netup_stv6110_tunerconfig_b, + &i2c_bus->i2c_adap)) { + if (!dvb_attach(lnbh24_attach, + fe0->dvb.frontend, + &i2c_bus->i2c_adap, + LNBH24_PCL, 0, 0x0a)) + printk(KERN_ERR + "No LNBH24 found!\n"); + + } + } + break; + } + break; default: printk(KERN_INFO "%s: The frontend of your DVB/ATSC card " " isn't supported yet\n", @@ -601,9 +679,33 @@ static int dvb_register(struct cx23885_tsport *port) fe0->dvb.frontend->ops.analog_ops.standby(fe0->dvb.frontend); /* register everything */ - return videobuf_dvb_register_bus(&port->frontends, THIS_MODULE, port, + ret = videobuf_dvb_register_bus(&port->frontends, THIS_MODULE, port, &dev->pci->dev, adapter_nr, 0); + /* init CI & MAC */ + switch (dev->board) { + case CX23885_BOARD_NETUP_DUAL_DVBS2_CI: { + static struct netup_card_info cinfo; + + netup_get_card_info(&dev->i2c_bus[0].i2c_adap, &cinfo); + memcpy(port->frontends.adapter.proposed_mac, + cinfo.port[port->nr - 1].mac, 6); + printk(KERN_INFO "NetUP Dual DVB-S2 CI card port%d MAC=" + "%02X:%02X:%02X:%02X:%02X:%02X\n", + port->nr, + port->frontends.adapter.proposed_mac[0], + port->frontends.adapter.proposed_mac[1], + port->frontends.adapter.proposed_mac[2], + port->frontends.adapter.proposed_mac[3], + port->frontends.adapter.proposed_mac[4], + port->frontends.adapter.proposed_mac[5]); + + netup_ci_init(port); + break; + } + } + + return ret; } int cx23885_dvb_register(struct cx23885_tsport *port) @@ -676,6 +778,8 @@ int cx23885_dvb_unregister(struct cx23885_tsport *port) if (fe0->dvb.frontend) videobuf_dvb_unregister_bus(&port->frontends); + netup_ci_exit(port); + return 0; } diff --git a/drivers/media/video/cx23885/cx23885-reg.h b/drivers/media/video/cx23885/cx23885-reg.h index 20b68a236260..eafbe5226bae 100644 --- a/drivers/media/video/cx23885/cx23885-reg.h +++ b/drivers/media/video/cx23885/cx23885-reg.h @@ -212,6 +212,8 @@ Channel manager Data Structure entry = 20 DWORD #define DEV_CNTRL2 0x00040000 +#define PCI_MSK_GPIO1 (1 << 24) +#define PCI_MSK_GPIO0 (1 << 23) #define PCI_MSK_APB_DMA (1 << 12) #define PCI_MSK_AL_WR (1 << 11) #define PCI_MSK_AL_RD (1 << 10) diff --git a/drivers/media/video/cx23885/cx23885.h b/drivers/media/video/cx23885/cx23885.h index 37a88b1683c3..779fc35b18d6 100644 --- a/drivers/media/video/cx23885/cx23885.h +++ b/drivers/media/video/cx23885/cx23885.h @@ -70,6 +70,7 @@ #define CX23885_BOARD_TBS_6920 14 #define CX23885_BOARD_TEVII_S470 15 #define CX23885_BOARD_DVBWORLD_2005 16 +#define CX23885_BOARD_NETUP_DUAL_DVBS2_CI 17 /* Currently unsupported by the driver: PAL/H, NTSC/Kr, SECAM B/G/H/LC */ #define CX23885_NORMS (\ @@ -187,6 +188,7 @@ struct cx23885_board { */ u32 clk_freq; struct cx23885_input input[MAX_CX23885_INPUT]; + int cimax; /* for NetUP */ }; struct cx23885_subid { @@ -269,6 +271,7 @@ struct cx23885_tsport { /* Allow a single tsport to have multiple frontends */ u32 num_frontends; + void *port_priv; }; struct cx23885_dev { -- cgit v1.2.3 From 19c96e4b7d3c80071982a052e4a921c1a39875d9 Mon Sep 17 00:00:00 2001 From: Trent Piepho Date: Wed, 4 Mar 2009 01:21:02 -0300 Subject: V4L/DVB (10811): videodev: only copy needed part of RW ioctl's parameter There are many RW ioctls() in v4l2 where userspace only supplies one or two of the first fields in the structure passed to the ioctl. The driver then fills in the rest of the fields. Instead of copying the entire structure from userspace to the kernel we only need to copy those fields that userspace is actually supposed to supply. What's more, the fields that are meant to be only be output from the driver can be zeroed out in the videodev code, in case the driver doesn't fill them all in. Many of the ioctl handlers in v4l2_ioctl do this already, but my patch does this at one common point and so all the memsets for each ioctl can be deleted. For VIDIOC_G_SLICED_VBI_CAP, which has one input field ('type') and other output-only fields, the input field is near the end of the structure instead of at the beginning. So there is still a memset in it's ioctl handler to zero out the beginning of the struct. There were a couple mistakes with the existing code: For VIDIOC_G_AUDIO the index field was preserved, but G_AUDIO is a read only ioctl so nothing is copied from userspace to preserve. For VIDIOC_G_FREQUENCY the tuner field was not preserved like it should have been. This would be a problem if there was any hardware with more than one tuner/modulator. For VIDIOC_ENUM_FRAMESIZES and VIDIOC_ENUM_FRAMEINTERVALS, none of the fields were preserved even though each ioctl has several field that are supposed to be inputs to the driver! Obviously these ioctls don't get used much. The index field is needed if the driver has multiple discrete sizes/rates and other fields can be used too, e.g. if the size depends on pixel format or frame rate depends on image size for example. Signed-off-by: Trent Piepho Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/v4l2-ioctl.c | 107 +++++++++++++++++++-------------------- 1 file changed, 52 insertions(+), 55 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/v4l2-ioctl.c b/drivers/media/video/v4l2-ioctl.c index 175688e9489f..00c0f76b9b5d 100644 --- a/drivers/media/video/v4l2-ioctl.c +++ b/drivers/media/video/v4l2-ioctl.c @@ -726,16 +726,8 @@ static long __video_do_ioctl(struct file *file, case VIDIOC_ENUM_FMT: { struct v4l2_fmtdesc *f = arg; - enum v4l2_buf_type type; - unsigned int index; - index = f->index; - type = f->type; - memset(f, 0, sizeof(*f)); - f->index = index; - f->type = type; - - switch (type) { + switch (f->type) { case V4L2_BUF_TYPE_VIDEO_CAPTURE: if (ops->vidioc_enum_fmt_vid_cap) ret = ops->vidioc_enum_fmt_vid_cap(file, fh, f); @@ -772,8 +764,6 @@ static long __video_do_ioctl(struct file *file, { struct v4l2_format *f = (struct v4l2_format *)arg; - memset(f->fmt.raw_data, 0, sizeof(f->fmt.raw_data)); - /* FIXME: Should be one dump per type */ dbgarg(cmd, "type=%s\n", prt_names(f->type, v4l2_type_names)); @@ -969,11 +959,6 @@ static long __video_do_ioctl(struct file *file, if (ret) break; - /* Zero out all fields starting with bytesysed, which is - * everything but index and type. */ - memset(0, &p->bytesused, - sizeof(*p) - offsetof(typeof(*p), bytesused)); - ret = ops->vidioc_querybuf(file, fh, p); if (!ret) dbgbuf(cmd, vfd, p); @@ -1159,12 +1144,9 @@ static long __video_do_ioctl(struct file *file, case VIDIOC_ENUMINPUT: { struct v4l2_input *p = arg; - int i = p->index; if (!ops->vidioc_enum_input) break; - memset(p, 0, sizeof(*p)); - p->index = i; ret = ops->vidioc_enum_input(file, fh, p); if (!ret) @@ -1203,12 +1185,9 @@ static long __video_do_ioctl(struct file *file, case VIDIOC_ENUMOUTPUT: { struct v4l2_output *p = arg; - int i = p->index; if (!ops->vidioc_enum_output) break; - memset(p, 0, sizeof(*p)); - p->index = i; ret = ops->vidioc_enum_output(file, fh, p); if (!ret) @@ -1384,13 +1363,11 @@ static long __video_do_ioctl(struct file *file, case VIDIOC_G_AUDIO: { struct v4l2_audio *p = arg; - __u32 index = p->index; if (!ops->vidioc_g_audio) break; memset(p, 0, sizeof(*p)); - p->index = index; ret = ops->vidioc_g_audio(file, fh, p); if (!ret) dbgarg(cmd, "index=%d, name=%s, capability=0x%x, " @@ -1485,15 +1462,10 @@ static long __video_do_ioctl(struct file *file, case VIDIOC_G_CROP: { struct v4l2_crop *p = arg; - __u32 type; if (!ops->vidioc_g_crop) break; - type = p->type; - memset(p, 0, sizeof(*p)); - p->type = type; - dbgarg(cmd, "type=%s\n", prt_names(p->type, v4l2_type_names)); ret = ops->vidioc_g_crop(file, fh, p); if (!ret) @@ -1514,16 +1486,11 @@ static long __video_do_ioctl(struct file *file, case VIDIOC_CROPCAP: { struct v4l2_cropcap *p = arg; - __u32 type; /*FIXME: Should also show v4l2_fract pixelaspect */ if (!ops->vidioc_cropcap) break; - type = p->type; - memset(p, 0, sizeof(*p)); - p->type = type; - dbgarg(cmd, "type=%s\n", prt_names(p->type, v4l2_type_names)); ret = ops->vidioc_cropcap(file, fh, p); if (!ret) { @@ -1581,7 +1548,6 @@ static long __video_do_ioctl(struct file *file, if (!ops->vidioc_encoder_cmd) break; - memset(&p->raw, 0, sizeof(p->raw)); ret = ops->vidioc_encoder_cmd(file, fh, p); if (!ret) dbgarg(cmd, "cmd=%d, flags=%x\n", p->cmd, p->flags); @@ -1593,7 +1559,6 @@ static long __video_do_ioctl(struct file *file, if (!ops->vidioc_try_encoder_cmd) break; - memset(&p->raw, 0, sizeof(p->raw)); ret = ops->vidioc_try_encoder_cmd(file, fh, p); if (!ret) dbgarg(cmd, "cmd=%d, flags=%x\n", p->cmd, p->flags); @@ -1602,10 +1567,6 @@ static long __video_do_ioctl(struct file *file, case VIDIOC_G_PARM: { struct v4l2_streamparm *p = arg; - __u32 type = p->type; - - memset(p, 0, sizeof(*p)); - p->type = type; if (ops->vidioc_g_parm) { ret = ops->vidioc_g_parm(file, fh, p); @@ -1638,14 +1599,10 @@ static long __video_do_ioctl(struct file *file, case VIDIOC_G_TUNER: { struct v4l2_tuner *p = arg; - __u32 index = p->index; if (!ops->vidioc_g_tuner) break; - memset(p, 0, sizeof(*p)); - p->index = index; - ret = ops->vidioc_g_tuner(file, fh, p); if (!ret) dbgarg(cmd, "index=%d, name=%s, type=%d, " @@ -1682,8 +1639,6 @@ static long __video_do_ioctl(struct file *file, if (!ops->vidioc_g_frequency) break; - memset(p->reserved, 0, sizeof(p->reserved)); - ret = ops->vidioc_g_frequency(file, fh, p); if (!ret) dbgarg(cmd, "tuner=%d, type=%d, frequency=%d\n", @@ -1704,12 +1659,13 @@ static long __video_do_ioctl(struct file *file, case VIDIOC_G_SLICED_VBI_CAP: { struct v4l2_sliced_vbi_cap *p = arg; - __u32 type = p->type; if (!ops->vidioc_g_sliced_vbi_cap) break; - memset(p, 0, sizeof(*p)); - p->type = type; + + /* Clear up to type, everything after type is zerod already */ + memset(p, 0, offsetof(struct v4l2_sliced_vbi_cap, type)); + dbgarg(cmd, "type=%s\n", prt_names(p->type, v4l2_type_names)); ret = ops->vidioc_g_sliced_vbi_cap(file, fh, p); if (!ret) @@ -1782,8 +1738,6 @@ static long __video_do_ioctl(struct file *file, if (!ops->vidioc_enum_framesizes) break; - memset(p, 0, sizeof(*p)); - ret = ops->vidioc_enum_framesizes(file, fh, p); dbgarg(cmd, "index=%d, pixelformat=%d, type=%d ", @@ -1815,8 +1769,6 @@ static long __video_do_ioctl(struct file *file, if (!ops->vidioc_enum_frameintervals) break; - memset(p, 0, sizeof(*p)); - ret = ops->vidioc_enum_frameintervals(file, fh, p); dbgarg(cmd, "index=%d, pixelformat=%d, width=%d, height=%d, type=%d ", @@ -1865,6 +1817,44 @@ static long __video_do_ioctl(struct file *file, return ret; } +/* In some cases, only a few fields are used as input, i.e. when the app sets + * "index" and then the driver fills in the rest of the structure for the thing + * with that index. We only need to copy up the first non-input field. */ +static unsigned long cmd_input_size(unsigned int cmd) +{ + /* Size of structure up to and including 'field' */ +#define CMDINSIZE(cmd, type, field) case _IOC_NR(VIDIOC_##cmd): return \ + offsetof(struct v4l2_##type, field) + \ + sizeof(((struct v4l2_##type *)0)->field); + + switch (_IOC_NR(cmd)) { + CMDINSIZE(ENUM_FMT, fmtdesc, type); + CMDINSIZE(G_FMT, format, type); + CMDINSIZE(QUERYBUF, buffer, type); + CMDINSIZE(G_PARM, streamparm, type); + CMDINSIZE(ENUMSTD, standard, index); + CMDINSIZE(ENUMINPUT, input, index); + CMDINSIZE(G_CTRL, control, id); + CMDINSIZE(G_TUNER, tuner, index); + CMDINSIZE(QUERYCTRL, queryctrl, id); + CMDINSIZE(QUERYMENU, querymenu, index); + CMDINSIZE(ENUMOUTPUT, output, index); + CMDINSIZE(G_MODULATOR, modulator, index); + CMDINSIZE(G_FREQUENCY, frequency, tuner); + CMDINSIZE(CROPCAP, cropcap, type); + CMDINSIZE(G_CROP, crop, type); + CMDINSIZE(ENUMAUDIO, audio, index); + CMDINSIZE(ENUMAUDOUT, audioout, index); + CMDINSIZE(ENCODER_CMD, encoder_cmd, flags); + CMDINSIZE(TRY_ENCODER_CMD, encoder_cmd, flags); + CMDINSIZE(G_SLICED_VBI_CAP, sliced_vbi_cap, type); + CMDINSIZE(ENUM_FRAMESIZES, frmsizeenum, pixel_format); + CMDINSIZE(ENUM_FRAMEINTERVALS, frmivalenum, height); + default: + return _IOC_SIZE(cmd); + } +} + long video_ioctl2(struct file *file, unsigned int cmd, unsigned long arg) { @@ -1901,9 +1891,16 @@ long video_ioctl2(struct file *file, } err = -EFAULT; - if (_IOC_DIR(cmd) & _IOC_WRITE) - if (copy_from_user(parg, (void __user *)arg, _IOC_SIZE(cmd))) + if (_IOC_DIR(cmd) & _IOC_WRITE) { + unsigned long n = cmd_input_size(cmd); + + if (copy_from_user(parg, (void __user *)arg, n)) goto out; + + /* zero out anything we don't copy from userspace */ + if (n < _IOC_SIZE(cmd)) + memset((u8 *)parg + n, 0, _IOC_SIZE(cmd) - n); + } break; } -- cgit v1.2.3 From 337f9d205972bfe1cb7982384fd0f4caa4af001d Mon Sep 17 00:00:00 2001 From: Trent Piepho Date: Wed, 4 Mar 2009 01:21:02 -0300 Subject: V4L/DVB (10812): v4l2: Zero out read-only ioctls in one place If an ioctl is read-only then the driver fills in all the fields. Lots of times drivers only care about some fields so it's best if video_ioctl2 takes care of zeroing out the entire structure before handing it to the driver. This saves code in each driver to do it and driver authors often forget. The existing memset code in some of the read-only ioctl handlers can be deleted. Convert a case statement to a single if statement. Deleted a debug line from ENUMAUDOUT that was copy-and-pasted to G_AUDOUT by mistake. Signed-off-by: Trent Piepho Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/v4l2-ioctl.c | 20 +++++--------------- 1 file changed, 5 insertions(+), 15 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/v4l2-ioctl.c b/drivers/media/video/v4l2-ioctl.c index 00c0f76b9b5d..64b4fda08dd5 100644 --- a/drivers/media/video/v4l2-ioctl.c +++ b/drivers/media/video/v4l2-ioctl.c @@ -655,8 +655,6 @@ static long __video_do_ioctl(struct file *file, if (cmd == VIDIOCGMBUF) { struct video_mbuf *p = arg; - memset(p, 0, sizeof(*p)); - if (!ops->vidiocgmbuf) return ret; ret = ops->vidiocgmbuf(file, fh, p); @@ -683,7 +681,6 @@ static long __video_do_ioctl(struct file *file, case VIDIOC_QUERYCAP: { struct v4l2_capability *cap = (struct v4l2_capability *)arg; - memset(cap, 0, sizeof(*cap)); if (!ops->vidioc_querycap) break; @@ -1367,7 +1364,6 @@ static long __video_do_ioctl(struct file *file, if (!ops->vidioc_g_audio) break; - memset(p, 0, sizeof(*p)); ret = ops->vidioc_g_audio(file, fh, p); if (!ret) dbgarg(cmd, "index=%d, name=%s, capability=0x%x, " @@ -1409,7 +1405,7 @@ static long __video_do_ioctl(struct file *file, if (!ops->vidioc_g_audout) break; - dbgarg(cmd, "Enum for index=%d\n", p->index); + ret = ops->vidioc_g_audout(file, fh, p); if (!ret) dbgarg2("index=%d, name=%s, capability=%d, " @@ -1506,8 +1502,6 @@ static long __video_do_ioctl(struct file *file, if (!ops->vidioc_g_jpegcomp) break; - memset(p, 0, sizeof(*p)); - ret = ops->vidioc_g_jpegcomp(file, fh, p); if (!ret) dbgarg(cmd, "quality=%d, APPn=%d, " @@ -1873,13 +1867,7 @@ long video_ioctl2(struct file *file, cmd == VIDIOC_TRY_EXT_CTRLS); /* Copy arguments into temp kernel buffer */ - switch (_IOC_DIR(cmd)) { - case _IOC_NONE: - parg = NULL; - break; - case _IOC_READ: - case _IOC_WRITE: - case (_IOC_WRITE | _IOC_READ): + if (_IOC_DIR(cmd) != _IOC_NONE) { if (_IOC_SIZE(cmd) <= sizeof(sbuf)) { parg = sbuf; } else { @@ -1900,8 +1888,10 @@ long video_ioctl2(struct file *file, /* zero out anything we don't copy from userspace */ if (n < _IOC_SIZE(cmd)) memset((u8 *)parg + n, 0, _IOC_SIZE(cmd) - n); + } else { + /* read-only ioctl */ + memset(parg, 0, _IOC_SIZE(cmd)); } - break; } if (is_ext_ctrl) { -- cgit v1.2.3 From 51f0b8d57af501624ee55e8ca15d09d5bdc2b0dd Mon Sep 17 00:00:00 2001 From: Trent Piepho Date: Wed, 4 Mar 2009 01:21:02 -0300 Subject: V4L/DVB (10813): v4l2: New function v4l2_video_std_frame_period Some code was calling v4l2_video_std_construct() when all it cared about was the frame period. So make a function that just returns that and have v4l2_video_std_construct() use it. At this point there are no users of v4l2_video_std_construct() left outside of v4l2-ioctl, so it could be un-exported and made static. Change v4l2_video_std_construct() so that it doesn't zero out the struct v4l2_standard passed in. It's already been zeroed out in the common ioctl code. Signed-off-by: Trent Piepho Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/bt8xx/bttv-driver.c | 6 ++--- drivers/media/video/v4l2-ioctl.c | 39 +++++++++++++++------------------ include/media/v4l2-ioctl.h | 1 + 3 files changed, 21 insertions(+), 25 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/bt8xx/bttv-driver.c b/drivers/media/video/bt8xx/bttv-driver.c index 826ca60b42e6..1f606d816a58 100644 --- a/drivers/media/video/bt8xx/bttv-driver.c +++ b/drivers/media/video/bt8xx/bttv-driver.c @@ -2932,13 +2932,11 @@ static int bttv_g_parm(struct file *file, void *f, { struct bttv_fh *fh = f; struct bttv *btv = fh->btv; - struct v4l2_standard s; if (parm->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) return -EINVAL; - v4l2_video_std_construct(&s, bttv_tvnorms[btv->tvnorm].v4l2_id, - bttv_tvnorms[btv->tvnorm].name); - parm->parm.capture.timeperframe = s.frameperiod; + v4l2_video_std_frame_period(bttv_tvnorms[btv->tvnorm].v4l2_id, + &parm->parm.capture.timeperframe); return 0; } diff --git a/drivers/media/video/v4l2-ioctl.c b/drivers/media/video/v4l2-ioctl.c index 64b4fda08dd5..efbc47004657 100644 --- a/drivers/media/video/v4l2-ioctl.c +++ b/drivers/media/video/v4l2-ioctl.c @@ -101,25 +101,27 @@ const char *v4l2_norm_to_name(v4l2_std_id id) } EXPORT_SYMBOL(v4l2_norm_to_name); +/* Returns frame period for the given standard */ +void v4l2_video_std_frame_period(int id, struct v4l2_fract *frameperiod) +{ + if (id & V4L2_STD_525_60) { + frameperiod->numerator = 1001; + frameperiod->denominator = 30000; + } else { + frameperiod->numerator = 1; + frameperiod->denominator = 25; + } +} +EXPORT_SYMBOL(v4l2_video_std_frame_period); + /* Fill in the fields of a v4l2_standard structure according to the 'id' and 'transmission' parameters. Returns negative on error. */ int v4l2_video_std_construct(struct v4l2_standard *vs, int id, const char *name) { - u32 index = vs->index; - - memset(vs, 0, sizeof(struct v4l2_standard)); - vs->index = index; - vs->id = id; - if (id & V4L2_STD_525_60) { - vs->frameperiod.numerator = 1001; - vs->frameperiod.denominator = 30000; - vs->framelines = 525; - } else { - vs->frameperiod.numerator = 1; - vs->frameperiod.denominator = 25; - vs->framelines = 625; - } + vs->id = id; + v4l2_video_std_frame_period(id, &vs->frameperiod); + vs->framelines = (id & V4L2_STD_525_60) ? 525 : 625; strlcpy(vs->name, name, sizeof(vs->name)); return 0; } @@ -1076,7 +1078,6 @@ static long __video_do_ioctl(struct file *file, return -EINVAL; v4l2_video_std_construct(p, curr_id, descr); - p->index = index; dbgarg(cmd, "index=%d, id=0x%Lx, name=%s, fps=%d/%d, " "framelines=%d\n", p->index, @@ -1565,15 +1566,11 @@ static long __video_do_ioctl(struct file *file, if (ops->vidioc_g_parm) { ret = ops->vidioc_g_parm(file, fh, p); } else { - struct v4l2_standard s; - if (p->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) return -EINVAL; - v4l2_video_std_construct(&s, vfd->current_norm, - v4l2_norm_to_name(vfd->current_norm)); - - p->parm.capture.timeperframe = s.frameperiod; + v4l2_video_std_frame_period(vfd->current_norm, + &p->parm.capture.timeperframe); ret = 0; } diff --git a/include/media/v4l2-ioctl.h b/include/media/v4l2-ioctl.h index b01c044868d0..a8b4c0b678ec 100644 --- a/include/media/v4l2-ioctl.h +++ b/include/media/v4l2-ioctl.h @@ -267,6 +267,7 @@ struct v4l2_ioctl_ops { /* Video standard functions */ extern const char *v4l2_norm_to_name(v4l2_std_id id); +extern void v4l2_video_std_frame_period(int id, struct v4l2_fract *frameperiod); extern int v4l2_video_std_construct(struct v4l2_standard *vs, int id, const char *name); /* Prints the ioctl in a human-readable format */ -- cgit v1.2.3 From 522a5f1430bb85ca00928b99caf3892023ad9632 Mon Sep 17 00:00:00 2001 From: Trent Piepho Date: Wed, 4 Mar 2009 01:21:03 -0300 Subject: V4L/DVB (10815): bttv: Don't need to zero ioctl parameter fields The v4l2 core code in v4l2_ioctl will zero out the structure the driver is supposed to fill in for read-only ioctls. For read/write ioctls, all the fields which aren't supplied from userspace will be zeroed out. Zeroing code is removed from enum_input and g_tuner. Signed-off-by: Trent Piepho Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/bt8xx/bttv-driver.c | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/bt8xx/bttv-driver.c b/drivers/media/video/bt8xx/bttv-driver.c index 1f606d816a58..b5fc3cc61888 100644 --- a/drivers/media/video/bt8xx/bttv-driver.c +++ b/drivers/media/video/bt8xx/bttv-driver.c @@ -1894,16 +1894,11 @@ static int bttv_enum_input(struct file *file, void *priv, { struct bttv_fh *fh = priv; struct bttv *btv = fh->btv; - unsigned int n; + int n; - n = i->index; - - if (n >= bttv_tvcards[btv->c.type].video_inputs) + if (i->index >= bttv_tvcards[btv->c.type].video_inputs) return -EINVAL; - memset(i, 0, sizeof(*i)); - - i->index = n; i->type = V4L2_INPUT_TYPE_CAMERA; i->audioset = 1; @@ -2952,7 +2947,6 @@ static int bttv_g_tuner(struct file *file, void *priv, return -EINVAL; mutex_lock(&btv->lock); - memset(t, 0, sizeof(*t)); t->rxsubchans = V4L2_TUNER_SUB_MONO; bttv_call_i2c_clients(btv, VIDIOC_G_TUNER, t); strcpy(t->name, "Television"); @@ -3495,7 +3489,6 @@ static int radio_g_tuner(struct file *file, void *priv, struct v4l2_tuner *t) if (0 != t->index) return -EINVAL; mutex_lock(&btv->lock); - memset(t, 0, sizeof(*t)); strcpy(t->name, "Radio"); t->type = V4L2_TUNER_RADIO; -- cgit v1.2.3 From f3334bcbf44ad9001460508ef4fbe51e706d24cf Mon Sep 17 00:00:00 2001 From: Trent Piepho Date: Wed, 4 Mar 2009 01:21:03 -0300 Subject: V4L/DVB (10816): cx88: Don't need to zero ioctl parameter fields The v4l2 core code in v4l2_ioctl will zero out the structure the driver is supposed to fill in for read-only ioctls. For read/write ioctls, all the fields which aren't supplied from userspace will be zeroed out. Zeroing code is removed from enum_input and g_tuner. Signed-off-by: Trent Piepho Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx88/cx88-video.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/cx88/cx88-video.c b/drivers/media/video/cx88/cx88-video.c index 5ed1c5a52cdd..2092e439ef00 100644 --- a/drivers/media/video/cx88/cx88-video.c +++ b/drivers/media/video/cx88/cx88-video.c @@ -1277,15 +1277,12 @@ int cx88_enum_input (struct cx88_core *core,struct v4l2_input *i) [ CX88_VMUX_DVB ] = "DVB", [ CX88_VMUX_DEBUG ] = "for debug only", }; - unsigned int n; + unsigned int n = i->index; - n = i->index; if (n >= 4) return -EINVAL; if (0 == INPUT(n).type) return -EINVAL; - memset(i,0,sizeof(*i)); - i->index = n; i->type = V4L2_INPUT_TYPE_CAMERA; strcpy(i->name,iname[INPUT(n).type]); if ((CX88_VMUX_TELEVISION == INPUT(n).type) || @@ -1521,7 +1518,6 @@ static int radio_g_audio (struct file *file, void *priv, struct v4l2_audio *a) if (unlikely(a->index)) return -EINVAL; - memset(a,0,sizeof(*a)); strcpy(a->name,"Radio"); return 0; } -- cgit v1.2.3 From df7bdfcd0efa9a25a7c9751a25b4d4efd9141b8d Mon Sep 17 00:00:00 2001 From: Trent Piepho Date: Wed, 4 Mar 2009 01:21:03 -0300 Subject: V4L/DVB (10817): stkwebcam: Don't need to zero ioctl parameter fields The v4l2 core code in v4l2_ioctl will zero out the structure the driver is supposed to fill in for read-only ioctls. For read/write ioctls, all the fields which aren't supplied from userspace will be zeroed out. Zeroing code is removed from enum_fmt_vid_cap, g_fmt_vid_cap, and g_parm. Signed-off-by: Trent Piepho Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/stk-webcam.c | 6 ------ 1 file changed, 6 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/stk-webcam.c b/drivers/media/video/stk-webcam.c index 686720d8bfed..6b7f0da9b515 100644 --- a/drivers/media/video/stk-webcam.c +++ b/drivers/media/video/stk-webcam.c @@ -933,8 +933,6 @@ static int stk_vidioc_s_ctrl(struct file *filp, static int stk_vidioc_enum_fmt_vid_cap(struct file *filp, void *priv, struct v4l2_fmtdesc *fmtd) { - fmtd->flags = 0; - switch (fmtd->index) { case 0: fmtd->pixelformat = V4L2_PIX_FMT_RGB565; @@ -992,7 +990,6 @@ static int stk_vidioc_g_fmt_vid_cap(struct file *filp, pix_format->height = stk_sizes[i].h; pix_format->field = V4L2_FIELD_NONE; pix_format->colorspace = V4L2_COLORSPACE_SRGB; - pix_format->priv = 0; pix_format->pixelformat = dev->vsettings.palette; if (dev->vsettings.palette == V4L2_PIX_FMT_SBGGR8) pix_format->bytesperline = pix_format->width; @@ -1246,13 +1243,10 @@ static int stk_vidioc_g_parm(struct file *filp, if (sp->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) return -EINVAL; - sp->parm.capture.capability = 0; - sp->parm.capture.capturemode = 0; /*FIXME This is not correct */ sp->parm.capture.timeperframe.numerator = 1; sp->parm.capture.timeperframe.denominator = 30; sp->parm.capture.readbuffers = 2; - sp->parm.capture.extendedmode = 0; return 0; } -- cgit v1.2.3 From 38367255185408748c2d46641e06c83570af161c Mon Sep 17 00:00:00 2001 From: Trent Piepho Date: Wed, 4 Mar 2009 01:21:03 -0300 Subject: V4L/DVB (10818): usbvision: Don't need to zero ioctl parameter fields The v4l2 core code in v4l2_ioctl will zero out the structure the driver is supposed to fill in for read-only ioctls. For read/write ioctls, all the fields which aren't supplied from userspace will be zeroed out. Zeroing code is removed from g_audio, queryctrl, and enum_fmt_vid_cap. Signed-off-by: Trent Piepho Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/usbvision/usbvision-video.c | 7 ------- 1 file changed, 7 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/usbvision/usbvision-video.c b/drivers/media/video/usbvision/usbvision-video.c index 863fcb31622f..3d400e4b7a27 100644 --- a/drivers/media/video/usbvision/usbvision-video.c +++ b/drivers/media/video/usbvision/usbvision-video.c @@ -697,7 +697,6 @@ static int vidioc_g_audio (struct file *file, void *priv, struct v4l2_audio *a) { struct usb_usbvision *usbvision = video_drvdata(file); - memset(a,0,sizeof(*a)); if(usbvision->radio) { strcpy(a->name,"Radio"); } else { @@ -721,10 +720,6 @@ static int vidioc_queryctrl (struct file *file, void *priv, struct v4l2_queryctrl *ctrl) { struct usb_usbvision *usbvision = video_drvdata(file); - int id=ctrl->id; - - memset(ctrl,0,sizeof(*ctrl)); - ctrl->id=id; call_all(usbvision, core, queryctrl, ctrl); @@ -926,11 +921,9 @@ static int vidioc_enum_fmt_vid_cap (struct file *file, void *priv, if(vfd->index>=USBVISION_SUPPORTED_PALETTES-1) { return -EINVAL; } - vfd->flags = 0; vfd->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; strcpy(vfd->description,usbvision_v4l2_format[vfd->index].desc); vfd->pixelformat = usbvision_v4l2_format[vfd->index].format; - memset(vfd->reserved, 0, sizeof(vfd->reserved)); return 0; } -- cgit v1.2.3 From c6a976e44ec37b93cbd62403971e9770ac60d389 Mon Sep 17 00:00:00 2001 From: Trent Piepho Date: Wed, 4 Mar 2009 01:21:03 -0300 Subject: V4L/DVB (10819): gspca: Don't need to zero ioctl parameter fields The v4l2 core code in v4l2_ioctl will zero out the structure the driver is supposed to fill in for read-only ioctls. For read/write ioctls, all the fields which aren't supplied from userspace will be zeroed out. Zeroing code is removed from g_audio, enum_input, g_parm and gmbuf. Signed-off-by: Trent Piepho Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/gspca.c | 4 ---- 1 file changed, 4 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/gspca/gspca.c b/drivers/media/video/gspca/gspca.c index 8aac7a1e8f33..ed18401fd8ba 100644 --- a/drivers/media/video/gspca/gspca.c +++ b/drivers/media/video/gspca/gspca.c @@ -1099,7 +1099,6 @@ static int vidioc_s_audio(struct file *file, void *priv, static int vidioc_g_audio(struct file *file, void *priv, struct v4l2_audio *audio) { - memset(audio, 0, sizeof *audio); strcpy(audio->name, "Microphone"); return 0; } @@ -1133,7 +1132,6 @@ static int vidioc_enum_input(struct file *file, void *priv, if (input->index != 0) return -EINVAL; - memset(input, 0, sizeof *input); input->type = V4L2_INPUT_TYPE_CAMERA; strncpy(input->name, gspca_dev->sd_desc->name, sizeof input->name); @@ -1341,7 +1339,6 @@ static int vidioc_g_parm(struct file *filp, void *priv, { struct gspca_dev *gspca_dev = priv; - memset(parm, 0, sizeof *parm); parm->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; parm->parm.capture.readbuffers = gspca_dev->nbufread; @@ -1411,7 +1408,6 @@ static int vidiocgmbuf(struct file *file, void *priv, { struct v4l2_format fmt; - memset(&fmt, 0, sizeof fmt); fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; i = gspca_dev->cam.nmodes - 1; /* highest mode */ fmt.fmt.pix.width = gspca_dev->cam.cam_mode[i].width; -- cgit v1.2.3 From 1a1500179a7c51c7851e18c56e7153c258fe91ab Mon Sep 17 00:00:00 2001 From: Trent Piepho Date: Wed, 4 Mar 2009 01:21:03 -0300 Subject: V4L/DVB (10820): meye: Don't need to zero ioctl parameter fields The v4l2 core code in v4l2_ioctl will zero out the structure the driver is supposed to fill in for read-only ioctls. For read/write ioctls, all the fields which aren't supplied from userspace will be zeroed out. Zeroing code is removed from querycap, enum_input, enum_fmt_vid_cap, and g_fmt_vid_cap. Signed-off-by: Trent Piepho Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/meye.c | 12 ------------ 1 file changed, 12 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/meye.c b/drivers/media/video/meye.c index 163fb2b329df..d9d73d888aa0 100644 --- a/drivers/media/video/meye.c +++ b/drivers/media/video/meye.c @@ -1017,7 +1017,6 @@ static int meyeioc_stilljcapt(int *len) static int vidioc_querycap(struct file *file, void *fh, struct v4l2_capability *cap) { - memset(cap, 0, sizeof(*cap)); strcpy(cap->driver, "meye"); strcpy(cap->card, "meye"); sprintf(cap->bus_info, "PCI:%s", pci_name(meye.mchip_dev)); @@ -1036,8 +1035,6 @@ static int vidioc_enum_input(struct file *file, void *fh, struct v4l2_input *i) if (i->index != 0) return -EINVAL; - memset(i, 0, sizeof(*i)); - i->index = 0; strcpy(i->name, "Camera"); i->type = V4L2_INPUT_TYPE_CAMERA; @@ -1264,16 +1261,12 @@ static int vidioc_enum_fmt_vid_cap(struct file *file, void *fh, if (f->index == 0) { /* standard YUV 422 capture */ - memset(f, 0, sizeof(*f)); - f->index = 0; f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; f->flags = 0; strcpy(f->description, "YUV422"); f->pixelformat = V4L2_PIX_FMT_YUYV; } else { /* compressed MJPEG capture */ - memset(f, 0, sizeof(*f)); - f->index = 1; f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; f->flags = V4L2_FMT_FLAG_COMPRESSED; strcpy(f->description, "MJPEG"); @@ -1322,9 +1315,6 @@ static int vidioc_g_fmt_vid_cap(struct file *file, void *fh, if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) return -EINVAL; - memset(&f->fmt.pix, 0, sizeof(struct v4l2_pix_format)); - f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - switch (meye.mchip_mode) { case MCHIP_HIC_MODE_CONT_OUT: default: @@ -1341,8 +1331,6 @@ static int vidioc_g_fmt_vid_cap(struct file *file, void *fh, f->fmt.pix.bytesperline = f->fmt.pix.width * 2; f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline; - f->fmt.pix.colorspace = 0; - f->fmt.pix.priv = 0; return 0; } -- cgit v1.2.3 From 04574185aa9ad0e6be7db96252f3c479beb5b3fa Mon Sep 17 00:00:00 2001 From: Matthias Schwarzott Date: Tue, 24 Feb 2009 12:35:16 -0300 Subject: V4L/DVB (10823): saa7134: add DVB support for Avermedia A700 cards Add DVB support for Avermedia DVB-S Pro and Avermedia DVB-S Hybrid+FM card both labled A700. They use zl10313 demod (driver mt312) and zl10036 tuner. [mchehab@redhat.com: change __FUNCTION__ into __func__] Signed-off-by: Matthias Schwarzott Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/saa7134/Kconfig | 2 ++ drivers/media/video/saa7134/saa7134-cards.c | 16 +++++++--------- drivers/media/video/saa7134/saa7134-dvb.c | 27 +++++++++++++++++++++++++++ 3 files changed, 36 insertions(+), 9 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/saa7134/Kconfig b/drivers/media/video/saa7134/Kconfig index fc2164e28e76..a3470ebad50a 100644 --- a/drivers/media/video/saa7134/Kconfig +++ b/drivers/media/video/saa7134/Kconfig @@ -37,6 +37,8 @@ config VIDEO_SAA7134_DVB select DVB_ISL6421 if !DVB_FE_CUSTOMISE select MEDIA_TUNER_TDA827X if !MEDIA_TUNER_CUSTOMIZE select MEDIA_TUNER_SIMPLE if !MEDIA_TUNER_CUSTOMIZE + select DVB_ZL10036 if !DVB_FE_CUSTOMISE + select DVB_MT312 if !DVB_FE_CUSTOMISE ---help--- This adds support for DVB cards based on the Philips saa7134 chip. diff --git a/drivers/media/video/saa7134/saa7134-cards.c b/drivers/media/video/saa7134/saa7134-cards.c index 67c223cc867f..9f69c7c85814 100644 --- a/drivers/media/video/saa7134/saa7134-cards.c +++ b/drivers/media/video/saa7134/saa7134-cards.c @@ -4421,8 +4421,7 @@ struct saa7134_board saa7134_boards[] = { .radio_type = UNSET, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, - /* no DVB support for now */ - /* .mpeg = SAA7134_MPEG_DVB, */ + .mpeg = SAA7134_MPEG_DVB, .inputs = { { .name = name_comp, .vmux = 1, @@ -4441,8 +4440,7 @@ struct saa7134_board saa7134_boards[] = { .radio_type = UNSET, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, - /* no DVB support for now */ - /* .mpeg = SAA7134_MPEG_DVB, */ + .mpeg = SAA7134_MPEG_DVB, .inputs = { { .name = name_comp, .vmux = 1, @@ -6084,15 +6082,15 @@ int saa7134_board_init1(struct saa7134_dev *dev) saa_andorl(SAA7134_GPIO_GPMODE0 >> 2, 0x8c040007, 0x8c040007); saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, 0x0c0007cd, 0x0c0007cd); break; - case SAA7134_BOARD_AVERMEDIA_A700_PRO: case SAA7134_BOARD_AVERMEDIA_A700_HYBRID: - /* write windows gpio values */ - saa_andorl(SAA7134_GPIO_GPMODE0 >> 2, 0x80040100, 0x80040100); - saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, 0x80040100, 0x00040100); printk("%s: %s: hybrid analog/dvb card\n" - "%s: Sorry, only analog s-video and composite input " + "%s: Sorry, of the analog inputs, only analog s-video and composite " "are supported for now.\n", dev->name, card(dev).name, dev->name); + case SAA7134_BOARD_AVERMEDIA_A700_PRO: + /* write windows gpio values */ + saa_andorl(SAA7134_GPIO_GPMODE0 >> 2, 0x80040100, 0x80040100); + saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, 0x80040100, 0x00040100); break; } return 0; diff --git a/drivers/media/video/saa7134/saa7134-dvb.c b/drivers/media/video/saa7134/saa7134-dvb.c index af9a22d1b94d..80ad96ad8939 100644 --- a/drivers/media/video/saa7134/saa7134-dvb.c +++ b/drivers/media/video/saa7134/saa7134-dvb.c @@ -51,6 +51,9 @@ #include "zl10353.h" +#include "zl10036.h" +#include "mt312.h" + MODULE_AUTHOR("Gerd Knorr [SuSE Labs]"); MODULE_LICENSE("GPL"); @@ -950,6 +953,17 @@ static struct nxt200x_config kworldatsc110 = { .demod_address = 0x0a, }; +/* ------------------------------------------------------------------ */ + +static struct mt312_config avertv_a700_mt312 = { + .demod_address = 0x0e, + .voltage_inverted = 1, +}; + +static struct zl10036_config avertv_a700_tuner = { + .tuner_address = 0x60, +}; + /* ================================================================== * Core code */ @@ -1376,6 +1390,19 @@ static int dvb_init(struct saa7134_dev *dev) TUNER_PHILIPS_FMD1216ME_MK3); } break; + case SAA7134_BOARD_AVERMEDIA_A700_PRO: + case SAA7134_BOARD_AVERMEDIA_A700_HYBRID: + /* Zarlink ZL10313 */ + fe0->dvb.frontend = dvb_attach(mt312_attach, + &avertv_a700_mt312, &dev->i2c_adap); + if (fe0->dvb.frontend) { + if (dvb_attach(zl10036_attach, fe0->dvb.frontend, + &avertv_a700_tuner, &dev->i2c_adap) == NULL) { + wprintk("%s: No zl10036 found!\n", + __func__); + } + } + break; default: wprintk("Huh? unknown DVB card?\n"); break; -- cgit v1.2.3 From f1735bb2a583b53ffdabe23ba8b22350e2d5e597 Mon Sep 17 00:00:00 2001 From: "Erik S. Beiser" Date: Sat, 28 Feb 2009 22:29:20 -0300 Subject: V4L/DVB (10826): cx88: Add IR support to pcHDTV HD3000 & HD5500 cx88: Add IR support to pcHDTV HD3000 & HD5500 Signed-off-by: Erik S. Beiser Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx88/cx88-input.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers/media/video') diff --git a/drivers/media/video/cx88/cx88-input.c b/drivers/media/video/cx88/cx88-input.c index 8683d104de72..ad0842136d8d 100644 --- a/drivers/media/video/cx88/cx88-input.c +++ b/drivers/media/video/cx88/cx88-input.c @@ -226,6 +226,8 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci) case CX88_BOARD_HAUPPAUGE_HVR3000: case CX88_BOARD_HAUPPAUGE_HVR4000: case CX88_BOARD_HAUPPAUGE_HVR4000LITE: + case CX88_BOARD_PCHDTV_HD3000: + case CX88_BOARD_PCHDTV_HD5500: ir_codes = ir_codes_hauppauge_new; ir_type = IR_TYPE_RC5; ir->sampling = 1; @@ -466,6 +468,8 @@ void cx88_ir_irq(struct cx88_core *core) case CX88_BOARD_HAUPPAUGE_HVR3000: case CX88_BOARD_HAUPPAUGE_HVR4000: case CX88_BOARD_HAUPPAUGE_HVR4000LITE: + case CX88_BOARD_PCHDTV_HD3000: + case CX88_BOARD_PCHDTV_HD5500: ircode = ir_decode_biphase(ir->samples, ir->scount, 5, 7); ir_dprintk("biphase decoded: %x\n", ircode); /* -- cgit v1.2.3 From 0c5db425519487d06a5a14eb369268f4a2b32677 Mon Sep 17 00:00:00 2001 From: Bruno Christo Date: Mon, 2 Mar 2009 22:38:59 -0300 Subject: V4L/DVB (10827): Add support for GeoVision GV-800(S) I have a GeoVision GV-800(S) card, it has 4 CONEXANT BT878A chips. It has 16 video inputs and 4 audio inputs, and it is almost identical to the GV-800, as seen on http://bttv-gallery.de . The only difference appears to be the analog mux, it has a CD22M3494 in place of the MT8816AP. The card has a blue PCB, as seen in this picture: http://www.gsbr.com.br/imagem/kits/GeoVision%20GV%20800.jpg . This card wasn't originally supported, and it was detected as UNKNOWN/GENERIC. The video inputs weren't working, so I tried "forcing" a few cards like the GeoVision GV-600, but there was still no video. So I made a patch to support this card, based on the Kodicom 4400r. The GV-800(S) is identified as follows: ... 02:00.0 Multimedia video controller: Brooktree Corporation Bt878 Video Capture (rev 11) 02:00.1 Multimedia controller: Brooktree Corporation Bt878 Audio Capture (rev 11) 02:04.0 Multimedia video controller: Brooktree Corporation Bt878 Video Capture (rev 11) 02:04.1 Multimedia controller: Brooktree Corporation Bt878 Audio Capture (rev 11) 02:08.0 Multimedia video controller: Brooktree Corporation Bt878 Video Capture (rev 11) 02:08.1 Multimedia controller: Brooktree Corporation Bt878 Audio Capture (rev 11) 02:0c.0 Multimedia video controller: Brooktree Corporation Bt878 Video Capture (rev 11) 02:0c.1 Multimedia controller: Brooktree Corporation Bt878 Audio Capture (rev 11) ... 02:00.0 0400: 109e:036e (rev 11) Subsystem: 800a:763d Flags: bus master, medium devsel, latency 32, IRQ 10 Memory at cdfff000 (32-bit, prefetchable) [size=4K] Capabilities: [44] Vital Product Data Capabilities: [4c] Power Management version 2 Kernel modules: bttv 02:00.1 0480: 109e:0878 (rev 11) Subsystem: 800a:763d Flags: bus master, medium devsel, latency 32, IRQ 10 Memory at cdffe000 (32-bit, prefetchable) [size=4K] Capabilities: [44] Vital Product Data Capabilities: [4c] Power Management version 2 02:04.0 0400: 109e:036e (rev 11) Subsystem: 800b:763d Flags: bus master, medium devsel, latency 32, IRQ 10 Memory at cdffd000 (32-bit, prefetchable) [size=4K] Capabilities: [44] Vital Product Data Capabilities: [4c] Power Management version 2 Kernel modules: bttv 02:04.1 0480: 109e:0878 (rev 11) Subsystem: 800b:763d Flags: bus master, medium devsel, latency 32, IRQ 10 Memory at cdffc000 (32-bit, prefetchable) [size=4K] Capabilities: [44] Vital Product Data Capabilities: [4c] Power Management version 2 02:08.0 0400: 109e:036e (rev 11) Subsystem: 800c:763d Flags: bus master, medium devsel, latency 32, IRQ 10 Memory at cdffb000 (32-bit, prefetchable) [size=4K] Capabilities: [44] Vital Product Data Capabilities: [4c] Power Management version 2 Kernel modules: bttv 02:08.1 0480: 109e:0878 (rev 11) Subsystem: 800c:763d Flags: bus master, medium devsel, latency 32, IRQ 10 Memory at cdffa000 (32-bit, prefetchable) [size=4K] Capabilities: [44] Vital Product Data Capabilities: [4c] Power Management version 2 02:0c.0 0400: 109e:036e (rev 11) Subsystem: 800d:763d Flags: bus master, medium devsel, latency 32, IRQ 10 Memory at cdff9000 (32-bit, prefetchable) [size=4K] Capabilities: [44] Vital Product Data Capabilities: [4c] Power Management version 2 Kernel modules: bttv 02:0c.1 0480: 109e:0878 (rev 11) Subsystem: 800d:763d Flags: bus master, medium devsel, latency 32, IRQ 10 Memory at cdff8000 (32-bit, prefetchable) [size=4K] Capabilities: [44] Vital Product Data Capabilities: [4c] Power Management version 2 As you can see, the GV-800(S) card is almost identical to the GV-800 on bttv-gallery, so this patch might also work for that card. If not, only a few changes should be required on the gv800s_write() function. After this patch, the video inputs work correctly on linux 2.6.24 and 2.6.27 using the software 'motion'. The input order may seem a little odd, but it's the order the original software/driver uses, and I decided to keep that order to get the most out of the card. I tried to get the audio working with the snd-bt87x module, but I only get noise from every audio input, even after selecting a different mux with alsamixer. Also, after trying to play sound from those sources, I randomly get a RISC error about an invalid RISC opcode, and then that output stops working. I also can't change the sampling rate when recording. Any pointers to adding audio support are welcome. Signed-off-by: Bruno Christo Signed-off-by: Mauro Carvalho Chehab --- Documentation/video4linux/CARDLIST.bttv | 2 + drivers/media/video/bt8xx/bttv-cards.c | 181 +++++++++++++++++++++++++++++++- drivers/media/video/bt8xx/bttv.h | 2 + 3 files changed, 184 insertions(+), 1 deletion(-) (limited to 'drivers/media/video') diff --git a/Documentation/video4linux/CARDLIST.bttv b/Documentation/video4linux/CARDLIST.bttv index 4dfe62641374..1da2c62715ae 100644 --- a/Documentation/video4linux/CARDLIST.bttv +++ b/Documentation/video4linux/CARDLIST.bttv @@ -155,3 +155,5 @@ 154 -> PHYTEC VD-012-X1 (bt878) 155 -> PHYTEC VD-012-X2 (bt878) 156 -> IVCE-8784 [0000:f050,0001:f050,0002:f050,0003:f050] +157 -> Geovision GV-800(S) (master) [800a:763d] +158 -> Geovision GV-800(S) (slave) [800b:763d,800c:763d,800d:763d] diff --git a/drivers/media/video/bt8xx/bttv-cards.c b/drivers/media/video/bt8xx/bttv-cards.c index fd1ab7a15cd4..fbeb396dc1c5 100644 --- a/drivers/media/video/bt8xx/bttv-cards.c +++ b/drivers/media/video/bt8xx/bttv-cards.c @@ -75,6 +75,9 @@ static void geovision_muxsel(struct bttv *btv, unsigned int input); static void phytec_muxsel(struct bttv *btv, unsigned int input); +static void gv800s_muxsel(struct bttv *btv, unsigned int input); +static void gv800s_init(struct bttv *btv); + static int terratec_active_radio_upgrade(struct bttv *btv); static int tea5757_read(struct bttv *btv); static int tea5757_write(struct bttv *btv, int value); @@ -311,6 +314,10 @@ static struct CARD { { 0xd200dbc0, BTTV_BOARD_DVICO_FUSIONHDTV_2, "DViCO FusionHDTV 2" }, { 0x763c008a, BTTV_BOARD_GEOVISION_GV600, "GeoVision GV-600" }, { 0x18011000, BTTV_BOARD_ENLTV_FM_2, "Encore ENL TV-FM-2" }, + { 0x763d800a, BTTV_BOARD_GEOVISION_GV800S, "GeoVision GV-800(S) (master)" }, + { 0x763d800b, BTTV_BOARD_GEOVISION_GV800S_SL, "GeoVision GV-800(S) (slave)" }, + { 0x763d800c, BTTV_BOARD_GEOVISION_GV800S_SL, "GeoVision GV-800(S) (slave)" }, + { 0x763d800d, BTTV_BOARD_GEOVISION_GV800S_SL, "GeoVision GV-800(S) (slave)" }, { 0, -1, NULL } }; @@ -2818,7 +2825,60 @@ struct tvcard bttv_tvcards[] = { .pll = PLL_28, .tuner_type = TUNER_ABSENT, .tuner_addr = ADDR_UNSET, - } + }, + [BTTV_BOARD_GEOVISION_GV800S] = { + /* Bruno Christo + * + * GeoVision GV-800(S) has 4 Conexant Fusion 878A: + * 1 audio input per BT878A = 4 audio inputs + * 4 video inputs per BT878A = 16 video inputs + * This is the first BT878A chip of the GV-800(S). It's the + * "master" chip and it controls the video inputs through an + * analog multiplexer (a CD22M3494) via some GPIO pins. The + * slaves should use card type 0x9e (following this one). + * There is a EEPROM on the card which is currently not handled. + * The audio input is not working yet. + */ + .name = "Geovision GV-800(S) (master)", + .video_inputs = 4, + /* .audio_inputs= 1, */ + .tuner_type = TUNER_ABSENT, + .tuner_addr = ADDR_UNSET, + .svhs = NO_SVHS, + .gpiomask = 0xf107f, + .no_gpioirq = 1, + .muxsel = MUXSEL(2, 2, 2, 2), + .pll = PLL_28, + .no_msp34xx = 1, + .no_tda7432 = 1, + .no_tda9875 = 1, + .muxsel_hook = gv800s_muxsel, + }, + [BTTV_BOARD_GEOVISION_GV800S_SL] = { + /* Bruno Christo + * + * GeoVision GV-800(S) has 4 Conexant Fusion 878A: + * 1 audio input per BT878A = 4 audio inputs + * 4 video inputs per BT878A = 16 video inputs + * The 3 other BT878A chips are "slave" chips of the GV-800(S) + * and should use this card type. + * The audio input is not working yet. + */ + .name = "Geovision GV-800(S) (slave)", + .video_inputs = 4, + /* .audio_inputs= 1, */ + .tuner_type = TUNER_ABSENT, + .tuner_addr = ADDR_UNSET, + .svhs = NO_SVHS, + .gpiomask = 0x00, + .no_gpioirq = 1, + .muxsel = MUXSEL(2, 2, 2, 2), + .pll = PLL_28, + .no_msp34xx = 1, + .no_tda7432 = 1, + .no_tda9875 = 1, + .muxsel_hook = gv800s_muxsel, + }, }; static const unsigned int bttv_num_tvcards = ARRAY_SIZE(bttv_tvcards); @@ -3338,6 +3398,9 @@ void __devinit bttv_init_card2(struct bttv *btv) case BTTV_BOARD_KODICOM_4400R: kodicom4400r_init(btv); break; + case BTTV_BOARD_GEOVISION_GV800S: + gv800s_init(btv); + break; } /* pll configuration */ @@ -4544,6 +4607,122 @@ static void phytec_muxsel(struct bttv *btv, unsigned int input) gpio_bits(0x3, mux); } +/* + * GeoVision GV-800(S) functions + * Bruno Christo +*/ + +/* This is a function to control the analog switch, which determines which + * camera is routed to which controller. The switch comprises an X-address + * (gpio bits 0-3, representing the camera, ranging from 0-15), and a + * Y-address (gpio bits 4-6, representing the controller, ranging from 0-3). + * A data value (gpio bit 18) of '1' enables the switch, and '0' disables + * the switch. A STROBE bit (gpio bit 17) latches the data value into the + * specified address. There is also a chip select (gpio bit 16). + * The idea is to set the address and chip select together, bring + * STROBE high, write the data, and finally bring STROBE back to low. + */ +static void gv800s_write(struct bttv *btv, + unsigned char xaddr, + unsigned char yaddr, + unsigned char data) { + /* On the "master" 878A: + * GPIO bits 0-9 are used for the analog switch: + * 00 - 03: camera selector + * 04 - 06: 878A (controller) selector + * 16: cselect + * 17: strobe + * 18: data (1->on, 0->off) + * 19: reset + */ + const u32 ADDRESS = ((xaddr&0xf) | (yaddr&3)<<4); + const u32 CSELECT = 1<<16; + const u32 STROBE = 1<<17; + const u32 DATA = data<<18; + + gpio_bits(0x1007f, ADDRESS | CSELECT); /* write ADDRESS and CSELECT */ + gpio_bits(0x20000, STROBE); /* STROBE high */ + gpio_bits(0x40000, DATA); /* write DATA */ + gpio_bits(0x20000, ~STROBE); /* STROBE low */ +} + +/* + * GeoVision GV-800(S) muxsel + * + * Each of the 4 cards (controllers) use this function. + * The controller using this function selects the input through the GPIO pins + * of the "master" card. A pointer to this card is stored in master[btv->c.nr]. + * + * The parameter 'input' is the requested camera number (0-4) on the controller. + * The map array has the address of each input. Note that the addresses in the + * array are in the sequence the original GeoVision driver uses, that is, set + * every controller to input 0, then to input 1, 2, 3, repeat. This means that + * the physical "camera 1" connector corresponds to controller 0 input 0, + * "camera 2" corresponds to controller 1 input 0, and so on. + * + * After getting the input address, the function then writes the appropriate + * data to the analog switch, and housekeeps the local copy of the switch + * information. + */ +static void gv800s_muxsel(struct bttv *btv, unsigned int input) +{ + struct bttv *mctlr; + char *sw_status; + int xaddr, yaddr; + static unsigned int map[4][4] = { { 0x0, 0x4, 0xa, 0x6 }, + { 0x1, 0x5, 0xb, 0x7 }, + { 0x2, 0x8, 0xc, 0xe }, + { 0x3, 0x9, 0xd, 0xf } }; + input = input%4; + mctlr = master[btv->c.nr]; + if (mctlr == NULL) { + /* do nothing until the "master" is detected */ + return; + } + yaddr = (btv->c.nr - mctlr->c.nr) & 3; + sw_status = (char *)(&mctlr->mbox_we); + xaddr = map[yaddr][input] & 0xf; + + /* Check if the controller/camera pair has changed, ignore otherwise */ + if (sw_status[yaddr] != xaddr) { + /* disable the old switch, enable the new one and save status */ + gv800s_write(mctlr, sw_status[yaddr], yaddr, 0); + sw_status[yaddr] = xaddr; + gv800s_write(mctlr, xaddr, yaddr, 1); + } +} + +/* GeoVision GV-800(S) "master" chip init */ +static void gv800s_init(struct bttv *btv) +{ + char *sw_status = (char *)(&btv->mbox_we); + int ix; + + gpio_inout(0xf107f, 0xf107f); + gpio_write(1<<19); /* reset the analog MUX */ + gpio_write(0); + + /* Preset camera 0 to the 4 controllers */ + for (ix = 0; ix < 4; ix++) { + sw_status[ix] = ix; + gv800s_write(btv, ix, ix, 1); + } + + /* Inputs on the "master" controller need this brightness fix */ + bttv_I2CWrite(btv, 0x18, 0x5, 0x90, 1); + + if (btv->c.nr > BTTV_MAX-4) + return; + /* + * Store the "master" controller pointer in the master + * array for later use in the muxsel function. + */ + master[btv->c.nr] = btv; + master[btv->c.nr+1] = btv; + master[btv->c.nr+2] = btv; + master[btv->c.nr+3] = btv; +} + /* ----------------------------------------------------------------------- */ /* motherboard chipset specific stuff */ diff --git a/drivers/media/video/bt8xx/bttv.h b/drivers/media/video/bt8xx/bttv.h index ead6e749372a..737a464606a9 100644 --- a/drivers/media/video/bt8xx/bttv.h +++ b/drivers/media/video/bt8xx/bttv.h @@ -181,6 +181,8 @@ #define BTTV_BOARD_VD012_X1 0x9a #define BTTV_BOARD_VD012_X2 0x9b #define BTTV_BOARD_IVCE8784 0x9c +#define BTTV_BOARD_GEOVISION_GV800S 0x9d +#define BTTV_BOARD_GEOVISION_GV800S_SL 0x9e /* more card-specific defines */ -- cgit v1.2.3 From 3b27591d4e0b455865969d9f9bfae0d19fd6e5c3 Mon Sep 17 00:00:00 2001 From: Adam Baker Date: Tue, 3 Mar 2009 20:20:47 -0300 Subject: V4L/DVB (10829): Support alternate resolutions for sq905 Add support for the alternate resolutions offered by SQ-905 based cameras. As well as 320x240 all cameras can do 160x120 and some can do 640x480. Signed-off-by: Adam Baker Signed-off-by: Theodore Kilgore Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/sq905.c | 100 ++++++++++++++++++++++---------------- 1 file changed, 59 insertions(+), 41 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/gspca/sq905.c b/drivers/media/video/gspca/sq905.c index dafaed69e9d0..da60eea51e44 100644 --- a/drivers/media/video/gspca/sq905.c +++ b/drivers/media/video/gspca/sq905.c @@ -60,23 +60,29 @@ MODULE_LICENSE("GPL"); #define SQ905_PING 0x07 /* when reading an "idling" command */ #define SQ905_READ_DONE 0xc0 /* ack bulk read completed */ +/* Any non-zero value in the bottom 2 bits of the 2nd byte of + * the ID appears to indicate the camera can do 640*480. If the + * LSB of that byte is set the image is just upside down, otherwise + * it is rotated 180 degrees. */ +#define SQ905_HIRES_MASK 0x00000300 +#define SQ905_ORIENTATION_MASK 0x00000100 + /* Some command codes. These go in the "index" slot. */ #define SQ905_ID 0xf0 /* asks for model string */ #define SQ905_CONFIG 0x20 /* gets photo alloc. table, not used here */ #define SQ905_DATA 0x30 /* accesses photo data, not used here */ #define SQ905_CLEAR 0xa0 /* clear everything */ -#define SQ905_CAPTURE_LOW 0x60 /* Starts capture at 160x120 */ -#define SQ905_CAPTURE_MED 0x61 /* Starts capture at 320x240 */ +#define SQ905_CAPTURE_LOW 0x60 /* Starts capture at 160x120 */ +#define SQ905_CAPTURE_MED 0x61 /* Starts capture at 320x240 */ +#define SQ905_CAPTURE_HIGH 0x62 /* Starts capture at 640x480 (some cams only) */ /* note that the capture command also controls the output dimensions */ -/* 0x60 -> 160x120, 0x61 -> 320x240 0x62 -> 640x480 depends on camera */ -/* 0x62 is not correct, at least for some cams. Should be 0x63 ? */ /* Structure to hold all of our device specific stuff */ struct sd { struct gspca_dev gspca_dev; /* !! must be the first item */ - u8 cam_type; + const struct v4l2_pix_format *cap_mode; /* * Driver stuff @@ -85,33 +91,24 @@ struct sd { struct workqueue_struct *work_thread; }; -/* The driver only supports 320x240 so far. */ -static struct v4l2_pix_format sq905_mode[1] = { +static struct v4l2_pix_format sq905_mode[] = { + { 160, 120, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE, + .bytesperline = 160, + .sizeimage = 160 * 120, + .colorspace = V4L2_COLORSPACE_SRGB, + .priv = 0}, { 320, 240, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE, .bytesperline = 320, .sizeimage = 320 * 240, .colorspace = V4L2_COLORSPACE_SRGB, + .priv = 0}, + { 640, 480, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE, + .bytesperline = 640, + .sizeimage = 640 * 480, + .colorspace = V4L2_COLORSPACE_SRGB, .priv = 0} }; -struct cam_type { - u32 ident_word; - char *name; - struct v4l2_pix_format *min_mode; - u8 num_modes; - u8 sensor_flags; -}; - -#define SQ905_FLIP_HORIZ (1 << 0) -#define SQ905_FLIP_VERT (1 << 1) - -/* Last entry is default if nothing else matches */ -static struct cam_type cam_types[] = { - { 0x19010509, "PocketCam", &sq905_mode[0], 1, SQ905_FLIP_HORIZ }, - { 0x32010509, "Magpix", &sq905_mode[0], 1, SQ905_FLIP_HORIZ }, - { 0, "Default", &sq905_mode[0], 1, SQ905_FLIP_HORIZ | SQ905_FLIP_VERT } -}; - /* * Send a command to the camera. */ @@ -240,7 +237,7 @@ static void sq905_dostream(struct work_struct *work) /* request some data and then read it until we have * a complete frame. */ - bytes_left = sq905_mode[0].sizeimage + FRAME_HEADER_LEN; + bytes_left = dev->cap_mode->sizeimage + FRAME_HEADER_LEN; header_read = 0; discarding = 0; @@ -272,11 +269,18 @@ static void sq905_dostream(struct work_struct *work) packet_type = INTER_PACKET; } frame = gspca_get_i_frame(gspca_dev); - if (frame && !discarding) + if (frame && !discarding) { gspca_frame_add(gspca_dev, packet_type, frame, data, data_len); - else + /* If entire frame fits in one packet we still + need to add a LAST_PACKET */ + if ((packet_type == FIRST_PACKET) && + (bytes_left == 0)) + gspca_frame_add(gspca_dev, LAST_PACKET, + frame, data, 0); + } else { discarding = 1; + } } /* acknowledge the frame */ mutex_lock(&gspca_dev->usb_lock); @@ -301,8 +305,6 @@ static int sd_config(struct gspca_dev *gspca_dev, struct cam *cam = &gspca_dev->cam; struct sd *dev = (struct sd *) gspca_dev; - cam->cam_mode = sq905_mode; - cam->nmodes = 1; /* We don't use the buffer gspca allocates so make it small. */ cam->bulk_size = 64; @@ -328,7 +330,6 @@ static void sd_stop0(struct gspca_dev *gspca_dev) /* this function is called at probe and resume time */ static int sd_init(struct gspca_dev *gspca_dev) { - struct sd *dev = (struct sd *) gspca_dev; u32 ident; int ret; @@ -344,17 +345,18 @@ static int sd_init(struct gspca_dev *gspca_dev) ret = sq905_read_data(gspca_dev, gspca_dev->usb_buf, 4); if (ret < 0) return ret; - /* usb_buf is allocated with kmalloc so is aligned. */ - ident = le32_to_cpup((u32 *)gspca_dev->usb_buf); + /* usb_buf is allocated with kmalloc so is aligned. + * Camera model number is the right way round if we assume this + * reverse engineered ID is supposed to be big endian. */ + ident = be32_to_cpup((__be32 *)gspca_dev->usb_buf); ret = sq905_command(gspca_dev, SQ905_CLEAR); if (ret < 0) return ret; - dev->cam_type = 0; - while (dev->cam_type < ARRAY_SIZE(cam_types) - 1 && - ident != cam_types[dev->cam_type].ident_word) - dev->cam_type++; - PDEBUG(D_CONF, "SQ905 camera %s, ID %08x detected", - cam_types[dev->cam_type].name, ident); + PDEBUG(D_CONF, "SQ905 camera ID %08x detected", ident); + gspca_dev->cam.cam_mode = sq905_mode; + gspca_dev->cam.nmodes = ARRAY_SIZE(sq905_mode); + if (!(ident & SQ905_HIRES_MASK)) + gspca_dev->cam.nmodes--; return 0; } @@ -364,13 +366,29 @@ static int sd_start(struct gspca_dev *gspca_dev) struct sd *dev = (struct sd *) gspca_dev; int ret; + /* Set capture mode based on selected resolution. */ + dev->cap_mode = gspca_dev->cam.cam_mode; /* "Open the shutter" and set size, to start capture */ - ret = sq905_command(&dev->gspca_dev, SQ905_CAPTURE_MED); + switch (gspca_dev->width) { + case 640: + PDEBUG(D_STREAM, "Start streaming at high resolution"); + dev->cap_mode += 2; + ret = sq905_command(&dev->gspca_dev, SQ905_CAPTURE_HIGH); + break; + case 320: + PDEBUG(D_STREAM, "Start streaming at medium resolution"); + dev->cap_mode++; + ret = sq905_command(&dev->gspca_dev, SQ905_CAPTURE_MED); + break; + default: + PDEBUG(D_STREAM, "Start streaming at low resolution"); + ret = sq905_command(&dev->gspca_dev, SQ905_CAPTURE_LOW); + } + if (ret < 0) { PDEBUG(D_ERR, "Start streaming command failed"); return ret; } - /* Start the workqueue function to do the streaming */ dev->work_thread = create_singlethread_workqueue(MODULE_NAME); queue_work(dev->work_thread, &dev->work_struct); -- cgit v1.2.3 From 2bd1d9eb1c27034a77c8e1887156da72d6160ae1 Mon Sep 17 00:00:00 2001 From: Vitaly Wool Date: Wed, 4 Mar 2009 08:27:52 -0300 Subject: V4L/DVB (10833): em28xx: enable Compro VideoMate ForYou sound Compro VideoMate uses an external audio DSP chip, controlled via tvaudio module (tda9874a). This patch improves em28xx infrastructure to support an external audio processor and fixes the Compro VideoMate entry to work with it. Signed-off-by: Vitaly Wool Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/em28xx/em28xx-cards.c | 21 ++++++++++++++++++++- drivers/media/video/em28xx/em28xx-core.c | 5 +++++ drivers/media/video/em28xx/em28xx-i2c.c | 6 ++++++ drivers/media/video/em28xx/em28xx-video.c | 7 +++++++ drivers/media/video/em28xx/em28xx.h | 1 + 5 files changed, 39 insertions(+), 1 deletion(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/em28xx/em28xx-cards.c b/drivers/media/video/em28xx/em28xx-cards.c index f7c817765752..650ccfda1428 100644 --- a/drivers/media/video/em28xx/em28xx-cards.c +++ b/drivers/media/video/em28xx/em28xx-cards.c @@ -122,6 +122,22 @@ static struct em28xx_reg_seq default_tuner_gpio[] = { { -1, -1, -1, -1}, }; +/* Mute/unmute */ +static struct em28xx_reg_seq compro_unmute_tv_gpio[] = { + {EM28XX_R08_GPIO, 5, 7, 10}, + { -1, -1, -1, -1}, +}; + +static struct em28xx_reg_seq compro_unmute_svid_gpio[] = { + {EM28XX_R08_GPIO, 4, 7, 10}, + { -1, -1, -1, -1}, +}; + +static struct em28xx_reg_seq compro_mute_gpio[] = { + {EM28XX_R08_GPIO, 6, 7, 10}, + { -1, -1, -1, -1}, +}; + /* * Board definitions */ @@ -1225,14 +1241,17 @@ struct em28xx_board em28xx_boards[] = { .tda9887_conf = TDA9887_PRESENT, .decoder = EM28XX_TVP5150, .adecoder = EM28XX_TVAUDIO, + .mute_gpio = compro_mute_gpio, .input = { { .type = EM28XX_VMUX_TELEVISION, .vmux = TVP5150_COMPOSITE0, - .amux = EM28XX_AMUX_LINE_IN, + .amux = EM28XX_AMUX_VIDEO, + .gpio = compro_unmute_tv_gpio, }, { .type = EM28XX_VMUX_SVIDEO, .vmux = TVP5150_SVIDEO, .amux = EM28XX_AMUX_LINE_IN, + .gpio = compro_unmute_svid_gpio, } }, }, [EM2860_BOARD_KAIOMY_TVNPC_U2] = { diff --git a/drivers/media/video/em28xx/em28xx-core.c b/drivers/media/video/em28xx/em28xx-core.c index eee8d015b249..c896d24032f5 100644 --- a/drivers/media/video/em28xx/em28xx-core.c +++ b/drivers/media/video/em28xx/em28xx-core.c @@ -378,6 +378,11 @@ static int em28xx_set_audio_source(struct em28xx *dev) } } + if (dev->board.mute_gpio && dev->mute) + em28xx_gpio_set(dev, dev->board.mute_gpio); + else + em28xx_gpio_set(dev, INPUT(dev->ctl_input)->gpio); + ret = em28xx_write_reg_bits(dev, EM28XX_R0E_AUDIOSRC, input, 0xc0); if (ret < 0) return ret; diff --git a/drivers/media/video/em28xx/em28xx-i2c.c b/drivers/media/video/em28xx/em28xx-i2c.c index 2dab43d22da2..02c12fe6361b 100644 --- a/drivers/media/video/em28xx/em28xx-i2c.c +++ b/drivers/media/video/em28xx/em28xx-i2c.c @@ -510,12 +510,17 @@ static int attach_inform(struct i2c_client *client) dprintk1(1, "attach_inform: tvp5150 detected.\n"); break; + case 0xb0: + dprintk1(1, "attach_inform: tda9874 detected\n"); + break; + default: if (!dev->tuner_addr) dev->tuner_addr = client->addr; dprintk1(1, "attach inform: detected I2C address %x\n", client->addr << 1); + dprintk1(1, "driver id %d\n", client->driver->id); } @@ -554,6 +559,7 @@ static char *i2c_devs[128] = { [0x80 >> 1] = "msp34xx", [0x88 >> 1] = "msp34xx", [0xa0 >> 1] = "eeprom", + [0xb0 >> 1] = "tda9874", [0xb8 >> 1] = "tvp5150a", [0xba >> 1] = "tvp5150a", [0xc0 >> 1] = "tuner (analog)", diff --git a/drivers/media/video/em28xx/em28xx-video.c b/drivers/media/video/em28xx/em28xx-video.c index efd641587e04..575472f1e702 100644 --- a/drivers/media/video/em28xx/em28xx-video.c +++ b/drivers/media/video/em28xx/em28xx-video.c @@ -540,6 +540,13 @@ static void video_mux(struct em28xx *dev, int index) &route); } + if (dev->board.adecoder != EM28XX_NOADECODER) { + route.input = dev->ctl_ainput; + route.output = dev->ctl_aoutput; + em28xx_i2c_call_clients(dev, VIDIOC_INT_S_AUDIO_ROUTING, + &route); + } + em28xx_audio_analog_set(dev); } diff --git a/drivers/media/video/em28xx/em28xx.h b/drivers/media/video/em28xx/em28xx.h index 57a4084f9b5e..a33a58da016e 100644 --- a/drivers/media/video/em28xx/em28xx.h +++ b/drivers/media/video/em28xx/em28xx.h @@ -374,6 +374,7 @@ struct em28xx_board { struct em28xx_reg_seq *dvb_gpio; struct em28xx_reg_seq *suspend_gpio; struct em28xx_reg_seq *tuner_gpio; + struct em28xx_reg_seq *mute_gpio; unsigned int is_em2800:1; unsigned int has_msp34xx:1; -- cgit v1.2.3 From c1bda50fabdfc7d3e463e2db6c588aa0a30eb1ac Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 6 Mar 2009 08:06:24 -0300 Subject: V4L/DVB (10835): Kconfig: Add some missing selects for a required frontends Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-usb/Kconfig | 1 + drivers/media/video/cx23885/Kconfig | 2 ++ drivers/media/video/saa7134/Kconfig | 1 + 3 files changed, 4 insertions(+) (limited to 'drivers/media/video') diff --git a/drivers/media/dvb/dvb-usb/Kconfig b/drivers/media/dvb/dvb-usb/Kconfig index bbddc9fb6b64..3e581409fe81 100644 --- a/drivers/media/dvb/dvb-usb/Kconfig +++ b/drivers/media/dvb/dvb-usb/Kconfig @@ -108,6 +108,7 @@ config DVB_USB_CXUSB select DVB_MT352 if !DVB_FE_CUSTOMISE select DVB_ZL10353 if !DVB_FE_CUSTOMISE select DVB_DIB7000P if !DVB_FE_CUSTOMISE + select DVB_LGS8GL5 if !DVB_FE_CUSTOMISE select DVB_TUNER_DIB0070 if !DVB_FE_CUSTOMISE select MEDIA_TUNER_SIMPLE if !MEDIA_TUNER_CUSTOMIZE select MEDIA_TUNER_XC2028 if !MEDIA_TUNER_CUSTOMIZE diff --git a/drivers/media/video/cx23885/Kconfig b/drivers/media/video/cx23885/Kconfig index b62f16d507d8..bbd990ff7f29 100644 --- a/drivers/media/video/cx23885/Kconfig +++ b/drivers/media/video/cx23885/Kconfig @@ -17,6 +17,8 @@ config VIDEO_CX23885 select DVB_ZL10353 if !DVB_FE_CUSTOMISE select DVB_TDA10048 if !DVB_FE_CUSTOMIZE select DVB_LNBP21 if !DVB_FE_CUSTOMIZE + select DVB_STV6110 if !DVB_FE_CUSTOMIZE + select DVB_STV0900 if !DVB_FE_CUSTOMIZE select MEDIA_TUNER_MT2131 if !MEDIA_TUNER_CUSTOMIZE select MEDIA_TUNER_XC2028 if !DVB_FE_CUSTOMIZE select MEDIA_TUNER_TDA8290 if !DVB_FE_CUSTOMIZE diff --git a/drivers/media/video/saa7134/Kconfig b/drivers/media/video/saa7134/Kconfig index a3470ebad50a..e69d504acecd 100644 --- a/drivers/media/video/saa7134/Kconfig +++ b/drivers/media/video/saa7134/Kconfig @@ -35,6 +35,7 @@ config VIDEO_SAA7134_DVB select DVB_TDA10086 if !DVB_FE_CUSTOMISE select DVB_TDA826X if !DVB_FE_CUSTOMISE select DVB_ISL6421 if !DVB_FE_CUSTOMISE + select DVB_ISL6405 if !DVB_FE_CUSTOMISE select MEDIA_TUNER_TDA827X if !MEDIA_TUNER_CUSTOMIZE select MEDIA_TUNER_SIMPLE if !MEDIA_TUNER_CUSTOMIZE select DVB_ZL10036 if !DVB_FE_CUSTOMISE -- cgit v1.2.3 From af2ffb2cfd72dc949f1bac7f7de291f116ae87da Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 6 Mar 2009 08:25:35 -0300 Subject: V4L/DVB (10836): Kconfig: replace DVB_FE_CUSTOMIZE to DVB_FE_CUSTOMISE The name of the option is DVB_FE_CUSTOMISE. However, on a few places, a wrong name were used, due to a typo (DVB_FE_CUSTOMIZE). Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/au0828/Kconfig | 2 +- drivers/media/video/cx23885/Kconfig | 8 ++++---- drivers/media/video/pvrusb2/Kconfig | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/au0828/Kconfig b/drivers/media/video/au0828/Kconfig index 018f72b8e3e2..621ec043f31a 100644 --- a/drivers/media/video/au0828/Kconfig +++ b/drivers/media/video/au0828/Kconfig @@ -4,7 +4,7 @@ config VIDEO_AU0828 depends on I2C && INPUT && DVB_CORE && USB select I2C_ALGOBIT select VIDEO_TVEEPROM - select DVB_AU8522 if !DVB_FE_CUSTOMIZE + select DVB_AU8522 if !DVB_FE_CUSTOMISE select MEDIA_TUNER_XC5000 if !DVB_FE_CUSTOMIZE select MEDIA_TUNER_MXL5007T if !DVB_FE_CUSTOMIZE select MEDIA_TUNER_TDA18271 if !DVB_FE_CUSTOMIZE diff --git a/drivers/media/video/cx23885/Kconfig b/drivers/media/video/cx23885/Kconfig index bbd990ff7f29..4066ca69c28a 100644 --- a/drivers/media/video/cx23885/Kconfig +++ b/drivers/media/video/cx23885/Kconfig @@ -15,10 +15,10 @@ config VIDEO_CX23885 select DVB_S5H1411 if !DVB_FE_CUSTOMISE select DVB_LGDT330X if !DVB_FE_CUSTOMISE select DVB_ZL10353 if !DVB_FE_CUSTOMISE - select DVB_TDA10048 if !DVB_FE_CUSTOMIZE - select DVB_LNBP21 if !DVB_FE_CUSTOMIZE - select DVB_STV6110 if !DVB_FE_CUSTOMIZE - select DVB_STV0900 if !DVB_FE_CUSTOMIZE + select DVB_TDA10048 if !DVB_FE_CUSTOMISE + select DVB_LNBP21 if !DVB_FE_CUSTOMISE + select DVB_STV6110 if !DVB_FE_CUSTOMISE + select DVB_STV0900 if !DVB_FE_CUSTOMISE select MEDIA_TUNER_MT2131 if !MEDIA_TUNER_CUSTOMIZE select MEDIA_TUNER_XC2028 if !DVB_FE_CUSTOMIZE select MEDIA_TUNER_TDA8290 if !DVB_FE_CUSTOMIZE diff --git a/drivers/media/video/pvrusb2/Kconfig b/drivers/media/video/pvrusb2/Kconfig index 854c2a885358..7f7b05c40e22 100644 --- a/drivers/media/video/pvrusb2/Kconfig +++ b/drivers/media/video/pvrusb2/Kconfig @@ -40,7 +40,7 @@ config VIDEO_PVRUSB2_DVB select DVB_LGDT330X if !DVB_FE_CUSTOMISE select DVB_S5H1409 if !DVB_FE_CUSTOMISE select DVB_S5H1411 if !DVB_FE_CUSTOMISE - select DVB_TDA10048 if !DVB_FE_CUSTOMIZE + select DVB_TDA10048 if !DVB_FE_CUSTOMISE select MEDIA_TUNER_TDA18271 if !DVB_FE_CUSTOMIZE select MEDIA_TUNER_SIMPLE if !MEDIA_TUNER_CUSTOMIZE select MEDIA_TUNER_TDA8290 if !DVB_FE_CUSTOMIZE -- cgit v1.2.3 From 45f5c1993fcc7501a4a431030242863abca38f69 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sun, 8 Mar 2009 08:02:53 -0300 Subject: V4L/DVB (10838): get rid of the other occurrences of DVB_FE_CUSTOMIZE typo There are still more places where DVB_FE_CUSTOMIZE is used, instead of DVB_FE_CUSTOMISE. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/au0828/Kconfig | 6 +++--- drivers/media/video/cx23885/Kconfig | 8 ++++---- drivers/media/video/pvrusb2/Kconfig | 4 ++-- 3 files changed, 9 insertions(+), 9 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/au0828/Kconfig b/drivers/media/video/au0828/Kconfig index 621ec043f31a..deb00e4acb94 100644 --- a/drivers/media/video/au0828/Kconfig +++ b/drivers/media/video/au0828/Kconfig @@ -5,9 +5,9 @@ config VIDEO_AU0828 select I2C_ALGOBIT select VIDEO_TVEEPROM select DVB_AU8522 if !DVB_FE_CUSTOMISE - select MEDIA_TUNER_XC5000 if !DVB_FE_CUSTOMIZE - select MEDIA_TUNER_MXL5007T if !DVB_FE_CUSTOMIZE - select MEDIA_TUNER_TDA18271 if !DVB_FE_CUSTOMIZE + select MEDIA_TUNER_XC5000 if !DVB_FE_CUSTOMISE + select MEDIA_TUNER_MXL5007T if !DVB_FE_CUSTOMISE + select MEDIA_TUNER_TDA18271 if !DVB_FE_CUSTOMISE ---help--- This is a video4linux driver for Auvitek's USB device. diff --git a/drivers/media/video/cx23885/Kconfig b/drivers/media/video/cx23885/Kconfig index 4066ca69c28a..28896aa31506 100644 --- a/drivers/media/video/cx23885/Kconfig +++ b/drivers/media/video/cx23885/Kconfig @@ -20,10 +20,10 @@ config VIDEO_CX23885 select DVB_STV6110 if !DVB_FE_CUSTOMISE select DVB_STV0900 if !DVB_FE_CUSTOMISE select MEDIA_TUNER_MT2131 if !MEDIA_TUNER_CUSTOMIZE - select MEDIA_TUNER_XC2028 if !DVB_FE_CUSTOMIZE - select MEDIA_TUNER_TDA8290 if !DVB_FE_CUSTOMIZE - select MEDIA_TUNER_TDA18271 if !DVB_FE_CUSTOMIZE - select MEDIA_TUNER_XC5000 if !DVB_FE_CUSTOMIZE + select MEDIA_TUNER_XC2028 if !DVB_FE_CUSTOMISE + select MEDIA_TUNER_TDA8290 if !DVB_FE_CUSTOMISE + select MEDIA_TUNER_TDA18271 if !DVB_FE_CUSTOMISE + select MEDIA_TUNER_XC5000 if !DVB_FE_CUSTOMISE ---help--- This is a video4linux driver for Conexant 23885 based TV cards. diff --git a/drivers/media/video/pvrusb2/Kconfig b/drivers/media/video/pvrusb2/Kconfig index 7f7b05c40e22..bb42713939ee 100644 --- a/drivers/media/video/pvrusb2/Kconfig +++ b/drivers/media/video/pvrusb2/Kconfig @@ -41,9 +41,9 @@ config VIDEO_PVRUSB2_DVB select DVB_S5H1409 if !DVB_FE_CUSTOMISE select DVB_S5H1411 if !DVB_FE_CUSTOMISE select DVB_TDA10048 if !DVB_FE_CUSTOMISE - select MEDIA_TUNER_TDA18271 if !DVB_FE_CUSTOMIZE + select MEDIA_TUNER_TDA18271 if !DVB_FE_CUSTOMISE select MEDIA_TUNER_SIMPLE if !MEDIA_TUNER_CUSTOMIZE - select MEDIA_TUNER_TDA8290 if !DVB_FE_CUSTOMIZE + select MEDIA_TUNER_TDA8290 if !DVB_FE_CUSTOMISE ---help--- This option enables a DVB interface for the pvrusb2 driver. -- cgit v1.2.3 From 7b9eb81e36b3926d3ee77fbd4bde88d28ab70fa0 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sun, 8 Mar 2009 12:55:29 -0300 Subject: V4L/DVB (10840): em28xx-dvb: Remove an unused header Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/em28xx/em28xx-dvb.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/em28xx/em28xx-dvb.c b/drivers/media/video/em28xx/em28xx-dvb.c index 9ad8527b3fda..fcd25511209b 100644 --- a/drivers/media/video/em28xx/em28xx-dvb.c +++ b/drivers/media/video/em28xx/em28xx-dvb.c @@ -29,9 +29,6 @@ #include "lgdt330x.h" #include "zl10353.h" #include "s5h1409.h" -#ifdef EM28XX_DRX397XD_SUPPORT -#include "drx397xD.h" -#endif MODULE_DESCRIPTION("driver for em28xx based DVB cards"); MODULE_AUTHOR("Mauro Carvalho Chehab "); -- cgit v1.2.3 From 7c9e34aaab50a6c8f69ce59816dd76a283090667 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sun, 8 Mar 2009 13:11:31 -0300 Subject: V4L/DVB (10842): Adds some missing frontend selects for saa7134 and dvb-usb Some dvb frontends are required on some boards, but those dependencies were missed. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-usb/Kconfig | 1 + drivers/media/video/saa7134/Kconfig | 2 ++ 2 files changed, 3 insertions(+) (limited to 'drivers/media/video') diff --git a/drivers/media/dvb/dvb-usb/Kconfig b/drivers/media/dvb/dvb-usb/Kconfig index 3e581409fe81..3763a9c68925 100644 --- a/drivers/media/dvb/dvb-usb/Kconfig +++ b/drivers/media/dvb/dvb-usb/Kconfig @@ -96,6 +96,7 @@ config DVB_USB_UMT_010 select DVB_PLL if !DVB_FE_CUSTOMISE select DVB_DIB3000MC select MEDIA_TUNER_MT2060 if !MEDIA_TUNER_CUSTOMIZE + select DVB_MT352 if !DVB_FE_CUSTOMISE help Say Y here to support the HanfTek UMT-010 USB2.0 stick-sized DVB-T receiver. diff --git a/drivers/media/video/saa7134/Kconfig b/drivers/media/video/saa7134/Kconfig index e69d504acecd..51f17c82bc30 100644 --- a/drivers/media/video/saa7134/Kconfig +++ b/drivers/media/video/saa7134/Kconfig @@ -40,6 +40,8 @@ config VIDEO_SAA7134_DVB select MEDIA_TUNER_SIMPLE if !MEDIA_TUNER_CUSTOMIZE select DVB_ZL10036 if !DVB_FE_CUSTOMISE select DVB_MT312 if !DVB_FE_CUSTOMISE + select DVB_LNBP21 if !DVB_FE_CUSTOMISE + select DVB_ZL10353 if !DVB_FE_CUSTOMISE ---help--- This adds support for DVB cards based on the Philips saa7134 chip. -- cgit v1.2.3 From e276f7b5f9c41536f22bec1d8205e6b201300743 Mon Sep 17 00:00:00 2001 From: Trent Piepho Date: Thu, 5 Mar 2009 08:02:05 -0300 Subject: V4L/DVB (10848): zoran: Change first argument to zoran_v4l2_buffer_status It was a struct file *, but all that function wants is the struct zoran_fh from the file's private data. Since every caller already has this, just pass the zoran_fh instead. Signed-off-by: Trent Piepho Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/zoran/zoran_driver.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/zoran/zoran_driver.c b/drivers/media/video/zoran/zoran_driver.c index 5dcd56c9b947..2dd8d90aedf9 100644 --- a/drivers/media/video/zoran/zoran_driver.c +++ b/drivers/media/video/zoran/zoran_driver.c @@ -1377,11 +1377,10 @@ setup_overlay (struct file *file, /* get the status of a buffer in the clients buffer queue */ static int -zoran_v4l2_buffer_status (struct file *file, +zoran_v4l2_buffer_status (struct zoran_fh *fh, struct v4l2_buffer *buf, int num) { - struct zoran_fh *fh = file->private_data; struct zoran *zr = fh->zr; buf->flags = V4L2_BUF_FLAG_MAPPED; @@ -2501,7 +2500,7 @@ static int zoran_querybuf(struct file *file, void *__fh, struct v4l2_buffer *buf int res; mutex_lock(&zr->resource_lock); - res = zoran_v4l2_buffer_status(file, buf, buf->index); + res = zoran_v4l2_buffer_status(fh, buf, buf->index); mutex_unlock(&zr->resource_lock); return res; @@ -2602,7 +2601,7 @@ static int zoran_dqbuf(struct file *file, void *__fh, struct v4l2_buffer *buf) if (res) goto dqbuf_unlock_and_return; zr->v4l_sync_tail++; - res = zoran_v4l2_buffer_status(file, buf, num); + res = zoran_v4l2_buffer_status(fh, buf, num); break; case ZORAN_MAP_MODE_JPG_REC: @@ -2633,7 +2632,7 @@ static int zoran_dqbuf(struct file *file, void *__fh, struct v4l2_buffer *buf) res = jpg_sync(file, &bs); if (res) goto dqbuf_unlock_and_return; - res = zoran_v4l2_buffer_status(file, buf, bs.frame); + res = zoran_v4l2_buffer_status(fh, buf, bs.frame); break; } -- cgit v1.2.3 From 098003d8e21c490c104b543918dea12b7608a173 Mon Sep 17 00:00:00 2001 From: Andy Walls Date: Sat, 28 Feb 2009 13:19:45 -0300 Subject: V4L/DVB (10850): cx18: Use strlcpy() instead of strncpy() for temp eeprom i2c_client setup Signed-off-by: Andy Walls Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx18/cx18-driver.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/cx18/cx18-driver.c b/drivers/media/video/cx18/cx18-driver.c index 0d24e2297457..210c68aaae00 100644 --- a/drivers/media/video/cx18/cx18-driver.c +++ b/drivers/media/video/cx18/cx18-driver.c @@ -273,8 +273,7 @@ void cx18_read_eeprom(struct cx18 *cx, struct tveeprom *tv) u8 eedata[256]; memset(&c, 0, sizeof(c)); - strncpy(c.name, "cx18 tveeprom tmp", sizeof(c.name)); - c.name[sizeof(c.name)-1] = '\0'; + strlcpy(c.name, "cx18 tveeprom tmp", sizeof(c.name)); c.adapter = &cx->i2c_adap[0]; c.addr = 0xA0 >> 1; -- cgit v1.2.3 From 72401b7a37c6f0132ea2d0c3236ec706a9e5759e Mon Sep 17 00:00:00 2001 From: Andy Walls Date: Sat, 28 Feb 2009 14:51:47 -0300 Subject: V4L/DVB (10851): cx18: Fix a video scaling check problem introduced by sliced VBI changes Fix a scaling check that was failing, due to a magic number I missed fixing during previous slice VBI changes. Now $ v4l2-ctl -v width=480,height=480,pixelformat=MPEG yields proper visual results again. Signed-off-by: Andy Walls Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx18/cx18-av-core.c | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/cx18/cx18-av-core.c b/drivers/media/video/cx18/cx18-av-core.c index cf256a999bd4..aeeb3cfa3390 100644 --- a/drivers/media/video/cx18/cx18-av-core.c +++ b/drivers/media/video/cx18/cx18-av-core.c @@ -867,8 +867,22 @@ static int cx18_av_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt) Hsrc = (cx18_av_read(cx, 0x472) & 0x3f) << 4; Hsrc |= (cx18_av_read(cx, 0x471) & 0xf0) >> 4; - Vlines = pix->height + (is_50Hz ? 4 : 7); + /* + * This adjustment reflects the excess of vactive, set in + * cx18_av_std_setup(), above standard values: + * + * 480 + 1 for 60 Hz systems + * 576 + 4 for 50 Hz systems + */ + Vlines = pix->height + (is_50Hz ? 4 : 1); + /* + * Invalid height and width scaling requests are: + * 1. width less than 1/16 of the source width + * 2. width greater than the source width + * 3. height less than 1/8 of the source height + * 4. height greater than the source height + */ if ((pix->width * 16 < Hsrc) || (Hsrc < pix->width) || (Vlines * 8 < Vsrc) || (Vsrc < Vlines)) { CX18_ERR_DEV(sd, "%dx%d is not a valid size!\n", -- cgit v1.2.3 From 386e439f0c32eb540e931b0d1874e3fd1a8a8f10 Mon Sep 17 00:00:00 2001 From: Andy Walls Date: Sat, 28 Feb 2009 16:42:51 -0300 Subject: V4L/DVB (10852): cx18: Include cx18-audio.h in cx18-audio.c to eliminate s-parse warning Signed-off-by: Andy Walls Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx18/cx18-audio.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/media/video') diff --git a/drivers/media/video/cx18/cx18-audio.c b/drivers/media/video/cx18/cx18-audio.c index ccd170887b89..bb5c5165dd5f 100644 --- a/drivers/media/video/cx18/cx18-audio.c +++ b/drivers/media/video/cx18/cx18-audio.c @@ -24,6 +24,7 @@ #include "cx18-driver.h" #include "cx18-io.h" #include "cx18-cards.h" +#include "cx18-audio.h" #define CX18_AUDIO_ENABLE 0xc72014 -- cgit v1.2.3 From 583803d135b14d414e77b6d2b546a811cac9944e Mon Sep 17 00:00:00 2001 From: Andy Walls Date: Sat, 28 Feb 2009 18:48:27 -0300 Subject: V4L/DVB (10853): cx18: Fix s-parse warnings and a logic error about extracting the VBI PTS My s-parse builds never griped about be32_to_cpu() casting to __be32, but Hans' builds did. This change explictly declares the pointer into the VBI buffer header as __be32, which is the correct thing to do as the data is always big endian when we go to fetch it. Hopefully this will quiet s-parse warnings. Also corrected a misplaced parenthesis logic error in checking for the VBI header magic number. Signed-off-by: Andy Walls Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx18/cx18-vbi.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/cx18/cx18-vbi.c b/drivers/media/video/cx18/cx18-vbi.c index a81fe2e985f2..355737bff13e 100644 --- a/drivers/media/video/cx18/cx18-vbi.c +++ b/drivers/media/video/cx18/cx18-vbi.c @@ -169,7 +169,7 @@ void cx18_process_vbi_data(struct cx18 *cx, struct cx18_buffer *buf, int streamtype) { u8 *p = (u8 *) buf->buf; - u32 *q = (u32 *) buf->buf; + __be32 *q = (__be32 *) buf->buf; u32 size = buf->bytesused; u32 pts; int lines; @@ -178,8 +178,9 @@ void cx18_process_vbi_data(struct cx18 *cx, struct cx18_buffer *buf, return; /* - * The CX23418 sends us data that is 32 bit LE swapped, but we want - * the raw VBI bytes in the order they were in the raster line + * The CX23418 sends us data that is 32 bit little-endian swapped, + * but we want the raw VBI bytes in the order they were in the raster + * line. This has a side effect of making the 12 byte header big endian */ cx18_buf_swap(buf); @@ -218,7 +219,7 @@ void cx18_process_vbi_data(struct cx18 *cx, struct cx18_buffer *buf, /* Sliced VBI data with data insertion */ - pts = (be32_to_cpu(q[0] == 0x3fffffff)) ? be32_to_cpu(q[2]) : 0; + pts = (be32_to_cpu(q[0]) == 0x3fffffff) ? be32_to_cpu(q[2]) : 0; /* * For calls to compress_sliced_buf(), ensure there are an integral -- cgit v1.2.3 From af7c58b1f5014bea181ef74d724ac960923dd403 Mon Sep 17 00:00:00 2001 From: Andy Walls Date: Sat, 28 Feb 2009 20:13:50 -0300 Subject: V4L/DVB (10854): cx18: Correct comments about vertical and horizontal blanking timings This change only affects comments. Signed-off-by: Andy Walls Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx18/cx18-av-core.c | 26 ++++++++++++++++---------- drivers/media/video/cx18/cx18-av-core.h | 19 ++++++++++++------- drivers/media/video/cx18/cx18-streams.c | 5 ++--- 3 files changed, 30 insertions(+), 20 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/cx18/cx18-av-core.c b/drivers/media/video/cx18/cx18-av-core.c index aeeb3cfa3390..21f4be8393b7 100644 --- a/drivers/media/video/cx18/cx18-av-core.c +++ b/drivers/media/video/cx18/cx18-av-core.c @@ -292,23 +292,29 @@ void cx18_av_std_setup(struct cx18 *cx) * * vsync: always 6 half-lines of vsync pulses * vactive: half lines of active video - * vblank656: half lines, after line 3, of blanked video - * vblank: half lines, after line 9, of blanked video + * vblank656: half lines, after line 3/mid-266, of blanked video + * vblank: half lines, after line 9/272, of blanked video * + * As far as I can tell: * vblank656 starts counting from the falling edge of the first - * vsync pulse (start of line 4) + * vsync pulse (start of line 4 or mid-266) * vblank starts counting from the after the 6 vsync pulses and - * 6 equalization pulses (start of line 10) + * 6 or 5 equalization pulses (start of line 10 or 272) * * For 525 line systems the driver will extract VBI information - * from lines 10 through 21. To avoid the EAV RP code from - * toggling at the start of hblank at line 22, where sliced VBI - * data from line 21 is stuffed, also treat line 22 as blanked. + * from lines 10-21 and lines 273-284. */ - vblank656 = 38; /* lines 4 through 22 */ - vblank = 26; /* lines 10 through 22 */ - vactive = 481; /* lines 23 through 262.5 */ + vblank656 = 38; /* lines 4 - 22 & 266 - 284 */ + vblank = 26; /* lines 10 - 22 & 272 - 284 */ + vactive = 481; /* lines 23 - 263 & 285 - 525 */ + /* + * For a 13.5 Mpps clock and 15,734.26 Hz line rate, a line is + * is 858 pixels = 720 active + 138 blanking. The Hsync leading + * edge should happen 1.2 us * 13.5 Mpps ~= 16 pixels after the + * end of active video, leaving 122 pixels of hblank to ignore + * before active video starts. + */ hactive = 720; hblank = 122; luma_lpf = 1; diff --git a/drivers/media/video/cx18/cx18-av-core.h b/drivers/media/video/cx18/cx18-av-core.h index fd0df4151211..2687a2c91ddd 100644 --- a/drivers/media/video/cx18/cx18-av-core.h +++ b/drivers/media/video/cx18/cx18-av-core.h @@ -89,16 +89,21 @@ struct cx18_av_state { /* * The VBI slicer starts operating and counting lines, begining at - * slicer line count of 1, at D lines after the deassertion of VRESET - * This staring field line, S, is 6 or 10 for 625 or 525 line systems. - * Sliced ancillary data captured on VBI slicer line M is sent at the - * beginning of the next VBI slicer line, VBI slicer line count N = M+1. - * Thus when the VBI slicer reports a VBI slicer line number with - * ancillary data, the IDID0 byte indicates VBI slicer line N. - * The actual field line that the captured data comes from is + * slicer line count of 1, at D lines after the deassertion of VRESET. + * This staring field line, S, is 6 (& 319) or 10 (& 273) for 625 or 525 + * line systems respectively. Sliced ancillary data captured on VBI + * slicer line M is inserted after the VBI slicer is done with line M, + * when VBI slicer line count is N = M+1. Thus when the VBI slicer + * reports a VBI slicer line number with ancillary data, the IDID0 byte + * indicates VBI slicer line N. The actual field line that the captured + * data comes from is + * * L = M+(S+D-1) = N-1+(S+D-1) = N + (S+D-2). * + * L is the line in the field, not frame, from which the VBI data came. + * N is the line reported by the slicer in the ancillary data. * D is the slicer_line_delay value programmed into register 0x47f. + * S is 6 for 625 line systems or 10 for 525 line systems * (S+D-2) is the slicer_line_offset used to convert slicer reported * line counts to actual field lines. */ diff --git a/drivers/media/video/cx18/cx18-streams.c b/drivers/media/video/cx18/cx18-streams.c index ce65cc6c86e8..0932b76b2373 100644 --- a/drivers/media/video/cx18/cx18-streams.c +++ b/drivers/media/video/cx18/cx18-streams.c @@ -413,9 +413,8 @@ static void cx18_vbi_setup(struct cx18_stream *s) * 0x90 (Task HorizontalBlank) * 0xd0 (Task EvenField HorizontalBlank) * - * We have set the digitzer to consider the first active line - * as part of VerticalBlank as well so we don't have to look for - * these problem codes nor lose the last line of sliced data. + * We have set the digitzer such that we don't have to worry + * about these problem codes. */ data[4] = 0xB0F0B0F0; /* -- cgit v1.2.3 From cb95a40e54b96938c2e81de6a95609e915922962 Mon Sep 17 00:00:00 2001 From: Andy Walls Date: Sat, 28 Feb 2009 23:06:08 -0300 Subject: V4L/DVB (10855): cx18: Fix VPS service register codes Based on a documentation clarification from Conexant, fix the register code used for sliced VBI VPS service. Signed-off-by: Andy Walls Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx18/cx18-av-vbi.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/cx18/cx18-av-vbi.c b/drivers/media/video/cx18/cx18-av-vbi.c index 43267d1afb92..27699839b80d 100644 --- a/drivers/media/video/cx18/cx18-av-vbi.c +++ b/drivers/media/video/cx18/cx18-av-vbi.c @@ -142,7 +142,7 @@ int cx18_av_vbi(struct cx18 *cx, unsigned int cmd, void *arg) 0, V4L2_SLICED_TELETEXT_B, 0, /* 1 */ 0, V4L2_SLICED_WSS_625, 0, /* 4 */ V4L2_SLICED_CAPTION_525, /* 6 */ - V4L2_SLICED_VPS, 0, 0, 0, 0, /* 7 - unlike cx25840 */ + 0, 0, V4L2_SLICED_VPS, 0, 0, /* 9 */ 0, 0, 0, 0 }; int is_pal = !(state->std & V4L2_STD_525_60); @@ -243,7 +243,7 @@ int cx18_av_vbi(struct cx18 *cx, unsigned int cmd, void *arg) lcr[i] |= 6 << (4 * x); break; case V4L2_SLICED_VPS: - lcr[i] |= 7 << (4 * x); /*'840 differs*/ + lcr[i] |= 9 << (4 * x); break; } } @@ -301,7 +301,7 @@ int cx18_av_vbi(struct cx18 *cx, unsigned int cmd, void *arg) sdid = V4L2_SLICED_CAPTION_525; err = !odd_parity(p[0]) || !odd_parity(p[1]); break; - case 7: /* Differs from cx25840 */ + case 9: sdid = V4L2_SLICED_VPS; if (decode_vps(p, p) != 0) err = 1; -- cgit v1.2.3 From 49a53750b266899f259b1734a4a2c80d4376ba75 Mon Sep 17 00:00:00 2001 From: Andy Walls Date: Sun, 1 Mar 2009 23:10:07 -0300 Subject: V4L/DVB (10856): cx18: Add interlock so sliced VBI insertion only happens for an MPEG PS The cx18 private packet insertion code only expects to operate on an MPEG PS when inserting private packets of sliced VBI data. This patch keeps the cx18 driver from corrupting the MPEG TS or other non-PS stream types, in case the user enables sliced VBI insertion for these MPEG stream types. Signed-off-by: Andy Walls Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx18/cx18-controls.c | 40 +++++++++++++++++++++++++------- 1 file changed, 31 insertions(+), 9 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/cx18/cx18-controls.c b/drivers/media/video/cx18/cx18-controls.c index 925e01fdbaa6..82fc2f9d4021 100644 --- a/drivers/media/video/cx18/cx18-controls.c +++ b/drivers/media/video/cx18/cx18-controls.c @@ -166,15 +166,26 @@ static int cx18_g_ctrl(struct cx18 *cx, struct v4l2_control *vctrl) return 0; } -static int cx18_setup_vbi_fmt(struct cx18 *cx, enum v4l2_mpeg_stream_vbi_fmt fmt) +static int cx18_setup_vbi_fmt(struct cx18 *cx, + enum v4l2_mpeg_stream_vbi_fmt fmt, + enum v4l2_mpeg_stream_type type) { if (!(cx->v4l2_cap & V4L2_CAP_SLICED_VBI_CAPTURE)) return -EINVAL; if (atomic_read(&cx->ana_capturing) > 0) return -EBUSY; - /* First try to allocate sliced VBI buffers if needed. */ - if (fmt && cx->vbi.sliced_mpeg_data[0] == NULL) { + if (fmt != V4L2_MPEG_STREAM_VBI_FMT_IVTV || + type != V4L2_MPEG_STREAM_TYPE_MPEG2_PS) { + /* We don't do VBI insertion aside from IVTV format in a PS */ + cx->vbi.insert_mpeg = V4L2_MPEG_STREAM_VBI_FMT_NONE; + CX18_DEBUG_INFO("disabled insertion of sliced VBI data into " + "the MPEG stream\n"); + return 0; + } + + /* Allocate sliced VBI buffers if needed. */ + if (cx->vbi.sliced_mpeg_data[0] == NULL) { int i; for (i = 0; i < CX18_VBI_FRAMES; i++) { @@ -185,19 +196,27 @@ static int cx18_setup_vbi_fmt(struct cx18 *cx, enum v4l2_mpeg_stream_vbi_fmt fmt kfree(cx->vbi.sliced_mpeg_data[i]); cx->vbi.sliced_mpeg_data[i] = NULL; } + cx->vbi.insert_mpeg = + V4L2_MPEG_STREAM_VBI_FMT_NONE; + CX18_WARN("Unable to allocate buffers for " + "sliced VBI data insertion\n"); return -ENOMEM; } } } cx->vbi.insert_mpeg = fmt; + CX18_DEBUG_INFO("enabled insertion of sliced VBI data into the MPEG PS," + "when sliced VBI is enabled\n"); - if (cx->vbi.insert_mpeg == 0) - return 0; - /* Need sliced data for mpeg insertion */ + /* + * If our current settings have no lines set for capture, store a valid, + * default set of service lines to capture, in our current settings. + */ if (cx18_get_service_set(cx->vbi.sliced_in) == 0) { if (cx->is_60hz) - cx->vbi.sliced_in->service_set = V4L2_SLICED_CAPTION_525; + cx->vbi.sliced_in->service_set = + V4L2_SLICED_CAPTION_525; else cx->vbi.sliced_in->service_set = V4L2_SLICED_WSS_625; cx18_expand_service_set(cx->vbi.sliced_in, cx->is_50hz); @@ -284,8 +303,11 @@ int cx18_s_ext_ctrls(struct file *file, void *fh, struct v4l2_ext_controls *c) priv.cx = cx; priv.s = &cx->streams[id->type]; err = cx2341x_update(&priv, cx18_api_func, &cx->params, &p); - if (!err && cx->params.stream_vbi_fmt != p.stream_vbi_fmt) - err = cx18_setup_vbi_fmt(cx, p.stream_vbi_fmt); + if (!err && + (cx->params.stream_vbi_fmt != p.stream_vbi_fmt || + cx->params.stream_type != p.stream_type)) + err = cx18_setup_vbi_fmt(cx, p.stream_vbi_fmt, + p.stream_type); cx->params = p; cx->dualwatch_stereo_mode = p.audio_properties & 0x0300; idx = p.audio_properties & 0x03; -- cgit v1.2.3 From c49cb361dbc5a33f35f8d7eb26f0bddd83019e97 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Thu, 12 Feb 2009 10:32:50 -0300 Subject: V4L/DVB (10858): vino: convert to video_ioctl2. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/vino.c | 490 ++++++++++++++++----------------------------- 1 file changed, 173 insertions(+), 317 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/vino.c b/drivers/media/video/vino.c index 88bf845a3d56..2ce2fe594cdf 100644 --- a/drivers/media/video/vino.c +++ b/drivers/media/video/vino.c @@ -2884,35 +2884,7 @@ static int vino_find_data_format(__u32 pixelformat) return VINO_DATA_FMT_NONE; } -static int vino_enum_data_norm(struct vino_channel_settings *vcs, __u32 index) -{ - int data_norm = VINO_DATA_NORM_NONE; - unsigned long flags; - - spin_lock_irqsave(&vino_drvdata->input_lock, flags); - switch(vcs->input) { - case VINO_INPUT_COMPOSITE: - case VINO_INPUT_SVIDEO: - if (index == 0) { - data_norm = VINO_DATA_NORM_PAL; - } else if (index == 1) { - data_norm = VINO_DATA_NORM_NTSC; - } else if (index == 2) { - data_norm = VINO_DATA_NORM_SECAM; - } - break; - case VINO_INPUT_D1: - if (index == 0) { - data_norm = VINO_DATA_NORM_D1; - } - break; - } - spin_unlock_irqrestore(&vino_drvdata->input_lock, flags); - - return data_norm; -} - -static int vino_enum_input(struct vino_channel_settings *vcs, __u32 index) +static int vino_int_enum_input(struct vino_channel_settings *vcs, __u32 index) { int input = VINO_INPUT_NONE; unsigned long flags; @@ -2991,7 +2963,8 @@ static __u32 vino_find_input_index(struct vino_channel_settings *vcs) /* V4L2 ioctls */ -static void vino_v4l2_querycap(struct v4l2_capability *cap) +static int vino_querycap(struct file *file, void *__fh, + struct v4l2_capability *cap) { memset(cap, 0, sizeof(struct v4l2_capability)); @@ -3003,16 +2976,18 @@ static void vino_v4l2_querycap(struct v4l2_capability *cap) V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING; // V4L2_CAP_OVERLAY, V4L2_CAP_READWRITE + return 0; } -static int vino_v4l2_enuminput(struct vino_channel_settings *vcs, +static int vino_enum_input(struct file *file, void *__fh, struct v4l2_input *i) { + struct vino_channel_settings *vcs = video_drvdata(file); __u32 index = i->index; int input; dprintk("requested index = %d\n", index); - input = vino_enum_input(vcs, index); + input = vino_int_enum_input(vcs, index); if (input == VINO_INPUT_NONE) return -EINVAL; @@ -3034,9 +3009,10 @@ static int vino_v4l2_enuminput(struct vino_channel_settings *vcs, return 0; } -static int vino_v4l2_g_input(struct vino_channel_settings *vcs, +static int vino_g_input(struct file *file, void *__fh, unsigned int *i) { + struct vino_channel_settings *vcs = video_drvdata(file); __u32 index; int input; unsigned long flags; @@ -3057,52 +3033,24 @@ static int vino_v4l2_g_input(struct vino_channel_settings *vcs, return 0; } -static int vino_v4l2_s_input(struct vino_channel_settings *vcs, - unsigned int *i) +static int vino_s_input(struct file *file, void *__fh, + unsigned int i) { + struct vino_channel_settings *vcs = video_drvdata(file); int input; - dprintk("requested input = %d\n", *i); + dprintk("requested input = %d\n", i); - input = vino_enum_input(vcs, *i); + input = vino_int_enum_input(vcs, i); if (input == VINO_INPUT_NONE) return -EINVAL; return vino_set_input(vcs, input); } -static int vino_v4l2_enumstd(struct vino_channel_settings *vcs, - struct v4l2_standard *s) -{ - int index = s->index; - int data_norm; - - data_norm = vino_enum_data_norm(vcs, index); - dprintk("standard index = %d\n", index); - - if (data_norm == VINO_DATA_NORM_NONE) - return -EINVAL; - - dprintk("standard name = %s\n", - vino_data_norms[data_norm].description); - - memset(s, 0, sizeof(struct v4l2_standard)); - s->index = index; - - s->id = vino_data_norms[data_norm].std; - s->frameperiod.numerator = 1; - s->frameperiod.denominator = - vino_data_norms[data_norm].fps_max; - s->framelines = - vino_data_norms[data_norm].framelines; - strcpy(s->name, - vino_data_norms[data_norm].description); - - return 0; -} - -static int vino_v4l2_querystd(struct vino_channel_settings *vcs, +static int vino_querystd(struct file *file, void *__fh, v4l2_std_id *std) { + struct vino_channel_settings *vcs = video_drvdata(file); unsigned long flags; int err = 0; @@ -3138,9 +3086,10 @@ static int vino_v4l2_querystd(struct vino_channel_settings *vcs, return err; } -static int vino_v4l2_g_std(struct vino_channel_settings *vcs, +static int vino_g_std(struct file *file, void *__fh, v4l2_std_id *std) { + struct vino_channel_settings *vcs = video_drvdata(file); unsigned long flags; spin_lock_irqsave(&vino_drvdata->input_lock, flags); @@ -3153,9 +3102,10 @@ static int vino_v4l2_g_std(struct vino_channel_settings *vcs, return 0; } -static int vino_v4l2_s_std(struct vino_channel_settings *vcs, +static int vino_s_std(struct file *file, void *__fh, v4l2_std_id *std) { + struct vino_channel_settings *vcs = video_drvdata(file); unsigned long flags; int ret = 0; @@ -3207,185 +3157,152 @@ out: return ret; } -static int vino_v4l2_enum_fmt(struct vino_channel_settings *vcs, +static int vino_enum_fmt_vid_cap(struct file *file, void *__fh, struct v4l2_fmtdesc *fd) { enum v4l2_buf_type type = fd->type; int index = fd->index; + dprintk("format index = %d\n", index); - switch (fd->type) { - case V4L2_BUF_TYPE_VIDEO_CAPTURE: - if ((fd->index < 0) || - (fd->index >= VINO_DATA_FMT_COUNT)) - return -EINVAL; - dprintk("format name = %s\n", - vino_data_formats[index].description); - - memset(fd, 0, sizeof(struct v4l2_fmtdesc)); - fd->index = index; - fd->type = type; - fd->pixelformat = vino_data_formats[index].pixelformat; - strcpy(fd->description, vino_data_formats[index].description); - break; - case V4L2_BUF_TYPE_VIDEO_OVERLAY: - default: + if ((fd->index < 0) || + (fd->index >= VINO_DATA_FMT_COUNT)) return -EINVAL; - } - + dprintk("format name = %s\n", + vino_data_formats[index].description); + + memset(fd, 0, sizeof(struct v4l2_fmtdesc)); + fd->index = index; + fd->type = type; + fd->pixelformat = vino_data_formats[index].pixelformat; + strcpy(fd->description, vino_data_formats[index].description); return 0; } -static int vino_v4l2_try_fmt(struct vino_channel_settings *vcs, +static int vino_try_fmt_vid_cap(struct file *file, void *__fh, struct v4l2_format *f) { + struct vino_channel_settings *vcs = video_drvdata(file); struct vino_channel_settings tempvcs; unsigned long flags; + struct v4l2_pix_format *pf = &f->fmt.pix; - switch (f->type) { - case V4L2_BUF_TYPE_VIDEO_CAPTURE: { - struct v4l2_pix_format *pf = &f->fmt.pix; + dprintk("requested: w = %d, h = %d\n", + pf->width, pf->height); - dprintk("requested: w = %d, h = %d\n", - pf->width, pf->height); - - spin_lock_irqsave(&vino_drvdata->input_lock, flags); - memcpy(&tempvcs, vcs, sizeof(struct vino_channel_settings)); - spin_unlock_irqrestore(&vino_drvdata->input_lock, flags); + spin_lock_irqsave(&vino_drvdata->input_lock, flags); + memcpy(&tempvcs, vcs, sizeof(struct vino_channel_settings)); + spin_unlock_irqrestore(&vino_drvdata->input_lock, flags); - tempvcs.data_format = vino_find_data_format(pf->pixelformat); - if (tempvcs.data_format == VINO_DATA_FMT_NONE) { - tempvcs.data_format = VINO_DATA_FMT_GREY; - pf->pixelformat = - vino_data_formats[tempvcs.data_format]. - pixelformat; - } + tempvcs.data_format = vino_find_data_format(pf->pixelformat); + if (tempvcs.data_format == VINO_DATA_FMT_NONE) { + tempvcs.data_format = VINO_DATA_FMT_GREY; + pf->pixelformat = + vino_data_formats[tempvcs.data_format]. + pixelformat; + } - /* data format must be set before clipping/scaling */ - vino_set_scaling(&tempvcs, pf->width, pf->height); + /* data format must be set before clipping/scaling */ + vino_set_scaling(&tempvcs, pf->width, pf->height); - dprintk("data format = %s\n", - vino_data_formats[tempvcs.data_format].description); + dprintk("data format = %s\n", + vino_data_formats[tempvcs.data_format].description); - pf->width = (tempvcs.clipping.right - tempvcs.clipping.left) / - tempvcs.decimation; - pf->height = (tempvcs.clipping.bottom - tempvcs.clipping.top) / - tempvcs.decimation; + pf->width = (tempvcs.clipping.right - tempvcs.clipping.left) / + tempvcs.decimation; + pf->height = (tempvcs.clipping.bottom - tempvcs.clipping.top) / + tempvcs.decimation; - pf->field = V4L2_FIELD_INTERLACED; - pf->bytesperline = tempvcs.line_size; - pf->sizeimage = tempvcs.line_size * - (tempvcs.clipping.bottom - tempvcs.clipping.top) / - tempvcs.decimation; - pf->colorspace = - vino_data_formats[tempvcs.data_format].colorspace; - - pf->priv = 0; - break; - } - case V4L2_BUF_TYPE_VIDEO_OVERLAY: - default: - return -EINVAL; - } + pf->field = V4L2_FIELD_INTERLACED; + pf->bytesperline = tempvcs.line_size; + pf->sizeimage = tempvcs.line_size * + (tempvcs.clipping.bottom - tempvcs.clipping.top) / + tempvcs.decimation; + pf->colorspace = + vino_data_formats[tempvcs.data_format].colorspace; + pf->priv = 0; return 0; } -static int vino_v4l2_g_fmt(struct vino_channel_settings *vcs, +static int vino_g_fmt_vid_cap(struct file *file, void *__fh, struct v4l2_format *f) { + struct vino_channel_settings *vcs = video_drvdata(file); unsigned long flags; + struct v4l2_pix_format *pf = &f->fmt.pix; - switch (f->type) { - case V4L2_BUF_TYPE_VIDEO_CAPTURE: { - struct v4l2_pix_format *pf = &f->fmt.pix; - - spin_lock_irqsave(&vino_drvdata->input_lock, flags); + spin_lock_irqsave(&vino_drvdata->input_lock, flags); - pf->width = (vcs->clipping.right - vcs->clipping.left) / - vcs->decimation; - pf->height = (vcs->clipping.bottom - vcs->clipping.top) / - vcs->decimation; - pf->pixelformat = - vino_data_formats[vcs->data_format].pixelformat; + pf->width = (vcs->clipping.right - vcs->clipping.left) / + vcs->decimation; + pf->height = (vcs->clipping.bottom - vcs->clipping.top) / + vcs->decimation; + pf->pixelformat = + vino_data_formats[vcs->data_format].pixelformat; - pf->field = V4L2_FIELD_INTERLACED; - pf->bytesperline = vcs->line_size; - pf->sizeimage = vcs->line_size * - (vcs->clipping.bottom - vcs->clipping.top) / - vcs->decimation; - pf->colorspace = - vino_data_formats[vcs->data_format].colorspace; + pf->field = V4L2_FIELD_INTERLACED; + pf->bytesperline = vcs->line_size; + pf->sizeimage = vcs->line_size * + (vcs->clipping.bottom - vcs->clipping.top) / + vcs->decimation; + pf->colorspace = + vino_data_formats[vcs->data_format].colorspace; - pf->priv = 0; - - spin_unlock_irqrestore(&vino_drvdata->input_lock, flags); - break; - } - case V4L2_BUF_TYPE_VIDEO_OVERLAY: - default: - return -EINVAL; - } + pf->priv = 0; + spin_unlock_irqrestore(&vino_drvdata->input_lock, flags); return 0; } -static int vino_v4l2_s_fmt(struct vino_channel_settings *vcs, +static int vino_s_fmt_vid_cap(struct file *file, void *__fh, struct v4l2_format *f) { + struct vino_channel_settings *vcs = video_drvdata(file); int data_format; unsigned long flags; + struct v4l2_pix_format *pf = &f->fmt.pix; - switch (f->type) { - case V4L2_BUF_TYPE_VIDEO_CAPTURE: { - struct v4l2_pix_format *pf = &f->fmt.pix; - - spin_lock_irqsave(&vino_drvdata->input_lock, flags); - - data_format = vino_find_data_format(pf->pixelformat); + spin_lock_irqsave(&vino_drvdata->input_lock, flags); - if (data_format == VINO_DATA_FMT_NONE) { - vcs->data_format = VINO_DATA_FMT_GREY; - pf->pixelformat = - vino_data_formats[vcs->data_format]. - pixelformat; - } else { - vcs->data_format = data_format; - } + data_format = vino_find_data_format(pf->pixelformat); - /* data format must be set before clipping/scaling */ - vino_set_scaling(vcs, pf->width, pf->height); + if (data_format == VINO_DATA_FMT_NONE) { + vcs->data_format = VINO_DATA_FMT_GREY; + pf->pixelformat = + vino_data_formats[vcs->data_format]. + pixelformat; + } else { + vcs->data_format = data_format; + } - dprintk("data format = %s\n", - vino_data_formats[vcs->data_format].description); + /* data format must be set before clipping/scaling */ + vino_set_scaling(vcs, pf->width, pf->height); - pf->width = vcs->clipping.right - vcs->clipping.left; - pf->height = vcs->clipping.bottom - vcs->clipping.top; + dprintk("data format = %s\n", + vino_data_formats[vcs->data_format].description); - pf->field = V4L2_FIELD_INTERLACED; - pf->bytesperline = vcs->line_size; - pf->sizeimage = vcs->line_size * - (vcs->clipping.bottom - vcs->clipping.top) / - vcs->decimation; - pf->colorspace = - vino_data_formats[vcs->data_format].colorspace; + pf->width = vcs->clipping.right - vcs->clipping.left; + pf->height = vcs->clipping.bottom - vcs->clipping.top; - pf->priv = 0; + pf->field = V4L2_FIELD_INTERLACED; + pf->bytesperline = vcs->line_size; + pf->sizeimage = vcs->line_size * + (vcs->clipping.bottom - vcs->clipping.top) / + vcs->decimation; + pf->colorspace = + vino_data_formats[vcs->data_format].colorspace; - spin_unlock_irqrestore(&vino_drvdata->input_lock, flags); - break; - } - case V4L2_BUF_TYPE_VIDEO_OVERLAY: - default: - return -EINVAL; - } + pf->priv = 0; + spin_unlock_irqrestore(&vino_drvdata->input_lock, flags); return 0; } -static int vino_v4l2_cropcap(struct vino_channel_settings *vcs, +static int vino_cropcap(struct file *file, void *__fh, struct v4l2_cropcap *ccap) { + struct vino_channel_settings *vcs = video_drvdata(file); const struct vino_data_norm *norm; unsigned long flags; @@ -3415,9 +3332,10 @@ static int vino_v4l2_cropcap(struct vino_channel_settings *vcs, return 0; } -static int vino_v4l2_g_crop(struct vino_channel_settings *vcs, +static int vino_g_crop(struct file *file, void *__fh, struct v4l2_crop *c) { + struct vino_channel_settings *vcs = video_drvdata(file); unsigned long flags; switch (c->type) { @@ -3439,9 +3357,10 @@ static int vino_v4l2_g_crop(struct vino_channel_settings *vcs, return 0; } -static int vino_v4l2_s_crop(struct vino_channel_settings *vcs, +static int vino_s_crop(struct file *file, void *__fh, struct v4l2_crop *c) { + struct vino_channel_settings *vcs = video_drvdata(file); unsigned long flags; switch (c->type) { @@ -3461,9 +3380,10 @@ static int vino_v4l2_s_crop(struct vino_channel_settings *vcs, return 0; } -static int vino_v4l2_g_parm(struct vino_channel_settings *vcs, +static int vino_g_parm(struct file *file, void *__fh, struct v4l2_streamparm *sp) { + struct vino_channel_settings *vcs = video_drvdata(file); unsigned long flags; switch (sp->type) { @@ -3491,9 +3411,10 @@ static int vino_v4l2_g_parm(struct vino_channel_settings *vcs, return 0; } -static int vino_v4l2_s_parm(struct vino_channel_settings *vcs, +static int vino_s_parm(struct file *file, void *__fh, struct v4l2_streamparm *sp) { + struct vino_channel_settings *vcs = video_drvdata(file); unsigned long flags; switch (sp->type) { @@ -3524,9 +3445,10 @@ static int vino_v4l2_s_parm(struct vino_channel_settings *vcs, return 0; } -static int vino_v4l2_reqbufs(struct vino_channel_settings *vcs, +static int vino_reqbufs(struct file *file, void *__fh, struct v4l2_requestbuffers *rb) { + struct vino_channel_settings *vcs = video_drvdata(file); if (vcs->reading) return -EBUSY; @@ -3606,9 +3528,10 @@ static void vino_v4l2_get_buffer_status(struct vino_channel_settings *vcs, fb->id, fb->size, fb->data_size, fb->offset); } -static int vino_v4l2_querybuf(struct vino_channel_settings *vcs, +static int vino_querybuf(struct file *file, void *__fh, struct v4l2_buffer *b) { + struct vino_channel_settings *vcs = video_drvdata(file); if (vcs->reading) return -EBUSY; @@ -3641,9 +3564,10 @@ static int vino_v4l2_querybuf(struct vino_channel_settings *vcs, return 0; } -static int vino_v4l2_qbuf(struct vino_channel_settings *vcs, +static int vino_qbuf(struct file *file, void *__fh, struct v4l2_buffer *b) { + struct vino_channel_settings *vcs = video_drvdata(file); if (vcs->reading) return -EBUSY; @@ -3679,10 +3603,11 @@ static int vino_v4l2_qbuf(struct vino_channel_settings *vcs, return 0; } -static int vino_v4l2_dqbuf(struct vino_channel_settings *vcs, - struct v4l2_buffer *b, - unsigned int nonblocking) +static int vino_dqbuf(struct file *file, void *__fh, + struct v4l2_buffer *b) { + struct vino_channel_settings *vcs = video_drvdata(file); + unsigned int nonblocking = file->f_flags & O_NONBLOCK; if (vcs->reading) return -EBUSY; @@ -3754,8 +3679,10 @@ static int vino_v4l2_dqbuf(struct vino_channel_settings *vcs, return 0; } -static int vino_v4l2_streamon(struct vino_channel_settings *vcs) +static int vino_streamon(struct file *file, void *__fh, + enum v4l2_buf_type i) { + struct vino_channel_settings *vcs = video_drvdata(file); unsigned int incoming; int ret; if (vcs->reading) @@ -3792,8 +3719,10 @@ static int vino_v4l2_streamon(struct vino_channel_settings *vcs) return 0; } -static int vino_v4l2_streamoff(struct vino_channel_settings *vcs) +static int vino_streamoff(struct file *file, void *__fh, + enum v4l2_buf_type i) { + struct vino_channel_settings *vcs = video_drvdata(file); if (vcs->reading) return -EBUSY; @@ -3806,9 +3735,10 @@ static int vino_v4l2_streamoff(struct vino_channel_settings *vcs) return 0; } -static int vino_v4l2_queryctrl(struct vino_channel_settings *vcs, +static int vino_queryctrl(struct file *file, void *__fh, struct v4l2_queryctrl *queryctrl) { + struct vino_channel_settings *vcs = video_drvdata(file); unsigned long flags; int i; int err = 0; @@ -3855,9 +3785,10 @@ static int vino_v4l2_queryctrl(struct vino_channel_settings *vcs, return err; } -static int vino_v4l2_g_ctrl(struct vino_channel_settings *vcs, +static int vino_g_ctrl(struct file *file, void *__fh, struct v4l2_control *control) { + struct vino_channel_settings *vcs = video_drvdata(file); unsigned long flags; int i; int err = 0; @@ -3928,9 +3859,10 @@ out: return err; } -static int vino_v4l2_s_ctrl(struct vino_channel_settings *vcs, +static int vino_s_ctrl(struct file *file, void *__fh, struct v4l2_control *control) { + struct vino_channel_settings *vcs = video_drvdata(file); unsigned long flags; int i; int err = 0; @@ -4237,112 +4169,6 @@ error: return ret; } -static long vino_do_ioctl(struct file *file, unsigned int cmd, void *arg) -{ - struct vino_channel_settings *vcs = video_drvdata(file); - -#ifdef VINO_DEBUG - switch (_IOC_TYPE(cmd)) { - case 'v': - dprintk("ioctl(): V4L1 unsupported (0x%08x)\n", cmd); - break; - case 'V': - dprintk("ioctl(): V4L2 %s (0x%08x)\n", - v4l2_ioctl_names[_IOC_NR(cmd)], cmd); - break; - default: - dprintk("ioctl(): unsupported command 0x%08x\n", cmd); - } -#endif - - switch (cmd) { - /* V4L2 interface */ - case VIDIOC_QUERYCAP: { - vino_v4l2_querycap(arg); - break; - } - case VIDIOC_ENUMINPUT: { - return vino_v4l2_enuminput(vcs, arg); - } - case VIDIOC_G_INPUT: { - return vino_v4l2_g_input(vcs, arg); - } - case VIDIOC_S_INPUT: { - return vino_v4l2_s_input(vcs, arg); - } - case VIDIOC_ENUMSTD: { - return vino_v4l2_enumstd(vcs, arg); - } - case VIDIOC_QUERYSTD: { - return vino_v4l2_querystd(vcs, arg); - } - case VIDIOC_G_STD: { - return vino_v4l2_g_std(vcs, arg); - } - case VIDIOC_S_STD: { - return vino_v4l2_s_std(vcs, arg); - } - case VIDIOC_ENUM_FMT: { - return vino_v4l2_enum_fmt(vcs, arg); - } - case VIDIOC_TRY_FMT: { - return vino_v4l2_try_fmt(vcs, arg); - } - case VIDIOC_G_FMT: { - return vino_v4l2_g_fmt(vcs, arg); - } - case VIDIOC_S_FMT: { - return vino_v4l2_s_fmt(vcs, arg); - } - case VIDIOC_CROPCAP: { - return vino_v4l2_cropcap(vcs, arg); - } - case VIDIOC_G_CROP: { - return vino_v4l2_g_crop(vcs, arg); - } - case VIDIOC_S_CROP: { - return vino_v4l2_s_crop(vcs, arg); - } - case VIDIOC_G_PARM: { - return vino_v4l2_g_parm(vcs, arg); - } - case VIDIOC_S_PARM: { - return vino_v4l2_s_parm(vcs, arg); - } - case VIDIOC_REQBUFS: { - return vino_v4l2_reqbufs(vcs, arg); - } - case VIDIOC_QUERYBUF: { - return vino_v4l2_querybuf(vcs, arg); - } - case VIDIOC_QBUF: { - return vino_v4l2_qbuf(vcs, arg); - } - case VIDIOC_DQBUF: { - return vino_v4l2_dqbuf(vcs, arg, file->f_flags & O_NONBLOCK); - } - case VIDIOC_STREAMON: { - return vino_v4l2_streamon(vcs); - } - case VIDIOC_STREAMOFF: { - return vino_v4l2_streamoff(vcs); - } - case VIDIOC_QUERYCTRL: { - return vino_v4l2_queryctrl(vcs, arg); - } - case VIDIOC_G_CTRL: { - return vino_v4l2_g_ctrl(vcs, arg); - } - case VIDIOC_S_CTRL: { - return vino_v4l2_s_ctrl(vcs, arg); - } - default: - return -ENOIOCTLCMD; - } - - return 0; -} - static long vino_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { @@ -4352,7 +4178,7 @@ static long vino_ioctl(struct file *file, if (mutex_lock_interruptible(&vcs->mutex)) return -EINTR; - ret = video_usercopy(file, cmd, arg, vino_do_ioctl); + ret = video_ioctl2(file, cmd, arg); mutex_unlock(&vcs->mutex); @@ -4364,6 +4190,34 @@ static long vino_ioctl(struct file *file, /* __initdata */ static int vino_init_stage; +const struct v4l2_ioctl_ops vino_ioctl_ops = { + .vidioc_enum_fmt_vid_cap = vino_enum_fmt_vid_cap, + .vidioc_g_fmt_vid_cap = vino_g_fmt_vid_cap, + .vidioc_s_fmt_vid_cap = vino_s_fmt_vid_cap, + .vidioc_try_fmt_vid_cap = vino_try_fmt_vid_cap, + .vidioc_querycap = vino_querycap, + .vidioc_enum_input = vino_enum_input, + .vidioc_g_input = vino_g_input, + .vidioc_s_input = vino_s_input, + .vidioc_g_std = vino_g_std, + .vidioc_s_std = vino_s_std, + .vidioc_querystd = vino_querystd, + .vidioc_cropcap = vino_cropcap, + .vidioc_s_crop = vino_s_crop, + .vidioc_g_crop = vino_g_crop, + .vidioc_s_parm = vino_s_parm, + .vidioc_g_parm = vino_g_parm, + .vidioc_reqbufs = vino_reqbufs, + .vidioc_querybuf = vino_querybuf, + .vidioc_qbuf = vino_qbuf, + .vidioc_dqbuf = vino_dqbuf, + .vidioc_streamon = vino_streamon, + .vidioc_streamoff = vino_streamoff, + .vidioc_queryctrl = vino_queryctrl, + .vidioc_g_ctrl = vino_g_ctrl, + .vidioc_s_ctrl = vino_s_ctrl, +}; + static const struct v4l2_file_operations vino_fops = { .owner = THIS_MODULE, .open = vino_open, @@ -4376,6 +4230,8 @@ static const struct v4l2_file_operations vino_fops = { static struct video_device v4l_device_template = { .name = "NOT SET", .fops = &vino_fops, + .ioctl_ops = &vino_ioctl_ops, + .tvnorms = V4L2_STD_NTSC | V4L2_STD_PAL | V4L2_STD_SECAM, .minor = -1, }; -- cgit v1.2.3 From 0ef4dbad4f2303b9210cd382bca430d016db5452 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Thu, 12 Feb 2009 11:31:13 -0300 Subject: V4L/DVB (10859): vino: minor renames Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/vino.c | 48 +++++++++++++++++++++++----------------------- 1 file changed, 24 insertions(+), 24 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/vino.c b/drivers/media/video/vino.c index 2ce2fe594cdf..f9ca27a9524e 100644 --- a/drivers/media/video/vino.c +++ b/drivers/media/video/vino.c @@ -289,7 +289,7 @@ struct vino_channel_settings { struct vino_interrupt_data int_data; /* V4L support */ - struct video_device *v4l_device; + struct video_device *vdev; }; struct vino_client { @@ -347,8 +347,8 @@ static struct vino_settings *vino_drvdata; static const char *vino_driver_name = "vino"; static const char *vino_driver_description = "SGI VINO"; static const char *vino_bus_name = "GIO64 bus"; -static const char *vino_v4l_device_name_a = "SGI VINO Channel A"; -static const char *vino_v4l_device_name_b = "SGI VINO Channel B"; +static const char *vino_vdev_name_a = "SGI VINO Channel A"; +static const char *vino_vdev_name_b = "SGI VINO Channel B"; static void vino_capture_tasklet(unsigned long channel); @@ -4227,7 +4227,7 @@ static const struct v4l2_file_operations vino_fops = { .poll = vino_poll, }; -static struct video_device v4l_device_template = { +static struct video_device vdev_template = { .name = "NOT SET", .fops = &vino_fops, .ioctl_ops = &vino_ioctl_ops, @@ -4239,24 +4239,24 @@ static void vino_module_cleanup(int stage) { switch(stage) { case 10: - video_unregister_device(vino_drvdata->b.v4l_device); - vino_drvdata->b.v4l_device = NULL; + video_unregister_device(vino_drvdata->b.vdev); + vino_drvdata->b.vdev = NULL; case 9: - video_unregister_device(vino_drvdata->a.v4l_device); - vino_drvdata->a.v4l_device = NULL; + video_unregister_device(vino_drvdata->a.vdev); + vino_drvdata->a.vdev = NULL; case 8: vino_i2c_del_bus(); case 7: free_irq(SGI_VINO_IRQ, NULL); case 6: - if (vino_drvdata->b.v4l_device) { - video_device_release(vino_drvdata->b.v4l_device); - vino_drvdata->b.v4l_device = NULL; + if (vino_drvdata->b.vdev) { + video_device_release(vino_drvdata->b.vdev); + vino_drvdata->b.vdev = NULL; } case 5: - if (vino_drvdata->a.v4l_device) { - video_device_release(vino_drvdata->a.v4l_device); - vino_drvdata->a.v4l_device = NULL; + if (vino_drvdata->a.vdev) { + video_device_release(vino_drvdata->a.vdev); + vino_drvdata->a.vdev = NULL; } case 4: /* all entries in dma_cpu dummy table have the same address */ @@ -4398,19 +4398,19 @@ static int vino_init_channel_settings(struct vino_channel_settings *vcs, spin_lock_init(&vcs->fb_queue.queue_lock); init_waitqueue_head(&vcs->fb_queue.frame_wait_queue); - vcs->v4l_device = video_device_alloc(); - if (!vcs->v4l_device) { + vcs->vdev = video_device_alloc(); + if (!vcs->vdev) { vino_module_cleanup(vino_init_stage); return -ENOMEM; } vino_init_stage++; - memcpy(vcs->v4l_device, &v4l_device_template, + memcpy(vcs->vdev, &vdev_template, sizeof(struct video_device)); - strcpy(vcs->v4l_device->name, name); - vcs->v4l_device->release = video_device_release; + strcpy(vcs->vdev->name, name); + vcs->vdev->release = video_device_release; - video_set_drvdata(vcs->v4l_device, vcs); + video_set_drvdata(vcs->vdev, vcs); return 0; } @@ -4436,12 +4436,12 @@ static int __init vino_module_init(void) spin_lock_init(&vino_drvdata->input_lock); ret = vino_init_channel_settings(&vino_drvdata->a, VINO_CHANNEL_A, - vino_v4l_device_name_a); + vino_vdev_name_a); if (ret) return ret; ret = vino_init_channel_settings(&vino_drvdata->b, VINO_CHANNEL_B, - vino_v4l_device_name_b); + vino_vdev_name_b); if (ret) return ret; @@ -4465,7 +4465,7 @@ static int __init vino_module_init(void) } vino_init_stage++; - ret = video_register_device(vino_drvdata->a.v4l_device, + ret = video_register_device(vino_drvdata->a.vdev, VFL_TYPE_GRABBER, -1); if (ret < 0) { printk(KERN_ERR "VINO channel A Video4Linux-device " @@ -4475,7 +4475,7 @@ static int __init vino_module_init(void) } vino_init_stage++; - ret = video_register_device(vino_drvdata->b.v4l_device, + ret = video_register_device(vino_drvdata->b.vdev, VFL_TYPE_GRABBER, -1); if (ret < 0) { printk(KERN_ERR "VINO channel B Video4Linux-device " -- cgit v1.2.3 From babb7dc7776dd6ded4e1e6cb7acc34c25c0eb521 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 13 Feb 2009 07:31:05 -0300 Subject: V4L/DVB (10860): saa7191: convert to v4l2-i2c-drv-legacy.h Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/saa7191.c | 157 +++++++++++++++++------------------------- 1 file changed, 63 insertions(+), 94 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/saa7191.c b/drivers/media/video/saa7191.c index b4018cce3285..9943e5c35e15 100644 --- a/drivers/media/video/saa7191.c +++ b/drivers/media/video/saa7191.c @@ -22,6 +22,8 @@ #include #include #include +#include +#include #include "saa7191.h" @@ -32,6 +34,10 @@ MODULE_VERSION(SAA7191_MODULE_VERSION); MODULE_AUTHOR("Mikael Nousiainen "); MODULE_LICENSE("GPL"); +static unsigned short normal_i2c[] = { 0x8a >> 1, 0x8e >> 1, I2C_CLIENT_END }; + +I2C_CLIENT_INSMOD; + // #define SAA7191_DEBUG #ifdef SAA7191_DEBUG @@ -54,8 +60,6 @@ struct saa7191 { int norm; }; -static struct i2c_driver i2c_driver_saa7191; - static const u8 initseq[] = { 0, /* Subaddress */ @@ -561,83 +565,6 @@ static int saa7191_set_control(struct i2c_client *client, /* I2C-interface */ -static int saa7191_attach(struct i2c_adapter *adap, int addr, int kind) -{ - int err = 0; - struct saa7191 *decoder; - struct i2c_client *client; - - printk(KERN_INFO "Philips SAA7191 driver version %s\n", - SAA7191_MODULE_VERSION); - - client = kzalloc(sizeof(*client), GFP_KERNEL); - if (!client) - return -ENOMEM; - decoder = kzalloc(sizeof(*decoder), GFP_KERNEL); - if (!decoder) { - err = -ENOMEM; - goto out_free_client; - } - - client->addr = addr; - client->adapter = adap; - client->driver = &i2c_driver_saa7191; - client->flags = 0; - strcpy(client->name, "saa7191 client"); - i2c_set_clientdata(client, decoder); - - decoder->client = client; - - err = i2c_attach_client(client); - if (err) - goto out_free_decoder; - - err = saa7191_write_block(client, sizeof(initseq), initseq); - if (err) { - printk(KERN_ERR "SAA7191 initialization failed\n"); - goto out_detach_client; - } - - printk(KERN_INFO "SAA7191 initialized\n"); - - decoder->input = SAA7191_INPUT_COMPOSITE; - decoder->norm = SAA7191_NORM_PAL; - - err = saa7191_autodetect_norm(client); - if (err && (err != -EBUSY)) { - printk(KERN_ERR "SAA7191: Signal auto-detection failed\n"); - } - - return 0; - -out_detach_client: - i2c_detach_client(client); -out_free_decoder: - kfree(decoder); -out_free_client: - kfree(client); - return err; -} - -static int saa7191_probe(struct i2c_adapter *adap) -{ - /* Always connected to VINO */ - if (adap->id == I2C_HW_SGI_VINO) - return saa7191_attach(adap, SAA7191_ADDR, 0); - /* Feel free to add probe here :-) */ - return -ENODEV; -} - -static int saa7191_detach(struct i2c_client *client) -{ - struct saa7191 *decoder = i2c_get_clientdata(client); - - i2c_detach_client(client); - kfree(decoder); - kfree(client); - return 0; -} - static int saa7191_command(struct i2c_client *client, unsigned int cmd, void *arg) { @@ -783,25 +710,67 @@ static int saa7191_command(struct i2c_client *client, unsigned int cmd, return 0; } -static struct i2c_driver i2c_driver_saa7191 = { - .driver = { - .name = "saa7191", - }, - .id = I2C_DRIVERID_SAA7191, - .attach_adapter = saa7191_probe, - .detach_client = saa7191_detach, - .command = saa7191_command -}; +static int saa7191_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + int err = 0; + struct saa7191 *decoder; -static int saa7191_init(void) + v4l_info(client, "chip found @ 0x%x (%s)\n", + client->addr << 1, client->adapter->name); + + decoder = kzalloc(sizeof(*decoder), GFP_KERNEL); + if (!decoder) + return -ENOMEM; + + i2c_set_clientdata(client, decoder); + + decoder->client = client; + + err = saa7191_write_block(client, sizeof(initseq), initseq); + if (err) { + printk(KERN_ERR "SAA7191 initialization failed\n"); + kfree(decoder); + return err; + } + + printk(KERN_INFO "SAA7191 initialized\n"); + + decoder->input = SAA7191_INPUT_COMPOSITE; + decoder->norm = SAA7191_NORM_PAL; + + err = saa7191_autodetect_norm(client); + if (err && (err != -EBUSY)) + printk(KERN_ERR "SAA7191: Signal auto-detection failed\n"); + + return 0; +} + +static int saa7191_remove(struct i2c_client *client) { - return i2c_add_driver(&i2c_driver_saa7191); + struct saa7191 *decoder = i2c_get_clientdata(client); + + kfree(decoder); + return 0; } -static void saa7191_exit(void) +static int saa7191_legacy_probe(struct i2c_adapter *adapter) { - i2c_del_driver(&i2c_driver_saa7191); + return adapter->id == I2C_HW_SGI_VINO; } -module_init(saa7191_init); -module_exit(saa7191_exit); +static const struct i2c_device_id saa7191_id[] = { + { "saa7191", 0 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, saa7191_id); + +static struct v4l2_i2c_driver_data v4l2_i2c_data = { + .name = "saa7191", + .driverid = I2C_DRIVERID_SAA7191, + .command = saa7191_command, + .probe = saa7191_probe, + .remove = saa7191_remove, + .legacy_probe = saa7191_legacy_probe, + .id_table = saa7191_id, +}; -- cgit v1.2.3 From cf4e9484f402c799fa25c9ffb7e9a3b620a3702d Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 27 Feb 2009 09:05:10 -0300 Subject: V4L/DVB (10861): vino/indycam/saa7191: convert to i2c modules to V4L2. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/indycam.c | 234 ++++++++----------------- drivers/media/video/indycam.h | 19 +- drivers/media/video/saa7191.c | 228 ++++++------------------ drivers/media/video/saa7191.h | 26 +-- drivers/media/video/vino.c | 396 ++++++++++++------------------------------ 5 files changed, 256 insertions(+), 647 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/indycam.c b/drivers/media/video/indycam.c index 84b9e4f2b3b3..54099e303c8d 100644 --- a/drivers/media/video/indycam.c +++ b/drivers/media/video/indycam.c @@ -19,10 +19,11 @@ #include #include -#include /* IndyCam decodes stream of photons into digital image representation ;-) */ -#include +#include #include +#include +#include #include "indycam.h" @@ -33,6 +34,10 @@ MODULE_VERSION(INDYCAM_MODULE_VERSION); MODULE_AUTHOR("Mikael Nousiainen "); MODULE_LICENSE("GPL"); +static unsigned short normal_i2c[] = { 0x56 >> 1, I2C_CLIENT_END }; + +I2C_CLIENT_INSMOD; + // #define INDYCAM_DEBUG #ifdef INDYCAM_DEBUG @@ -48,8 +53,6 @@ struct indycam { u8 version; }; -static struct i2c_driver i2c_driver_indycam; - static const u8 initseq[] = { INDYCAM_CONTROL_AGCENA, /* INDYCAM_CONTROL */ INDYCAM_SHUTTER_60, /* INDYCAM_SHUTTER */ @@ -138,44 +141,44 @@ static void indycam_regdump_debug(struct i2c_client *client) #endif static int indycam_get_control(struct i2c_client *client, - struct indycam_control *ctrl) + struct v4l2_control *ctrl) { struct indycam *camera = i2c_get_clientdata(client); u8 reg; int ret = 0; - switch (ctrl->type) { - case INDYCAM_CONTROL_AGC: - case INDYCAM_CONTROL_AWB: + switch (ctrl->id) { + case V4L2_CID_AUTOGAIN: + case V4L2_CID_AUTO_WHITE_BALANCE: ret = indycam_read_reg(client, INDYCAM_REG_CONTROL, ®); if (ret) return -EIO; - if (ctrl->type == INDYCAM_CONTROL_AGC) + if (ctrl->id == V4L2_CID_AUTOGAIN) ctrl->value = (reg & INDYCAM_CONTROL_AGCENA) ? 1 : 0; else ctrl->value = (reg & INDYCAM_CONTROL_AWBCTL) ? 1 : 0; break; - case INDYCAM_CONTROL_SHUTTER: + case V4L2_CID_EXPOSURE: ret = indycam_read_reg(client, INDYCAM_REG_SHUTTER, ®); if (ret) return -EIO; ctrl->value = ((s32)reg == 0x00) ? 0xff : ((s32)reg - 1); break; - case INDYCAM_CONTROL_GAIN: + case V4L2_CID_GAIN: ret = indycam_read_reg(client, INDYCAM_REG_GAIN, ®); if (ret) return -EIO; ctrl->value = (s32)reg; break; - case INDYCAM_CONTROL_RED_BALANCE: + case V4L2_CID_RED_BALANCE: ret = indycam_read_reg(client, INDYCAM_REG_RED_BALANCE, ®); if (ret) return -EIO; ctrl->value = (s32)reg; break; - case INDYCAM_CONTROL_BLUE_BALANCE: + case V4L2_CID_BLUE_BALANCE: ret = indycam_read_reg(client, INDYCAM_REG_BLUE_BALANCE, ®); if (ret) return -EIO; @@ -195,7 +198,7 @@ static int indycam_get_control(struct i2c_client *client, return -EIO; ctrl->value = (s32)reg; break; - case INDYCAM_CONTROL_GAMMA: + case V4L2_CID_GAMMA: if (camera->version == CAMERA_VERSION_MOOSE) { ret = indycam_read_reg(client, INDYCAM_REG_GAMMA, ®); @@ -214,20 +217,20 @@ static int indycam_get_control(struct i2c_client *client, } static int indycam_set_control(struct i2c_client *client, - struct indycam_control *ctrl) + struct v4l2_control *ctrl) { struct indycam *camera = i2c_get_clientdata(client); u8 reg; int ret = 0; - switch (ctrl->type) { - case INDYCAM_CONTROL_AGC: - case INDYCAM_CONTROL_AWB: + switch (ctrl->id) { + case V4L2_CID_AUTOGAIN: + case V4L2_CID_AUTO_WHITE_BALANCE: ret = indycam_read_reg(client, INDYCAM_REG_CONTROL, ®); if (ret) break; - if (ctrl->type == INDYCAM_CONTROL_AGC) { + if (ctrl->id == V4L2_CID_AUTOGAIN) { if (ctrl->value) reg |= INDYCAM_CONTROL_AGCENA; else @@ -241,18 +244,18 @@ static int indycam_set_control(struct i2c_client *client, ret = indycam_write_reg(client, INDYCAM_REG_CONTROL, reg); break; - case INDYCAM_CONTROL_SHUTTER: + case V4L2_CID_EXPOSURE: reg = (ctrl->value == 0xff) ? 0x00 : (ctrl->value + 1); ret = indycam_write_reg(client, INDYCAM_REG_SHUTTER, reg); break; - case INDYCAM_CONTROL_GAIN: + case V4L2_CID_GAIN: ret = indycam_write_reg(client, INDYCAM_REG_GAIN, ctrl->value); break; - case INDYCAM_CONTROL_RED_BALANCE: + case V4L2_CID_RED_BALANCE: ret = indycam_write_reg(client, INDYCAM_REG_RED_BALANCE, ctrl->value); break; - case INDYCAM_CONTROL_BLUE_BALANCE: + case V4L2_CID_BLUE_BALANCE: ret = indycam_write_reg(client, INDYCAM_REG_BLUE_BALANCE, ctrl->value); break; @@ -264,7 +267,7 @@ static int indycam_set_control(struct i2c_client *client, ret = indycam_write_reg(client, INDYCAM_REG_BLUE_SATURATION, ctrl->value); break; - case INDYCAM_CONTROL_GAMMA: + case V4L2_CID_GAMMA: if (camera->version == CAMERA_VERSION_MOOSE) { ret = indycam_write_reg(client, INDYCAM_REG_GAMMA, ctrl->value); @@ -279,44 +282,50 @@ static int indycam_set_control(struct i2c_client *client, /* I2C-interface */ -static int indycam_attach(struct i2c_adapter *adap, int addr, int kind) +static int indycam_command(struct i2c_client *client, unsigned int cmd, + void *arg) +{ + /* The old video_decoder interface just isn't enough, + * so we'll use some custom commands. */ + switch (cmd) { + case VIDIOC_G_CTRL: + return indycam_get_control(client, arg); + + case VIDIOC_S_CTRL: + return indycam_set_control(client, arg); + + default: + return -EINVAL; + } + + return 0; +} + +static int indycam_probe(struct i2c_client *client, + const struct i2c_device_id *id) { int err = 0; struct indycam *camera; - struct i2c_client *client; - printk(KERN_INFO "SGI IndyCam driver version %s\n", - INDYCAM_MODULE_VERSION); + v4l_info(client, "chip found @ 0x%x (%s)\n", + client->addr << 1, client->adapter->name); - client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL); - if (!client) - return -ENOMEM; camera = kzalloc(sizeof(struct indycam), GFP_KERNEL); - if (!camera) { - err = -ENOMEM; - goto out_free_client; - } + if (!camera) + return -ENOMEM; - client->addr = addr; - client->adapter = adap; - client->driver = &i2c_driver_indycam; - client->flags = 0; - strcpy(client->name, "IndyCam client"); i2c_set_clientdata(client, camera); camera->client = client; - err = i2c_attach_client(client); - if (err) - goto out_free_camera; - camera->version = i2c_smbus_read_byte_data(client, INDYCAM_REG_VERSION); if (camera->version != CAMERA_VERSION_INDY && camera->version != CAMERA_VERSION_MOOSE) { - err = -ENODEV; - goto out_detach_client; + kfree(camera); + return -ENODEV; } + printk(KERN_INFO "IndyCam v%d.%d detected\n", INDYCAM_VERSION_MAJOR(camera->version), INDYCAM_VERSION_MINOR(camera->version)); @@ -327,8 +336,8 @@ static int indycam_attach(struct i2c_adapter *adap, int addr, int kind) err = indycam_write_block(client, 0, sizeof(initseq), (u8 *)&initseq); if (err) { printk(KERN_ERR "IndyCam initialization failed\n"); - err = -EIO; - goto out_detach_client; + kfree(camera); + return -EIO; } indycam_regdump(client); @@ -338,8 +347,8 @@ static int indycam_attach(struct i2c_adapter *adap, int addr, int kind) INDYCAM_CONTROL_AGCENA | INDYCAM_CONTROL_AWBCTL); if (err) { printk(KERN_ERR "IndyCam: White balancing camera failed\n"); - err = -EIO; - goto out_detach_client; + kfree(camera); + return -EIO; } indycam_regdump(client); @@ -347,124 +356,33 @@ static int indycam_attach(struct i2c_adapter *adap, int addr, int kind) printk(KERN_INFO "IndyCam initialized\n"); return 0; - -out_detach_client: - i2c_detach_client(client); -out_free_camera: - kfree(camera); -out_free_client: - kfree(client); - return err; } -static int indycam_probe(struct i2c_adapter *adap) -{ - /* Indy specific crap */ - if (adap->id == I2C_HW_SGI_VINO) - return indycam_attach(adap, INDYCAM_ADDR, 0); - /* Feel free to add probe here :-) */ - return -ENODEV; -} - -static int indycam_detach(struct i2c_client *client) +static int indycam_remove(struct i2c_client *client) { struct indycam *camera = i2c_get_clientdata(client); - i2c_detach_client(client); kfree(camera); - kfree(client); return 0; } -static int indycam_command(struct i2c_client *client, unsigned int cmd, - void *arg) +static int indycam_legacy_probe(struct i2c_adapter *adapter) { - // struct indycam *camera = i2c_get_clientdata(client); - - /* The old video_decoder interface just isn't enough, - * so we'll use some custom commands. */ - switch (cmd) { - case DECODER_GET_CAPABILITIES: { - struct video_decoder_capability *cap = arg; - - cap->flags = VIDEO_DECODER_NTSC; - cap->inputs = 1; - cap->outputs = 1; - break; - } - case DECODER_GET_STATUS: { - int *iarg = arg; - - *iarg = DECODER_STATUS_GOOD | DECODER_STATUS_NTSC | - DECODER_STATUS_COLOR; - break; - } - case DECODER_SET_NORM: { - int *iarg = arg; - - switch (*iarg) { - case VIDEO_MODE_NTSC: - break; - default: - return -EINVAL; - } - break; - } - case DECODER_SET_INPUT: { - int *iarg = arg; - - if (*iarg != 0) - return -EINVAL; - break; - } - case DECODER_SET_OUTPUT: { - int *iarg = arg; - - if (*iarg != 0) - return -EINVAL; - break; - } - case DECODER_ENABLE_OUTPUT: { - /* Always enabled */ - break; - } - case DECODER_SET_PICTURE: { - // struct video_picture *pic = arg; - /* TODO: convert values for indycam_set_controls() */ - break; - } - case DECODER_INDYCAM_GET_CONTROL: { - return indycam_get_control(client, arg); - } - case DECODER_INDYCAM_SET_CONTROL: { - return indycam_set_control(client, arg); - } - default: - return -EINVAL; - } - - return 0; + return adapter->id == I2C_HW_SGI_VINO; } -static struct i2c_driver i2c_driver_indycam = { - .driver = { - .name = "indycam", - }, - .id = I2C_DRIVERID_INDYCAM, - .attach_adapter = indycam_probe, - .detach_client = indycam_detach, - .command = indycam_command, +static const struct i2c_device_id indycam_id[] = { + { "indycam", 0 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, indycam_id); + +static struct v4l2_i2c_driver_data v4l2_i2c_data = { + .name = "indycam", + .driverid = I2C_DRIVERID_INDYCAM, + .command = indycam_command, + .probe = indycam_probe, + .remove = indycam_remove, + .legacy_probe = indycam_legacy_probe, + .id_table = indycam_id, }; - -static int __init indycam_init(void) -{ - return i2c_add_driver(&i2c_driver_indycam); -} - -static void __exit indycam_exit(void) -{ - i2c_del_driver(&i2c_driver_indycam); -} - -module_init(indycam_init); -module_exit(indycam_exit); diff --git a/drivers/media/video/indycam.h b/drivers/media/video/indycam.h index e6ee82063ed8..881f21c474c4 100644 --- a/drivers/media/video/indycam.h +++ b/drivers/media/video/indycam.h @@ -87,22 +87,7 @@ /* Driver interface definitions */ -#define INDYCAM_CONTROL_AGC 0 /* boolean */ -#define INDYCAM_CONTROL_AWB 1 /* boolean */ -#define INDYCAM_CONTROL_SHUTTER 2 -#define INDYCAM_CONTROL_GAIN 3 -#define INDYCAM_CONTROL_RED_BALANCE 4 -#define INDYCAM_CONTROL_BLUE_BALANCE 5 -#define INDYCAM_CONTROL_RED_SATURATION 6 -#define INDYCAM_CONTROL_BLUE_SATURATION 7 -#define INDYCAM_CONTROL_GAMMA 8 - -struct indycam_control { - u8 type; - s32 value; -}; - -#define DECODER_INDYCAM_GET_CONTROL _IOR('d', 193, struct indycam_control) -#define DECODER_INDYCAM_SET_CONTROL _IOW('d', 194, struct indycam_control) +#define INDYCAM_CONTROL_RED_SATURATION (V4L2_CID_PRIVATE_BASE + 0) +#define INDYCAM_CONTROL_BLUE_SATURATION (V4L2_CID_PRIVATE_BASE + 1) #endif diff --git a/drivers/media/video/saa7191.c b/drivers/media/video/saa7191.c index 9943e5c35e15..4c7bddf4b7ee 100644 --- a/drivers/media/video/saa7191.c +++ b/drivers/media/video/saa7191.c @@ -19,8 +19,7 @@ #include #include -#include -#include +#include #include #include #include @@ -57,7 +56,7 @@ struct saa7191 { u8 reg[25]; int input; - int norm; + v4l2_std_id norm; }; static const u8 initseq[] = { @@ -191,7 +190,7 @@ static int saa7191_set_input(struct i2c_client *client, int input) return 0; } -static int saa7191_set_norm(struct i2c_client *client, int norm) +static int saa7191_set_norm(struct i2c_client *client, v4l2_std_id norm) { struct saa7191 *decoder = i2c_get_clientdata(client); u8 stdc = saa7191_read_reg(client, SAA7191_REG_STDC); @@ -199,24 +198,20 @@ static int saa7191_set_norm(struct i2c_client *client, int norm) u8 chcv = saa7191_read_reg(client, SAA7191_REG_CHCV); int err; - switch(norm) { - case SAA7191_NORM_PAL: + if (norm & V4L2_STD_PAL) { stdc &= ~SAA7191_STDC_SECS; ctl3 &= ~(SAA7191_CTL3_AUFD | SAA7191_CTL3_FSEL); chcv = SAA7191_CHCV_PAL; - break; - case SAA7191_NORM_NTSC: + } else if (norm & V4L2_STD_NTSC) { stdc &= ~SAA7191_STDC_SECS; ctl3 &= ~SAA7191_CTL3_AUFD; ctl3 |= SAA7191_CTL3_FSEL; chcv = SAA7191_CHCV_NTSC; - break; - case SAA7191_NORM_SECAM: + } else if (norm & V4L2_STD_SECAM) { stdc |= SAA7191_STDC_SECS; ctl3 &= ~(SAA7191_CTL3_AUFD | SAA7191_CTL3_FSEL); chcv = SAA7191_CHCV_PAL; - break; - default: + } else { return -EINVAL; } @@ -234,7 +229,7 @@ static int saa7191_set_norm(struct i2c_client *client, int norm) dprintk("ctl3: %02x stdc: %02x chcv: %02x\n", ctl3, stdc, chcv); - dprintk("norm: %d\n", norm); + dprintk("norm: %llx\n", norm); return 0; } @@ -262,15 +257,19 @@ static int saa7191_wait_for_signal(struct i2c_client *client, u8 *status) return -EBUSY; } -static int saa7191_autodetect_norm_extended(struct i2c_client *client) +static int saa7191_autodetect_norm_extended(struct i2c_client *client, + v4l2_std_id *norm) { + struct saa7191 *decoder = i2c_get_clientdata(client); u8 stdc = saa7191_read_reg(client, SAA7191_REG_STDC); u8 ctl3 = saa7191_read_reg(client, SAA7191_REG_CTL3); u8 status; + v4l2_std_id old_norm = decoder->norm; int err = 0; dprintk("SAA7191 extended signal auto-detection...\n"); + *norm = V4L2_STD_NTSC | V4L2_STD_PAL | V4L2_STD_SECAM; stdc &= ~SAA7191_STDC_SECS; ctl3 &= ~(SAA7191_CTL3_FSEL); @@ -301,14 +300,15 @@ static int saa7191_autodetect_norm_extended(struct i2c_client *client) if (status & SAA7191_STATUS_FIDT) { /* 60Hz signal -> NTSC */ dprintk("60Hz signal: NTSC\n"); - return saa7191_set_norm(client, SAA7191_NORM_NTSC); + *norm = V4L2_STD_NTSC; + return 0; } /* 50Hz signal */ dprintk("50Hz signal: Trying PAL...\n"); /* try PAL first */ - err = saa7191_set_norm(client, SAA7191_NORM_PAL); + err = saa7191_set_norm(client, V4L2_STD_PAL); if (err) goto out; @@ -321,20 +321,20 @@ static int saa7191_autodetect_norm_extended(struct i2c_client *client) /* not 50Hz ? */ if (status & SAA7191_STATUS_FIDT) { dprintk("No 50Hz signal\n"); - err = -EAGAIN; - goto out; + saa7191_set_norm(client, old_norm); + return -EAGAIN; } if (status & SAA7191_STATUS_CODE) { dprintk("PAL\n"); - return 0; + *norm = V4L2_STD_PAL; + return saa7191_set_norm(client, old_norm); } dprintk("No color detected with PAL - Trying SECAM...\n"); /* no color detected ? -> try SECAM */ - err = saa7191_set_norm(client, - SAA7191_NORM_SECAM); + err = saa7191_set_norm(client, V4L2_STD_SECAM); if (err) goto out; @@ -354,29 +354,14 @@ static int saa7191_autodetect_norm_extended(struct i2c_client *client) if (status & SAA7191_STATUS_CODE) { /* Color detected -> SECAM */ dprintk("SECAM\n"); - return 0; + *norm = V4L2_STD_SECAM; + return saa7191_set_norm(client, old_norm); } dprintk("No color detected with SECAM - Going back to PAL.\n"); - /* still no color detected ? - * -> set norm back to PAL */ - err = saa7191_set_norm(client, - SAA7191_NORM_PAL); - if (err) - goto out; - out: - ctl3 = saa7191_read_reg(client, SAA7191_REG_CTL3); - if (ctl3 & SAA7191_CTL3_AUFD) { - ctl3 &= ~(SAA7191_CTL3_AUFD); - err = saa7191_write_reg(client, SAA7191_REG_CTL3, ctl3); - if (err) { - err = -EIO; - } - } - - return err; + return saa7191_set_norm(client, old_norm); } static int saa7191_autodetect_norm(struct i2c_client *client) @@ -403,26 +388,26 @@ static int saa7191_autodetect_norm(struct i2c_client *client) if (status & SAA7191_STATUS_FIDT) { /* 60hz signal -> NTSC */ dprintk("NTSC\n"); - return saa7191_set_norm(client, SAA7191_NORM_NTSC); + return saa7191_set_norm(client, V4L2_STD_NTSC); } else { /* 50hz signal -> PAL */ dprintk("PAL\n"); - return saa7191_set_norm(client, SAA7191_NORM_PAL); + return saa7191_set_norm(client, V4L2_STD_PAL); } } static int saa7191_get_control(struct i2c_client *client, - struct saa7191_control *ctrl) + struct v4l2_control *ctrl) { u8 reg; int ret = 0; - switch (ctrl->type) { + switch (ctrl->id) { case SAA7191_CONTROL_BANDPASS: case SAA7191_CONTROL_BANDPASS_WEIGHT: case SAA7191_CONTROL_CORING: reg = saa7191_read_reg(client, SAA7191_REG_LUMA); - switch (ctrl->type) { + switch (ctrl->id) { case SAA7191_CONTROL_BANDPASS: ctrl->value = ((s32)reg & SAA7191_LUMA_BPSS_MASK) >> SAA7191_LUMA_BPSS_SHIFT; @@ -440,13 +425,13 @@ static int saa7191_get_control(struct i2c_client *client, case SAA7191_CONTROL_FORCE_COLOUR: case SAA7191_CONTROL_CHROMA_GAIN: reg = saa7191_read_reg(client, SAA7191_REG_GAIN); - if (ctrl->type == SAA7191_CONTROL_FORCE_COLOUR) + if (ctrl->id == SAA7191_CONTROL_FORCE_COLOUR) ctrl->value = ((s32)reg & SAA7191_GAIN_COLO) ? 1 : 0; else ctrl->value = ((s32)reg & SAA7191_GAIN_LFIS_MASK) >> SAA7191_GAIN_LFIS_SHIFT; break; - case SAA7191_CONTROL_HUE: + case V4L2_CID_HUE: reg = saa7191_read_reg(client, SAA7191_REG_HUEC); if (reg < 0x80) reg += 0x80; @@ -478,17 +463,17 @@ static int saa7191_get_control(struct i2c_client *client, } static int saa7191_set_control(struct i2c_client *client, - struct saa7191_control *ctrl) + struct v4l2_control *ctrl) { u8 reg; int ret = 0; - switch (ctrl->type) { + switch (ctrl->id) { case SAA7191_CONTROL_BANDPASS: case SAA7191_CONTROL_BANDPASS_WEIGHT: case SAA7191_CONTROL_CORING: reg = saa7191_read_reg(client, SAA7191_REG_LUMA); - switch (ctrl->type) { + switch (ctrl->id) { case SAA7191_CONTROL_BANDPASS: reg &= ~SAA7191_LUMA_BPSS_MASK; reg |= (ctrl->value << SAA7191_LUMA_BPSS_SHIFT) @@ -510,7 +495,7 @@ static int saa7191_set_control(struct i2c_client *client, case SAA7191_CONTROL_FORCE_COLOUR: case SAA7191_CONTROL_CHROMA_GAIN: reg = saa7191_read_reg(client, SAA7191_REG_GAIN); - if (ctrl->type == SAA7191_CONTROL_FORCE_COLOUR) { + if (ctrl->id == SAA7191_CONTROL_FORCE_COLOUR) { if (ctrl->value) reg |= SAA7191_GAIN_COLO; else @@ -522,7 +507,7 @@ static int saa7191_set_control(struct i2c_client *client, } ret = saa7191_write_reg(client, SAA7191_REG_GAIN, reg); break; - case SAA7191_CONTROL_HUE: + case V4L2_CID_HUE: reg = ctrl->value & 0xff; if (reg < 0x80) reg += 0x80; @@ -568,141 +553,42 @@ static int saa7191_set_control(struct i2c_client *client, static int saa7191_command(struct i2c_client *client, unsigned int cmd, void *arg) { - struct saa7191 *decoder = i2c_get_clientdata(client); - switch (cmd) { - case DECODER_GET_CAPABILITIES: { - struct video_decoder_capability *cap = arg; - - cap->flags = VIDEO_DECODER_PAL | VIDEO_DECODER_NTSC | - VIDEO_DECODER_SECAM | VIDEO_DECODER_AUTO; - cap->inputs = (client->adapter->id == I2C_HW_SGI_VINO) ? 2 : 1; - cap->outputs = 1; - break; - } - case DECODER_GET_STATUS: { - int *iarg = arg; + case VIDIOC_INT_G_INPUT_STATUS: { + u32 *iarg = arg; u8 status; - int res = 0; + int res = V4L2_IN_ST_NO_SIGNAL; - if (saa7191_read_status(client, &status)) { + if (saa7191_read_status(client, &status)) return -EIO; - } if ((status & SAA7191_STATUS_HLCK) == 0) - res |= DECODER_STATUS_GOOD; - if (status & SAA7191_STATUS_CODE) - res |= DECODER_STATUS_COLOR; - switch (decoder->norm) { - case SAA7191_NORM_NTSC: - res |= DECODER_STATUS_NTSC; - break; - case SAA7191_NORM_PAL: - res |= DECODER_STATUS_PAL; - break; - case SAA7191_NORM_SECAM: - res |= DECODER_STATUS_SECAM; - break; - case SAA7191_NORM_AUTO: - default: - if (status & SAA7191_STATUS_FIDT) - res |= DECODER_STATUS_NTSC; - else - res |= DECODER_STATUS_PAL; - break; - } + res = 0; + if (!(status & SAA7191_STATUS_CODE)) + res |= V4L2_IN_ST_NO_COLOR; *iarg = res; break; } - case DECODER_SET_NORM: { - int *iarg = arg; - - switch (*iarg) { - case VIDEO_MODE_AUTO: - return saa7191_autodetect_norm(client); - case VIDEO_MODE_PAL: - return saa7191_set_norm(client, SAA7191_NORM_PAL); - case VIDEO_MODE_NTSC: - return saa7191_set_norm(client, SAA7191_NORM_NTSC); - case VIDEO_MODE_SECAM: - return saa7191_set_norm(client, SAA7191_NORM_SECAM); - default: - return -EINVAL; - } - break; - } - case DECODER_SET_INPUT: { - int *iarg = arg; - - switch (client->adapter->id) { - case I2C_HW_SGI_VINO: - return saa7191_set_input(client, *iarg); - default: - if (*iarg != 0) - return -EINVAL; - } - break; - } - case DECODER_SET_OUTPUT: { - int *iarg = arg; - /* not much choice of outputs */ - if (*iarg != 0) - return -EINVAL; - break; - } - case DECODER_ENABLE_OUTPUT: { - /* Always enabled */ - break; - } - case DECODER_SET_PICTURE: { - struct video_picture *pic = arg; - unsigned val; - int err; - - val = (pic->hue >> 8) - 0x80; + case VIDIOC_QUERYSTD: + return saa7191_autodetect_norm_extended(client, arg); - err = saa7191_write_reg(client, SAA7191_REG_HUEC, val); - if (err) - return -EIO; + case VIDIOC_S_STD: { + v4l2_std_id *istd = arg; - break; + return saa7191_set_norm(client, *istd); } - case DECODER_SAA7191_GET_STATUS: { - struct saa7191_status *status = arg; - u8 status_reg; - - if (saa7191_read_status(client, &status_reg)) - return -EIO; - - status->signal = ((status_reg & SAA7191_STATUS_HLCK) == 0) - ? 1 : 0; - status->signal_60hz = (status_reg & SAA7191_STATUS_FIDT) - ? 1 : 0; - status->color = (status_reg & SAA7191_STATUS_CODE) ? 1 : 0; + case VIDIOC_INT_S_VIDEO_ROUTING: { + struct v4l2_routing *route = arg; - status->input = decoder->input; - status->norm = decoder->norm; - - break; + return saa7191_set_input(client, route->input); } - case DECODER_SAA7191_SET_NORM: { - int *norm = arg; - - switch (*norm) { - case SAA7191_NORM_AUTO: - return saa7191_autodetect_norm(client); - case SAA7191_NORM_AUTO_EXT: - return saa7191_autodetect_norm_extended(client); - default: - return saa7191_set_norm(client, *norm); - } - } - case DECODER_SAA7191_GET_CONTROL: { + + case VIDIOC_G_CTRL: return saa7191_get_control(client, arg); - } - case DECODER_SAA7191_SET_CONTROL: { + + case VIDIOC_S_CTRL: return saa7191_set_control(client, arg); - } + default: return -EINVAL; } @@ -737,7 +623,7 @@ static int saa7191_probe(struct i2c_client *client, printk(KERN_INFO "SAA7191 initialized\n"); decoder->input = SAA7191_INPUT_COMPOSITE; - decoder->norm = SAA7191_NORM_PAL; + decoder->norm = V4L2_STD_PAL; err = saa7191_autodetect_norm(client); if (err && (err != -EBUSY)) diff --git a/drivers/media/video/saa7191.h b/drivers/media/video/saa7191.h index a2310da1940d..803c74d6066f 100644 --- a/drivers/media/video/saa7191.h +++ b/drivers/media/video/saa7191.h @@ -176,11 +176,9 @@ #define SAA7191_INPUT_COMPOSITE 0 #define SAA7191_INPUT_SVIDEO 1 -#define SAA7191_NORM_AUTO 0 #define SAA7191_NORM_PAL 1 #define SAA7191_NORM_NTSC 2 #define SAA7191_NORM_SECAM 3 -#define SAA7191_NORM_AUTO_EXT 4 /* extended auto-detection */ struct saa7191_status { /* 0=no signal, 1=signal detected */ @@ -232,24 +230,16 @@ struct saa7191_status { #define SAA7191_VNR_MAX 0x03 #define SAA7191_VNR_DEFAULT 0x00 -#define SAA7191_CONTROL_BANDPASS 0 -#define SAA7191_CONTROL_BANDPASS_WEIGHT 1 -#define SAA7191_CONTROL_CORING 2 -#define SAA7191_CONTROL_FORCE_COLOUR 3 /* boolean */ -#define SAA7191_CONTROL_CHROMA_GAIN 4 -#define SAA7191_CONTROL_HUE 5 -#define SAA7191_CONTROL_VTRC 6 /* boolean */ -#define SAA7191_CONTROL_LUMA_DELAY 7 -#define SAA7191_CONTROL_VNR 8 - -struct saa7191_control { - u8 type; - s32 value; -}; +#define SAA7191_CONTROL_BANDPASS (V4L2_CID_PRIVATE_BASE + 0) +#define SAA7191_CONTROL_BANDPASS_WEIGHT (V4L2_CID_PRIVATE_BASE + 1) +#define SAA7191_CONTROL_CORING (V4L2_CID_PRIVATE_BASE + 2) +#define SAA7191_CONTROL_FORCE_COLOUR (V4L2_CID_PRIVATE_BASE + 3) +#define SAA7191_CONTROL_CHROMA_GAIN (V4L2_CID_PRIVATE_BASE + 4) +#define SAA7191_CONTROL_VTRC (V4L2_CID_PRIVATE_BASE + 5) +#define SAA7191_CONTROL_LUMA_DELAY (V4L2_CID_PRIVATE_BASE + 6) +#define SAA7191_CONTROL_VNR (V4L2_CID_PRIVATE_BASE + 7) #define DECODER_SAA7191_GET_STATUS _IOR('d', 195, struct saa7191_status) #define DECODER_SAA7191_SET_NORM _IOW('d', 196, int) -#define DECODER_SAA7191_GET_CONTROL _IOR('d', 197, struct saa7191_control) -#define DECODER_SAA7191_SET_CONTROL _IOW('d', 198, struct saa7191_control) #endif diff --git a/drivers/media/video/vino.c b/drivers/media/video/vino.c index f9ca27a9524e..0a5cd567bfb1 100644 --- a/drivers/media/video/vino.c +++ b/drivers/media/video/vino.c @@ -38,7 +38,6 @@ #include #include #include -#include #include #include @@ -139,10 +138,6 @@ MODULE_LICENSE("GPL"); #define VINO_DATA_NORM_PAL 1 #define VINO_DATA_NORM_SECAM 2 #define VINO_DATA_NORM_D1 3 -/* The following are special entries that can be used to - * autodetect the norm. */ -#define VINO_DATA_NORM_AUTO 0xfe -#define VINO_DATA_NORM_AUTO_EXT 0xff #define VINO_DATA_NORM_COUNT 4 @@ -360,11 +355,11 @@ static const struct vino_input vino_inputs[] = { .name = "Composite", .std = V4L2_STD_NTSC | V4L2_STD_PAL | V4L2_STD_SECAM, - },{ + }, { .name = "S-Video", .std = V4L2_STD_NTSC | V4L2_STD_PAL | V4L2_STD_SECAM, - },{ + }, { .name = "D1/IndyCam", .std = V4L2_STD_NTSC, } @@ -376,17 +371,17 @@ static const struct vino_data_format vino_data_formats[] = { .bpp = 1, .pixelformat = V4L2_PIX_FMT_GREY, .colorspace = V4L2_COLORSPACE_SMPTE170M, - },{ + }, { .description = "8-bit dithered RGB 3-3-2", .bpp = 1, .pixelformat = V4L2_PIX_FMT_RGB332, .colorspace = V4L2_COLORSPACE_SRGB, - },{ + }, { .description = "32-bit RGB", .bpp = 4, .pixelformat = V4L2_PIX_FMT_RGB32, .colorspace = V4L2_COLORSPACE_SRGB, - },{ + }, { .description = "YUV 4:2:2", .bpp = 2, .pixelformat = V4L2_PIX_FMT_YUYV, // XXX: swapped? @@ -417,7 +412,7 @@ static const struct vino_data_norm vino_data_norms[] = { + VINO_NTSC_HEIGHT / 2 - 1, .right = VINO_NTSC_WIDTH, }, - },{ + }, { .description = "PAL", .std = V4L2_STD_PAL, .fps_min = 5, @@ -439,7 +434,7 @@ static const struct vino_data_norm vino_data_norms[] = { + VINO_PAL_HEIGHT / 2 - 1, .right = VINO_PAL_WIDTH, }, - },{ + }, { .description = "SECAM", .std = V4L2_STD_SECAM, .fps_min = 5, @@ -461,7 +456,7 @@ static const struct vino_data_norm vino_data_norms[] = { + VINO_PAL_HEIGHT / 2 - 1, .right = VINO_PAL_WIDTH, }, - },{ + }, { .description = "NTSC/D1", .std = V4L2_STD_NTSC, .fps_min = 6, @@ -497,9 +492,7 @@ struct v4l2_queryctrl vino_indycam_v4l2_controls[] = { .maximum = 1, .step = 1, .default_value = INDYCAM_AGC_DEFAULT, - .flags = 0, - .reserved = { INDYCAM_CONTROL_AGC, 0 }, - },{ + }, { .id = V4L2_CID_AUTO_WHITE_BALANCE, .type = V4L2_CTRL_TYPE_BOOLEAN, .name = "Automatic White Balance", @@ -507,9 +500,7 @@ struct v4l2_queryctrl vino_indycam_v4l2_controls[] = { .maximum = 1, .step = 1, .default_value = INDYCAM_AWB_DEFAULT, - .flags = 0, - .reserved = { INDYCAM_CONTROL_AWB, 0 }, - },{ + }, { .id = V4L2_CID_GAIN, .type = V4L2_CTRL_TYPE_INTEGER, .name = "Gain", @@ -517,29 +508,23 @@ struct v4l2_queryctrl vino_indycam_v4l2_controls[] = { .maximum = INDYCAM_GAIN_MAX, .step = 1, .default_value = INDYCAM_GAIN_DEFAULT, - .flags = 0, - .reserved = { INDYCAM_CONTROL_GAIN, 0 }, - },{ - .id = V4L2_CID_PRIVATE_BASE, + }, { + .id = INDYCAM_CONTROL_RED_SATURATION, .type = V4L2_CTRL_TYPE_INTEGER, .name = "Red Saturation", .minimum = INDYCAM_RED_SATURATION_MIN, .maximum = INDYCAM_RED_SATURATION_MAX, .step = 1, .default_value = INDYCAM_RED_SATURATION_DEFAULT, - .flags = 0, - .reserved = { INDYCAM_CONTROL_RED_SATURATION, 0 }, - },{ - .id = V4L2_CID_PRIVATE_BASE + 1, + }, { + .id = INDYCAM_CONTROL_BLUE_SATURATION, .type = V4L2_CTRL_TYPE_INTEGER, .name = "Blue Saturation", .minimum = INDYCAM_BLUE_SATURATION_MIN, .maximum = INDYCAM_BLUE_SATURATION_MAX, .step = 1, .default_value = INDYCAM_BLUE_SATURATION_DEFAULT, - .flags = 0, - .reserved = { INDYCAM_CONTROL_BLUE_SATURATION, 0 }, - },{ + }, { .id = V4L2_CID_RED_BALANCE, .type = V4L2_CTRL_TYPE_INTEGER, .name = "Red Balance", @@ -547,9 +532,7 @@ struct v4l2_queryctrl vino_indycam_v4l2_controls[] = { .maximum = INDYCAM_RED_BALANCE_MAX, .step = 1, .default_value = INDYCAM_RED_BALANCE_DEFAULT, - .flags = 0, - .reserved = { INDYCAM_CONTROL_RED_BALANCE, 0 }, - },{ + }, { .id = V4L2_CID_BLUE_BALANCE, .type = V4L2_CTRL_TYPE_INTEGER, .name = "Blue Balance", @@ -557,9 +540,7 @@ struct v4l2_queryctrl vino_indycam_v4l2_controls[] = { .maximum = INDYCAM_BLUE_BALANCE_MAX, .step = 1, .default_value = INDYCAM_BLUE_BALANCE_DEFAULT, - .flags = 0, - .reserved = { INDYCAM_CONTROL_BLUE_BALANCE, 0 }, - },{ + }, { .id = V4L2_CID_EXPOSURE, .type = V4L2_CTRL_TYPE_INTEGER, .name = "Shutter Control", @@ -567,9 +548,7 @@ struct v4l2_queryctrl vino_indycam_v4l2_controls[] = { .maximum = INDYCAM_SHUTTER_MAX, .step = 1, .default_value = INDYCAM_SHUTTER_DEFAULT, - .flags = 0, - .reserved = { INDYCAM_CONTROL_SHUTTER, 0 }, - },{ + }, { .id = V4L2_CID_GAMMA, .type = V4L2_CTRL_TYPE_INTEGER, .name = "Gamma", @@ -577,8 +556,6 @@ struct v4l2_queryctrl vino_indycam_v4l2_controls[] = { .maximum = INDYCAM_GAMMA_MAX, .step = 1, .default_value = INDYCAM_GAMMA_DEFAULT, - .flags = 0, - .reserved = { INDYCAM_CONTROL_GAMMA, 0 }, } }; @@ -593,88 +570,70 @@ struct v4l2_queryctrl vino_saa7191_v4l2_controls[] = { .maximum = SAA7191_HUE_MAX, .step = 1, .default_value = SAA7191_HUE_DEFAULT, - .flags = 0, - .reserved = { SAA7191_CONTROL_HUE, 0 }, - },{ - .id = V4L2_CID_PRIVATE_BASE, + }, { + .id = SAA7191_CONTROL_BANDPASS, .type = V4L2_CTRL_TYPE_INTEGER, .name = "Luminance Bandpass", .minimum = SAA7191_BANDPASS_MIN, .maximum = SAA7191_BANDPASS_MAX, .step = 1, .default_value = SAA7191_BANDPASS_DEFAULT, - .flags = 0, - .reserved = { SAA7191_CONTROL_BANDPASS, 0 }, - },{ - .id = V4L2_CID_PRIVATE_BASE + 1, + }, { + .id = SAA7191_CONTROL_BANDPASS_WEIGHT, .type = V4L2_CTRL_TYPE_INTEGER, .name = "Luminance Bandpass Weight", .minimum = SAA7191_BANDPASS_WEIGHT_MIN, .maximum = SAA7191_BANDPASS_WEIGHT_MAX, .step = 1, .default_value = SAA7191_BANDPASS_WEIGHT_DEFAULT, - .flags = 0, - .reserved = { SAA7191_CONTROL_BANDPASS_WEIGHT, 0 }, - },{ - .id = V4L2_CID_PRIVATE_BASE + 2, + }, { + .id = SAA7191_CONTROL_CORING, .type = V4L2_CTRL_TYPE_INTEGER, .name = "HF Luminance Coring", .minimum = SAA7191_CORING_MIN, .maximum = SAA7191_CORING_MAX, .step = 1, .default_value = SAA7191_CORING_DEFAULT, - .flags = 0, - .reserved = { SAA7191_CONTROL_CORING, 0 }, - },{ - .id = V4L2_CID_PRIVATE_BASE + 3, + }, { + .id = SAA7191_CONTROL_FORCE_COLOUR, .type = V4L2_CTRL_TYPE_BOOLEAN, .name = "Force Colour", .minimum = SAA7191_FORCE_COLOUR_MIN, .maximum = SAA7191_FORCE_COLOUR_MAX, .step = 1, .default_value = SAA7191_FORCE_COLOUR_DEFAULT, - .flags = 0, - .reserved = { SAA7191_CONTROL_FORCE_COLOUR, 0 }, - },{ - .id = V4L2_CID_PRIVATE_BASE + 4, + }, { + .id = SAA7191_CONTROL_CHROMA_GAIN, .type = V4L2_CTRL_TYPE_INTEGER, .name = "Chrominance Gain Control", .minimum = SAA7191_CHROMA_GAIN_MIN, .maximum = SAA7191_CHROMA_GAIN_MAX, .step = 1, .default_value = SAA7191_CHROMA_GAIN_DEFAULT, - .flags = 0, - .reserved = { SAA7191_CONTROL_CHROMA_GAIN, 0 }, - },{ - .id = V4L2_CID_PRIVATE_BASE + 5, + }, { + .id = SAA7191_CONTROL_VTRC, .type = V4L2_CTRL_TYPE_BOOLEAN, .name = "VTR Time Constant", .minimum = SAA7191_VTRC_MIN, .maximum = SAA7191_VTRC_MAX, .step = 1, .default_value = SAA7191_VTRC_DEFAULT, - .flags = 0, - .reserved = { SAA7191_CONTROL_VTRC, 0 }, - },{ - .id = V4L2_CID_PRIVATE_BASE + 6, + }, { + .id = SAA7191_CONTROL_LUMA_DELAY, .type = V4L2_CTRL_TYPE_INTEGER, .name = "Luminance Delay Compensation", .minimum = SAA7191_LUMA_DELAY_MIN, .maximum = SAA7191_LUMA_DELAY_MAX, .step = 1, .default_value = SAA7191_LUMA_DELAY_DEFAULT, - .flags = 0, - .reserved = { SAA7191_CONTROL_LUMA_DELAY, 0 }, - },{ - .id = V4L2_CID_PRIVATE_BASE + 7, + }, { + .id = SAA7191_CONTROL_VNR, .type = V4L2_CTRL_TYPE_INTEGER, .name = "Vertical Noise Reduction", .minimum = SAA7191_VNR_MIN, .maximum = SAA7191_VNR_MAX, .step = 1, .default_value = SAA7191_VNR_DEFAULT, - .flags = 0, - .reserved = { SAA7191_CONTROL_VNR, 0 }, } }; @@ -2490,77 +2449,6 @@ static int vino_get_saa7191_input(int input) } } -static int vino_get_saa7191_norm(unsigned int data_norm) -{ - switch (data_norm) { - case VINO_DATA_NORM_AUTO: - return SAA7191_NORM_AUTO; - case VINO_DATA_NORM_AUTO_EXT: - return SAA7191_NORM_AUTO_EXT; - case VINO_DATA_NORM_PAL: - return SAA7191_NORM_PAL; - case VINO_DATA_NORM_NTSC: - return SAA7191_NORM_NTSC; - case VINO_DATA_NORM_SECAM: - return SAA7191_NORM_SECAM; - default: - printk(KERN_ERR "VINO: vino_get_saa7191_norm(): " - "invalid norm!\n"); - return -1; - } -} - -static int vino_get_from_saa7191_norm(int saa7191_norm) -{ - switch (saa7191_norm) { - case SAA7191_NORM_PAL: - return VINO_DATA_NORM_PAL; - case SAA7191_NORM_NTSC: - return VINO_DATA_NORM_NTSC; - case SAA7191_NORM_SECAM: - return VINO_DATA_NORM_SECAM; - default: - printk(KERN_ERR "VINO: vino_get_from_saa7191_norm(): " - "invalid norm!\n"); - return VINO_DATA_NORM_NONE; - } -} - -static int vino_saa7191_set_norm(unsigned int *data_norm) -{ - int saa7191_norm, new_data_norm; - int err = 0; - - saa7191_norm = vino_get_saa7191_norm(*data_norm); - - err = i2c_decoder_command(DECODER_SAA7191_SET_NORM, - &saa7191_norm); - if (err) - goto out; - - if ((*data_norm == VINO_DATA_NORM_AUTO) - || (*data_norm == VINO_DATA_NORM_AUTO_EXT)) { - struct saa7191_status status; - - err = i2c_decoder_command(DECODER_SAA7191_GET_STATUS, - &status); - if (err) - goto out; - - new_data_norm = - vino_get_from_saa7191_norm(status.norm); - if (new_data_norm == VINO_DATA_NORM_NONE) { - err = -EINVAL; - goto out; - } - - *data_norm = (unsigned int)new_data_norm; - } - -out: - return err; -} - /* execute with input_lock locked */ static int vino_is_input_owner(struct vino_channel_settings *vcs) { @@ -2593,15 +2481,16 @@ static int vino_acquire_input(struct vino_channel_settings *vcs) vcs->data_norm = VINO_DATA_NORM_D1; } else if (vino_drvdata->decoder.driver && (vino_drvdata->decoder.owner == VINO_NO_CHANNEL)) { - int input, data_norm; - int saa7191_input; + int input; + int data_norm; + v4l2_std_id norm; + struct v4l2_routing route = { 0, 0 }; i2c_use_client(vino_drvdata->decoder.driver); input = VINO_INPUT_COMPOSITE; - saa7191_input = vino_get_saa7191_input(input); - ret = i2c_decoder_command(DECODER_SET_INPUT, - &saa7191_input); + route.input = vino_get_saa7191_input(input); + ret = i2c_decoder_command(VIDIOC_INT_S_VIDEO_ROUTING, &route); if (ret) { ret = -EINVAL; goto out; @@ -2612,12 +2501,15 @@ static int vino_acquire_input(struct vino_channel_settings *vcs) /* Don't hold spinlocks while auto-detecting norm * as it may take a while... */ - data_norm = VINO_DATA_NORM_AUTO_EXT; - - ret = vino_saa7191_set_norm(&data_norm); - if ((ret == -EBUSY) || (ret == -EAGAIN)) { - data_norm = VINO_DATA_NORM_PAL; - ret = vino_saa7191_set_norm(&data_norm); + ret = i2c_decoder_command(VIDIOC_QUERYSTD, &norm); + if (!ret) { + for (data_norm = 0; data_norm < 3; data_norm++) { + if (vino_data_norms[data_norm].std & norm) + break; + } + if (data_norm == 3) + data_norm = VINO_DATA_NORM_PAL; + ret = i2c_decoder_command(VIDIOC_S_STD, &norm); } spin_lock_irqsave(&vino_drvdata->input_lock, flags); @@ -2684,11 +2576,11 @@ static int vino_set_input(struct vino_channel_settings *vcs, int input) if (vino_drvdata->decoder.owner == vcs->channel) { int data_norm; - int saa7191_input; + v4l2_std_id norm; + struct v4l2_routing route = { 0, 0 }; - saa7191_input = vino_get_saa7191_input(input); - ret = i2c_decoder_command(DECODER_SET_INPUT, - &saa7191_input); + route.input = vino_get_saa7191_input(input); + ret = i2c_decoder_command(VIDIOC_INT_S_VIDEO_ROUTING, &route); if (ret) { vino_drvdata->decoder.owner = VINO_NO_CHANNEL; ret = -EINVAL; @@ -2700,12 +2592,15 @@ static int vino_set_input(struct vino_channel_settings *vcs, int input) /* Don't hold spinlocks while auto-detecting norm * as it may take a while... */ - data_norm = VINO_DATA_NORM_AUTO_EXT; - - ret = vino_saa7191_set_norm(&data_norm); - if ((ret == -EBUSY) || (ret == -EAGAIN)) { - data_norm = VINO_DATA_NORM_PAL; - ret = vino_saa7191_set_norm(&data_norm); + ret = i2c_decoder_command(VIDIOC_QUERYSTD, &norm); + if (!ret) { + for (data_norm = 0; data_norm < 3; data_norm++) { + if (vino_data_norms[data_norm].std & norm) + break; + } + if (data_norm == 3) + data_norm = VINO_DATA_NORM_PAL; + ret = i2c_decoder_command(VIDIOC_S_STD, &norm); } spin_lock_irqsave(&vino_drvdata->input_lock, flags); @@ -2733,8 +2628,7 @@ static int vino_set_input(struct vino_channel_settings *vcs, int input) if (vcs2->input == VINO_INPUT_D1) { vino_drvdata->camera.owner = vcs2->channel; } else { - i2c_release_client(vino_drvdata-> - camera.driver); + i2c_release_client(vino_drvdata->camera.driver); vino_drvdata->camera.owner = VINO_NO_CHANNEL; } } @@ -2829,18 +2723,16 @@ static int vino_set_data_norm(struct vino_channel_settings *vcs, switch (vcs->input) { case VINO_INPUT_D1: /* only one "norm" supported */ - if ((data_norm != VINO_DATA_NORM_D1) - && (data_norm != VINO_DATA_NORM_AUTO) - && (data_norm != VINO_DATA_NORM_AUTO_EXT)) + if (data_norm != VINO_DATA_NORM_D1) return -EINVAL; break; case VINO_INPUT_COMPOSITE: case VINO_INPUT_SVIDEO: { + v4l2_std_id norm; + if ((data_norm != VINO_DATA_NORM_PAL) && (data_norm != VINO_DATA_NORM_NTSC) - && (data_norm != VINO_DATA_NORM_SECAM) - && (data_norm != VINO_DATA_NORM_AUTO) - && (data_norm != VINO_DATA_NORM_AUTO_EXT)) + && (data_norm != VINO_DATA_NORM_SECAM)) return -EINVAL; spin_unlock_irqrestore(&vino_drvdata->input_lock, *flags); @@ -2848,7 +2740,8 @@ static int vino_set_data_norm(struct vino_channel_settings *vcs, /* Don't hold spinlocks while setting norm * as it may take a while... */ - err = vino_saa7191_set_norm(&data_norm); + norm = vino_data_norms[data_norm].std; + err = i2c_decoder_command(VIDIOC_S_STD, &norm); spin_lock_irqsave(&vino_drvdata->input_lock, *flags); @@ -2998,14 +2891,8 @@ static int vino_enum_input(struct file *file, void *__fh, i->std = vino_inputs[input].std; strcpy(i->name, vino_inputs[input].name); - if ((input == VINO_INPUT_COMPOSITE) - || (input == VINO_INPUT_SVIDEO)) { - struct saa7191_status status; - i2c_decoder_command(DECODER_SAA7191_GET_STATUS, &status); - i->status |= status.signal ? 0 : V4L2_IN_ST_NO_SIGNAL; - i->status |= status.color ? 0 : V4L2_IN_ST_NO_COLOR; - } - + if (input == VINO_INPUT_COMPOSITE || input == VINO_INPUT_SVIDEO) + i2c_decoder_command(VIDIOC_INT_G_INPUT_STATUS, &i->status); return 0; } @@ -3062,19 +2949,7 @@ static int vino_querystd(struct file *file, void *__fh, break; case VINO_INPUT_COMPOSITE: case VINO_INPUT_SVIDEO: { - struct saa7191_status status; - - i2c_decoder_command(DECODER_SAA7191_GET_STATUS, &status); - - if (status.signal) { - if (status.signal_60hz) { - *std = V4L2_STD_NTSC; - } else { - *std = V4L2_STD_PAL | V4L2_STD_SECAM; - } - } else { - *std = vino_inputs[vcs->input].std; - } + i2c_decoder_command(VIDIOC_QUERYSTD, std); break; } default: @@ -3126,12 +3001,7 @@ static int vino_s_std(struct file *file, void *__fh, if (vcs->input == VINO_INPUT_D1) goto out; - if (((*std) & V4L2_STD_PAL) - && ((*std) & V4L2_STD_NTSC) - && ((*std) & V4L2_STD_SECAM)) { - ret = vino_set_data_norm(vcs, VINO_DATA_NORM_AUTO_EXT, - &flags); - } else if ((*std) & V4L2_STD_PAL) { + if ((*std) & V4L2_STD_PAL) { ret = vino_set_data_norm(vcs, VINO_DATA_NORM_PAL, &flags); } else if ((*std) & V4L2_STD_NTSC) { @@ -3797,56 +3667,38 @@ static int vino_g_ctrl(struct file *file, void *__fh, switch (vcs->input) { case VINO_INPUT_D1: { - struct indycam_control indycam_ctrl; - + err = -EINVAL; for (i = 0; i < VINO_INDYCAM_V4L2_CONTROL_COUNT; i++) { - if (vino_indycam_v4l2_controls[i].id == - control->id) { - goto found1; + if (vino_indycam_v4l2_controls[i].id == control->id) { + err = 0; + break; } } - err = -EINVAL; - goto out; - -found1: - indycam_ctrl.type = vino_indycam_v4l2_controls[i].reserved[0]; - - err = i2c_camera_command(DECODER_INDYCAM_GET_CONTROL, - &indycam_ctrl); - if (err) { - err = -EINVAL; + if (err) goto out; - } - control->value = indycam_ctrl.value; + err = i2c_camera_command(VIDIOC_G_CTRL, &control); + if (err) + err = -EINVAL; break; } case VINO_INPUT_COMPOSITE: case VINO_INPUT_SVIDEO: { - struct saa7191_control saa7191_ctrl; - + err = -EINVAL; for (i = 0; i < VINO_SAA7191_V4L2_CONTROL_COUNT; i++) { - if (vino_saa7191_v4l2_controls[i].id == - control->id) { - goto found2; + if (vino_saa7191_v4l2_controls[i].id == control->id) { + err = 0; + break; } } - err = -EINVAL; - goto out; - -found2: - saa7191_ctrl.type = vino_saa7191_v4l2_controls[i].reserved[0]; - - err = i2c_decoder_command(DECODER_SAA7191_GET_CONTROL, - &saa7191_ctrl); - if (err) { - err = -EINVAL; + if (err) goto out; - } - control->value = saa7191_ctrl.value; + err = i2c_decoder_command(VIDIOC_G_CTRL, &control); + if (err) + err = -EINVAL; break; } default: @@ -3876,65 +3728,43 @@ static int vino_s_ctrl(struct file *file, void *__fh, switch (vcs->input) { case VINO_INPUT_D1: { - struct indycam_control indycam_ctrl; - + err = -EINVAL; for (i = 0; i < VINO_INDYCAM_V4L2_CONTROL_COUNT; i++) { - if (vino_indycam_v4l2_controls[i].id == - control->id) { - if ((control->value >= - vino_indycam_v4l2_controls[i].minimum) - && (control->value <= - vino_indycam_v4l2_controls[i]. - maximum)) { - goto found1; - } else { - err = -ERANGE; - goto out; - } + if (vino_indycam_v4l2_controls[i].id == control->id) { + err = 0; + break; } } - - err = -EINVAL; - goto out; - -found1: - indycam_ctrl.type = vino_indycam_v4l2_controls[i].reserved[0]; - indycam_ctrl.value = control->value; - - err = i2c_camera_command(DECODER_INDYCAM_SET_CONTROL, - &indycam_ctrl); + if (err) + goto out; + if (control->value < vino_indycam_v4l2_controls[i].minimum || + control->value > vino_indycam_v4l2_controls[i].maximum) { + err = -ERANGE; + goto out; + } + err = i2c_camera_command(VIDIOC_S_CTRL, &control); if (err) err = -EINVAL; break; } case VINO_INPUT_COMPOSITE: case VINO_INPUT_SVIDEO: { - struct saa7191_control saa7191_ctrl; - + err = -EINVAL; for (i = 0; i < VINO_SAA7191_V4L2_CONTROL_COUNT; i++) { - if (vino_saa7191_v4l2_controls[i].id == - control->id) { - if ((control->value >= - vino_saa7191_v4l2_controls[i].minimum) - && (control->value <= - vino_saa7191_v4l2_controls[i]. - maximum)) { - goto found2; - } else { - err = -ERANGE; - goto out; - } + if (vino_saa7191_v4l2_controls[i].id == control->id) { + err = 0; + break; } } - err = -EINVAL; - goto out; - -found2: - saa7191_ctrl.type = vino_saa7191_v4l2_controls[i].reserved[0]; - saa7191_ctrl.value = control->value; + if (err) + goto out; + if (control->value < vino_saa7191_v4l2_controls[i].minimum || + control->value > vino_saa7191_v4l2_controls[i].maximum) { + err = -ERANGE; + goto out; + } - err = i2c_decoder_command(DECODER_SAA7191_SET_CONTROL, - &saa7191_ctrl); + err = i2c_decoder_command(VIDIOC_S_CTRL, &control); if (err) err = -EINVAL; break; -- cgit v1.2.3 From 2b80a19181af3bb15ef1c022f4a56deabcc5bd5e Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 13 Feb 2009 19:38:10 -0300 Subject: V4L/DVB (10862): indycam: convert to v4l2_subdev Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/indycam.c | 128 ++++++++++++++++++++++------------------ include/media/v4l2-chip-ident.h | 3 + 2 files changed, 74 insertions(+), 57 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/indycam.c b/drivers/media/video/indycam.c index 54099e303c8d..eb5078c07a33 100644 --- a/drivers/media/video/indycam.c +++ b/drivers/media/video/indycam.c @@ -22,7 +22,8 @@ /* IndyCam decodes stream of photons into digital image representation ;-) */ #include #include -#include +#include +#include #include #include "indycam.h" @@ -49,10 +50,15 @@ I2C_CLIENT_INSMOD; #endif struct indycam { - struct i2c_client *client; + struct v4l2_subdev sd; u8 version; }; +static inline struct indycam *to_indycam(struct v4l2_subdev *sd) +{ + return container_of(sd, struct indycam, sd); +} + static const u8 initseq[] = { INDYCAM_CONTROL_AGCENA, /* INDYCAM_CONTROL */ INDYCAM_SHUTTER_60, /* INDYCAM_SHUTTER */ @@ -66,8 +72,9 @@ static const u8 initseq[] = { /* IndyCam register handling */ -static int indycam_read_reg(struct i2c_client *client, u8 reg, u8 *value) +static int indycam_read_reg(struct v4l2_subdev *sd, u8 reg, u8 *value) { + struct i2c_client *client = v4l2_get_subdevdata(sd); int ret; if (reg == INDYCAM_REG_RESET) { @@ -90,12 +97,12 @@ static int indycam_read_reg(struct i2c_client *client, u8 reg, u8 *value) return 0; } -static int indycam_write_reg(struct i2c_client *client, u8 reg, u8 value) +static int indycam_write_reg(struct v4l2_subdev *sd, u8 reg, u8 value) { + struct i2c_client *client = v4l2_get_subdevdata(sd); int err; - if ((reg == INDYCAM_REG_BRIGHTNESS) - || (reg == INDYCAM_REG_VERSION)) { + if (reg == INDYCAM_REG_BRIGHTNESS || reg == INDYCAM_REG_VERSION) { dprintk("indycam_write_reg(): " "skipping read-only register %d\n", reg); return 0; @@ -111,13 +118,13 @@ static int indycam_write_reg(struct i2c_client *client, u8 reg, u8 value) return err; } -static int indycam_write_block(struct i2c_client *client, u8 reg, +static int indycam_write_block(struct v4l2_subdev *sd, u8 reg, u8 length, u8 *data) { int i, err; for (i = 0; i < length; i++) { - err = indycam_write_reg(client, reg + i, data[i]); + err = indycam_write_reg(sd, reg + i, data[i]); if (err) return err; } @@ -128,29 +135,28 @@ static int indycam_write_block(struct i2c_client *client, u8 reg, /* Helper functions */ #ifdef INDYCAM_DEBUG -static void indycam_regdump_debug(struct i2c_client *client) +static void indycam_regdump_debug(struct v4l2_subdev *sd) { int i; u8 val; for (i = 0; i < 9; i++) { - indycam_read_reg(client, i, &val); + indycam_read_reg(sd, i, &val); dprintk("Reg %d = 0x%02x\n", i, val); } } #endif -static int indycam_get_control(struct i2c_client *client, - struct v4l2_control *ctrl) +static int indycam_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) { - struct indycam *camera = i2c_get_clientdata(client); + struct indycam *camera = to_indycam(sd); u8 reg; int ret = 0; switch (ctrl->id) { case V4L2_CID_AUTOGAIN: case V4L2_CID_AUTO_WHITE_BALANCE: - ret = indycam_read_reg(client, INDYCAM_REG_CONTROL, ®); + ret = indycam_read_reg(sd, INDYCAM_REG_CONTROL, ®); if (ret) return -EIO; if (ctrl->id == V4L2_CID_AUTOGAIN) @@ -161,38 +167,38 @@ static int indycam_get_control(struct i2c_client *client, ? 1 : 0; break; case V4L2_CID_EXPOSURE: - ret = indycam_read_reg(client, INDYCAM_REG_SHUTTER, ®); + ret = indycam_read_reg(sd, INDYCAM_REG_SHUTTER, ®); if (ret) return -EIO; ctrl->value = ((s32)reg == 0x00) ? 0xff : ((s32)reg - 1); break; case V4L2_CID_GAIN: - ret = indycam_read_reg(client, INDYCAM_REG_GAIN, ®); + ret = indycam_read_reg(sd, INDYCAM_REG_GAIN, ®); if (ret) return -EIO; ctrl->value = (s32)reg; break; case V4L2_CID_RED_BALANCE: - ret = indycam_read_reg(client, INDYCAM_REG_RED_BALANCE, ®); + ret = indycam_read_reg(sd, INDYCAM_REG_RED_BALANCE, ®); if (ret) return -EIO; ctrl->value = (s32)reg; break; case V4L2_CID_BLUE_BALANCE: - ret = indycam_read_reg(client, INDYCAM_REG_BLUE_BALANCE, ®); + ret = indycam_read_reg(sd, INDYCAM_REG_BLUE_BALANCE, ®); if (ret) return -EIO; ctrl->value = (s32)reg; break; case INDYCAM_CONTROL_RED_SATURATION: - ret = indycam_read_reg(client, + ret = indycam_read_reg(sd, INDYCAM_REG_RED_SATURATION, ®); if (ret) return -EIO; ctrl->value = (s32)reg; break; case INDYCAM_CONTROL_BLUE_SATURATION: - ret = indycam_read_reg(client, + ret = indycam_read_reg(sd, INDYCAM_REG_BLUE_SATURATION, ®); if (ret) return -EIO; @@ -200,7 +206,7 @@ static int indycam_get_control(struct i2c_client *client, break; case V4L2_CID_GAMMA: if (camera->version == CAMERA_VERSION_MOOSE) { - ret = indycam_read_reg(client, + ret = indycam_read_reg(sd, INDYCAM_REG_GAMMA, ®); if (ret) return -EIO; @@ -216,17 +222,16 @@ static int indycam_get_control(struct i2c_client *client, return ret; } -static int indycam_set_control(struct i2c_client *client, - struct v4l2_control *ctrl) +static int indycam_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) { - struct indycam *camera = i2c_get_clientdata(client); + struct indycam *camera = to_indycam(sd); u8 reg; int ret = 0; switch (ctrl->id) { case V4L2_CID_AUTOGAIN: case V4L2_CID_AUTO_WHITE_BALANCE: - ret = indycam_read_reg(client, INDYCAM_REG_CONTROL, ®); + ret = indycam_read_reg(sd, INDYCAM_REG_CONTROL, ®); if (ret) break; @@ -242,34 +247,34 @@ static int indycam_set_control(struct i2c_client *client, reg &= ~INDYCAM_CONTROL_AWBCTL; } - ret = indycam_write_reg(client, INDYCAM_REG_CONTROL, reg); + ret = indycam_write_reg(sd, INDYCAM_REG_CONTROL, reg); break; case V4L2_CID_EXPOSURE: reg = (ctrl->value == 0xff) ? 0x00 : (ctrl->value + 1); - ret = indycam_write_reg(client, INDYCAM_REG_SHUTTER, reg); + ret = indycam_write_reg(sd, INDYCAM_REG_SHUTTER, reg); break; case V4L2_CID_GAIN: - ret = indycam_write_reg(client, INDYCAM_REG_GAIN, ctrl->value); + ret = indycam_write_reg(sd, INDYCAM_REG_GAIN, ctrl->value); break; case V4L2_CID_RED_BALANCE: - ret = indycam_write_reg(client, INDYCAM_REG_RED_BALANCE, + ret = indycam_write_reg(sd, INDYCAM_REG_RED_BALANCE, ctrl->value); break; case V4L2_CID_BLUE_BALANCE: - ret = indycam_write_reg(client, INDYCAM_REG_BLUE_BALANCE, + ret = indycam_write_reg(sd, INDYCAM_REG_BLUE_BALANCE, ctrl->value); break; case INDYCAM_CONTROL_RED_SATURATION: - ret = indycam_write_reg(client, INDYCAM_REG_RED_SATURATION, + ret = indycam_write_reg(sd, INDYCAM_REG_RED_SATURATION, ctrl->value); break; case INDYCAM_CONTROL_BLUE_SATURATION: - ret = indycam_write_reg(client, INDYCAM_REG_BLUE_SATURATION, + ret = indycam_write_reg(sd, INDYCAM_REG_BLUE_SATURATION, ctrl->value); break; case V4L2_CID_GAMMA: if (camera->version == CAMERA_VERSION_MOOSE) { - ret = indycam_write_reg(client, INDYCAM_REG_GAMMA, + ret = indycam_write_reg(sd, INDYCAM_REG_GAMMA, ctrl->value); } break; @@ -282,30 +287,39 @@ static int indycam_set_control(struct i2c_client *client, /* I2C-interface */ -static int indycam_command(struct i2c_client *client, unsigned int cmd, - void *arg) +static int indycam_g_chip_ident(struct v4l2_subdev *sd, + struct v4l2_dbg_chip_ident *chip) { - /* The old video_decoder interface just isn't enough, - * so we'll use some custom commands. */ - switch (cmd) { - case VIDIOC_G_CTRL: - return indycam_get_control(client, arg); - - case VIDIOC_S_CTRL: - return indycam_set_control(client, arg); + struct i2c_client *client = v4l2_get_subdevdata(sd); + struct indycam *camera = to_indycam(sd); - default: - return -EINVAL; - } + return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_INDYCAM, + camera->version); +} - return 0; +static int indycam_command(struct i2c_client *client, unsigned cmd, void *arg) +{ + return v4l2_subdev_command(i2c_get_clientdata(client), cmd, arg); } +/* ----------------------------------------------------------------------- */ + +static const struct v4l2_subdev_core_ops indycam_core_ops = { + .g_chip_ident = indycam_g_chip_ident, + .g_ctrl = indycam_g_ctrl, + .s_ctrl = indycam_s_ctrl, +}; + +static const struct v4l2_subdev_ops indycam_ops = { + .core = &indycam_core_ops, +}; + static int indycam_probe(struct i2c_client *client, const struct i2c_device_id *id) { int err = 0; struct indycam *camera; + struct v4l2_subdev *sd; v4l_info(client, "chip found @ 0x%x (%s)\n", client->addr << 1, client->adapter->name); @@ -314,9 +328,8 @@ static int indycam_probe(struct i2c_client *client, if (!camera) return -ENOMEM; - i2c_set_clientdata(client, camera); - - camera->client = client; + sd = &camera->sd; + v4l2_i2c_subdev_init(sd, client, &indycam_ops); camera->version = i2c_smbus_read_byte_data(client, INDYCAM_REG_VERSION); @@ -330,20 +343,20 @@ static int indycam_probe(struct i2c_client *client, INDYCAM_VERSION_MAJOR(camera->version), INDYCAM_VERSION_MINOR(camera->version)); - indycam_regdump(client); + indycam_regdump(sd); // initialize - err = indycam_write_block(client, 0, sizeof(initseq), (u8 *)&initseq); + err = indycam_write_block(sd, 0, sizeof(initseq), (u8 *)&initseq); if (err) { printk(KERN_ERR "IndyCam initialization failed\n"); kfree(camera); return -EIO; } - indycam_regdump(client); + indycam_regdump(sd); // white balance - err = indycam_write_reg(client, INDYCAM_REG_CONTROL, + err = indycam_write_reg(sd, INDYCAM_REG_CONTROL, INDYCAM_CONTROL_AGCENA | INDYCAM_CONTROL_AWBCTL); if (err) { printk(KERN_ERR "IndyCam: White balancing camera failed\n"); @@ -351,7 +364,7 @@ static int indycam_probe(struct i2c_client *client, return -EIO; } - indycam_regdump(client); + indycam_regdump(sd); printk(KERN_INFO "IndyCam initialized\n"); @@ -360,9 +373,10 @@ static int indycam_probe(struct i2c_client *client, static int indycam_remove(struct i2c_client *client) { - struct indycam *camera = i2c_get_clientdata(client); + struct v4l2_subdev *sd = i2c_get_clientdata(client); - kfree(camera); + v4l2_device_unregister_subdev(sd); + kfree(to_indycam(sd)); return 0; } diff --git a/include/media/v4l2-chip-ident.h b/include/media/v4l2-chip-ident.h index 70117e748f20..f02517bdf534 100644 --- a/include/media/v4l2-chip-ident.h +++ b/include/media/v4l2-chip-ident.h @@ -70,6 +70,9 @@ enum { V4L2_IDENT_CX23416 = 416, V4L2_IDENT_CX23418 = 418, + /* module indycam: just ident 2000 */ + V4L2_IDENT_INDYCAM = 2000, + /* module bt819: reserved range 810-819 */ V4L2_IDENT_BT815A = 815, V4L2_IDENT_BT817A = 817, -- cgit v1.2.3 From 8340ff43c49fe8e0cd049b65fbd2156bd651697e Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 13 Feb 2009 19:58:12 -0300 Subject: V4L/DVB (10863): saa7191: convert to v4l2_subdev. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/saa7191.c | 240 +++++++++++++++++++++------------------- include/media/v4l2-chip-ident.h | 3 + 2 files changed, 129 insertions(+), 114 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/saa7191.c b/drivers/media/video/saa7191.c index 4c7bddf4b7ee..40ae2787326f 100644 --- a/drivers/media/video/saa7191.c +++ b/drivers/media/video/saa7191.c @@ -21,7 +21,8 @@ #include #include -#include +#include +#include #include #include "saa7191.h" @@ -49,7 +50,7 @@ I2C_CLIENT_INSMOD; #define SAA7191_SYNC_DELAY 100 /* milliseconds */ struct saa7191 { - struct i2c_client *client; + struct v4l2_subdev sd; /* the register values are stored here as the actual * I2C-registers are write-only */ @@ -59,6 +60,11 @@ struct saa7191 { v4l2_std_id norm; }; +static inline struct saa7191 *to_saa7191(struct v4l2_subdev *sd) +{ + return container_of(sd, struct saa7191, sd); +} + static const u8 initseq[] = { 0, /* Subaddress */ @@ -103,15 +109,14 @@ static const u8 initseq[] = { /* SAA7191 register handling */ -static u8 saa7191_read_reg(struct i2c_client *client, - u8 reg) +static u8 saa7191_read_reg(struct v4l2_subdev *sd, u8 reg) { - return ((struct saa7191 *)i2c_get_clientdata(client))->reg[reg]; + return to_saa7191(sd)->reg[reg]; } -static int saa7191_read_status(struct i2c_client *client, - u8 *value) +static int saa7191_read_status(struct v4l2_subdev *sd, u8 *value) { + struct i2c_client *client = v4l2_get_subdevdata(sd); int ret; ret = i2c_master_recv(client, value, 1); @@ -124,21 +129,23 @@ static int saa7191_read_status(struct i2c_client *client, } -static int saa7191_write_reg(struct i2c_client *client, u8 reg, - u8 value) +static int saa7191_write_reg(struct v4l2_subdev *sd, u8 reg, u8 value) { - ((struct saa7191 *)i2c_get_clientdata(client))->reg[reg] = value; + struct i2c_client *client = v4l2_get_subdevdata(sd); + + to_saa7191(sd)->reg[reg] = value; return i2c_smbus_write_byte_data(client, reg, value); } /* the first byte of data must be the first subaddress number (register) */ -static int saa7191_write_block(struct i2c_client *client, +static int saa7191_write_block(struct v4l2_subdev *sd, u8 length, const u8 *data) { + struct i2c_client *client = v4l2_get_subdevdata(sd); + struct saa7191 *decoder = to_saa7191(sd); int i; int ret; - struct saa7191 *decoder = (struct saa7191 *)i2c_get_clientdata(client); for (i = 0; i < (length - 1); i++) { decoder->reg[data[0] + i] = data[i + 1]; } @@ -155,14 +162,15 @@ static int saa7191_write_block(struct i2c_client *client, /* Helper functions */ -static int saa7191_set_input(struct i2c_client *client, int input) +static int saa7191_s_routing(struct v4l2_subdev *sd, + const struct v4l2_routing *route) { - struct saa7191 *decoder = i2c_get_clientdata(client); - u8 luma = saa7191_read_reg(client, SAA7191_REG_LUMA); - u8 iock = saa7191_read_reg(client, SAA7191_REG_IOCK); + struct saa7191 *decoder = to_saa7191(sd); + u8 luma = saa7191_read_reg(sd, SAA7191_REG_LUMA); + u8 iock = saa7191_read_reg(sd, SAA7191_REG_IOCK); int err; - switch (input) { + switch (route->input) { case SAA7191_INPUT_COMPOSITE: /* Set Composite input */ iock &= ~(SAA7191_IOCK_CHRS | SAA7191_IOCK_GPSW1 | SAA7191_IOCK_GPSW2); @@ -178,24 +186,24 @@ static int saa7191_set_input(struct i2c_client *client, int input) return -EINVAL; } - err = saa7191_write_reg(client, SAA7191_REG_LUMA, luma); + err = saa7191_write_reg(sd, SAA7191_REG_LUMA, luma); if (err) return -EIO; - err = saa7191_write_reg(client, SAA7191_REG_IOCK, iock); + err = saa7191_write_reg(sd, SAA7191_REG_IOCK, iock); if (err) return -EIO; - decoder->input = input; + decoder->input = route->input; return 0; } -static int saa7191_set_norm(struct i2c_client *client, v4l2_std_id norm) +static int saa7191_s_std(struct v4l2_subdev *sd, v4l2_std_id norm) { - struct saa7191 *decoder = i2c_get_clientdata(client); - u8 stdc = saa7191_read_reg(client, SAA7191_REG_STDC); - u8 ctl3 = saa7191_read_reg(client, SAA7191_REG_CTL3); - u8 chcv = saa7191_read_reg(client, SAA7191_REG_CHCV); + struct saa7191 *decoder = to_saa7191(sd); + u8 stdc = saa7191_read_reg(sd, SAA7191_REG_STDC); + u8 ctl3 = saa7191_read_reg(sd, SAA7191_REG_CTL3); + u8 chcv = saa7191_read_reg(sd, SAA7191_REG_CHCV); int err; if (norm & V4L2_STD_PAL) { @@ -215,13 +223,13 @@ static int saa7191_set_norm(struct i2c_client *client, v4l2_std_id norm) return -EINVAL; } - err = saa7191_write_reg(client, SAA7191_REG_CTL3, ctl3); + err = saa7191_write_reg(sd, SAA7191_REG_CTL3, ctl3); if (err) return -EIO; - err = saa7191_write_reg(client, SAA7191_REG_STDC, stdc); + err = saa7191_write_reg(sd, SAA7191_REG_STDC, stdc); if (err) return -EIO; - err = saa7191_write_reg(client, SAA7191_REG_CHCV, chcv); + err = saa7191_write_reg(sd, SAA7191_REG_CHCV, chcv); if (err) return -EIO; @@ -234,14 +242,14 @@ static int saa7191_set_norm(struct i2c_client *client, v4l2_std_id norm) return 0; } -static int saa7191_wait_for_signal(struct i2c_client *client, u8 *status) +static int saa7191_wait_for_signal(struct v4l2_subdev *sd, u8 *status) { int i = 0; dprintk("Checking for signal...\n"); for (i = 0; i < SAA7191_SYNC_COUNT; i++) { - if (saa7191_read_status(client, status)) + if (saa7191_read_status(sd, status)) return -EIO; if (((*status) & SAA7191_STATUS_HLCK) == 0) { @@ -257,12 +265,11 @@ static int saa7191_wait_for_signal(struct i2c_client *client, u8 *status) return -EBUSY; } -static int saa7191_autodetect_norm_extended(struct i2c_client *client, - v4l2_std_id *norm) +static int saa7191_querystd(struct v4l2_subdev *sd, v4l2_std_id *norm) { - struct saa7191 *decoder = i2c_get_clientdata(client); - u8 stdc = saa7191_read_reg(client, SAA7191_REG_STDC); - u8 ctl3 = saa7191_read_reg(client, SAA7191_REG_CTL3); + struct saa7191 *decoder = to_saa7191(sd); + u8 stdc = saa7191_read_reg(sd, SAA7191_REG_STDC); + u8 ctl3 = saa7191_read_reg(sd, SAA7191_REG_CTL3); u8 status; v4l2_std_id old_norm = decoder->norm; int err = 0; @@ -273,19 +280,19 @@ static int saa7191_autodetect_norm_extended(struct i2c_client *client, stdc &= ~SAA7191_STDC_SECS; ctl3 &= ~(SAA7191_CTL3_FSEL); - err = saa7191_write_reg(client, SAA7191_REG_STDC, stdc); + err = saa7191_write_reg(sd, SAA7191_REG_STDC, stdc); if (err) { err = -EIO; goto out; } - err = saa7191_write_reg(client, SAA7191_REG_CTL3, ctl3); + err = saa7191_write_reg(sd, SAA7191_REG_CTL3, ctl3); if (err) { err = -EIO; goto out; } ctl3 |= SAA7191_CTL3_AUFD; - err = saa7191_write_reg(client, SAA7191_REG_CTL3, ctl3); + err = saa7191_write_reg(sd, SAA7191_REG_CTL3, ctl3); if (err) { err = -EIO; goto out; @@ -293,7 +300,7 @@ static int saa7191_autodetect_norm_extended(struct i2c_client *client, msleep(SAA7191_SYNC_DELAY); - err = saa7191_wait_for_signal(client, &status); + err = saa7191_wait_for_signal(sd, &status); if (err) goto out; @@ -308,39 +315,39 @@ static int saa7191_autodetect_norm_extended(struct i2c_client *client, dprintk("50Hz signal: Trying PAL...\n"); /* try PAL first */ - err = saa7191_set_norm(client, V4L2_STD_PAL); + err = saa7191_s_std(sd, V4L2_STD_PAL); if (err) goto out; msleep(SAA7191_SYNC_DELAY); - err = saa7191_wait_for_signal(client, &status); + err = saa7191_wait_for_signal(sd, &status); if (err) goto out; /* not 50Hz ? */ if (status & SAA7191_STATUS_FIDT) { dprintk("No 50Hz signal\n"); - saa7191_set_norm(client, old_norm); + saa7191_s_std(sd, old_norm); return -EAGAIN; } if (status & SAA7191_STATUS_CODE) { dprintk("PAL\n"); *norm = V4L2_STD_PAL; - return saa7191_set_norm(client, old_norm); + return saa7191_s_std(sd, old_norm); } dprintk("No color detected with PAL - Trying SECAM...\n"); /* no color detected ? -> try SECAM */ - err = saa7191_set_norm(client, V4L2_STD_SECAM); + err = saa7191_s_std(sd, V4L2_STD_SECAM); if (err) goto out; msleep(SAA7191_SYNC_DELAY); - err = saa7191_wait_for_signal(client, &status); + err = saa7191_wait_for_signal(sd, &status); if (err) goto out; @@ -355,16 +362,16 @@ static int saa7191_autodetect_norm_extended(struct i2c_client *client, /* Color detected -> SECAM */ dprintk("SECAM\n"); *norm = V4L2_STD_SECAM; - return saa7191_set_norm(client, old_norm); + return saa7191_s_std(sd, old_norm); } dprintk("No color detected with SECAM - Going back to PAL.\n"); out: - return saa7191_set_norm(client, old_norm); + return saa7191_s_std(sd, old_norm); } -static int saa7191_autodetect_norm(struct i2c_client *client) +static int saa7191_autodetect_norm(struct v4l2_subdev *sd) { u8 status; @@ -372,7 +379,7 @@ static int saa7191_autodetect_norm(struct i2c_client *client) dprintk("Reading status...\n"); - if (saa7191_read_status(client, &status)) + if (saa7191_read_status(sd, &status)) return -EIO; dprintk("Checking for signal...\n"); @@ -388,16 +395,15 @@ static int saa7191_autodetect_norm(struct i2c_client *client) if (status & SAA7191_STATUS_FIDT) { /* 60hz signal -> NTSC */ dprintk("NTSC\n"); - return saa7191_set_norm(client, V4L2_STD_NTSC); + return saa7191_s_std(sd, V4L2_STD_NTSC); } else { /* 50hz signal -> PAL */ dprintk("PAL\n"); - return saa7191_set_norm(client, V4L2_STD_PAL); + return saa7191_s_std(sd, V4L2_STD_PAL); } } -static int saa7191_get_control(struct i2c_client *client, - struct v4l2_control *ctrl) +static int saa7191_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) { u8 reg; int ret = 0; @@ -406,7 +412,7 @@ static int saa7191_get_control(struct i2c_client *client, case SAA7191_CONTROL_BANDPASS: case SAA7191_CONTROL_BANDPASS_WEIGHT: case SAA7191_CONTROL_CORING: - reg = saa7191_read_reg(client, SAA7191_REG_LUMA); + reg = saa7191_read_reg(sd, SAA7191_REG_LUMA); switch (ctrl->id) { case SAA7191_CONTROL_BANDPASS: ctrl->value = ((s32)reg & SAA7191_LUMA_BPSS_MASK) @@ -424,7 +430,7 @@ static int saa7191_get_control(struct i2c_client *client, break; case SAA7191_CONTROL_FORCE_COLOUR: case SAA7191_CONTROL_CHROMA_GAIN: - reg = saa7191_read_reg(client, SAA7191_REG_GAIN); + reg = saa7191_read_reg(sd, SAA7191_REG_GAIN); if (ctrl->id == SAA7191_CONTROL_FORCE_COLOUR) ctrl->value = ((s32)reg & SAA7191_GAIN_COLO) ? 1 : 0; else @@ -432,7 +438,7 @@ static int saa7191_get_control(struct i2c_client *client, >> SAA7191_GAIN_LFIS_SHIFT; break; case V4L2_CID_HUE: - reg = saa7191_read_reg(client, SAA7191_REG_HUEC); + reg = saa7191_read_reg(sd, SAA7191_REG_HUEC); if (reg < 0x80) reg += 0x80; else @@ -440,18 +446,18 @@ static int saa7191_get_control(struct i2c_client *client, ctrl->value = (s32)reg; break; case SAA7191_CONTROL_VTRC: - reg = saa7191_read_reg(client, SAA7191_REG_STDC); + reg = saa7191_read_reg(sd, SAA7191_REG_STDC); ctrl->value = ((s32)reg & SAA7191_STDC_VTRC) ? 1 : 0; break; case SAA7191_CONTROL_LUMA_DELAY: - reg = saa7191_read_reg(client, SAA7191_REG_CTL3); + reg = saa7191_read_reg(sd, SAA7191_REG_CTL3); ctrl->value = ((s32)reg & SAA7191_CTL3_YDEL_MASK) >> SAA7191_CTL3_YDEL_SHIFT; if (ctrl->value >= 4) ctrl->value -= 8; break; case SAA7191_CONTROL_VNR: - reg = saa7191_read_reg(client, SAA7191_REG_CTL4); + reg = saa7191_read_reg(sd, SAA7191_REG_CTL4); ctrl->value = ((s32)reg & SAA7191_CTL4_VNOI_MASK) >> SAA7191_CTL4_VNOI_SHIFT; break; @@ -462,8 +468,7 @@ static int saa7191_get_control(struct i2c_client *client, return ret; } -static int saa7191_set_control(struct i2c_client *client, - struct v4l2_control *ctrl) +static int saa7191_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) { u8 reg; int ret = 0; @@ -472,7 +477,7 @@ static int saa7191_set_control(struct i2c_client *client, case SAA7191_CONTROL_BANDPASS: case SAA7191_CONTROL_BANDPASS_WEIGHT: case SAA7191_CONTROL_CORING: - reg = saa7191_read_reg(client, SAA7191_REG_LUMA); + reg = saa7191_read_reg(sd, SAA7191_REG_LUMA); switch (ctrl->id) { case SAA7191_CONTROL_BANDPASS: reg &= ~SAA7191_LUMA_BPSS_MASK; @@ -490,11 +495,11 @@ static int saa7191_set_control(struct i2c_client *client, & SAA7191_LUMA_CORI_MASK; break; } - ret = saa7191_write_reg(client, SAA7191_REG_LUMA, reg); + ret = saa7191_write_reg(sd, SAA7191_REG_LUMA, reg); break; case SAA7191_CONTROL_FORCE_COLOUR: case SAA7191_CONTROL_CHROMA_GAIN: - reg = saa7191_read_reg(client, SAA7191_REG_GAIN); + reg = saa7191_read_reg(sd, SAA7191_REG_GAIN); if (ctrl->id == SAA7191_CONTROL_FORCE_COLOUR) { if (ctrl->value) reg |= SAA7191_GAIN_COLO; @@ -505,7 +510,7 @@ static int saa7191_set_control(struct i2c_client *client, reg |= (ctrl->value << SAA7191_GAIN_LFIS_SHIFT) & SAA7191_GAIN_LFIS_MASK; } - ret = saa7191_write_reg(client, SAA7191_REG_GAIN, reg); + ret = saa7191_write_reg(sd, SAA7191_REG_GAIN, reg); break; case V4L2_CID_HUE: reg = ctrl->value & 0xff; @@ -513,33 +518,33 @@ static int saa7191_set_control(struct i2c_client *client, reg += 0x80; else reg -= 0x80; - ret = saa7191_write_reg(client, SAA7191_REG_HUEC, reg); + ret = saa7191_write_reg(sd, SAA7191_REG_HUEC, reg); break; case SAA7191_CONTROL_VTRC: - reg = saa7191_read_reg(client, SAA7191_REG_STDC); + reg = saa7191_read_reg(sd, SAA7191_REG_STDC); if (ctrl->value) reg |= SAA7191_STDC_VTRC; else reg &= ~SAA7191_STDC_VTRC; - ret = saa7191_write_reg(client, SAA7191_REG_STDC, reg); + ret = saa7191_write_reg(sd, SAA7191_REG_STDC, reg); break; case SAA7191_CONTROL_LUMA_DELAY: { s32 value = ctrl->value; if (value < 0) value += 8; - reg = saa7191_read_reg(client, SAA7191_REG_CTL3); + reg = saa7191_read_reg(sd, SAA7191_REG_CTL3); reg &= ~SAA7191_CTL3_YDEL_MASK; reg |= (value << SAA7191_CTL3_YDEL_SHIFT) & SAA7191_CTL3_YDEL_MASK; - ret = saa7191_write_reg(client, SAA7191_REG_CTL3, reg); + ret = saa7191_write_reg(sd, SAA7191_REG_CTL3, reg); break; } case SAA7191_CONTROL_VNR: - reg = saa7191_read_reg(client, SAA7191_REG_CTL4); + reg = saa7191_read_reg(sd, SAA7191_REG_CTL4); reg &= ~SAA7191_CTL4_VNOI_MASK; reg |= (ctrl->value << SAA7191_CTL4_VNOI_SHIFT) & SAA7191_CTL4_VNOI_MASK; - ret = saa7191_write_reg(client, SAA7191_REG_CTL4, reg); + ret = saa7191_write_reg(sd, SAA7191_REG_CTL4, reg); break; default: ret = -EINVAL; @@ -550,57 +555,64 @@ static int saa7191_set_control(struct i2c_client *client, /* I2C-interface */ -static int saa7191_command(struct i2c_client *client, unsigned int cmd, - void *arg) +static int saa7191_g_input_status(struct v4l2_subdev *sd, u32 *status) { - switch (cmd) { - case VIDIOC_INT_G_INPUT_STATUS: { - u32 *iarg = arg; - u8 status; - int res = V4L2_IN_ST_NO_SIGNAL; + u8 status_reg; + int res = V4L2_IN_ST_NO_SIGNAL; - if (saa7191_read_status(client, &status)) - return -EIO; - if ((status & SAA7191_STATUS_HLCK) == 0) - res = 0; - if (!(status & SAA7191_STATUS_CODE)) - res |= V4L2_IN_ST_NO_COLOR; - *iarg = res; - break; - } + if (saa7191_read_status(sd, &status_reg)) + return -EIO; + if ((status_reg & SAA7191_STATUS_HLCK) == 0) + res = 0; + if (!(status_reg & SAA7191_STATUS_CODE)) + res |= V4L2_IN_ST_NO_COLOR; + *status = res; + return 0; +} - case VIDIOC_QUERYSTD: - return saa7191_autodetect_norm_extended(client, arg); - case VIDIOC_S_STD: { - v4l2_std_id *istd = arg; +static int saa7191_g_chip_ident(struct v4l2_subdev *sd, + struct v4l2_dbg_chip_ident *chip) +{ + struct i2c_client *client = v4l2_get_subdevdata(sd); - return saa7191_set_norm(client, *istd); - } - case VIDIOC_INT_S_VIDEO_ROUTING: { - struct v4l2_routing *route = arg; + return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_SAA7191, 0); +} - return saa7191_set_input(client, route->input); - } +static int saa7191_command(struct i2c_client *client, unsigned cmd, void *arg) +{ + return v4l2_subdev_command(i2c_get_clientdata(client), cmd, arg); +} - case VIDIOC_G_CTRL: - return saa7191_get_control(client, arg); +/* ----------------------------------------------------------------------- */ - case VIDIOC_S_CTRL: - return saa7191_set_control(client, arg); +static const struct v4l2_subdev_core_ops saa7191_core_ops = { + .g_chip_ident = saa7191_g_chip_ident, + .g_ctrl = saa7191_g_ctrl, + .s_ctrl = saa7191_s_ctrl, +}; - default: - return -EINVAL; - } +static const struct v4l2_subdev_tuner_ops saa7191_tuner_ops = { + .s_std = saa7191_s_std, +}; - return 0; -} +static const struct v4l2_subdev_video_ops saa7191_video_ops = { + .s_routing = saa7191_s_routing, + .querystd = saa7191_querystd, + .g_input_status = saa7191_g_input_status, +}; + +static const struct v4l2_subdev_ops saa7191_ops = { + .core = &saa7191_core_ops, + .video = &saa7191_video_ops, +}; static int saa7191_probe(struct i2c_client *client, const struct i2c_device_id *id) { int err = 0; struct saa7191 *decoder; + struct v4l2_subdev *sd; v4l_info(client, "chip found @ 0x%x (%s)\n", client->addr << 1, client->adapter->name); @@ -609,11 +621,10 @@ static int saa7191_probe(struct i2c_client *client, if (!decoder) return -ENOMEM; - i2c_set_clientdata(client, decoder); - - decoder->client = client; + sd = &decoder->sd; + v4l2_i2c_subdev_init(sd, client, &saa7191_ops); - err = saa7191_write_block(client, sizeof(initseq), initseq); + err = saa7191_write_block(sd, sizeof(initseq), initseq); if (err) { printk(KERN_ERR "SAA7191 initialization failed\n"); kfree(decoder); @@ -625,7 +636,7 @@ static int saa7191_probe(struct i2c_client *client, decoder->input = SAA7191_INPUT_COMPOSITE; decoder->norm = V4L2_STD_PAL; - err = saa7191_autodetect_norm(client); + err = saa7191_autodetect_norm(sd); if (err && (err != -EBUSY)) printk(KERN_ERR "SAA7191: Signal auto-detection failed\n"); @@ -634,9 +645,10 @@ static int saa7191_probe(struct i2c_client *client, static int saa7191_remove(struct i2c_client *client) { - struct saa7191 *decoder = i2c_get_clientdata(client); + struct v4l2_subdev *sd = i2c_get_clientdata(client); - kfree(decoder); + v4l2_device_unregister_subdev(sd); + kfree(to_saa7191(sd)); return 0; } diff --git a/include/media/v4l2-chip-ident.h b/include/media/v4l2-chip-ident.h index f02517bdf534..43684f105fd8 100644 --- a/include/media/v4l2-chip-ident.h +++ b/include/media/v4l2-chip-ident.h @@ -131,6 +131,9 @@ enum { /* module saa7185: just ident 7185 */ V4L2_IDENT_SAA7185 = 7185, + /* module saa7191: just ident 7191 */ + V4L2_IDENT_SAA7191 = 7191, + /* module wm8739: just ident 8739 */ V4L2_IDENT_WM8739 = 8739, -- cgit v1.2.3 From 289596382e6aca005ca53ef20bbc44b9886cb0e0 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 18 Feb 2009 18:53:47 -0300 Subject: V4L/DVB (10864): vino: introduce v4l2_device. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/vino.c | 33 ++++++++++++++++++++++----------- 1 file changed, 22 insertions(+), 11 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/vino.c b/drivers/media/video/vino.c index 0a5cd567bfb1..308fa419ae04 100644 --- a/drivers/media/video/vino.c +++ b/drivers/media/video/vino.c @@ -36,7 +36,7 @@ #include #include -#include +#include #include #include @@ -295,6 +295,7 @@ struct vino_client { }; struct vino_settings { + struct v4l2_device v4l2_dev; struct vino_channel_settings a; struct vino_channel_settings b; @@ -3995,7 +3996,6 @@ over: ret = POLLIN | POLLRDNORM; error: - return ret; } @@ -4052,7 +4052,7 @@ static const struct v4l2_file_operations vino_fops = { .owner = THIS_MODULE, .open = vino_open, .release = vino_close, - .ioctl = vino_ioctl, + .unlocked_ioctl = vino_ioctl, .mmap = vino_mmap, .poll = vino_poll, }; @@ -4068,27 +4068,27 @@ static struct video_device vdev_template = { static void vino_module_cleanup(int stage) { switch(stage) { - case 10: + case 11: video_unregister_device(vino_drvdata->b.vdev); vino_drvdata->b.vdev = NULL; - case 9: + case 10: video_unregister_device(vino_drvdata->a.vdev); vino_drvdata->a.vdev = NULL; - case 8: + case 9: vino_i2c_del_bus(); - case 7: + case 8: free_irq(SGI_VINO_IRQ, NULL); - case 6: + case 7: if (vino_drvdata->b.vdev) { video_device_release(vino_drvdata->b.vdev); vino_drvdata->b.vdev = NULL; } - case 5: + case 6: if (vino_drvdata->a.vdev) { video_device_release(vino_drvdata->a.vdev); vino_drvdata->a.vdev = NULL; } - case 4: + case 5: /* all entries in dma_cpu dummy table have the same address */ dma_unmap_single(NULL, vino_drvdata->dummy_desc_table.dma_cpu[0], @@ -4098,8 +4098,10 @@ static void vino_module_cleanup(int stage) (void *)vino_drvdata-> dummy_desc_table.dma_cpu, vino_drvdata->dummy_desc_table.dma); - case 3: + case 4: free_page(vino_drvdata->dummy_page); + case 3: + v4l2_device_unregister(&vino_drvdata->v4l2_dev); case 2: kfree(vino_drvdata); case 1: @@ -4154,6 +4156,7 @@ static int vino_probe(void) static int vino_init(void) { dma_addr_t dma_dummy_address; + int err; int i; vino_drvdata = kzalloc(sizeof(struct vino_settings), GFP_KERNEL); @@ -4162,6 +4165,12 @@ static int vino_init(void) return -ENOMEM; } vino_init_stage++; + strlcpy(vino_drvdata->v4l2_dev.name, "vino", + sizeof(vino_drvdata->v4l2_dev.name)); + err = v4l2_device_register(NULL, &vino_drvdata->v4l2_dev); + if (err) + return err; + vino_init_stage++; /* create a dummy dma descriptor */ vino_drvdata->dummy_page = get_zeroed_page(GFP_KERNEL | GFP_DMA); @@ -4239,6 +4248,7 @@ static int vino_init_channel_settings(struct vino_channel_settings *vcs, sizeof(struct video_device)); strcpy(vcs->vdev->name, name); vcs->vdev->release = video_device_release; + vcs->vdev->v4l2_dev = &vino_drvdata->v4l2_dev; video_set_drvdata(vcs->vdev, vcs); @@ -4293,6 +4303,7 @@ static int __init vino_module_init(void) vino_module_cleanup(vino_init_stage); return ret; } + i2c_set_adapdata(&vino_i2c_adapter, &vino_drvdata->v4l2_dev); vino_init_stage++; ret = video_register_device(vino_drvdata->a.vdev, -- cgit v1.2.3 From 48f4dacb6759d6357036e2a37434bf8bade119c9 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 18 Feb 2009 19:18:26 -0300 Subject: V4L/DVB (10865): vino: convert to v4l2_subdev. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/vino.c | 207 +++++++++++++++------------------------------ 1 file changed, 67 insertions(+), 140 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/vino.c b/drivers/media/video/vino.c index 308fa419ae04..96ce68a3dd95 100644 --- a/drivers/media/video/vino.c +++ b/drivers/media/video/vino.c @@ -287,20 +287,17 @@ struct vino_channel_settings { struct video_device *vdev; }; -struct vino_client { - /* the channel which owns this client: - * VINO_NO_CHANNEL, VINO_CHANNEL_A or VINO_CHANNEL_B */ - unsigned int owner; - struct i2c_client *driver; -}; - struct vino_settings { struct v4l2_device v4l2_dev; struct vino_channel_settings a; struct vino_channel_settings b; - struct vino_client decoder; - struct vino_client camera; + /* the channel which owns this client: + * VINO_NO_CHANNEL, VINO_CHANNEL_A or VINO_CHANNEL_B */ + unsigned int decoder_owner; + struct v4l2_subdev *decoder; + unsigned int camera_owner; + struct v4l2_subdev *camera; /* a lock for vino register access */ spinlock_t vino_lock; @@ -340,6 +337,11 @@ static struct sgi_vino *vino; static struct vino_settings *vino_drvdata; +#define camera_call(o, f, args...) \ + v4l2_subdev_call(vino_drvdata->camera, o, f, ##args) +#define decoder_call(o, f, args...) \ + v4l2_subdev_call(vino_drvdata->decoder, o, f, ##args) + static const char *vino_driver_name = "vino"; static const char *vino_driver_description = "SGI VINO"; static const char *vino_bus_name = "GIO64 bus"; @@ -670,66 +672,12 @@ static struct i2c_algo_sgi_data i2c_sgi_vino_data = .ack_timeout = 1000, }; -/* - * There are two possible clients on VINO I2C bus, so we limit usage only - * to them. - */ -static int i2c_vino_client_reg(struct i2c_client *client) -{ - unsigned long flags; - int ret = 0; - - spin_lock_irqsave(&vino_drvdata->input_lock, flags); - switch (client->driver->id) { - case I2C_DRIVERID_SAA7191: - if (vino_drvdata->decoder.driver) - ret = -EBUSY; - else - vino_drvdata->decoder.driver = client; - break; - case I2C_DRIVERID_INDYCAM: - if (vino_drvdata->camera.driver) - ret = -EBUSY; - else - vino_drvdata->camera.driver = client; - break; - default: - ret = -ENODEV; - } - spin_unlock_irqrestore(&vino_drvdata->input_lock, flags); - - return ret; -} - -static int i2c_vino_client_unreg(struct i2c_client *client) -{ - unsigned long flags; - int ret = 0; - - spin_lock_irqsave(&vino_drvdata->input_lock, flags); - if (client == vino_drvdata->decoder.driver) { - if (vino_drvdata->decoder.owner != VINO_NO_CHANNEL) - ret = -EBUSY; - else - vino_drvdata->decoder.driver = NULL; - } else if (client == vino_drvdata->camera.driver) { - if (vino_drvdata->camera.owner != VINO_NO_CHANNEL) - ret = -EBUSY; - else - vino_drvdata->camera.driver = NULL; - } - spin_unlock_irqrestore(&vino_drvdata->input_lock, flags); - - return ret; -} - static struct i2c_adapter vino_i2c_adapter = { .name = "VINO I2C bus", .id = I2C_HW_SGI_VINO, .algo_data = &i2c_sgi_vino_data, - .client_register = &i2c_vino_client_reg, - .client_unregister = &i2c_vino_client_unreg, + .owner = THIS_MODULE, }; static int vino_i2c_add_bus(void) @@ -742,20 +690,6 @@ static int vino_i2c_del_bus(void) return i2c_del_adapter(&vino_i2c_adapter); } -static int i2c_camera_command(unsigned int cmd, void *arg) -{ - return vino_drvdata->camera.driver-> - driver->command(vino_drvdata->camera.driver, - cmd, arg); -} - -static int i2c_decoder_command(unsigned int cmd, void *arg) -{ - return vino_drvdata->decoder.driver-> - driver->command(vino_drvdata->decoder.driver, - cmd, arg); -} - /* VINO framebuffer/DMA descriptor management */ static void vino_free_buffer_with_count(struct vino_framebuffer *fb, @@ -2456,9 +2390,9 @@ static int vino_is_input_owner(struct vino_channel_settings *vcs) switch(vcs->input) { case VINO_INPUT_COMPOSITE: case VINO_INPUT_SVIDEO: - return (vino_drvdata->decoder.owner == vcs->channel); + return vino_drvdata->decoder_owner == vcs->channel; case VINO_INPUT_D1: - return (vino_drvdata->camera.owner == vcs->channel); + return vino_drvdata->camera_owner == vcs->channel; default: return 0; } @@ -2474,24 +2408,22 @@ static int vino_acquire_input(struct vino_channel_settings *vcs) spin_lock_irqsave(&vino_drvdata->input_lock, flags); /* First try D1 and then SAA7191 */ - if (vino_drvdata->camera.driver - && (vino_drvdata->camera.owner == VINO_NO_CHANNEL)) { - i2c_use_client(vino_drvdata->camera.driver); - vino_drvdata->camera.owner = vcs->channel; + if (vino_drvdata->camera + && (vino_drvdata->camera_owner == VINO_NO_CHANNEL)) { + vino_drvdata->camera_owner = vcs->channel; vcs->input = VINO_INPUT_D1; vcs->data_norm = VINO_DATA_NORM_D1; - } else if (vino_drvdata->decoder.driver - && (vino_drvdata->decoder.owner == VINO_NO_CHANNEL)) { + } else if (vino_drvdata->decoder + && (vino_drvdata->decoder_owner == VINO_NO_CHANNEL)) { int input; int data_norm; v4l2_std_id norm; struct v4l2_routing route = { 0, 0 }; - i2c_use_client(vino_drvdata->decoder.driver); input = VINO_INPUT_COMPOSITE; route.input = vino_get_saa7191_input(input); - ret = i2c_decoder_command(VIDIOC_INT_S_VIDEO_ROUTING, &route); + ret = decoder_call(video, s_routing, &route); if (ret) { ret = -EINVAL; goto out; @@ -2502,7 +2434,7 @@ static int vino_acquire_input(struct vino_channel_settings *vcs) /* Don't hold spinlocks while auto-detecting norm * as it may take a while... */ - ret = i2c_decoder_command(VIDIOC_QUERYSTD, &norm); + ret = decoder_call(video, querystd, &norm); if (!ret) { for (data_norm = 0; data_norm < 3; data_norm++) { if (vino_data_norms[data_norm].std & norm) @@ -2510,7 +2442,7 @@ static int vino_acquire_input(struct vino_channel_settings *vcs) } if (data_norm == 3) data_norm = VINO_DATA_NORM_PAL; - ret = i2c_decoder_command(VIDIOC_S_STD, &norm); + ret = decoder_call(tuner, s_std, norm); } spin_lock_irqsave(&vino_drvdata->input_lock, flags); @@ -2520,7 +2452,7 @@ static int vino_acquire_input(struct vino_channel_settings *vcs) goto out; } - vino_drvdata->decoder.owner = vcs->channel; + vino_drvdata->decoder_owner = vcs->channel; vcs->input = input; vcs->data_norm = data_norm; @@ -2565,25 +2497,24 @@ static int vino_set_input(struct vino_channel_settings *vcs, int input) switch (input) { case VINO_INPUT_COMPOSITE: case VINO_INPUT_SVIDEO: - if (!vino_drvdata->decoder.driver) { + if (!vino_drvdata->decoder) { ret = -EINVAL; goto out; } - if (vino_drvdata->decoder.owner == VINO_NO_CHANNEL) { - i2c_use_client(vino_drvdata->decoder.driver); - vino_drvdata->decoder.owner = vcs->channel; + if (vino_drvdata->decoder_owner == VINO_NO_CHANNEL) { + vino_drvdata->decoder_owner = vcs->channel; } - if (vino_drvdata->decoder.owner == vcs->channel) { + if (vino_drvdata->decoder_owner == vcs->channel) { int data_norm; v4l2_std_id norm; struct v4l2_routing route = { 0, 0 }; route.input = vino_get_saa7191_input(input); - ret = i2c_decoder_command(VIDIOC_INT_S_VIDEO_ROUTING, &route); + ret = decoder_call(video, s_routing, &route); if (ret) { - vino_drvdata->decoder.owner = VINO_NO_CHANNEL; + vino_drvdata->decoder_owner = VINO_NO_CHANNEL; ret = -EINVAL; goto out; } @@ -2593,7 +2524,7 @@ static int vino_set_input(struct vino_channel_settings *vcs, int input) /* Don't hold spinlocks while auto-detecting norm * as it may take a while... */ - ret = i2c_decoder_command(VIDIOC_QUERYSTD, &norm); + ret = decoder_call(video, querystd, &norm); if (!ret) { for (data_norm = 0; data_norm < 3; data_norm++) { if (vino_data_norms[data_norm].std & norm) @@ -2601,13 +2532,13 @@ static int vino_set_input(struct vino_channel_settings *vcs, int input) } if (data_norm == 3) data_norm = VINO_DATA_NORM_PAL; - ret = i2c_decoder_command(VIDIOC_S_STD, &norm); + ret = decoder_call(tuner, s_std, norm); } spin_lock_irqsave(&vino_drvdata->input_lock, flags); if (ret) { - vino_drvdata->decoder.owner = VINO_NO_CHANNEL; + vino_drvdata->decoder_owner = VINO_NO_CHANNEL; ret = -EINVAL; goto out; } @@ -2624,36 +2555,31 @@ static int vino_set_input(struct vino_channel_settings *vcs, int input) vcs->data_norm = vcs2->data_norm; } - if (vino_drvdata->camera.owner == vcs->channel) { + if (vino_drvdata->camera_owner == vcs->channel) { /* Transfer the ownership or release the input */ if (vcs2->input == VINO_INPUT_D1) { - vino_drvdata->camera.owner = vcs2->channel; + vino_drvdata->camera_owner = vcs2->channel; } else { - i2c_release_client(vino_drvdata->camera.driver); - vino_drvdata->camera.owner = VINO_NO_CHANNEL; + vino_drvdata->camera_owner = VINO_NO_CHANNEL; } } break; case VINO_INPUT_D1: - if (!vino_drvdata->camera.driver) { + if (!vino_drvdata->camera) { ret = -EINVAL; goto out; } - if (vino_drvdata->camera.owner == VINO_NO_CHANNEL) { - i2c_use_client(vino_drvdata->camera.driver); - vino_drvdata->camera.owner = vcs->channel; - } + if (vino_drvdata->camera_owner == VINO_NO_CHANNEL) + vino_drvdata->camera_owner = vcs->channel; - if (vino_drvdata->decoder.owner == vcs->channel) { + if (vino_drvdata->decoder_owner == vcs->channel) { /* Transfer the ownership or release the input */ if ((vcs2->input == VINO_INPUT_COMPOSITE) || (vcs2->input == VINO_INPUT_SVIDEO)) { - vino_drvdata->decoder.owner = vcs2->channel; + vino_drvdata->decoder_owner = vcs2->channel; } else { - i2c_release_client(vino_drvdata-> - decoder.driver); - vino_drvdata->decoder.owner = VINO_NO_CHANNEL; + vino_drvdata->decoder_owner = VINO_NO_CHANNEL; } } @@ -2690,20 +2616,18 @@ static void vino_release_input(struct vino_channel_settings *vcs) /* Release ownership of the channel * and if the other channel takes input from * the same source, transfer the ownership */ - if (vino_drvdata->camera.owner == vcs->channel) { + if (vino_drvdata->camera_owner == vcs->channel) { if (vcs2->input == VINO_INPUT_D1) { - vino_drvdata->camera.owner = vcs2->channel; + vino_drvdata->camera_owner = vcs2->channel; } else { - i2c_release_client(vino_drvdata->camera.driver); - vino_drvdata->camera.owner = VINO_NO_CHANNEL; + vino_drvdata->camera_owner = VINO_NO_CHANNEL; } - } else if (vino_drvdata->decoder.owner == vcs->channel) { + } else if (vino_drvdata->decoder_owner == vcs->channel) { if ((vcs2->input == VINO_INPUT_COMPOSITE) || (vcs2->input == VINO_INPUT_SVIDEO)) { - vino_drvdata->decoder.owner = vcs2->channel; + vino_drvdata->decoder_owner = vcs2->channel; } else { - i2c_release_client(vino_drvdata->decoder.driver); - vino_drvdata->decoder.owner = VINO_NO_CHANNEL; + vino_drvdata->decoder_owner = VINO_NO_CHANNEL; } } vcs->input = VINO_INPUT_NONE; @@ -2742,7 +2666,7 @@ static int vino_set_data_norm(struct vino_channel_settings *vcs, * as it may take a while... */ norm = vino_data_norms[data_norm].std; - err = i2c_decoder_command(VIDIOC_S_STD, &norm); + err = decoder_call(tuner, s_std, norm); spin_lock_irqsave(&vino_drvdata->input_lock, *flags); @@ -2784,7 +2708,7 @@ static int vino_int_enum_input(struct vino_channel_settings *vcs, __u32 index) unsigned long flags; spin_lock_irqsave(&vino_drvdata->input_lock, flags); - if (vino_drvdata->decoder.driver && vino_drvdata->camera.driver) { + if (vino_drvdata->decoder && vino_drvdata->camera) { switch (index) { case 0: input = VINO_INPUT_COMPOSITE; @@ -2796,7 +2720,7 @@ static int vino_int_enum_input(struct vino_channel_settings *vcs, __u32 index) input = VINO_INPUT_D1; break; } - } else if (vino_drvdata->decoder.driver) { + } else if (vino_drvdata->decoder) { switch (index) { case 0: input = VINO_INPUT_COMPOSITE; @@ -2805,7 +2729,7 @@ static int vino_int_enum_input(struct vino_channel_settings *vcs, __u32 index) input = VINO_INPUT_SVIDEO; break; } - } else if (vino_drvdata->camera.driver) { + } else if (vino_drvdata->camera) { switch (index) { case 0: input = VINO_INPUT_D1; @@ -2823,7 +2747,7 @@ static __u32 vino_find_input_index(struct vino_channel_settings *vcs) __u32 index = 0; // FIXME: detect when no inputs available - if (vino_drvdata->decoder.driver && vino_drvdata->camera.driver) { + if (vino_drvdata->decoder && vino_drvdata->camera) { switch (vcs->input) { case VINO_INPUT_COMPOSITE: index = 0; @@ -2835,7 +2759,7 @@ static __u32 vino_find_input_index(struct vino_channel_settings *vcs) index = 2; break; } - } else if (vino_drvdata->decoder.driver) { + } else if (vino_drvdata->decoder) { switch (vcs->input) { case VINO_INPUT_COMPOSITE: index = 0; @@ -2844,7 +2768,7 @@ static __u32 vino_find_input_index(struct vino_channel_settings *vcs) index = 1; break; } - } else if (vino_drvdata->camera.driver) { + } else if (vino_drvdata->camera) { switch (vcs->input) { case VINO_INPUT_D1: index = 0; @@ -2893,7 +2817,7 @@ static int vino_enum_input(struct file *file, void *__fh, strcpy(i->name, vino_inputs[input].name); if (input == VINO_INPUT_COMPOSITE || input == VINO_INPUT_SVIDEO) - i2c_decoder_command(VIDIOC_INT_G_INPUT_STATUS, &i->status); + decoder_call(video, g_input_status, &i->status); return 0; } @@ -2950,7 +2874,7 @@ static int vino_querystd(struct file *file, void *__fh, break; case VINO_INPUT_COMPOSITE: case VINO_INPUT_SVIDEO: { - i2c_decoder_command(VIDIOC_QUERYSTD, std); + decoder_call(video, querystd, std); break; } default: @@ -3679,7 +3603,7 @@ static int vino_g_ctrl(struct file *file, void *__fh, if (err) goto out; - err = i2c_camera_command(VIDIOC_G_CTRL, &control); + err = camera_call(core, g_ctrl, control); if (err) err = -EINVAL; break; @@ -3697,7 +3621,7 @@ static int vino_g_ctrl(struct file *file, void *__fh, if (err) goto out; - err = i2c_decoder_command(VIDIOC_G_CTRL, &control); + err = decoder_call(core, g_ctrl, control); if (err) err = -EINVAL; break; @@ -3743,7 +3667,7 @@ static int vino_s_ctrl(struct file *file, void *__fh, err = -ERANGE; goto out; } - err = i2c_camera_command(VIDIOC_S_CTRL, &control); + err = camera_call(core, s_ctrl, control); if (err) err = -EINVAL; break; @@ -3765,7 +3689,7 @@ static int vino_s_ctrl(struct file *file, void *__fh, goto out; } - err = i2c_decoder_command(VIDIOC_S_CTRL, &control); + err = decoder_call(core, s_ctrl, control); if (err) err = -EINVAL; break; @@ -4257,6 +4181,7 @@ static int vino_init_channel_settings(struct vino_channel_settings *vcs, static int __init vino_module_init(void) { + unsigned short addr[] = { 0, I2C_CLIENT_END }; int ret; printk(KERN_INFO "SGI VINO driver version %s\n", @@ -4326,10 +4251,12 @@ static int __init vino_module_init(void) } vino_init_stage++; -#ifdef MODULE - request_module("saa7191"); - request_module("indycam"); -#endif + addr[0] = 0x45; + vino_drvdata->decoder = v4l2_i2c_new_probed_subdev(&vino_i2c_adapter, + "saa7191", "saa7191", addr); + addr[0] = 0x2b; + vino_drvdata->camera = v4l2_i2c_new_probed_subdev(&vino_i2c_adapter, + "indycam", "indycam", addr); dprintk("init complete!\n"); -- cgit v1.2.3 From a0720d3b7b80163150fde73aa43ba8fcd417b9cb Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 18 Feb 2009 19:23:43 -0300 Subject: V4L/DVB (10866): saa7191, indycam: remove compat code. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/indycam.c | 18 +----------------- drivers/media/video/saa7191.c | 18 +----------------- 2 files changed, 2 insertions(+), 34 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/indycam.c b/drivers/media/video/indycam.c index eb5078c07a33..3d6940163b12 100644 --- a/drivers/media/video/indycam.c +++ b/drivers/media/video/indycam.c @@ -24,7 +24,7 @@ #include #include #include -#include +#include #include "indycam.h" @@ -35,9 +35,6 @@ MODULE_VERSION(INDYCAM_MODULE_VERSION); MODULE_AUTHOR("Mikael Nousiainen "); MODULE_LICENSE("GPL"); -static unsigned short normal_i2c[] = { 0x56 >> 1, I2C_CLIENT_END }; - -I2C_CLIENT_INSMOD; // #define INDYCAM_DEBUG @@ -297,11 +294,6 @@ static int indycam_g_chip_ident(struct v4l2_subdev *sd, camera->version); } -static int indycam_command(struct i2c_client *client, unsigned cmd, void *arg) -{ - return v4l2_subdev_command(i2c_get_clientdata(client), cmd, arg); -} - /* ----------------------------------------------------------------------- */ static const struct v4l2_subdev_core_ops indycam_core_ops = { @@ -380,11 +372,6 @@ static int indycam_remove(struct i2c_client *client) return 0; } -static int indycam_legacy_probe(struct i2c_adapter *adapter) -{ - return adapter->id == I2C_HW_SGI_VINO; -} - static const struct i2c_device_id indycam_id[] = { { "indycam", 0 }, { } @@ -393,10 +380,7 @@ MODULE_DEVICE_TABLE(i2c, indycam_id); static struct v4l2_i2c_driver_data v4l2_i2c_data = { .name = "indycam", - .driverid = I2C_DRIVERID_INDYCAM, - .command = indycam_command, .probe = indycam_probe, .remove = indycam_remove, - .legacy_probe = indycam_legacy_probe, .id_table = indycam_id, }; diff --git a/drivers/media/video/saa7191.c b/drivers/media/video/saa7191.c index 40ae2787326f..2e6fce5b51fd 100644 --- a/drivers/media/video/saa7191.c +++ b/drivers/media/video/saa7191.c @@ -23,7 +23,7 @@ #include #include #include -#include +#include #include "saa7191.h" @@ -34,9 +34,6 @@ MODULE_VERSION(SAA7191_MODULE_VERSION); MODULE_AUTHOR("Mikael Nousiainen "); MODULE_LICENSE("GPL"); -static unsigned short normal_i2c[] = { 0x8a >> 1, 0x8e >> 1, I2C_CLIENT_END }; - -I2C_CLIENT_INSMOD; // #define SAA7191_DEBUG @@ -579,11 +576,6 @@ static int saa7191_g_chip_ident(struct v4l2_subdev *sd, return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_SAA7191, 0); } -static int saa7191_command(struct i2c_client *client, unsigned cmd, void *arg) -{ - return v4l2_subdev_command(i2c_get_clientdata(client), cmd, arg); -} - /* ----------------------------------------------------------------------- */ static const struct v4l2_subdev_core_ops saa7191_core_ops = { @@ -652,11 +644,6 @@ static int saa7191_remove(struct i2c_client *client) return 0; } -static int saa7191_legacy_probe(struct i2c_adapter *adapter) -{ - return adapter->id == I2C_HW_SGI_VINO; -} - static const struct i2c_device_id saa7191_id[] = { { "saa7191", 0 }, { } @@ -665,10 +652,7 @@ MODULE_DEVICE_TABLE(i2c, saa7191_id); static struct v4l2_i2c_driver_data v4l2_i2c_data = { .name = "saa7191", - .driverid = I2C_DRIVERID_SAA7191, - .command = saa7191_command, .probe = saa7191_probe, .remove = saa7191_remove, - .legacy_probe = saa7191_legacy_probe, .id_table = saa7191_id, }; -- cgit v1.2.3 From cea0c681bef872d0618d87be078cb006665a6fdf Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Fri, 6 Mar 2009 12:05:43 -0300 Subject: V4L/DVB (10867): vino: fold i2c-algo-sgi code into vino. Signed-off-by: Jean Delvare Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/Kconfig | 1 - drivers/media/video/vino.c | 247 ++++++++++++++++++++++++++++++++++---------- 2 files changed, 194 insertions(+), 54 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig index 6c26618b8869..534a022c4d1b 100644 --- a/drivers/media/video/Kconfig +++ b/drivers/media/video/Kconfig @@ -582,7 +582,6 @@ config VIDEO_SAA5249 config VIDEO_VINO tristate "SGI Vino Video For Linux (EXPERIMENTAL)" depends on I2C && SGI_IP22 && EXPERIMENTAL && VIDEO_V4L2 - select I2C_ALGO_SGI select VIDEO_SAA7191 if VIDEO_HELPER_CHIPS_AUTO help Say Y here to build in support for the Vino video input system found diff --git a/drivers/media/video/vino.c b/drivers/media/video/vino.c index 96ce68a3dd95..b62e030ba83a 100644 --- a/drivers/media/video/vino.c +++ b/drivers/media/video/vino.c @@ -33,7 +33,6 @@ #include #include -#include #include #include @@ -141,6 +140,20 @@ MODULE_LICENSE("GPL"); #define VINO_DATA_NORM_COUNT 4 +/* I2C controller flags */ +#define SGI_I2C_FORCE_IDLE (0 << 0) +#define SGI_I2C_NOT_IDLE (1 << 0) +#define SGI_I2C_WRITE (0 << 1) +#define SGI_I2C_READ (1 << 1) +#define SGI_I2C_RELEASE_BUS (0 << 2) +#define SGI_I2C_HOLD_BUS (1 << 2) +#define SGI_I2C_XFER_DONE (0 << 4) +#define SGI_I2C_XFER_BUSY (1 << 4) +#define SGI_I2C_ACK (0 << 5) +#define SGI_I2C_NACK (1 << 5) +#define SGI_I2C_BUS_OK (0 << 7) +#define SGI_I2C_BUS_ERR (1 << 7) + /* Internal data structure definitions */ struct vino_input { @@ -640,56 +653,6 @@ struct v4l2_queryctrl vino_saa7191_v4l2_controls[] = { } }; -/* VINO I2C bus functions */ - -unsigned i2c_vino_getctrl(void *data) -{ - return vino->i2c_control; -} - -void i2c_vino_setctrl(void *data, unsigned val) -{ - vino->i2c_control = val; -} - -unsigned i2c_vino_rdata(void *data) -{ - return vino->i2c_data; -} - -void i2c_vino_wdata(void *data, unsigned val) -{ - vino->i2c_data = val; -} - -static struct i2c_algo_sgi_data i2c_sgi_vino_data = -{ - .getctrl = &i2c_vino_getctrl, - .setctrl = &i2c_vino_setctrl, - .rdata = &i2c_vino_rdata, - .wdata = &i2c_vino_wdata, - .xfer_timeout = 200, - .ack_timeout = 1000, -}; - -static struct i2c_adapter vino_i2c_adapter = -{ - .name = "VINO I2C bus", - .id = I2C_HW_SGI_VINO, - .algo_data = &i2c_sgi_vino_data, - .owner = THIS_MODULE, -}; - -static int vino_i2c_add_bus(void) -{ - return i2c_sgi_add_bus(&vino_i2c_adapter); -} - -static int vino_i2c_del_bus(void) -{ - return i2c_del_adapter(&vino_i2c_adapter); -} - /* VINO framebuffer/DMA descriptor management */ static void vino_free_buffer_with_count(struct vino_framebuffer *fb, @@ -1635,6 +1598,184 @@ static inline void vino_set_default_framerate(struct vino_set_framerate(vcs, vino_data_norms[vcs->data_norm].fps_max); } +/* VINO I2C bus functions */ + +struct i2c_algo_sgi_data { + void *data; /* private data for lowlevel routines */ + unsigned (*getctrl)(void *data); + void (*setctrl)(void *data, unsigned val); + unsigned (*rdata)(void *data); + void (*wdata)(void *data, unsigned val); + + int xfer_timeout; + int ack_timeout; +}; + +static int wait_xfer_done(struct i2c_algo_sgi_data *adap) +{ + int i; + + for (i = 0; i < adap->xfer_timeout; i++) { + if ((adap->getctrl(adap->data) & SGI_I2C_XFER_BUSY) == 0) + return 0; + udelay(1); + } + + return -ETIMEDOUT; +} + +static int wait_ack(struct i2c_algo_sgi_data *adap) +{ + int i; + + if (wait_xfer_done(adap)) + return -ETIMEDOUT; + for (i = 0; i < adap->ack_timeout; i++) { + if ((adap->getctrl(adap->data) & SGI_I2C_NACK) == 0) + return 0; + udelay(1); + } + + return -ETIMEDOUT; +} + +static int force_idle(struct i2c_algo_sgi_data *adap) +{ + int i; + + adap->setctrl(adap->data, SGI_I2C_FORCE_IDLE); + for (i = 0; i < adap->xfer_timeout; i++) { + if ((adap->getctrl(adap->data) & SGI_I2C_NOT_IDLE) == 0) + goto out; + udelay(1); + } + return -ETIMEDOUT; +out: + if (adap->getctrl(adap->data) & SGI_I2C_BUS_ERR) + return -EIO; + return 0; +} + +static int do_address(struct i2c_algo_sgi_data *adap, unsigned int addr, + int rd) +{ + if (rd) + adap->setctrl(adap->data, SGI_I2C_NOT_IDLE); + /* Check if bus is idle, eventually force it to do so */ + if (adap->getctrl(adap->data) & SGI_I2C_NOT_IDLE) + if (force_idle(adap)) + return -EIO; + /* Write out the i2c chip address and specify operation */ + adap->setctrl(adap->data, + SGI_I2C_HOLD_BUS | SGI_I2C_WRITE | SGI_I2C_NOT_IDLE); + if (rd) + addr |= 1; + adap->wdata(adap->data, addr); + if (wait_ack(adap)) + return -EIO; + return 0; +} + +static int i2c_read(struct i2c_algo_sgi_data *adap, unsigned char *buf, + unsigned int len) +{ + int i; + + adap->setctrl(adap->data, + SGI_I2C_HOLD_BUS | SGI_I2C_READ | SGI_I2C_NOT_IDLE); + for (i = 0; i < len; i++) { + if (wait_xfer_done(adap)) + return -EIO; + buf[i] = adap->rdata(adap->data); + } + adap->setctrl(adap->data, SGI_I2C_RELEASE_BUS | SGI_I2C_FORCE_IDLE); + + return 0; + +} + +static int i2c_write(struct i2c_algo_sgi_data *adap, unsigned char *buf, + unsigned int len) +{ + int i; + + /* We are already in write state */ + for (i = 0; i < len; i++) { + adap->wdata(adap->data, buf[i]); + if (wait_ack(adap)) + return -EIO; + } + return 0; +} + +static int sgi_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg *msgs, + int num) +{ + struct i2c_algo_sgi_data *adap = i2c_adap->algo_data; + struct i2c_msg *p; + int i, err = 0; + + for (i = 0; !err && i < num; i++) { + p = &msgs[i]; + err = do_address(adap, p->addr, p->flags & I2C_M_RD); + if (err || !p->len) + continue; + if (p->flags & I2C_M_RD) + err = i2c_read(adap, p->buf, p->len); + else + err = i2c_write(adap, p->buf, p->len); + } + + return (err < 0) ? err : i; +} + +static u32 sgi_func(struct i2c_adapter *adap) +{ + return I2C_FUNC_SMBUS_EMUL; +} + +static const struct i2c_algorithm sgi_algo = { + .master_xfer = sgi_xfer, + .functionality = sgi_func, +}; + +static unsigned i2c_vino_getctrl(void *data) +{ + return vino->i2c_control; +} + +static void i2c_vino_setctrl(void *data, unsigned val) +{ + vino->i2c_control = val; +} + +static unsigned i2c_vino_rdata(void *data) +{ + return vino->i2c_data; +} + +static void i2c_vino_wdata(void *data, unsigned val) +{ + vino->i2c_data = val; +} + +static struct i2c_algo_sgi_data i2c_sgi_vino_data = { + .getctrl = &i2c_vino_getctrl, + .setctrl = &i2c_vino_setctrl, + .rdata = &i2c_vino_rdata, + .wdata = &i2c_vino_wdata, + .xfer_timeout = 200, + .ack_timeout = 1000, +}; + +static struct i2c_adapter vino_i2c_adapter = { + .name = "VINO I2C bus", + .id = I2C_HW_SGI_VINO, + .algo = &sgi_algo, + .algo_data = &i2c_sgi_vino_data, + .owner = THIS_MODULE, +}; + /* * Prepare VINO for DMA transfer... * (execute only with vino_lock and input_lock locked) @@ -3999,7 +4140,7 @@ static void vino_module_cleanup(int stage) video_unregister_device(vino_drvdata->a.vdev); vino_drvdata->a.vdev = NULL; case 9: - vino_i2c_del_bus(); + i2c_del_adapter(&vino_i2c_adapter); case 8: free_irq(SGI_VINO_IRQ, NULL); case 7: @@ -4222,7 +4363,7 @@ static int __init vino_module_init(void) } vino_init_stage++; - ret = vino_i2c_add_bus(); + ret = i2c_add_adapter(&vino_i2c_adapter); if (ret) { printk(KERN_ERR "VINO I2C bus registration failed\n"); vino_module_cleanup(vino_init_stage); -- cgit v1.2.3 From a99e30d70bcb83bdd097945df282199ead9c9a4b Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 6 Mar 2009 12:15:08 -0300 Subject: V4L/DVB (10868): vino: add note that this conversion is untested. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/vino.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers/media/video') diff --git a/drivers/media/video/vino.c b/drivers/media/video/vino.c index b62e030ba83a..675067f92d96 100644 --- a/drivers/media/video/vino.c +++ b/drivers/media/video/vino.c @@ -8,6 +8,12 @@ * * Based on the previous version of the driver for 2.4 kernels by: * Copyright (C) 2003 Ladislav Michl + * + * v4l2_device/v4l2_subdev conversion by: + * Copyright (C) 2009 Hans Verkuil + * + * Note: this conversion is untested! Please contact the linux-media + * mailinglist if you can test this, together with the test results. */ /* -- cgit v1.2.3 From bd894b590ef45297c941b7af0e8de13a2fd306d6 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 9 Mar 2009 22:16:42 -0300 Subject: V4L/DVB (10870): v4l2-ioctl: get rid of video_decoder.h The V4L1 obsoleted header video_decoder.h is not used anymore by any driver. Only a name decoding function at v4l2-ioctl still implements it. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/v4l2-ioctl.c | 14 -------------- 1 file changed, 14 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/v4l2-ioctl.c b/drivers/media/video/v4l2-ioctl.c index efbc47004657..6a7955547474 100644 --- a/drivers/media/video/v4l2-ioctl.c +++ b/drivers/media/video/v4l2-ioctl.c @@ -25,7 +25,6 @@ #include #include #include -#include #define dbgarg(cmd, fmt, arg...) \ do { \ @@ -276,19 +275,6 @@ static const char *v4l2_ioctls[] = { #define V4L2_IOCTLS ARRAY_SIZE(v4l2_ioctls) static const char *v4l2_int_ioctls[] = { -#ifdef CONFIG_VIDEO_V4L1_COMPAT - [_IOC_NR(DECODER_GET_CAPABILITIES)] = "DECODER_GET_CAPABILITIES", - [_IOC_NR(DECODER_GET_STATUS)] = "DECODER_GET_STATUS", - [_IOC_NR(DECODER_SET_NORM)] = "DECODER_SET_NORM", - [_IOC_NR(DECODER_SET_INPUT)] = "DECODER_SET_INPUT", - [_IOC_NR(DECODER_SET_OUTPUT)] = "DECODER_SET_OUTPUT", - [_IOC_NR(DECODER_ENABLE_OUTPUT)] = "DECODER_ENABLE_OUTPUT", - [_IOC_NR(DECODER_SET_PICTURE)] = "DECODER_SET_PICTURE", - [_IOC_NR(DECODER_SET_GPIO)] = "DECODER_SET_GPIO", - [_IOC_NR(DECODER_INIT)] = "DECODER_INIT", - [_IOC_NR(DECODER_SET_VBI_BYPASS)] = "DECODER_SET_VBI_BYPASS", - [_IOC_NR(DECODER_DUMP)] = "DECODER_DUMP", -#endif [_IOC_NR(AUDC_SET_RADIO)] = "AUDC_SET_RADIO", [_IOC_NR(TUNER_SET_TYPE_ADDR)] = "TUNER_SET_TYPE_ADDR", -- cgit v1.2.3 From 4e06839fc7221872d7868855c05659f08d1c9f3d Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sun, 8 Mar 2009 06:56:19 -0300 Subject: V4L/DVB (10873): w9968cf: add v4l2_device. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/w9968cf.c | 20 +++++++++++++------- drivers/media/video/w9968cf.h | 16 ++++++++-------- 2 files changed, 21 insertions(+), 15 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/w9968cf.c b/drivers/media/video/w9968cf.c index 105a832531f2..3318be5688c9 100644 --- a/drivers/media/video/w9968cf.c +++ b/drivers/media/video/w9968cf.c @@ -3495,12 +3495,14 @@ w9968cf_usb_probe(struct usb_interface* intf, const struct usb_device_id* id) if (!cam) return -ENOMEM; + err = v4l2_device_register(&udev->dev, &cam->v4l2_dev); + if (err) + goto fail0; + mutex_init(&cam->dev_mutex); mutex_lock(&cam->dev_mutex); cam->usbdev = udev; - /* NOTE: a local copy is used to avoid possible race conditions */ - memcpy(&cam->dev, &udev->dev, sizeof(struct device)); DBG(2, "%s detected", symbolic(camlist, mod_id)) @@ -3549,7 +3551,7 @@ w9968cf_usb_probe(struct usb_interface* intf, const struct usb_device_id* id) cam->v4ldev->minor = video_nr[dev_nr]; cam->v4ldev->release = video_device_release; video_set_drvdata(cam->v4ldev, cam); - cam->v4ldev->parent = &cam->dev; + cam->v4ldev->v4l2_dev = &cam->v4l2_dev; err = video_register_device(cam->v4ldev, VFL_TYPE_GRABBER, video_nr[dev_nr]); @@ -3579,6 +3581,9 @@ w9968cf_usb_probe(struct usb_interface* intf, const struct usb_device_id* id) usb_set_intfdata(intf, cam); mutex_unlock(&cam->dev_mutex); + + if (ovmod_load) + request_module("ovcamchip"); return 0; fail: /* Free unused memory */ @@ -3587,6 +3592,8 @@ fail: /* Free unused memory */ if (cam->v4ldev) video_device_release(cam->v4ldev); mutex_unlock(&cam->dev_mutex); + v4l2_device_unregister(&cam->v4l2_dev); +fail0: kfree(cam); return err; } @@ -3622,8 +3629,10 @@ static void w9968cf_usb_disconnect(struct usb_interface* intf) mutex_unlock(&cam->dev_mutex); - if (!cam->users) + if (!cam->users) { + v4l2_device_unregister(&cam->v4l2_dev); kfree(cam); + } } up_write(&w9968cf_disconnect); @@ -3650,9 +3659,6 @@ static int __init w9968cf_module_init(void) KDBG(2, W9968CF_MODULE_NAME" "W9968CF_MODULE_VERSION) KDBG(3, W9968CF_MODULE_AUTHOR) - if (ovmod_load) - request_module("ovcamchip"); - if ((err = usb_register(&w9968cf_usb_driver))) return err; diff --git a/drivers/media/video/w9968cf.h b/drivers/media/video/w9968cf.h index 30032e15e23c..c59883552545 100644 --- a/drivers/media/video/w9968cf.h +++ b/drivers/media/video/w9968cf.h @@ -33,6 +33,7 @@ #include #include +#include #include #include "w9968cf_vpp.h" @@ -195,10 +196,9 @@ enum w9968cf_vpp_flag { /* Main device driver structure */ struct w9968cf_device { - struct device dev; /* device structure */ - enum w9968cf_model_id id; /* private device identifier */ + struct v4l2_device v4l2_dev; struct video_device* v4ldev; /* -> V4L structure */ struct list_head v4llist; /* entry of the list of V4L cameras */ @@ -291,14 +291,14 @@ struct w9968cf_device { if ( ((specific_debug) && (debug == (level))) || \ ((!specific_debug) && (debug >= (level))) ) { \ if ((level) == 1) \ - dev_err(&cam->dev, fmt "\n", ## args); \ + v4l2_err(&cam->v4l2_dev, fmt "\n", ## args); \ else if ((level) == 2 || (level) == 3) \ - dev_info(&cam->dev, fmt "\n", ## args); \ + v4l2_info(&cam->v4l2_dev, fmt "\n", ## args); \ else if ((level) == 4) \ - dev_warn(&cam->dev, fmt "\n", ## args); \ + v4l2_warn(&cam->v4l2_dev, fmt "\n", ## args); \ else if ((level) >= 5) \ - dev_info(&cam->dev, "[%s:%d] " fmt "\n", \ - __func__, __LINE__ , ## args); \ + v4l2_info(&cam->v4l2_dev, "[%s:%d] " fmt "\n", \ + __func__, __LINE__ , ## args); \ } \ } /* For generic kernel (not device specific) messages */ @@ -321,7 +321,7 @@ struct w9968cf_device { #undef PDBG #define PDBG(fmt, args...) \ -dev_info(&cam->dev, "[%s:%d] " fmt "\n", __func__, __LINE__ , ## args); +v4l2_info(&cam->v4l2_dev, "[%s:%d] " fmt "\n", __func__, __LINE__ , ## args); #undef PDBGG #define PDBGG(fmt, args...) do {;} while(0); /* nothing: it's a placeholder */ -- cgit v1.2.3 From 3160fbc556aa2e60404fa4da35b3e13dd741a5a2 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sun, 8 Mar 2009 10:19:44 -0300 Subject: V4L/DVB (10874): w9968cf/ovcamchip: convert to v4l2_subdev. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/ovcamchip/ovcamchip_core.c | 203 +++++++++++-------------- drivers/media/video/ovcamchip/ovcamchip_priv.h | 7 + drivers/media/video/w9968cf.c | 114 ++++---------- drivers/media/video/w9968cf.h | 8 +- 4 files changed, 126 insertions(+), 206 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/ovcamchip/ovcamchip_core.c b/drivers/media/video/ovcamchip/ovcamchip_core.c index c841f4e4fbe4..21ec1dd2e1e5 100644 --- a/drivers/media/video/ovcamchip/ovcamchip_core.c +++ b/drivers/media/video/ovcamchip/ovcamchip_core.c @@ -15,6 +15,9 @@ #include #include #include +#include +#include +#include #include "ovcamchip_priv.h" #define DRIVER_VERSION "v2.27 for Linux 2.6" @@ -44,6 +47,7 @@ MODULE_AUTHOR(DRIVER_AUTHOR); MODULE_DESCRIPTION(DRIVER_DESC); MODULE_LICENSE("GPL"); + /* Registers common to all chips, that are needed for detection */ #define GENERIC_REG_ID_HIGH 0x1C /* manufacturer ID MSB */ #define GENERIC_REG_ID_LOW 0x1D /* manufacturer ID LSB */ @@ -61,10 +65,6 @@ static char *chip_names[NUM_CC_TYPES] = { [CC_OV6630AF] = "OV6630AF", }; -/* Forward declarations */ -static struct i2c_driver driver; -static struct i2c_client client_template; - /* ----------------------------------------------------------------------- */ int ov_write_regvals(struct i2c_client *c, struct ovcamchip_regvals *rvals) @@ -253,112 +253,36 @@ static int ovcamchip_detect(struct i2c_client *c) /* Test for 7xx0 */ PDEBUG(3, "Testing for 0V7xx0"); - c->addr = OV7xx0_SID; - if (init_camchip(c) < 0) { - /* Test for 6xx0 */ - PDEBUG(3, "Testing for 0V6xx0"); - c->addr = OV6xx0_SID; - if (init_camchip(c) < 0) { - return -ENODEV; - } else { - if (ov6xx0_detect(c) < 0) { - PERROR("Failed to init OV6xx0"); - return -EIO; - } - } - } else { + if (init_camchip(c) < 0) + return -ENODEV; + /* 7-bit addresses with bit 0 set are for the OV7xx0 */ + if (c->addr & 1) { if (ov7xx0_detect(c) < 0) { PERROR("Failed to init OV7xx0"); return -EIO; } + return 0; + } + /* Test for 6xx0 */ + PDEBUG(3, "Testing for 0V6xx0"); + if (ov6xx0_detect(c) < 0) { + PERROR("Failed to init OV6xx0"); + return -EIO; } - return 0; } /* ----------------------------------------------------------------------- */ -static int ovcamchip_attach(struct i2c_adapter *adap) -{ - int rc = 0; - struct ovcamchip *ov; - struct i2c_client *c; - - /* I2C is not a PnP bus, so we can never be certain that we're talking - * to the right chip. To prevent damage to EEPROMS and such, only - * attach to adapters that are known to contain OV camera chips. */ - - switch (adap->id) { - case I2C_HW_SMBUS_OV511: - case I2C_HW_SMBUS_OV518: - case I2C_HW_SMBUS_W9968CF: - PDEBUG(1, "Adapter ID 0x%06x accepted", adap->id); - break; - default: - PDEBUG(1, "Adapter ID 0x%06x rejected", adap->id); - return -ENODEV; - } - - c = kmalloc(sizeof *c, GFP_KERNEL); - if (!c) { - rc = -ENOMEM; - goto no_client; - } - memcpy(c, &client_template, sizeof *c); - c->adapter = adap; - strcpy(c->name, "OV????"); - - ov = kzalloc(sizeof *ov, GFP_KERNEL); - if (!ov) { - rc = -ENOMEM; - goto no_ov; - } - i2c_set_clientdata(c, ov); - - rc = ovcamchip_detect(c); - if (rc < 0) - goto error; - - strcpy(c->name, chip_names[ov->subtype]); - - PDEBUG(1, "Camera chip detection complete"); - - i2c_attach_client(c); - - return rc; -error: - kfree(ov); -no_ov: - kfree(c); -no_client: - PDEBUG(1, "returning %d", rc); - return rc; -} - -static int ovcamchip_detach(struct i2c_client *c) +static long ovcamchip_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg) { - struct ovcamchip *ov = i2c_get_clientdata(c); - int rc; - - rc = ov->sops->free(c); - if (rc < 0) - return rc; - - i2c_detach_client(c); - - kfree(ov); - kfree(c); - return 0; -} - -static int ovcamchip_command(struct i2c_client *c, unsigned int cmd, void *arg) -{ - struct ovcamchip *ov = i2c_get_clientdata(c); + struct ovcamchip *ov = to_ovcamchip(sd); + struct i2c_client *c = v4l2_get_subdevdata(sd); if (!ov->initialized && cmd != OVCAMCHIP_CMD_Q_SUBTYPE && cmd != OVCAMCHIP_CMD_INITIALIZE) { - dev_err(&c->dev, "ERROR: Camera chip not initialized yet!\n"); + v4l2_err(sd, "Camera chip not initialized yet!\n"); return -EPERM; } @@ -379,10 +303,10 @@ static int ovcamchip_command(struct i2c_client *c, unsigned int cmd, void *arg) if (ov->mono) { if (ov->subtype != CC_OV7620) - dev_warn(&c->dev, "Warning: Monochrome not " + v4l2_warn(sd, "Monochrome not " "implemented for this chip\n"); else - dev_info(&c->dev, "Initializing chip as " + v4l2_info(sd, "Initializing chip as " "monochrome\n"); } @@ -398,37 +322,80 @@ static int ovcamchip_command(struct i2c_client *c, unsigned int cmd, void *arg) } } +static int ovcamchip_command(struct i2c_client *client, unsigned cmd, void *arg) +{ + return v4l2_subdev_command(i2c_get_clientdata(client), cmd, arg); +} + /* ----------------------------------------------------------------------- */ -static struct i2c_driver driver = { - .driver = { - .name = "ovcamchip", - }, - .id = I2C_DRIVERID_OVCAMCHIP, - .attach_adapter = ovcamchip_attach, - .detach_client = ovcamchip_detach, - .command = ovcamchip_command, +static const struct v4l2_subdev_core_ops ovcamchip_core_ops = { + .ioctl = ovcamchip_ioctl, }; -static struct i2c_client client_template = { - .name = "(unset)", - .driver = &driver, +static const struct v4l2_subdev_ops ovcamchip_ops = { + .core = &ovcamchip_core_ops, }; -static int __init ovcamchip_init(void) +static int ovcamchip_probe(struct i2c_client *client, + const struct i2c_device_id *id) { -#ifdef DEBUG - ovcamchip_debug = debug; -#endif + struct ovcamchip *ov; + struct v4l2_subdev *sd; + int rc = 0; - PINFO(DRIVER_VERSION " : " DRIVER_DESC); - return i2c_add_driver(&driver); + ov = kzalloc(sizeof *ov, GFP_KERNEL); + if (!ov) { + rc = -ENOMEM; + goto no_ov; + } + sd = &ov->sd; + v4l2_i2c_subdev_init(sd, client, &ovcamchip_ops); + + rc = ovcamchip_detect(client); + if (rc < 0) + goto error; + + v4l_info(client, "%s found @ 0x%02x (%s)\n", + chip_names[ov->subtype], client->addr << 1, client->adapter->name); + + PDEBUG(1, "Camera chip detection complete"); + + return rc; +error: + kfree(ov); +no_ov: + PDEBUG(1, "returning %d", rc); + return rc; } -static void __exit ovcamchip_exit(void) +static int ovcamchip_remove(struct i2c_client *client) { - i2c_del_driver(&driver); + struct v4l2_subdev *sd = i2c_get_clientdata(client); + struct ovcamchip *ov = to_ovcamchip(sd); + int rc; + + v4l2_device_unregister_subdev(sd); + rc = ov->sops->free(client); + if (rc < 0) + return rc; + + kfree(ov); + return 0; } -module_init(ovcamchip_init); -module_exit(ovcamchip_exit); +/* ----------------------------------------------------------------------- */ + +static const struct i2c_device_id ovcamchip_id[] = { + { "ovcamchip", 0 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, ovcamchip_id); + +static struct v4l2_i2c_driver_data v4l2_i2c_data = { + .name = "ovcamchip", + .command = ovcamchip_command, + .probe = ovcamchip_probe, + .remove = ovcamchip_remove, + .id_table = ovcamchip_id, +}; diff --git a/drivers/media/video/ovcamchip/ovcamchip_priv.h b/drivers/media/video/ovcamchip/ovcamchip_priv.h index a05650faedda..4f07b78c88bc 100644 --- a/drivers/media/video/ovcamchip/ovcamchip_priv.h +++ b/drivers/media/video/ovcamchip/ovcamchip_priv.h @@ -16,6 +16,7 @@ #define __LINUX_OVCAMCHIP_PRIV_H #include +#include #include #ifdef DEBUG @@ -46,6 +47,7 @@ struct ovcamchip_ops { }; struct ovcamchip { + struct v4l2_subdev sd; struct ovcamchip_ops *sops; void *spriv; /* Private data for OV7x10.c etc... */ int subtype; /* = SEN_OV7610 etc... */ @@ -53,6 +55,11 @@ struct ovcamchip { int initialized; /* OVCAMCHIP_CMD_INITIALIZE was successful */ }; +static inline struct ovcamchip *to_ovcamchip(struct v4l2_subdev *sd) +{ + return container_of(sd, struct ovcamchip, sd); +} + extern struct ovcamchip_ops ov6x20_ops; extern struct ovcamchip_ops ov6x30_ops; extern struct ovcamchip_ops ov7x10_ops; diff --git a/drivers/media/video/w9968cf.c b/drivers/media/video/w9968cf.c index 3318be5688c9..fd5c4c87a73b 100644 --- a/drivers/media/video/w9968cf.c +++ b/drivers/media/video/w9968cf.c @@ -68,7 +68,6 @@ MODULE_VERSION(W9968CF_MODULE_VERSION); MODULE_LICENSE(W9968CF_MODULE_LICENSE); MODULE_SUPPORTED_DEVICE("Video"); -static int ovmod_load = W9968CF_OVMOD_LOAD; static unsigned short simcams = W9968CF_SIMCAMS; static short video_nr[]={[0 ... W9968CF_MAX_DEVICES-1] = -1}; /*-1=first free*/ static unsigned int packet_size[] = {[0 ... W9968CF_MAX_DEVICES-1] = @@ -111,9 +110,6 @@ static int specific_debug = W9968CF_SPECIFIC_DEBUG; static unsigned int param_nv[24]; /* number of values per parameter */ -#ifdef CONFIG_MODULES -module_param(ovmod_load, bool, 0644); -#endif module_param(simcams, ushort, 0644); module_param_array(video_nr, short, ¶m_nv[0], 0444); module_param_array(packet_size, uint, ¶m_nv[1], 0444); @@ -144,18 +140,6 @@ module_param(debug, ushort, 0644); module_param(specific_debug, bool, 0644); #endif -#ifdef CONFIG_MODULES -MODULE_PARM_DESC(ovmod_load, - "\n<0|1> Automatic 'ovcamchip' module loading." - "\n0 disabled, 1 enabled." - "\nIf enabled,'insmod' searches for the required 'ovcamchip'" - "\nmodule in the system, according to its configuration, and" - "\nattempts to load that module automatically. This action is" - "\nperformed once as soon as the 'w9968cf' module is loaded" - "\ninto memory." - "\nDefault value is "__MODULE_STRING(W9968CF_OVMOD_LOAD)"." - "\n"); -#endif MODULE_PARM_DESC(simcams, "\n Number of cameras allowed to stream simultaneously." "\nn may vary from 0 to " @@ -443,8 +427,6 @@ static int w9968cf_i2c_smbus_xfer(struct i2c_adapter*, u16 addr, unsigned short flags, char read_write, u8 command, int size, union i2c_smbus_data*); static u32 w9968cf_i2c_func(struct i2c_adapter*); -static int w9968cf_i2c_attach_inform(struct i2c_client*); -static int w9968cf_i2c_detach_inform(struct i2c_client*); /* Memory management */ static void* rvmalloc(unsigned long size); @@ -1443,19 +1425,11 @@ w9968cf_i2c_smbus_xfer(struct i2c_adapter *adapter, u16 addr, unsigned short flags, char read_write, u8 command, int size, union i2c_smbus_data *data) { - struct w9968cf_device* cam = i2c_get_adapdata(adapter); + struct v4l2_device *v4l2_dev = i2c_get_adapdata(adapter); + struct w9968cf_device *cam = to_cam(v4l2_dev); u8 i; int err = 0; - switch (addr) { - case OV6xx0_SID: - case OV7xx0_SID: - break; - default: - DBG(4, "Rejected slave ID 0x%04X", addr) - return -EINVAL; - } - if (size == I2C_SMBUS_BYTE) { /* Why addr <<= 1? See OVXXX0_SID defines in ovcamchip.h */ addr <<= 1; @@ -1463,8 +1437,17 @@ w9968cf_i2c_smbus_xfer(struct i2c_adapter *adapter, u16 addr, if (read_write == I2C_SMBUS_WRITE) err = w9968cf_i2c_adap_write_byte(cam, addr, command); else if (read_write == I2C_SMBUS_READ) - err = w9968cf_i2c_adap_read_byte(cam,addr,&data->byte); - + for (i = 1; i <= W9968CF_I2C_RW_RETRIES; i++) { + err = w9968cf_i2c_adap_read_byte(cam, addr, + &data->byte); + if (err) { + if (w9968cf_smbus_refresh_bus(cam)) { + err = -EIO; + break; + } + } else + break; + } } else if (size == I2C_SMBUS_BYTE_DATA) { addr <<= 1; @@ -1491,7 +1474,6 @@ w9968cf_i2c_smbus_xfer(struct i2c_adapter *adapter, u16 addr, DBG(4, "Unsupported I2C transfer mode (%d)", size) return -EINVAL; } - return err; } @@ -1504,44 +1486,6 @@ static u32 w9968cf_i2c_func(struct i2c_adapter* adap) } -static int w9968cf_i2c_attach_inform(struct i2c_client* client) -{ - struct w9968cf_device* cam = i2c_get_adapdata(client->adapter); - int id = client->driver->id, err = 0; - - if (id == I2C_DRIVERID_OVCAMCHIP) { - cam->sensor_client = client; - err = w9968cf_sensor_init(cam); - if (err) { - cam->sensor_client = NULL; - return err; - } - } else { - DBG(4, "Rejected client [%s] with driver [%s]", - client->name, client->driver->driver.name) - return -EINVAL; - } - - DBG(5, "I2C attach client [%s] with driver [%s]", - client->name, client->driver->driver.name) - - return 0; -} - - -static int w9968cf_i2c_detach_inform(struct i2c_client* client) -{ - struct w9968cf_device* cam = i2c_get_adapdata(client->adapter); - - if (cam->sensor_client == client) - cam->sensor_client = NULL; - - DBG(5, "I2C detach client [%s]", client->name) - - return 0; -} - - static int w9968cf_i2c_init(struct w9968cf_device* cam) { int err = 0; @@ -1554,15 +1498,13 @@ static int w9968cf_i2c_init(struct w9968cf_device* cam) static struct i2c_adapter adap = { .id = I2C_HW_SMBUS_W9968CF, .owner = THIS_MODULE, - .client_register = w9968cf_i2c_attach_inform, - .client_unregister = w9968cf_i2c_detach_inform, .algo = &algo, }; memcpy(&cam->i2c_adapter, &adap, sizeof(struct i2c_adapter)); strcpy(cam->i2c_adapter.name, "w9968cf"); cam->i2c_adapter.dev.parent = &cam->usbdev->dev; - i2c_set_adapdata(&cam->i2c_adapter, cam); + i2c_set_adapdata(&cam->i2c_adapter, &cam->v4l2_dev); DBG(6, "Registering I2C adapter with kernel...") @@ -2165,13 +2107,9 @@ w9968cf_sensor_get_control(struct w9968cf_device* cam, int cid, int* val) static int w9968cf_sensor_cmd(struct w9968cf_device* cam, unsigned int cmd, void* arg) { - struct i2c_client* c = cam->sensor_client; - int rc = 0; + int rc; - if (!c || !c->driver || !c->driver->command) - return -EINVAL; - - rc = c->driver->command(c, cmd, arg); + rc = v4l2_subdev_call(cam->sensor_sd, core, ioctl, cmd, arg); /* The I2C driver returns -EPERM on non-supported controls */ return (rc < 0 && rc != -EPERM) ? rc : 0; } @@ -2346,7 +2284,7 @@ static int w9968cf_sensor_init(struct w9968cf_device* cam) goto error; /* NOTE: Make sure width and height are a multiple of 16 */ - switch (cam->sensor_client->addr) { + switch (v4l2_i2c_subdev_addr(cam->sensor_sd)) { case OV6xx0_SID: cam->maxwidth = 352; cam->maxheight = 288; @@ -2651,6 +2589,7 @@ static void w9968cf_release_resources(struct w9968cf_device* cam) w9968cf_deallocate_memory(cam); kfree(cam->control_buffer); kfree(cam->data_buffer); + v4l2_device_unregister(&cam->v4l2_dev); mutex_unlock(&w9968cf_devlist_mutex); } @@ -3480,6 +3419,11 @@ w9968cf_usb_probe(struct usb_interface* intf, const struct usb_device_id* 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 addrs[] = { + OV7xx0_SID, + OV6xx0_SID, + I2C_CLIENT_END + }; if (le16_to_cpu(udev->descriptor.idVendor) == winbond_id_table[0].idVendor && le16_to_cpu(udev->descriptor.idProduct) == winbond_id_table[0].idProduct) @@ -3578,12 +3522,13 @@ w9968cf_usb_probe(struct usb_interface* intf, const struct usb_device_id* id) w9968cf_turn_on_led(cam); w9968cf_i2c_init(cam); + cam->sensor_sd = v4l2_i2c_new_probed_subdev(&cam->i2c_adapter, + "ovcamchip", "ovcamchip", addrs); usb_set_intfdata(intf, cam); mutex_unlock(&cam->dev_mutex); - if (ovmod_load) - request_module("ovcamchip"); + err = w9968cf_sensor_init(cam); return 0; fail: /* Free unused memory */ @@ -3604,9 +3549,8 @@ static void w9968cf_usb_disconnect(struct usb_interface* intf) struct w9968cf_device* cam = (struct w9968cf_device*)usb_get_intfdata(intf); - down_write(&w9968cf_disconnect); - if (cam) { + down_write(&w9968cf_disconnect); /* Prevent concurrent accesses to data */ mutex_lock(&cam->dev_mutex); @@ -3628,14 +3572,12 @@ static void w9968cf_usb_disconnect(struct usb_interface* intf) w9968cf_release_resources(cam); mutex_unlock(&cam->dev_mutex); + up_write(&w9968cf_disconnect); if (!cam->users) { - v4l2_device_unregister(&cam->v4l2_dev); kfree(cam); } } - - up_write(&w9968cf_disconnect); } diff --git a/drivers/media/video/w9968cf.h b/drivers/media/video/w9968cf.h index c59883552545..fdfc6a4e1c8f 100644 --- a/drivers/media/video/w9968cf.h +++ b/drivers/media/video/w9968cf.h @@ -43,7 +43,6 @@ * Default values * ****************************************************************************/ -#define W9968CF_OVMOD_LOAD 1 /* automatic 'ovcamchip' module loading */ #define W9968CF_VPPMOD_LOAD 1 /* automatic 'w9968cf-vpp' module loading */ /* Comment/uncomment the following line to enable/disable debugging messages */ @@ -265,7 +264,7 @@ struct w9968cf_device { /* I2C interface to kernel */ struct i2c_adapter i2c_adapter; - struct i2c_client* sensor_client; + struct v4l2_subdev *sensor_sd; /* Locks */ struct mutex dev_mutex, /* for probe, disconnect,open and close */ @@ -277,6 +276,11 @@ struct w9968cf_device { char command[16]; /* name of the program holding the device */ }; +static inline struct w9968cf_device *to_cam(struct v4l2_device *v4l2_dev) +{ + return container_of(v4l2_dev, struct w9968cf_device, v4l2_dev); +} + /**************************************************************************** * Macros for debugging * -- cgit v1.2.3 From f9996c95623d63de6f5957512976137bbac729f0 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Sat, 28 Feb 2009 17:45:17 -0300 Subject: V4L/DVB (10877): saa7134: add analog support for Hauppauge HVR1110r3 boards Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- Documentation/video4linux/CARDLIST.saa7134 | 2 + drivers/media/video/saa7134/saa7134-cards.c | 173 +++++++++++++++++++++++++++- drivers/media/video/saa7134/saa7134.h | 2 + 3 files changed, 175 insertions(+), 2 deletions(-) (limited to 'drivers/media/video') diff --git a/Documentation/video4linux/CARDLIST.saa7134 b/Documentation/video4linux/CARDLIST.saa7134 index b8d470596b0c..325c69fe91fd 100644 --- a/Documentation/video4linux/CARDLIST.saa7134 +++ b/Documentation/video4linux/CARDLIST.saa7134 @@ -153,3 +153,5 @@ 152 -> Asus Tiger Rev:1.00 [1043:4857] 153 -> Kworld Plus TV Analog Lite PCI [17de:7128] 154 -> Avermedia AVerTV GO 007 FM Plus [1461:f31d] +155 -> Hauppauge WinTV-HVR1150 [0070:6706,0070:6708] +156 -> Hauppauge WinTV-HVR1110r3 [0070:6707,0070:6709,0070:670a] diff --git a/drivers/media/video/saa7134/saa7134-cards.c b/drivers/media/video/saa7134/saa7134-cards.c index 9f69c7c85814..88f0b8f06e10 100644 --- a/drivers/media/video/saa7134/saa7134-cards.c +++ b/drivers/media/video/saa7134/saa7134-cards.c @@ -31,6 +31,7 @@ #include #include #include "tea5767.h" +#include "tda18271.h" /* commly used strings */ static char name_mute[] = "mute"; @@ -3291,6 +3292,66 @@ struct saa7134_board saa7134_boards[] = { .gpio = 0x0200100, }, }, + [SAA7134_BOARD_HAUPPAUGE_HVR1150] = { + .name = "Hauppauge WinTV-HVR1150", + .audio_clock = 0x00187de7, + .tuner_type = TUNER_PHILIPS_TDA8290, + .radio_type = UNSET, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .tuner_config = 3, + .gpiomask = 0x0800100, /* GPIO 21 is an INPUT */ + .inputs = {{ + .name = name_tv, + .vmux = 1, + .amux = TV, + .tv = 1, + .gpio = 0x0000100, + }, { + .name = name_comp1, + .vmux = 3, + .amux = LINE1, + }, { + .name = name_svideo, + .vmux = 8, + .amux = LINE1, + } }, + .radio = { + .name = name_radio, + .amux = TV, + .gpio = 0x0800100, /* GPIO 23 HI for FM */ + }, + }, + [SAA7134_BOARD_HAUPPAUGE_HVR1110R3] = { + .name = "Hauppauge WinTV-HVR1110r3", + .audio_clock = 0x00187de7, + .tuner_type = TUNER_PHILIPS_TDA8290, + .radio_type = UNSET, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .tuner_config = 3, + .gpiomask = 0x0800100, /* GPIO 21 is an INPUT */ + .inputs = {{ + .name = name_tv, + .vmux = 1, + .amux = TV, + .tv = 1, + .gpio = 0x0000100, + }, { + .name = name_comp1, + .vmux = 3, + .amux = LINE1, + }, { + .name = name_svideo, + .vmux = 8, + .amux = LINE1, + } }, + .radio = { + .name = name_radio, + .amux = TV, + .gpio = 0x0800100, /* GPIO 23 HI for FM */ + }, + }, [SAA7134_BOARD_CINERGY_HT_PCMCIA] = { .name = "Terratec Cinergy HT PCMCIA", .audio_clock = 0x00187de7, @@ -5400,6 +5461,36 @@ struct pci_device_id saa7134_pci_tbl[] = { .subvendor = 0x0070, .subdevice = 0x6705, .driver_data = SAA7134_BOARD_HAUPPAUGE_HVR1110, + },{ + .vendor = PCI_VENDOR_ID_PHILIPS, + .device = PCI_DEVICE_ID_PHILIPS_SAA7133, + .subvendor = 0x0070, + .subdevice = 0x6706, + .driver_data = SAA7134_BOARD_HAUPPAUGE_HVR1150, + },{ + .vendor = PCI_VENDOR_ID_PHILIPS, + .device = PCI_DEVICE_ID_PHILIPS_SAA7133, + .subvendor = 0x0070, + .subdevice = 0x6707, + .driver_data = SAA7134_BOARD_HAUPPAUGE_HVR1110R3, + },{ + .vendor = PCI_VENDOR_ID_PHILIPS, + .device = PCI_DEVICE_ID_PHILIPS_SAA7133, + .subvendor = 0x0070, + .subdevice = 0x6708, + .driver_data = SAA7134_BOARD_HAUPPAUGE_HVR1150, + },{ + .vendor = PCI_VENDOR_ID_PHILIPS, + .device = PCI_DEVICE_ID_PHILIPS_SAA7133, + .subvendor = 0x0070, + .subdevice = 0x6709, + .driver_data = SAA7134_BOARD_HAUPPAUGE_HVR1110R3, + },{ + .vendor = PCI_VENDOR_ID_PHILIPS, + .device = PCI_DEVICE_ID_PHILIPS_SAA7133, + .subvendor = 0x0070, + .subdevice = 0x670a, + .driver_data = SAA7134_BOARD_HAUPPAUGE_HVR1110R3, },{ .vendor = PCI_VENDOR_ID_PHILIPS, .device = PCI_DEVICE_ID_PHILIPS_SAA7133, @@ -5819,8 +5910,8 @@ static int saa7134_xc2028_callback(struct saa7134_dev *dev, } -static int saa7134_tda8290_callback(struct saa7134_dev *dev, - int command, int arg) +static int saa7134_tda8290_827x_callback(struct saa7134_dev *dev, + int command, int arg) { u8 sync_control; @@ -5846,6 +5937,65 @@ static int saa7134_tda8290_callback(struct saa7134_dev *dev, return 0; } +static inline int saa7134_tda18271_hvr11x0_toggle_agc(struct saa7134_dev *dev, + enum tda18271_mode mode) +{ + /* toggle AGC switch through GPIO 26 */ + switch (mode) { + case TDA18271_ANALOG: + saa7134_set_gpio(dev, 26, 0); + break; + case TDA18271_DIGITAL: + saa7134_set_gpio(dev, 26, 1); + break; + default: + return -EINVAL; + } + return 0; +} + +static int saa7134_tda8290_18271_callback(struct saa7134_dev *dev, + int command, int arg) +{ + int ret = 0; + + switch (command) { + case TDA18271_CALLBACK_CMD_AGC_ENABLE: /* 0 */ + switch (dev->board) { + case SAA7134_BOARD_HAUPPAUGE_HVR1150: + case SAA7134_BOARD_HAUPPAUGE_HVR1110R3: + ret = saa7134_tda18271_hvr11x0_toggle_agc(dev, arg); + break; + default: + break; + } + break; + default: + ret = -EINVAL; + break; + } + return ret; +} + +static int saa7134_tda8290_callback(struct saa7134_dev *dev, + int command, int arg) +{ + int ret; + + switch (dev->board) { + case SAA7134_BOARD_HAUPPAUGE_HVR1150: + case SAA7134_BOARD_HAUPPAUGE_HVR1110R3: + /* tda8290 + tda18271 */ + ret = saa7134_tda8290_18271_callback(dev, command, arg); + break; + default: + /* tda8290 + tda827x */ + ret = saa7134_tda8290_827x_callback(dev, command, arg); + break; + } + return ret; +} + int saa7134_tuner_callback(void *priv, int component, int command, int arg) { struct saa7134_dev *dev = priv; @@ -5876,11 +6026,16 @@ static void hauppauge_eeprom(struct saa7134_dev *dev, u8 *eeprom_data) switch (tv.model) { case 67019: /* WinTV-HVR1110 (Retail, IR Blaster, hybrid, FM, SVid/Comp, 3.5mm audio in) */ case 67109: /* WinTV-HVR1000 (Retail, IR Receive, analog, no FM, SVid/Comp, 3.5mm audio in) */ + case 67201: /* WinTV-HVR1150 (Retail, IR Receive, hybrid, FM, SVid/Comp, 3.5mm audio in) */ + case 67301: /* WinTV-HVR1000 (Retail, IR Receive, analog, no FM, SVid/Comp, 3.5mm audio in) */ + case 67209: /* WinTV-HVR1110 (Retail, IR Receive, hybrid, FM, SVid/Comp, 3.5mm audio in) */ case 67559: /* WinTV-HVR1110 (OEM, no IR, hybrid, FM, SVid/Comp, RCA aud) */ case 67569: /* WinTV-HVR1110 (OEM, no IR, hybrid, FM) */ case 67579: /* WinTV-HVR1110 (OEM, no IR, hybrid, no FM) */ case 67589: /* WinTV-HVR1110 (OEM, no IR, hybrid, no FM, SVid/Comp, RCA aud) */ case 67599: /* WinTV-HVR1110 (OEM, no IR, hybrid, no FM, SVid/Comp, RCA aud) */ + case 67651: /* WinTV-HVR1150 (OEM, no IR, hybrid, FM, SVid/Comp, RCA aud) */ + case 67659: /* WinTV-HVR1110 (OEM, no IR, hybrid, FM, SVid/Comp, RCA aud) */ break; default: printk(KERN_WARNING "%s: warning: " @@ -6057,6 +6212,16 @@ int saa7134_board_init1(struct saa7134_dev *dev) saa_writeb (SAA7134_PRODUCTION_TEST_MODE, 0x00); break; + case SAA7134_BOARD_HAUPPAUGE_HVR1150: + case SAA7134_BOARD_HAUPPAUGE_HVR1110R3: + /* GPIO 26 high for digital, low for analog */ + saa7134_set_gpio(dev, 26, 0); + msleep(1); + + saa7134_set_gpio(dev, 22, 0); + msleep(10); + saa7134_set_gpio(dev, 22, 1); + break; /* i2c remotes */ case SAA7134_BOARD_PINNACLE_PCTV_110i: case SAA7134_BOARD_PINNACLE_PCTV_310i: @@ -6309,6 +6474,10 @@ int saa7134_board_init2(struct saa7134_dev *dev) dev->name, saa7134_boards[dev->board].name); } break; + case SAA7134_BOARD_HAUPPAUGE_HVR1150: + case SAA7134_BOARD_HAUPPAUGE_HVR1110R3: + hauppauge_eeprom(dev, dev->eedata+0x80); + break; case SAA7134_BOARD_HAUPPAUGE_HVR1110: hauppauge_eeprom(dev, dev->eedata+0x80); /* break intentionally omitted */ diff --git a/drivers/media/video/saa7134/saa7134.h b/drivers/media/video/saa7134/saa7134.h index 4552a4d6f192..52d9397ad779 100644 --- a/drivers/media/video/saa7134/saa7134.h +++ b/drivers/media/video/saa7134/saa7134.h @@ -278,6 +278,8 @@ struct saa7134_format { #define SAA7134_BOARD_ASUSTeK_TIGER 152 #define SAA7134_BOARD_KWORLD_PLUS_TV_ANALOG 153 #define SAA7134_BOARD_AVERMEDIA_GO_007_FM_PLUS 154 +#define SAA7134_BOARD_HAUPPAUGE_HVR1150 155 +#define SAA7134_BOARD_HAUPPAUGE_HVR1110R3 156 #define SAA7134_MAXBOARDS 32 #define SAA7134_INPUT_MAX 8 -- cgit v1.2.3 From 0aab2e6044037c34ccb5fe94c616e532ba95f541 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 10 Mar 2009 02:30:23 -0300 Subject: V4L/DVB (10897): Fix Kbuild MEDIA_TUNER_CUSTOMIZE dependencies Signed-off-by: Mauro Carvalho Chehab --- drivers/media/common/tuners/Kconfig | 20 ++++++++++---------- drivers/media/video/au0828/Kconfig | 6 +++--- drivers/media/video/cx23885/Kconfig | 8 ++++---- drivers/media/video/pvrusb2/Kconfig | 4 ++-- 4 files changed, 19 insertions(+), 19 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/common/tuners/Kconfig b/drivers/media/common/tuners/Kconfig index 7969b695cb50..724e6870c412 100644 --- a/drivers/media/common/tuners/Kconfig +++ b/drivers/media/common/tuners/Kconfig @@ -66,14 +66,14 @@ config MEDIA_TUNER_TDA8290 config MEDIA_TUNER_TDA827X tristate "Philips TDA827X silicon tuner" depends on VIDEO_MEDIA && I2C - default m if DVB_FE_CUSTOMISE + default m if MEDIA_TUNER_CUSTOMIZE help A DVB-T silicon tuner module. Say Y when you want to support this tuner. config MEDIA_TUNER_TDA18271 tristate "NXP TDA18271 silicon tuner" depends on VIDEO_MEDIA && I2C - default m if DVB_FE_CUSTOMISE + default m if MEDIA_TUNER_CUSTOMIZE help A silicon tuner module. Say Y when you want to support this tuner. @@ -110,28 +110,28 @@ config MEDIA_TUNER_MT20XX config MEDIA_TUNER_MT2060 tristate "Microtune MT2060 silicon IF tuner" depends on VIDEO_MEDIA && I2C - default m if DVB_FE_CUSTOMISE + default m if MEDIA_TUNER_CUSTOMIZE help A driver for the silicon IF tuner MT2060 from Microtune. config MEDIA_TUNER_MT2266 tristate "Microtune MT2266 silicon tuner" depends on VIDEO_MEDIA && I2C - default m if DVB_FE_CUSTOMISE + default m if MEDIA_TUNER_CUSTOMIZE help A driver for the silicon baseband tuner MT2266 from Microtune. config MEDIA_TUNER_MT2131 tristate "Microtune MT2131 silicon tuner" depends on VIDEO_MEDIA && I2C - default m if DVB_FE_CUSTOMISE + default m if MEDIA_TUNER_CUSTOMIZE help A driver for the silicon baseband tuner MT2131 from Microtune. config MEDIA_TUNER_QT1010 tristate "Quantek QT1010 silicon tuner" depends on VIDEO_MEDIA && I2C - default m if DVB_FE_CUSTOMISE + default m if MEDIA_TUNER_CUSTOMIZE help A driver for the silicon tuner QT1010 from Quantek. @@ -145,7 +145,7 @@ config MEDIA_TUNER_XC2028 config MEDIA_TUNER_XC5000 tristate "Xceive XC5000 silicon tuner" depends on VIDEO_MEDIA && I2C - default m if DVB_FE_CUSTOMISE + default m if MEDIA_TUNER_CUSTOMIZE help A driver for the silicon tuner XC5000 from Xceive. This device is only used inside a SiP called togther with a @@ -154,21 +154,21 @@ config MEDIA_TUNER_XC5000 config MEDIA_TUNER_MXL5005S tristate "MaxLinear MSL5005S silicon tuner" depends on VIDEO_MEDIA && I2C - default m if DVB_FE_CUSTOMISE + default m if MEDIA_TUNER_CUSTOMIZE help A driver for the silicon tuner MXL5005S from MaxLinear. config MEDIA_TUNER_MXL5007T tristate "MaxLinear MxL5007T silicon tuner" depends on VIDEO_MEDIA && I2C - default m if DVB_FE_CUSTOMISE + default m if MEDIA_TUNER_CUSTOMIZE help A driver for the silicon tuner MxL5007T from MaxLinear. config MEDIA_TUNER_MC44S803 tristate "Freescale MC44S803 Low Power CMOS Broadband tuners" depends on VIDEO_MEDIA && I2C - default m if DVB_FE_CUSTOMISE + default m if MEDIA_TUNER_CUSTOMIZE help Say Y here to support the Freescale MC44S803 based tuners diff --git a/drivers/media/video/au0828/Kconfig b/drivers/media/video/au0828/Kconfig index deb00e4acb94..20993ae17d36 100644 --- a/drivers/media/video/au0828/Kconfig +++ b/drivers/media/video/au0828/Kconfig @@ -5,9 +5,9 @@ config VIDEO_AU0828 select I2C_ALGOBIT select VIDEO_TVEEPROM select DVB_AU8522 if !DVB_FE_CUSTOMISE - select MEDIA_TUNER_XC5000 if !DVB_FE_CUSTOMISE - select MEDIA_TUNER_MXL5007T if !DVB_FE_CUSTOMISE - select MEDIA_TUNER_TDA18271 if !DVB_FE_CUSTOMISE + select MEDIA_TUNER_XC5000 if !MEDIA_TUNER_CUSTOMIZE + select MEDIA_TUNER_MXL5007T if !MEDIA_TUNER_CUSTOMIZE + select MEDIA_TUNER_TDA18271 if !MEDIA_TUNER_CUSTOMIZE ---help--- This is a video4linux driver for Auvitek's USB device. diff --git a/drivers/media/video/cx23885/Kconfig b/drivers/media/video/cx23885/Kconfig index 28896aa31506..e603ceb2811b 100644 --- a/drivers/media/video/cx23885/Kconfig +++ b/drivers/media/video/cx23885/Kconfig @@ -20,10 +20,10 @@ config VIDEO_CX23885 select DVB_STV6110 if !DVB_FE_CUSTOMISE select DVB_STV0900 if !DVB_FE_CUSTOMISE select MEDIA_TUNER_MT2131 if !MEDIA_TUNER_CUSTOMIZE - select MEDIA_TUNER_XC2028 if !DVB_FE_CUSTOMISE - select MEDIA_TUNER_TDA8290 if !DVB_FE_CUSTOMISE - select MEDIA_TUNER_TDA18271 if !DVB_FE_CUSTOMISE - select MEDIA_TUNER_XC5000 if !DVB_FE_CUSTOMISE + select MEDIA_TUNER_XC2028 if !MEDIA_TUNER_CUSTOMIZE + select MEDIA_TUNER_TDA8290 if !MEDIA_TUNER_CUSTOMIZE + select MEDIA_TUNER_TDA18271 if !MEDIA_TUNER_CUSTOMIZE + select MEDIA_TUNER_XC5000 if !MEDIA_TUNER_CUSTOMIZE ---help--- This is a video4linux driver for Conexant 23885 based TV cards. diff --git a/drivers/media/video/pvrusb2/Kconfig b/drivers/media/video/pvrusb2/Kconfig index bb42713939ee..17cde17571c7 100644 --- a/drivers/media/video/pvrusb2/Kconfig +++ b/drivers/media/video/pvrusb2/Kconfig @@ -41,9 +41,9 @@ config VIDEO_PVRUSB2_DVB select DVB_S5H1409 if !DVB_FE_CUSTOMISE select DVB_S5H1411 if !DVB_FE_CUSTOMISE select DVB_TDA10048 if !DVB_FE_CUSTOMISE - select MEDIA_TUNER_TDA18271 if !DVB_FE_CUSTOMISE + select MEDIA_TUNER_TDA18271 if !MEDIA_TUNER_CUSTOMIZE select MEDIA_TUNER_SIMPLE if !MEDIA_TUNER_CUSTOMIZE - select MEDIA_TUNER_TDA8290 if !DVB_FE_CUSTOMISE + select MEDIA_TUNER_TDA8290 if !MEDIA_TUNER_CUSTOMIZE ---help--- This option enables a DVB interface for the pvrusb2 driver. -- cgit v1.2.3 From 42d12f5aa105af08bc0ed0580e32156a1a325c6b Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 10 Mar 2009 05:02:28 -0300 Subject: V4L/DVB (10870a): remove all references for video_decoder.h changeset 04934e44e3784a1b969582e2d59afcec278470c6 removed the last implementation that were still using the V4L1 obsoleted header. Now, video_decoder.h is not used anymore by any driver. Let's remove it and all references for it in Kernel. Signed-off-by: Mauro Carvalho Chehab --- Documentation/feature-removal-schedule.txt | 8 ++--- Documentation/ioctl/ioctl-number.txt | 1 - drivers/media/video/mxb.c | 1 - include/linux/Kbuild | 1 - include/linux/video_decoder.h | 48 ------------------------------ 5 files changed, 4 insertions(+), 55 deletions(-) delete mode 100644 include/linux/video_decoder.h (limited to 'drivers/media/video') diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt index 1135996bec8b..5e02b83ac12b 100644 --- a/Documentation/feature-removal-schedule.txt +++ b/Documentation/feature-removal-schedule.txt @@ -64,10 +64,10 @@ Who: Pavel Machek --------------------------- -What: Video4Linux API 1 ioctls and video_decoder.h from Video devices. -When: December 2008 -Files: include/linux/video_decoder.h include/linux/videodev.h -Check: include/linux/video_decoder.h include/linux/videodev.h +What: Video4Linux API 1 ioctls and from Video devices. +When: July 2009 +Files: include/linux/videodev.h +Check: include/linux/videodev.h Why: V4L1 AP1 was replaced by V4L2 API during migration from 2.4 to 2.6 series. The old API have lots of drawbacks and don't provide enough means to work with all video and audio standards. The newer API is diff --git a/Documentation/ioctl/ioctl-number.txt b/Documentation/ioctl/ioctl-number.txt index 3a311fe952ed..1f779a25c703 100644 --- a/Documentation/ioctl/ioctl-number.txt +++ b/Documentation/ioctl/ioctl-number.txt @@ -122,7 +122,6 @@ Code Seq# Include File Comments 'c' 00-7F linux/coda.h conflict! 'c' 80-9F arch/s390/include/asm/chsc.h 'd' 00-FF linux/char/drm/drm/h conflict! -'d' 00-DF linux/video_decoder.h conflict! 'd' F0-FF linux/digi1.h 'e' all linux/digi1.h conflict! 'e' 00-1F net/irda/irtty.h conflict! diff --git a/drivers/media/video/mxb.c b/drivers/media/video/mxb.c index 996011f2aba5..84aec62e8452 100644 --- a/drivers/media/video/mxb.c +++ b/drivers/media/video/mxb.c @@ -25,7 +25,6 @@ #include #include -#include #include #include diff --git a/include/linux/Kbuild b/include/linux/Kbuild index da7ff0ba3860..a67b6227d272 100644 --- a/include/linux/Kbuild +++ b/include/linux/Kbuild @@ -158,7 +158,6 @@ header-y += ultrasound.h header-y += un.h header-y += utime.h header-y += veth.h -header-y += video_decoder.h header-y += videotext.h header-y += x25.h diff --git a/include/linux/video_decoder.h b/include/linux/video_decoder.h deleted file mode 100644 index e26c0c86a6ea..000000000000 --- a/include/linux/video_decoder.h +++ /dev/null @@ -1,48 +0,0 @@ -#ifndef _LINUX_VIDEO_DECODER_H -#define _LINUX_VIDEO_DECODER_H - -#include - -#define HAVE_VIDEO_DECODER 1 - -struct video_decoder_capability { /* this name is too long */ - __u32 flags; -#define VIDEO_DECODER_PAL 1 /* can decode PAL signal */ -#define VIDEO_DECODER_NTSC 2 /* can decode NTSC */ -#define VIDEO_DECODER_SECAM 4 /* can decode SECAM */ -#define VIDEO_DECODER_AUTO 8 /* can autosense norm */ -#define VIDEO_DECODER_CCIR 16 /* CCIR-601 pixel rate (720 pixels per line) instead of square pixel rate */ - int inputs; /* number of inputs */ - int outputs; /* number of outputs */ -}; - -/* -DECODER_GET_STATUS returns the following flags. The only one you need is -DECODER_STATUS_GOOD, the others are just nice things to know. -*/ -#define DECODER_STATUS_GOOD 1 /* receiving acceptable input */ -#define DECODER_STATUS_COLOR 2 /* receiving color information */ -#define DECODER_STATUS_PAL 4 /* auto detected */ -#define DECODER_STATUS_NTSC 8 /* auto detected */ -#define DECODER_STATUS_SECAM 16 /* auto detected */ - -struct video_decoder_init { - unsigned char len; - const unsigned char *data; -}; - -#define DECODER_GET_CAPABILITIES _IOR('d', 1, struct video_decoder_capability) -#define DECODER_GET_STATUS _IOR('d', 2, int) -#define DECODER_SET_NORM _IOW('d', 3, int) -#define DECODER_SET_INPUT _IOW('d', 4, int) /* 0 <= input < #inputs */ -#define DECODER_SET_OUTPUT _IOW('d', 5, int) /* 0 <= output < #outputs */ -#define DECODER_ENABLE_OUTPUT _IOW('d', 6, int) /* boolean output enable control */ -#define DECODER_SET_PICTURE _IOW('d', 7, struct video_picture) -#define DECODER_SET_GPIO _IOW('d', 8, int) /* switch general purpose pin */ -#define DECODER_INIT _IOW('d', 9, struct video_decoder_init) /* init internal registers at once */ -#define DECODER_SET_VBI_BYPASS _IOW('d', 10, int) /* switch vbi bypass */ - -#define DECODER_DUMP _IO('d', 192) /* debug hook */ - - -#endif -- cgit v1.2.3 From 7e0a16f6118a297dd467c1e5a0908429fcdf56af Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 10 Mar 2009 05:31:34 -0300 Subject: V4L/DVB (10907): avoid loading the entire videodev.h header on V4L2 drivers Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/bt8xx/bttv.h | 2 +- drivers/media/video/bt8xx/bttvp.h | 1 - drivers/media/video/cpia2/cpia2_v4l.c | 1 + drivers/media/video/cx23885/cx23885-video.c | 5 ----- drivers/media/video/cx88/cx88-video.c | 5 ----- drivers/media/video/msp3400-driver.c | 2 +- drivers/media/video/ov7670.c | 2 +- drivers/media/video/saa7134/saa7134-video.c | 5 ----- drivers/media/video/saa7146.h | 2 -- drivers/media/video/v4l2-ioctl.c | 1 + drivers/media/video/vivi.c | 4 ---- drivers/media/video/w9966.c | 2 +- drivers/media/video/w9968cf.c | 1 + drivers/media/video/zoran/zoran_driver.c | 2 +- include/linux/videodev.h | 18 ++++++++++++++++++ include/media/v4l2-ioctl.h | 1 + 16 files changed, 27 insertions(+), 27 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/bt8xx/bttv.h b/drivers/media/video/bt8xx/bttv.h index 737a464606a9..e08719b378bd 100644 --- a/drivers/media/video/bt8xx/bttv.h +++ b/drivers/media/video/bt8xx/bttv.h @@ -14,7 +14,7 @@ #ifndef _BTTV_H_ #define _BTTV_H_ -#include +#include #include #include #include diff --git a/drivers/media/video/bt8xx/bttvp.h b/drivers/media/video/bt8xx/bttvp.h index b8274d233fd0..2c0a2cc61d03 100644 --- a/drivers/media/video/bt8xx/bttvp.h +++ b/drivers/media/video/bt8xx/bttvp.h @@ -32,7 +32,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/media/video/cpia2/cpia2_v4l.c b/drivers/media/video/cpia2/cpia2_v4l.c index 9c25894fdd8e..d4099f5312ac 100644 --- a/drivers/media/video/cpia2/cpia2_v4l.c +++ b/drivers/media/video/cpia2/cpia2_v4l.c @@ -37,6 +37,7 @@ #include #include #include +#include #include #include "cpia2.h" diff --git a/drivers/media/video/cx23885/cx23885-video.c b/drivers/media/video/cx23885/cx23885-video.c index c2ed2505b725..726602935353 100644 --- a/drivers/media/video/cx23885/cx23885-video.c +++ b/drivers/media/video/cx23885/cx23885-video.c @@ -35,11 +35,6 @@ #include #include -#ifdef CONFIG_VIDEO_V4L1_COMPAT -/* Include V4L1 specific functions. Should be removed soon */ -#include -#endif - MODULE_DESCRIPTION("v4l2 driver module for cx23885 based TV cards"); MODULE_AUTHOR("Steven Toth "); MODULE_LICENSE("GPL"); diff --git a/drivers/media/video/cx88/cx88-video.c b/drivers/media/video/cx88/cx88-video.c index 2092e439ef00..5b0fbc602f3e 100644 --- a/drivers/media/video/cx88/cx88-video.c +++ b/drivers/media/video/cx88/cx88-video.c @@ -41,11 +41,6 @@ #include #include -#ifdef CONFIG_VIDEO_V4L1_COMPAT -/* Include V4L1 specific functions. Should be removed soon */ -#include -#endif - MODULE_DESCRIPTION("v4l2 driver module for cx2388x based TV cards"); MODULE_AUTHOR("Gerd Knorr [SuSE Labs]"); MODULE_LICENSE("GPL"); diff --git a/drivers/media/video/msp3400-driver.c b/drivers/media/video/msp3400-driver.c index d972828d1cbe..bca768a1f34c 100644 --- a/drivers/media/video/msp3400-driver.c +++ b/drivers/media/video/msp3400-driver.c @@ -53,7 +53,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/drivers/media/video/ov7670.c b/drivers/media/video/ov7670.c index 05c14a29375a..003120c07482 100644 --- a/drivers/media/video/ov7670.c +++ b/drivers/media/video/ov7670.c @@ -14,7 +14,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/drivers/media/video/saa7134/saa7134-video.c b/drivers/media/video/saa7134/saa7134-video.c index aa7fa1f73a56..6a4ae89a81a9 100644 --- a/drivers/media/video/saa7134/saa7134-video.c +++ b/drivers/media/video/saa7134/saa7134-video.c @@ -31,11 +31,6 @@ #include "saa7134.h" #include -#ifdef CONFIG_VIDEO_V4L1_COMPAT -/* Include V4L1 specific functions. Should be removed soon */ -#include -#endif - /* ------------------------------------------------------------------ */ unsigned int video_debug; diff --git a/drivers/media/video/saa7146.h b/drivers/media/video/saa7146.h index 2830b5e33aec..9fadb331a40b 100644 --- a/drivers/media/video/saa7146.h +++ b/drivers/media/video/saa7146.h @@ -25,8 +25,6 @@ #include #include -#include - #ifndef O_NONCAP #define O_NONCAP O_TRUNC #endif diff --git a/drivers/media/video/v4l2-ioctl.c b/drivers/media/video/v4l2-ioctl.c index 6a7955547474..583f9c158e63 100644 --- a/drivers/media/video/v4l2-ioctl.c +++ b/drivers/media/video/v4l2-ioctl.c @@ -17,6 +17,7 @@ #include #define __OLD_VIDIOC_ /* To allow fixing old calls */ +#include #include #ifdef CONFIG_VIDEO_V4L1 diff --git a/drivers/media/video/vivi.c b/drivers/media/video/vivi.c index 616eb1a8dbee..980620f411f0 100644 --- a/drivers/media/video/vivi.c +++ b/drivers/media/video/vivi.c @@ -28,10 +28,6 @@ #include #include #include -#ifdef CONFIG_VIDEO_V4L1_COMPAT -/* Include V4L1 specific functions. Should be removed soon */ -#include -#endif #include #include #include diff --git a/drivers/media/video/w9966.c b/drivers/media/video/w9966.c index 038ff32b01b8..dcade619cbd8 100644 --- a/drivers/media/video/w9966.c +++ b/drivers/media/video/w9966.c @@ -57,7 +57,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/drivers/media/video/w9968cf.c b/drivers/media/video/w9968cf.c index fd5c4c87a73b..2a25580a4b66 100644 --- a/drivers/media/video/w9968cf.c +++ b/drivers/media/video/w9968cf.c @@ -42,6 +42,7 @@ #include #include #include +#include #include #include "w9968cf.h" diff --git a/drivers/media/video/zoran/zoran_driver.c b/drivers/media/video/zoran/zoran_driver.c index 2dd8d90aedf9..b7f03d163730 100644 --- a/drivers/media/video/zoran/zoran_driver.c +++ b/drivers/media/video/zoran/zoran_driver.c @@ -59,7 +59,7 @@ #include -#include +#include #include #include #include "videocodec.h" diff --git a/include/linux/videodev.h b/include/linux/videodev.h index 837f392fbe97..b19eab140977 100644 --- a/include/linux/videodev.h +++ b/include/linux/videodev.h @@ -16,6 +16,23 @@ #include #include +#if defined(__MIN_V4L1) && defined (__KERNEL__) + +/* + * Used by those V4L2 core functions that need a minimum V4L1 support, + * in order to allow V4L1 Compatibilty code compilation. + */ + +struct video_mbuf +{ + int size; /* Total memory to map */ + int frames; /* Frames */ + int offsets[VIDEO_MAX_FRAME]; +}; + +#define VIDIOCGMBUF _IOR('v',20, struct video_mbuf) /* Memory map buffer info */ + +#else #if defined(CONFIG_VIDEO_V4L1_COMPAT) || !defined (__KERNEL__) #define VID_TYPE_CAPTURE 1 /* Can capture */ @@ -312,6 +329,7 @@ struct video_code #define VID_PLAY_END_MARK 14 #endif /* CONFIG_VIDEO_V4L1_COMPAT */ +#endif /* __MIN_V4L1 */ #endif /* __LINUX_VIDEODEV_H */ diff --git a/include/media/v4l2-ioctl.h b/include/media/v4l2-ioctl.h index a8b4c0b678ec..7a4529defa88 100644 --- a/include/media/v4l2-ioctl.h +++ b/include/media/v4l2-ioctl.h @@ -15,6 +15,7 @@ #include #include /* need __user */ #ifdef CONFIG_VIDEO_V4L1_COMPAT +#define __MIN_V4L1 #include #else #include -- cgit v1.2.3 From cf5193c74009e33428daefbf74f4770733c8ee36 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 6 Mar 2009 09:29:09 -0300 Subject: V4L/DVB (10909): tvmixer: remove last remaining references to this deleted module. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- Documentation/video4linux/bttv/Insmod-options | 10 ---------- drivers/media/video/Makefile | 1 - 2 files changed, 11 deletions(-) (limited to 'drivers/media/video') diff --git a/Documentation/video4linux/bttv/Insmod-options b/Documentation/video4linux/bttv/Insmod-options index 5ef75787f83a..bbe3ed667d91 100644 --- a/Documentation/video4linux/bttv/Insmod-options +++ b/Documentation/video4linux/bttv/Insmod-options @@ -81,16 +81,6 @@ tuner.o pal=[bdgil] select PAL variant (used for some tuners only, important for the audio carrier). -tvmixer.o - registers a mixer device for the TV card's volume/bass/treble - controls (requires a i2c audio control chip like the msp3400). - - insmod args: - debug=1 print some debug info to the syslog. - devnr=n allocate device #n (0 == /dev/mixer, - 1 = /dev/mixer1, ...), default is to - use the first free one. - tvaudio.o new, experimental module which is supported to provide a single driver for all simple i2c audio control chips (tda/tea*). diff --git a/drivers/media/video/Makefile b/drivers/media/video/Makefile index 307490ebc230..08a0675fea34 100644 --- a/drivers/media/video/Makefile +++ b/drivers/media/video/Makefile @@ -30,7 +30,6 @@ obj-$(CONFIG_VIDEO_IR_I2C) += ir-kbd-i2c.o obj-$(CONFIG_VIDEO_TVAUDIO) += tvaudio.o obj-$(CONFIG_VIDEO_TDA7432) += tda7432.o obj-$(CONFIG_VIDEO_TDA9875) += tda9875.o -obj-$(CONFIG_SOUND_TVMIXER) += tvmixer.o obj-$(CONFIG_VIDEO_SAA6588) += saa6588.o obj-$(CONFIG_VIDEO_SAA5246A) += saa5246a.o -- cgit v1.2.3 From fbc9fa4e8781170e2fbca2859feda114d4758132 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 6 Mar 2009 09:55:42 -0300 Subject: V4L/DVB (10910): videodev2.h: remove deprecated VIDIOC_G_CHIP_IDENT_OLD As announced VIDIOC_G_CHIP_IDENT_OLD is now removed for 2.6.30. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/v4l2-compat-ioctl32.c | 1 - drivers/media/video/v4l2-ioctl.c | 5 ----- include/linux/videodev2.h | 10 ---------- 3 files changed, 16 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/v4l2-compat-ioctl32.c b/drivers/media/video/v4l2-compat-ioctl32.c index 110376be5d2b..0056b115b42e 100644 --- a/drivers/media/video/v4l2-compat-ioctl32.c +++ b/drivers/media/video/v4l2-compat-ioctl32.c @@ -1047,7 +1047,6 @@ long v4l2_compat_ioctl32(struct file *file, unsigned int cmd, unsigned long arg) case VIDIOC_DBG_S_REGISTER: case VIDIOC_DBG_G_REGISTER: case VIDIOC_DBG_G_CHIP_IDENT: - case VIDIOC_G_CHIP_IDENT_OLD: case VIDIOC_S_HW_FREQ_SEEK: ret = do_video_ioctl(file, cmd, arg); break; diff --git a/drivers/media/video/v4l2-ioctl.c b/drivers/media/video/v4l2-ioctl.c index 583f9c158e63..df8d1ff1a577 100644 --- a/drivers/media/video/v4l2-ioctl.c +++ b/drivers/media/video/v4l2-ioctl.c @@ -1692,11 +1692,6 @@ static long __video_do_ioctl(struct file *file, dbgarg(cmd, "chip_ident=%u, revision=0x%x\n", p->ident, p->revision); break; } - case VIDIOC_G_CHIP_IDENT_OLD: - printk(KERN_ERR "VIDIOC_G_CHIP_IDENT has been deprecated and will disappear in 2.6.30.\n"); - printk(KERN_ERR "It is a debugging ioctl and must not be used in applications!\n"); - return -EINVAL; - case VIDIOC_S_HW_FREQ_SEEK: { struct v4l2_hw_freq_seek *p = arg; diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h index 11b8b3ec77b4..78ba0755ffb3 100644 --- a/include/linux/videodev2.h +++ b/include/linux/videodev2.h @@ -1412,14 +1412,6 @@ struct v4l2_dbg_chip_ident { __u32 revision; /* chip revision, chip specific */ } __attribute__ ((packed)); -/* VIDIOC_G_CHIP_IDENT_OLD: Deprecated, do not use */ -struct v4l2_chip_ident_old { - __u32 match_type; /* Match type */ - __u32 match_chip; /* Match this chip, meaning determined by match_type */ - __u32 ident; /* chip identifier as specified in */ - __u32 revision; /* chip revision, chip specific */ -}; - /* * I O C T L C O D E S F O R V I D E O D E V I C E S * @@ -1497,8 +1489,6 @@ struct v4l2_chip_ident_old { /* Experimental, meant for debugging, testing and internal use. Never use this ioctl in applications! */ #define VIDIOC_DBG_G_CHIP_IDENT _IOWR('V', 81, struct v4l2_dbg_chip_ident) -/* This is deprecated and will go away in 2.6.30 */ -#define VIDIOC_G_CHIP_IDENT_OLD _IOWR('V', 81, struct v4l2_chip_ident_old) #endif #define VIDIOC_S_HW_FREQ_SEEK _IOW('V', 82, struct v4l2_hw_freq_seek) -- cgit v1.2.3 From 9185cbfc336a080695304bcb781186559d987974 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 6 Mar 2009 09:58:12 -0300 Subject: V4L/DVB (10912): vivi: fix compile warning. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/vivi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/vivi.c b/drivers/media/video/vivi.c index 980620f411f0..fbfefae7886f 100644 --- a/drivers/media/video/vivi.c +++ b/drivers/media/video/vivi.c @@ -1406,7 +1406,7 @@ free_dev: */ static int __init vivi_init(void) { - int ret, i; + int ret = 0, i; if (n_devs <= 0) n_devs = 1; -- cgit v1.2.3 From cc5cef8ea4fdc41b44007c5d2c116fe97cb87293 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 6 Mar 2009 10:15:01 -0300 Subject: V4L/DVB (10914): v4l2: fix compile warnings when printing u64 value. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/adv7170.c | 7 ++++--- drivers/media/video/adv7175.c | 5 +++-- drivers/media/video/bt819.c | 5 +++-- drivers/media/video/bt856.c | 2 +- drivers/media/video/bt866.c | 2 +- drivers/media/video/ks0127.c | 4 ++-- drivers/media/video/saa7110.c | 2 +- drivers/media/video/vpx3220.c | 2 +- 8 files changed, 16 insertions(+), 13 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/adv7170.c b/drivers/media/video/adv7170.c index 43fd1d24cdeb..873c30a41bd7 100644 --- a/drivers/media/video/adv7170.c +++ b/drivers/media/video/adv7170.c @@ -195,7 +195,7 @@ static int adv7170_s_std_output(struct v4l2_subdev *sd, v4l2_std_id std) { struct adv7170 *encoder = to_adv7170(sd); - v4l2_dbg(1, debug, sd, "set norm %llx\n", std); + v4l2_dbg(1, debug, sd, "set norm %llx\n", (unsigned long long)std); if (std & V4L2_STD_NTSC) { adv7170_write_block(sd, init_NTSC, sizeof(init_NTSC)); @@ -210,10 +210,11 @@ static int adv7170_s_std_output(struct v4l2_subdev *sd, v4l2_std_id std) adv7170_write(sd, 0x07, TR0MODE | TR0RST); adv7170_write(sd, 0x07, TR0MODE); } else { - v4l2_dbg(1, debug, sd, "illegal norm: %llx\n", std); + v4l2_dbg(1, debug, sd, "illegal norm: %llx\n", + (unsigned long long)std); return -EINVAL; } - v4l2_dbg(1, debug, sd, "switched to %llx\n", std); + v4l2_dbg(1, debug, sd, "switched to %llx\n", (unsigned long long)std); encoder->norm = std; return 0; } diff --git a/drivers/media/video/adv7175.c b/drivers/media/video/adv7175.c index 709e044f007d..ff1210303295 100644 --- a/drivers/media/video/adv7175.c +++ b/drivers/media/video/adv7175.c @@ -228,10 +228,11 @@ static int adv7175_s_std_output(struct v4l2_subdev *sd, v4l2_std_id std) adv7175_write(sd, 0x07, TR0MODE | TR0RST); adv7175_write(sd, 0x07, TR0MODE); } else { - v4l2_dbg(1, debug, sd, "illegal norm: %llx\n", std); + v4l2_dbg(1, debug, sd, "illegal norm: %llx\n", + (unsigned long long)std); return -EINVAL; } - v4l2_dbg(1, debug, sd, "switched to %llx\n", std); + v4l2_dbg(1, debug, sd, "switched to %llx\n", (unsigned long long)std); encoder->norm = std; return 0; } diff --git a/drivers/media/video/bt819.c b/drivers/media/video/bt819.c index f2ebf8441aa0..e0d8e2b186d1 100644 --- a/drivers/media/video/bt819.c +++ b/drivers/media/video/bt819.c @@ -248,7 +248,7 @@ static int bt819_s_std(struct v4l2_subdev *sd, v4l2_std_id std) struct bt819 *decoder = to_bt819(sd); struct timing *timing = NULL; - v4l2_dbg(1, debug, sd, "set norm %llx\n", std); + v4l2_dbg(1, debug, sd, "set norm %llx\n", (unsigned long long)std); if (std & V4L2_STD_NTSC) { bt819_setbit(decoder, 0x01, 0, 1); @@ -267,7 +267,8 @@ static int bt819_s_std(struct v4l2_subdev *sd, v4l2_std_id std) /* bt819_setbit(decoder, 0x1a, 5, 0); */ timing = &timing_data[0]; } else { - v4l2_dbg(1, debug, sd, "unsupported norm %llx\n", std); + v4l2_dbg(1, debug, sd, "unsupported norm %llx\n", + (unsigned long long)std); return -EINVAL; } bt819_write(decoder, 0x03, diff --git a/drivers/media/video/bt856.c b/drivers/media/video/bt856.c index af3c7a885d50..78db39503947 100644 --- a/drivers/media/video/bt856.c +++ b/drivers/media/video/bt856.c @@ -125,7 +125,7 @@ static int bt856_s_std_output(struct v4l2_subdev *sd, v4l2_std_id std) { struct bt856 *encoder = to_bt856(sd); - v4l2_dbg(1, debug, sd, "set norm %llx\n", std); + v4l2_dbg(1, debug, sd, "set norm %llx\n", (unsigned long long)std); if (std & V4L2_STD_NTSC) { bt856_setbit(encoder, 0xdc, 2, 0); diff --git a/drivers/media/video/bt866.c b/drivers/media/video/bt866.c index 0a32221fa3f9..350cae4b02c3 100644 --- a/drivers/media/video/bt866.c +++ b/drivers/media/video/bt866.c @@ -91,7 +91,7 @@ static int bt866_write(struct bt866 *encoder, u8 subaddr, u8 data) static int bt866_s_std_output(struct v4l2_subdev *sd, v4l2_std_id std) { - v4l2_dbg(1, debug, sd, "set norm %llx\n", std); + v4l2_dbg(1, debug, sd, "set norm %llx\n", (unsigned long long)std); /* Only PAL supported by this driver at the moment! */ if (!(std & V4L2_STD_NTSC)) diff --git a/drivers/media/video/ks0127.c b/drivers/media/video/ks0127.c index 678c4e23f0e8..4b3a116f2f59 100644 --- a/drivers/media/video/ks0127.c +++ b/drivers/media/video/ks0127.c @@ -579,8 +579,8 @@ static int ks0127_s_std(struct v4l2_subdev *sd, v4l2_std_id std) /* force to secam mode */ ks0127_and_or(sd, KS_DEMOD, 0xf0, 0x0f); } else { - v4l2_dbg(1, debug, sd, - "VIDIOC_S_STD: Unknown norm %llx\n", std); + v4l2_dbg(1, debug, sd, "VIDIOC_S_STD: Unknown norm %llx\n", + (unsigned long long)std); } return 0; } diff --git a/drivers/media/video/saa7110.c b/drivers/media/video/saa7110.c index 977de63fded0..df4e08d2dceb 100644 --- a/drivers/media/video/saa7110.c +++ b/drivers/media/video/saa7110.c @@ -251,7 +251,7 @@ static int saa7110_g_input_status(struct v4l2_subdev *sd, u32 *pstatus) int status = saa7110_read(sd); v4l2_dbg(1, debug, sd, "status=0x%02x norm=%llx\n", - status, decoder->norm); + status, (unsigned long long)decoder->norm); if (!(status & 0x40)) res = 0; if (!(status & 0x03)) diff --git a/drivers/media/video/vpx3220.c b/drivers/media/video/vpx3220.c index ed50b912d8a0..0cc23539f74d 100644 --- a/drivers/media/video/vpx3220.c +++ b/drivers/media/video/vpx3220.c @@ -354,7 +354,7 @@ static int vpx3220_s_std(struct v4l2_subdev *sd, v4l2_std_id std) choosen video norm */ temp_input = vpx3220_fp_read(sd, 0xf2); - v4l2_dbg(1, debug, sd, "VIDIOC_S_STD %llx\n", std); + v4l2_dbg(1, debug, sd, "VIDIOC_S_STD %llx\n", (unsigned long long)std); if (std & V4L2_STD_NTSC) { vpx3220_write_fp_block(sd, init_ntsc, sizeof(init_ntsc) >> 1); v4l2_dbg(1, debug, sd, "norm switched to NTSC\n"); -- cgit v1.2.3 From 501cd11a34cd29e20f040bfd8a9e2b6fe6908c91 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sat, 7 Mar 2009 13:10:43 -0300 Subject: V4L/DVB (10919): tlv320aic23b: use v4l2-i2c-drv.h instead of drv-legacy.h This driver isn't used in any legacy mode, so no need for v4l2-i2c-drv-legacy.h. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/tlv320aic23b.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/tlv320aic23b.c b/drivers/media/video/tlv320aic23b.c index b6e838ada66d..b8cc7d39a90a 100644 --- a/drivers/media/video/tlv320aic23b.c +++ b/drivers/media/video/tlv320aic23b.c @@ -31,15 +31,12 @@ #include #include #include -#include +#include MODULE_DESCRIPTION("tlv320aic23b driver"); MODULE_AUTHOR("Scott Alfter, Ulf Eklund, Hans Verkuil"); MODULE_LICENSE("GPL"); -static unsigned short normal_i2c[] = { 0x34 >> 1, I2C_CLIENT_END }; - -I2C_CLIENT_INSMOD; /* ----------------------------------------------------------------------- */ -- cgit v1.2.3 From 9f1a693f76700018d921cd7af86f7c994a300613 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sun, 8 Mar 2009 10:35:23 -0300 Subject: V4L/DVB (10920): v4l2-ioctl: fix partial-copy code. The code to optimize the usercopy only checked the ioctl NR field. However, this code is also called for non-V4L2 ioctls (either private or ioctls from linux/dvb/audio.h and linux/dvb/video.h for decoder drivers like ivtv). If such an ioctl has the same NR as a V4L2 ioctl, then disaster strikes. Modified the code to check on the full command ID. Thanks to Martin Dauskardt for tracing the ivtv breakage to this particular change. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/v4l2-ioctl.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/v4l2-ioctl.c b/drivers/media/video/v4l2-ioctl.c index df8d1ff1a577..54ba6b0b951f 100644 --- a/drivers/media/video/v4l2-ioctl.c +++ b/drivers/media/video/v4l2-ioctl.c @@ -1796,11 +1796,12 @@ static long __video_do_ioctl(struct file *file, static unsigned long cmd_input_size(unsigned int cmd) { /* Size of structure up to and including 'field' */ -#define CMDINSIZE(cmd, type, field) case _IOC_NR(VIDIOC_##cmd): return \ - offsetof(struct v4l2_##type, field) + \ - sizeof(((struct v4l2_##type *)0)->field); +#define CMDINSIZE(cmd, type, field) \ + case VIDIOC_##cmd: \ + return offsetof(struct v4l2_##type, field) + \ + sizeof(((struct v4l2_##type *)0)->field); - switch (_IOC_NR(cmd)) { + switch (cmd) { CMDINSIZE(ENUM_FMT, fmtdesc, type); CMDINSIZE(G_FMT, format, type); CMDINSIZE(QUERYBUF, buffer, type); -- cgit v1.2.3 From 1d578540a949802eebe8655c7ef9566c85966e32 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Tue, 10 Mar 2009 10:42:44 -0300 Subject: V4L/DVB (10921): msp3400: remove obsolete V4L1 code There are no drivers left that call msp3400 with V4L1 commands. Remove it from this driver. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/msp3400-driver.c | 116 ----------------------------------- 1 file changed, 116 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/msp3400-driver.c b/drivers/media/video/msp3400-driver.c index bca768a1f34c..204513ee3364 100644 --- a/drivers/media/video/msp3400-driver.c +++ b/drivers/media/video/msp3400-driver.c @@ -366,29 +366,6 @@ int msp_sleep(struct msp_state *state, int timeout) } /* ------------------------------------------------------------------------ */ -#ifdef CONFIG_VIDEO_ALLOW_V4L1 -static int msp_mode_v4l2_to_v4l1(int rxsubchans, int audmode) -{ - if (rxsubchans == V4L2_TUNER_SUB_MONO) - return VIDEO_SOUND_MONO; - if (rxsubchans == V4L2_TUNER_SUB_STEREO) - return VIDEO_SOUND_STEREO; - if (audmode == V4L2_TUNER_MODE_LANG2) - return VIDEO_SOUND_LANG2; - return VIDEO_SOUND_LANG1; -} - -static int msp_mode_v4l1_to_v4l2(int mode) -{ - if (mode & VIDEO_SOUND_STEREO) - return V4L2_TUNER_MODE_STEREO; - if (mode & VIDEO_SOUND_LANG2) - return V4L2_TUNER_MODE_LANG2; - if (mode & VIDEO_SOUND_LANG1) - return V4L2_TUNER_MODE_LANG1; - return V4L2_TUNER_MODE_MONO; -} -#endif static int msp_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) { @@ -482,96 +459,6 @@ static int msp_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) return 0; } -#ifdef CONFIG_VIDEO_ALLOW_V4L1 -static long msp_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg) -{ - struct msp_state *state = to_state(sd); - struct i2c_client *client = v4l2_get_subdevdata(sd); - - switch (cmd) { - /* --- v4l ioctls --- */ - /* take care: bttv does userspace copying, we'll get a - kernel pointer here... */ - case VIDIOCGAUDIO: - { - struct video_audio *va = arg; - - va->flags |= VIDEO_AUDIO_VOLUME | VIDEO_AUDIO_MUTABLE; - if (state->has_sound_processing) - va->flags |= VIDEO_AUDIO_BALANCE | - VIDEO_AUDIO_BASS | - VIDEO_AUDIO_TREBLE; - if (state->muted) - va->flags |= VIDEO_AUDIO_MUTE; - va->volume = state->volume; - va->balance = state->volume ? state->balance : 32768; - va->bass = state->bass; - va->treble = state->treble; - - if (state->radio) - break; - if (state->opmode == OPMODE_AUTOSELECT) - msp_detect_stereo(client); - va->mode = msp_mode_v4l2_to_v4l1(state->rxsubchans, state->audmode); - break; - } - - case VIDIOCSAUDIO: - { - struct video_audio *va = arg; - - state->muted = (va->flags & VIDEO_AUDIO_MUTE); - state->volume = va->volume; - state->balance = va->balance; - state->bass = va->bass; - state->treble = va->treble; - msp_set_audio(client); - - if (va->mode != 0 && state->radio == 0 && - state->audmode != msp_mode_v4l1_to_v4l2(va->mode)) { - state->audmode = msp_mode_v4l1_to_v4l2(va->mode); - msp_set_audmode(client); - } - break; - } - - case VIDIOCSCHAN: - { - struct video_channel *vc = arg; - int update = 0; - v4l2_std_id std; - - if (state->radio) - update = 1; - state->radio = 0; - if (vc->norm == VIDEO_MODE_PAL) - std = V4L2_STD_PAL; - else if (vc->norm == VIDEO_MODE_SECAM) - std = V4L2_STD_SECAM; - else - std = V4L2_STD_NTSC; - if (std != state->v4l2_std) { - state->v4l2_std = std; - update = 1; - } - if (update) - msp_wake_thread(client); - break; - } - - case VIDIOCSFREQ: - { - /* new channel -- kick audio carrier scan */ - msp_wake_thread(client); - break; - } - default: - return -ENOIOCTLCMD; - } - return 0; -} -#endif - /* --- v4l2 ioctls --- */ static int msp_s_radio(struct v4l2_subdev *sd) { @@ -822,9 +709,6 @@ static const struct v4l2_subdev_core_ops msp_core_ops = { .g_ctrl = msp_g_ctrl, .s_ctrl = msp_s_ctrl, .queryctrl = msp_queryctrl, -#ifdef CONFIG_VIDEO_ALLOW_V4L1 - .ioctl = msp_ioctl, -#endif }; static const struct v4l2_subdev_tuner_ops msp_tuner_ops = { -- cgit v1.2.3 From e8944282a76f94bcf84ae3b7a91328bd03835ea1 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Tue, 10 Mar 2009 17:02:07 -0300 Subject: V4L/DVB (10923): saa7134: fix typo in product name replace occurances of "HVR1150" with "HVR1120" - this was a typo. Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- Documentation/video4linux/CARDLIST.saa7134 | 2 +- drivers/media/video/saa7134/saa7134-cards.c | 20 ++++++++++---------- drivers/media/video/saa7134/saa7134.h | 2 +- 3 files changed, 12 insertions(+), 12 deletions(-) (limited to 'drivers/media/video') diff --git a/Documentation/video4linux/CARDLIST.saa7134 b/Documentation/video4linux/CARDLIST.saa7134 index 325c69fe91fd..626820e519e3 100644 --- a/Documentation/video4linux/CARDLIST.saa7134 +++ b/Documentation/video4linux/CARDLIST.saa7134 @@ -153,5 +153,5 @@ 152 -> Asus Tiger Rev:1.00 [1043:4857] 153 -> Kworld Plus TV Analog Lite PCI [17de:7128] 154 -> Avermedia AVerTV GO 007 FM Plus [1461:f31d] -155 -> Hauppauge WinTV-HVR1150 [0070:6706,0070:6708] +155 -> Hauppauge WinTV-HVR1120 [0070:6706,0070:6708] 156 -> Hauppauge WinTV-HVR1110r3 [0070:6707,0070:6709,0070:670a] diff --git a/drivers/media/video/saa7134/saa7134-cards.c b/drivers/media/video/saa7134/saa7134-cards.c index 88f0b8f06e10..be53d8f35425 100644 --- a/drivers/media/video/saa7134/saa7134-cards.c +++ b/drivers/media/video/saa7134/saa7134-cards.c @@ -3292,8 +3292,8 @@ struct saa7134_board saa7134_boards[] = { .gpio = 0x0200100, }, }, - [SAA7134_BOARD_HAUPPAUGE_HVR1150] = { - .name = "Hauppauge WinTV-HVR1150", + [SAA7134_BOARD_HAUPPAUGE_HVR1120] = { + .name = "Hauppauge WinTV-HVR1120", .audio_clock = 0x00187de7, .tuner_type = TUNER_PHILIPS_TDA8290, .radio_type = UNSET, @@ -5466,7 +5466,7 @@ struct pci_device_id saa7134_pci_tbl[] = { .device = PCI_DEVICE_ID_PHILIPS_SAA7133, .subvendor = 0x0070, .subdevice = 0x6706, - .driver_data = SAA7134_BOARD_HAUPPAUGE_HVR1150, + .driver_data = SAA7134_BOARD_HAUPPAUGE_HVR1120, },{ .vendor = PCI_VENDOR_ID_PHILIPS, .device = PCI_DEVICE_ID_PHILIPS_SAA7133, @@ -5478,7 +5478,7 @@ struct pci_device_id saa7134_pci_tbl[] = { .device = PCI_DEVICE_ID_PHILIPS_SAA7133, .subvendor = 0x0070, .subdevice = 0x6708, - .driver_data = SAA7134_BOARD_HAUPPAUGE_HVR1150, + .driver_data = SAA7134_BOARD_HAUPPAUGE_HVR1120, },{ .vendor = PCI_VENDOR_ID_PHILIPS, .device = PCI_DEVICE_ID_PHILIPS_SAA7133, @@ -5962,7 +5962,7 @@ static int saa7134_tda8290_18271_callback(struct saa7134_dev *dev, switch (command) { case TDA18271_CALLBACK_CMD_AGC_ENABLE: /* 0 */ switch (dev->board) { - case SAA7134_BOARD_HAUPPAUGE_HVR1150: + case SAA7134_BOARD_HAUPPAUGE_HVR1120: case SAA7134_BOARD_HAUPPAUGE_HVR1110R3: ret = saa7134_tda18271_hvr11x0_toggle_agc(dev, arg); break; @@ -5983,7 +5983,7 @@ static int saa7134_tda8290_callback(struct saa7134_dev *dev, int ret; switch (dev->board) { - case SAA7134_BOARD_HAUPPAUGE_HVR1150: + case SAA7134_BOARD_HAUPPAUGE_HVR1120: case SAA7134_BOARD_HAUPPAUGE_HVR1110R3: /* tda8290 + tda18271 */ ret = saa7134_tda8290_18271_callback(dev, command, arg); @@ -6026,7 +6026,7 @@ static void hauppauge_eeprom(struct saa7134_dev *dev, u8 *eeprom_data) switch (tv.model) { case 67019: /* WinTV-HVR1110 (Retail, IR Blaster, hybrid, FM, SVid/Comp, 3.5mm audio in) */ case 67109: /* WinTV-HVR1000 (Retail, IR Receive, analog, no FM, SVid/Comp, 3.5mm audio in) */ - case 67201: /* WinTV-HVR1150 (Retail, IR Receive, hybrid, FM, SVid/Comp, 3.5mm audio in) */ + case 67201: /* WinTV-HVR1120 (Retail, IR Receive, hybrid, FM, SVid/Comp, 3.5mm audio in) */ case 67301: /* WinTV-HVR1000 (Retail, IR Receive, analog, no FM, SVid/Comp, 3.5mm audio in) */ case 67209: /* WinTV-HVR1110 (Retail, IR Receive, hybrid, FM, SVid/Comp, 3.5mm audio in) */ case 67559: /* WinTV-HVR1110 (OEM, no IR, hybrid, FM, SVid/Comp, RCA aud) */ @@ -6034,7 +6034,7 @@ static void hauppauge_eeprom(struct saa7134_dev *dev, u8 *eeprom_data) case 67579: /* WinTV-HVR1110 (OEM, no IR, hybrid, no FM) */ case 67589: /* WinTV-HVR1110 (OEM, no IR, hybrid, no FM, SVid/Comp, RCA aud) */ case 67599: /* WinTV-HVR1110 (OEM, no IR, hybrid, no FM, SVid/Comp, RCA aud) */ - case 67651: /* WinTV-HVR1150 (OEM, no IR, hybrid, FM, SVid/Comp, RCA aud) */ + case 67651: /* WinTV-HVR1120 (OEM, no IR, hybrid, FM, SVid/Comp, RCA aud) */ case 67659: /* WinTV-HVR1110 (OEM, no IR, hybrid, FM, SVid/Comp, RCA aud) */ break; default: @@ -6212,7 +6212,7 @@ int saa7134_board_init1(struct saa7134_dev *dev) saa_writeb (SAA7134_PRODUCTION_TEST_MODE, 0x00); break; - case SAA7134_BOARD_HAUPPAUGE_HVR1150: + case SAA7134_BOARD_HAUPPAUGE_HVR1120: case SAA7134_BOARD_HAUPPAUGE_HVR1110R3: /* GPIO 26 high for digital, low for analog */ saa7134_set_gpio(dev, 26, 0); @@ -6474,7 +6474,7 @@ int saa7134_board_init2(struct saa7134_dev *dev) dev->name, saa7134_boards[dev->board].name); } break; - case SAA7134_BOARD_HAUPPAUGE_HVR1150: + case SAA7134_BOARD_HAUPPAUGE_HVR1120: case SAA7134_BOARD_HAUPPAUGE_HVR1110R3: hauppauge_eeprom(dev, dev->eedata+0x80); break; diff --git a/drivers/media/video/saa7134/saa7134.h b/drivers/media/video/saa7134/saa7134.h index 52d9397ad779..f078de98ef57 100644 --- a/drivers/media/video/saa7134/saa7134.h +++ b/drivers/media/video/saa7134/saa7134.h @@ -278,7 +278,7 @@ struct saa7134_format { #define SAA7134_BOARD_ASUSTeK_TIGER 152 #define SAA7134_BOARD_KWORLD_PLUS_TV_ANALOG 153 #define SAA7134_BOARD_AVERMEDIA_GO_007_FM_PLUS 154 -#define SAA7134_BOARD_HAUPPAUGE_HVR1150 155 +#define SAA7134_BOARD_HAUPPAUGE_HVR1120 155 #define SAA7134_BOARD_HAUPPAUGE_HVR1110R3 156 #define SAA7134_MAXBOARDS 32 -- cgit v1.2.3 From 90a4cc70fa853d83f0a7cc34b960744d8d0280e9 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Tue, 13 Jan 2009 04:03:26 -0300 Subject: V4L/DVB (10924): saa7134: enable serial transport streaming interface Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/saa7134/saa7134-ts.c | 15 +++++++++++++-- drivers/media/video/saa7134/saa7134.h | 6 ++++++ 2 files changed, 19 insertions(+), 2 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/saa7134/saa7134-ts.c b/drivers/media/video/saa7134/saa7134-ts.c index ef55a59f0cda..cc8b923afbc0 100644 --- a/drivers/media/video/saa7134/saa7134-ts.c +++ b/drivers/media/video/saa7134/saa7134-ts.c @@ -79,8 +79,19 @@ static int buffer_activate(struct saa7134_dev *dev, saa_writeb(SAA7134_TS_SERIAL1, 0x00); /* Start TS stream */ - saa_writeb(SAA7134_TS_SERIAL0, 0x40); - saa_writeb(SAA7134_TS_PARALLEL, 0xEC); + switch (saa7134_boards[dev->board].ts_type) { + case SAA7134_MPEG_TS_PARALLEL: + saa_writeb(SAA7134_TS_SERIAL0, 0x40); + saa_writeb(SAA7134_TS_PARALLEL, 0xec); + break; + case SAA7134_MPEG_TS_SERIAL: + saa_writeb(SAA7134_TS_SERIAL0, 0xd8); + saa_writeb(SAA7134_TS_PARALLEL, 0x6c); + saa_writeb(SAA7134_TS_PARALLEL_SERIAL, 0xbc); + saa_writeb(SAA7134_TS_SERIAL1, 0x02); + break; + } + dev->ts_state = SAA7134_TS_STARTED; } diff --git a/drivers/media/video/saa7134/saa7134.h b/drivers/media/video/saa7134/saa7134.h index f078de98ef57..d1498e55bef3 100644 --- a/drivers/media/video/saa7134/saa7134.h +++ b/drivers/media/video/saa7134/saa7134.h @@ -312,6 +312,11 @@ enum saa7134_mpeg_type { SAA7134_MPEG_DVB, }; +enum saa7134_mpeg_ts_type { + SAA7134_MPEG_TS_PARALLEL = 0, + SAA7134_MPEG_TS_SERIAL, +}; + struct saa7134_board { char *name; unsigned int audio_clock; @@ -334,6 +339,7 @@ struct saa7134_board { /* peripheral I/O */ enum saa7134_video_out video_out; enum saa7134_mpeg_type mpeg; + enum saa7134_mpeg_ts_type ts_type; unsigned int vid_port_opts; }; -- cgit v1.2.3 From 3abdedd8a4e3b1a0ad164c67929b3e798c85cd11 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Mon, 19 Jan 2009 01:10:49 -0300 Subject: V4L/DVB (10926): saa7134: enable digital tv support for Hauppauge WinTV-HVR1120 Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- Documentation/video4linux/CARDLIST.saa7134 | 2 +- drivers/media/video/saa7134/Kconfig | 3 ++ drivers/media/video/saa7134/saa7134-cards.c | 4 ++- drivers/media/video/saa7134/saa7134-dvb.c | 44 +++++++++++++++++++++++++++++ 4 files changed, 51 insertions(+), 2 deletions(-) (limited to 'drivers/media/video') diff --git a/Documentation/video4linux/CARDLIST.saa7134 b/Documentation/video4linux/CARDLIST.saa7134 index 626820e519e3..6dacf2825259 100644 --- a/Documentation/video4linux/CARDLIST.saa7134 +++ b/Documentation/video4linux/CARDLIST.saa7134 @@ -153,5 +153,5 @@ 152 -> Asus Tiger Rev:1.00 [1043:4857] 153 -> Kworld Plus TV Analog Lite PCI [17de:7128] 154 -> Avermedia AVerTV GO 007 FM Plus [1461:f31d] -155 -> Hauppauge WinTV-HVR1120 [0070:6706,0070:6708] +155 -> Hauppauge WinTV-HVR1120 ATSC/QAM-Hybrid [0070:6706,0070:6708] 156 -> Hauppauge WinTV-HVR1110r3 [0070:6707,0070:6709,0070:670a] diff --git a/drivers/media/video/saa7134/Kconfig b/drivers/media/video/saa7134/Kconfig index 51f17c82bc30..e62b2996768f 100644 --- a/drivers/media/video/saa7134/Kconfig +++ b/drivers/media/video/saa7134/Kconfig @@ -42,6 +42,9 @@ config VIDEO_SAA7134_DVB select DVB_MT312 if !DVB_FE_CUSTOMISE select DVB_LNBP21 if !DVB_FE_CUSTOMISE select DVB_ZL10353 if !DVB_FE_CUSTOMISE + select DVB_LGDT3305 if !DVB_FE_CUSTOMISE + select MEDIA_TUNER_TDA18271 if !MEDIA_TUNER_CUSTOMIZE + select MEDIA_TUNER_TDA8290 if !MEDIA_TUNER_CUSTOMIZE ---help--- This adds support for DVB cards based on the Philips saa7134 chip. diff --git a/drivers/media/video/saa7134/saa7134-cards.c b/drivers/media/video/saa7134/saa7134-cards.c index be53d8f35425..265a52ff8c33 100644 --- a/drivers/media/video/saa7134/saa7134-cards.c +++ b/drivers/media/video/saa7134/saa7134-cards.c @@ -3293,13 +3293,15 @@ struct saa7134_board saa7134_boards[] = { }, }, [SAA7134_BOARD_HAUPPAUGE_HVR1120] = { - .name = "Hauppauge WinTV-HVR1120", + .name = "Hauppauge WinTV-HVR1120 ATSC/QAM-Hybrid", .audio_clock = 0x00187de7, .tuner_type = TUNER_PHILIPS_TDA8290, .radio_type = UNSET, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, .tuner_config = 3, + .mpeg = SAA7134_MPEG_DVB, + .ts_type = SAA7134_MPEG_TS_SERIAL, .gpiomask = 0x0800100, /* GPIO 21 is an INPUT */ .inputs = {{ .name = name_tv, diff --git a/drivers/media/video/saa7134/saa7134-dvb.c b/drivers/media/video/saa7134/saa7134-dvb.c index 80ad96ad8939..4eff1ca8593c 100644 --- a/drivers/media/video/saa7134/saa7134-dvb.c +++ b/drivers/media/video/saa7134/saa7134-dvb.c @@ -48,6 +48,9 @@ #include "isl6405.h" #include "lnbp21.h" #include "tuner-simple.h" +#include "tda18271.h" +#include "lgdt3305.h" +#include "tda8290.h" #include "zl10353.h" @@ -964,6 +967,34 @@ static struct zl10036_config avertv_a700_tuner = { .tuner_address = 0x60, }; +static struct lgdt3305_config hcw_lgdt3305_config = { + .i2c_addr = 0x0e, + .mpeg_mode = LGDT3305_MPEG_SERIAL, + .tpclk_edge = LGDT3305_TPCLK_RISING_EDGE, + .tpvalid_polarity = LGDT3305_TP_VALID_HIGH, + .deny_i2c_rptr = 1, + .spectral_inversion = 1, + .qam_if_khz = 4000, + .vsb_if_khz = 3250, +}; + +static struct tda18271_std_map hauppauge_tda18271_std_map = { + .atsc_6 = { .if_freq = 3250, .agc_mode = 3, .std = 4, + .if_lvl = 1, .rfagc_top = 0x58, }, + .qam_6 = { .if_freq = 4000, .agc_mode = 3, .std = 5, + .if_lvl = 1, .rfagc_top = 0x58, }, +}; + +static struct tda18271_config hcw_tda18271_config = { + .std_map = &hauppauge_tda18271_std_map, + .gate = TDA18271_GATE_ANALOG, + .config = 3, +}; + +static struct tda829x_config tda829x_no_probe = { + .probe_tuner = TDA829X_DONT_PROBE, +}; + /* ================================================================== * Core code */ @@ -1090,6 +1121,19 @@ static int dvb_init(struct saa7134_dev *dev) &tda827x_cfg_1) < 0) goto dettach_frontend; break; + case SAA7134_BOARD_HAUPPAUGE_HVR1120: + fe0->dvb.frontend = dvb_attach(lgdt3305_attach, + &hcw_lgdt3305_config, + &dev->i2c_adap); + if (fe0->dvb.frontend) { + dvb_attach(tda829x_attach, fe0->dvb.frontend, + &dev->i2c_adap, 0x4b, + &tda829x_no_probe); + dvb_attach(tda18271_attach, fe0->dvb.frontend, + 0x60, &dev->i2c_adap, + &hcw_tda18271_config); + } + break; case SAA7134_BOARD_ASUSTeK_P7131_DUAL: if (configure_tda827x_fe(dev, &asus_p7131_dual_config, &tda827x_cfg_0) < 0) -- cgit v1.2.3 From 1159b7f19f324db0c61d1277987374865690ec06 Mon Sep 17 00:00:00 2001 From: Trent Piepho Date: Tue, 10 Mar 2009 23:28:16 -0300 Subject: V4L/DVB (10930): zoran: Unify buffer descriptors The zoran driver had two kinds of buffer descriptors, one for jpg buffers and one for raw buffers. They were mostly the same with only a couple Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/zoran/zoran.h | 59 +-- drivers/media/video/zoran/zoran_device.c | 12 +- drivers/media/video/zoran/zoran_driver.c | 829 +++++++++++++------------------ 3 files changed, 386 insertions(+), 514 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/zoran/zoran.h b/drivers/media/video/zoran/zoran.h index 8beada9613f6..afecf32f1a87 100644 --- a/drivers/media/video/zoran/zoran.h +++ b/drivers/media/video/zoran/zoran.h @@ -172,6 +172,8 @@ Private IOCTL to set up for displaying MJPEG #endif #define V4L_MASK_FRAME (V4L_MAX_FRAME - 1) +#define MAX_FRAME (BUZ_MAX_FRAME > VIDEO_MAX_FRAME ? BUZ_MAX_FRAME : VIDEO_MAX_FRAME) + #include "zr36057.h" enum card_type { @@ -280,21 +282,21 @@ struct zoran_mapping { int count; }; -struct zoran_jpg_buffer { - struct zoran_mapping *map; - __le32 *frag_tab; /* addresses of frag table */ - u32 frag_tab_bus; /* same value cached to save time in ISR */ - enum zoran_buffer_state state; /* non-zero if corresponding buffer is in use in grab queue */ - struct zoran_sync bs; /* DONE: info to return to application */ -}; - -struct zoran_v4l_buffer { +struct zoran_buffer { struct zoran_mapping *map; - char *fbuffer; /* virtual address of frame buffer */ - unsigned long fbuffer_phys; /* physical address of frame buffer */ - unsigned long fbuffer_bus; /* bus address of frame buffer */ - enum zoran_buffer_state state; /* state: unused/pending/done */ - struct zoran_sync bs; /* DONE: info to return to application */ + enum zoran_buffer_state state; /* state: unused/pending/dma/done */ + struct zoran_sync bs; /* DONE: info to return to application */ + union { + struct { + __le32 *frag_tab; /* addresses of frag table */ + u32 frag_tab_bus; /* same value cached to save time in ISR */ + } jpg; + struct { + char *fbuffer; /* virtual address of frame buffer */ + unsigned long fbuffer_phys;/* physical address of frame buffer */ + unsigned long fbuffer_bus;/* bus address of frame buffer */ + } v4l; + }; }; enum zoran_lock_activity { @@ -304,19 +306,13 @@ enum zoran_lock_activity { }; /* buffer collections */ -struct zoran_jpg_struct { +struct zoran_buffer_col { enum zoran_lock_activity active; /* feature currently in use? */ - struct zoran_jpg_buffer buffer[BUZ_MAX_FRAME]; /* buffers */ - int num_buffers, buffer_size; + unsigned int num_buffers, buffer_size; + struct zoran_buffer buffer[MAX_FRAME]; /* buffers */ u8 allocated; /* Flag if buffers are allocated */ u8 need_contiguous; /* Flag if contiguous buffers are needed */ -}; - -struct zoran_v4l_struct { - enum zoran_lock_activity active; /* feature currently in use? */ - struct zoran_v4l_buffer buffer[VIDEO_MAX_FRAME]; /* buffers */ - int num_buffers, buffer_size; - u8 allocated; /* Flag if buffers are allocated */ + /* only applies to jpg buffers, raw buffers are always contiguous */ }; struct zoran; @@ -325,17 +321,16 @@ struct zoran; struct zoran_fh { struct zoran *zr; - enum zoran_map_mode map_mode; /* Flag which bufferset will map by next mmap() */ + enum zoran_map_mode map_mode; /* Flag which bufferset will map by next mmap() */ struct zoran_overlay_settings overlay_settings; - u32 *overlay_mask; /* overlay mask */ - enum zoran_lock_activity overlay_active; /* feature currently in use? */ + u32 *overlay_mask; /* overlay mask */ + enum zoran_lock_activity overlay_active;/* feature currently in use? */ - struct zoran_v4l_settings v4l_settings; /* structure with a lot of things to play with */ - struct zoran_v4l_struct v4l_buffers; /* V4L buffers' info */ + struct zoran_buffer_col buffers; /* buffers' info */ + struct zoran_v4l_settings v4l_settings; /* structure with a lot of things to play with */ struct zoran_jpg_settings jpg_settings; /* structure with a lot of things to play with */ - struct zoran_jpg_struct jpg_buffers; /* MJPEG buffers' info */ }; struct card_info { @@ -434,7 +429,7 @@ struct zoran { unsigned long v4l_pend_tail; unsigned long v4l_sync_tail; int v4l_pend[V4L_MAX_FRAME]; - struct zoran_v4l_struct v4l_buffers; /* V4L buffers' info */ + struct zoran_buffer_col v4l_buffers; /* V4L buffers' info */ /* Buz MJPEG parameters */ enum zoran_codec_mode codec_mode; /* status of codec */ @@ -461,7 +456,7 @@ struct zoran { int jpg_pend[BUZ_MAX_FRAME]; /* array indexed by frame number */ - struct zoran_jpg_struct jpg_buffers; /* MJPEG buffers' info */ + struct zoran_buffer_col jpg_buffers; /* MJPEG buffers' info */ /* Additional stuff for testing */ #ifdef CONFIG_PROC_FS diff --git a/drivers/media/video/zoran/zoran_device.c b/drivers/media/video/zoran/zoran_device.c index 49e91b2ed552..4dc951322ef4 100644 --- a/drivers/media/video/zoran/zoran_device.c +++ b/drivers/media/video/zoran/zoran_device.c @@ -1125,7 +1125,7 @@ zoran_feed_stat_com (struct zoran *zr) if (!(zr->stat_com[i] & cpu_to_le32(1))) break; zr->stat_com[i] = - cpu_to_le32(zr->jpg_buffers.buffer[frame].frag_tab_bus); + cpu_to_le32(zr->jpg_buffers.buffer[frame].jpg.frag_tab_bus); } else { /* fill 2 stat_com entries */ i = ((zr->jpg_dma_head - @@ -1133,9 +1133,9 @@ zoran_feed_stat_com (struct zoran *zr) if (!(zr->stat_com[i] & cpu_to_le32(1))) break; zr->stat_com[i] = - cpu_to_le32(zr->jpg_buffers.buffer[frame].frag_tab_bus); + cpu_to_le32(zr->jpg_buffers.buffer[frame].jpg.frag_tab_bus); zr->stat_com[i + 1] = - cpu_to_le32(zr->jpg_buffers.buffer[frame].frag_tab_bus); + cpu_to_le32(zr->jpg_buffers.buffer[frame].jpg.frag_tab_bus); } zr->jpg_buffers.buffer[frame].state = BUZ_STATE_DMA; zr->jpg_dma_head++; @@ -1155,7 +1155,7 @@ zoran_reap_stat_com (struct zoran *zr) u32 stat_com; unsigned int seq; unsigned int dif; - struct zoran_jpg_buffer *buffer; + struct zoran_buffer *buffer; int frame; /* In motion decompress we don't have a hardware frame counter, @@ -1298,7 +1298,7 @@ error_handler (struct zoran *zr, printk(KERN_INFO "stat_com frames:"); for (j = 0; j < BUZ_NUM_STAT_COM; j++) { for (i = 0; i < zr->jpg_buffers.num_buffers; i++) { - if (le32_to_cpu(zr->stat_com[j]) == zr->jpg_buffers.buffer[i].frag_tab_bus) + if (le32_to_cpu(zr->stat_com[j]) == zr->jpg_buffers.buffer[i].jpg.frag_tab_bus) printk(KERN_CONT "% d->%d", j, i); } } @@ -1437,7 +1437,7 @@ zoran_irq (int irq, /* Buffer address */ - reg = zr->v4l_buffers.buffer[frame].fbuffer_bus; + reg = zr->v4l_buffers.buffer[frame].v4l.fbuffer_bus; btwrite(reg, ZR36057_VDTR); if (zr->v4l_settings.height > BUZ_MAX_HEIGHT / 2) reg += zr->v4l_settings.bytesperline; diff --git a/drivers/media/video/zoran/zoran_driver.c b/drivers/media/video/zoran/zoran_driver.c index b7f03d163730..26be1a8908a3 100644 --- a/drivers/media/video/zoran/zoran_driver.c +++ b/drivers/media/video/zoran/zoran_driver.c @@ -193,6 +193,24 @@ zoran_v4l2_calc_bufsize (struct zoran_jpg_settings *settings) static void v4l_fbuffer_free(struct file *file); static void jpg_fbuffer_free(struct file *file); +/* Set mapping mode */ +static void map_mode_raw(struct zoran_fh *fh) +{ + fh->map_mode = ZORAN_MAP_MODE_RAW; + fh->buffers.buffer_size = v4l_bufsize; + fh->buffers.num_buffers = v4l_nbufs; +} +static void map_mode_jpg(struct zoran_fh *fh, int play) +{ + fh->map_mode = play ? ZORAN_MAP_MODE_JPG_PLAY : ZORAN_MAP_MODE_JPG_REC; + fh->buffers.buffer_size = jpg_bufsize; + fh->buffers.num_buffers = jpg_nbufs; +} +static inline const char *mode_name(enum zoran_map_mode mode) +{ + return mode == ZORAN_MAP_MODE_RAW ? "V4L" : "JPG"; +} + /* * Allocate the V4L grab buffers * @@ -207,15 +225,15 @@ v4l_fbuffer_alloc (struct file *file) int i, off; unsigned char *mem; - for (i = 0; i < fh->v4l_buffers.num_buffers; i++) { - if (fh->v4l_buffers.buffer[i].fbuffer) + for (i = 0; i < fh->buffers.num_buffers; i++) { + if (fh->buffers.buffer[i].v4l.fbuffer) dprintk(2, KERN_WARNING "%s: v4l_fbuffer_alloc() - buffer %d already allocated!?\n", ZR_DEVNAME(zr), i); //udelay(20); - mem = kmalloc(fh->v4l_buffers.buffer_size, GFP_KERNEL); + mem = kmalloc(fh->buffers.buffer_size, GFP_KERNEL); if (!mem) { dprintk(1, KERN_ERR @@ -224,12 +242,10 @@ v4l_fbuffer_alloc (struct file *file) v4l_fbuffer_free(file); return -ENOBUFS; } - fh->v4l_buffers.buffer[i].fbuffer = mem; - fh->v4l_buffers.buffer[i].fbuffer_phys = - virt_to_phys(mem); - fh->v4l_buffers.buffer[i].fbuffer_bus = - virt_to_bus(mem); - for (off = 0; off < fh->v4l_buffers.buffer_size; + fh->buffers.buffer[i].v4l.fbuffer = mem; + fh->buffers.buffer[i].v4l.fbuffer_phys = virt_to_phys(mem); + fh->buffers.buffer[i].v4l.fbuffer_bus = virt_to_bus(mem); + for (off = 0; off < fh->buffers.buffer_size; off += PAGE_SIZE) SetPageReserved(virt_to_page(mem + off)); dprintk(4, @@ -239,7 +255,7 @@ v4l_fbuffer_alloc (struct file *file) virt_to_bus(mem)); } - fh->v4l_buffers.allocated = 1; + fh->buffers.allocated = 1; return 0; } @@ -255,19 +271,19 @@ v4l_fbuffer_free (struct file *file) dprintk(4, KERN_INFO "%s: v4l_fbuffer_free()\n", ZR_DEVNAME(zr)); - for (i = 0; i < fh->v4l_buffers.num_buffers; i++) { - if (!fh->v4l_buffers.buffer[i].fbuffer) + for (i = 0; i < fh->buffers.num_buffers; i++) { + if (!fh->buffers.buffer[i].v4l.fbuffer) continue; - mem = fh->v4l_buffers.buffer[i].fbuffer; - for (off = 0; off < fh->v4l_buffers.buffer_size; + mem = fh->buffers.buffer[i].v4l.fbuffer; + for (off = 0; off < fh->buffers.buffer_size; off += PAGE_SIZE) ClearPageReserved(virt_to_page(mem + off)); - kfree((void *) fh->v4l_buffers.buffer[i].fbuffer); - fh->v4l_buffers.buffer[i].fbuffer = NULL; + kfree(fh->buffers.buffer[i].v4l.fbuffer); + fh->buffers.buffer[i].v4l.fbuffer = NULL; } - fh->v4l_buffers.allocated = 0; + fh->buffers.allocated = 0; } /* @@ -304,10 +320,10 @@ jpg_fbuffer_alloc (struct file *file) struct zoran_fh *fh = file->private_data; struct zoran *zr = fh->zr; int i, j, off; - unsigned long mem; + u8 *mem; - for (i = 0; i < fh->jpg_buffers.num_buffers; i++) { - if (fh->jpg_buffers.buffer[i].frag_tab) + for (i = 0; i < fh->buffers.num_buffers; i++) { + if (fh->buffers.buffer[i].jpg.frag_tab) dprintk(2, KERN_WARNING "%s: jpg_fbuffer_alloc() - buffer %d already allocated!?\n", @@ -315,7 +331,7 @@ jpg_fbuffer_alloc (struct file *file) /* Allocate fragment table for this buffer */ - mem = get_zeroed_page(GFP_KERNEL); + mem = (void *)get_zeroed_page(GFP_KERNEL); if (mem == 0) { dprintk(1, KERN_ERR @@ -324,17 +340,12 @@ jpg_fbuffer_alloc (struct file *file) jpg_fbuffer_free(file); return -ENOBUFS; } - fh->jpg_buffers.buffer[i].frag_tab = (__le32 *) mem; - fh->jpg_buffers.buffer[i].frag_tab_bus = - virt_to_bus((void *) mem); - - //if (alloc_contig) { - if (fh->jpg_buffers.need_contiguous) { - mem = - (unsigned long) kmalloc(fh->jpg_buffers. - buffer_size, - GFP_KERNEL); - if (mem == 0) { + fh->buffers.buffer[i].jpg.frag_tab = (__le32 *)mem; + fh->buffers.buffer[i].jpg.frag_tab_bus = virt_to_bus(mem); + + if (fh->buffers.need_contiguous) { + mem = kmalloc(fh->buffers.buffer_size, GFP_KERNEL); + if (mem == NULL) { dprintk(1, KERN_ERR "%s: jpg_fbuffer_alloc() - kmalloc failed for buffer %d\n", @@ -342,20 +353,17 @@ jpg_fbuffer_alloc (struct file *file) jpg_fbuffer_free(file); return -ENOBUFS; } - fh->jpg_buffers.buffer[i].frag_tab[0] = - cpu_to_le32(virt_to_bus((void *) mem)); - fh->jpg_buffers.buffer[i].frag_tab[1] = - cpu_to_le32(((fh->jpg_buffers.buffer_size / 4) << 1) | 1); - for (off = 0; off < fh->jpg_buffers.buffer_size; - off += PAGE_SIZE) + fh->buffers.buffer[i].jpg.frag_tab[0] = + cpu_to_le32(virt_to_bus(mem)); + fh->buffers.buffer[i].jpg.frag_tab[1] = + cpu_to_le32((fh->buffers.buffer_size >> 1) | 1); + for (off = 0; off < fh->buffers.buffer_size; off += PAGE_SIZE) SetPageReserved(virt_to_page(mem + off)); } else { /* jpg_bufsize is already page aligned */ - for (j = 0; - j < fh->jpg_buffers.buffer_size / PAGE_SIZE; - j++) { - mem = get_zeroed_page(GFP_KERNEL); - if (mem == 0) { + for (j = 0; j < fh->buffers.buffer_size / PAGE_SIZE; j++) { + mem = (void *)get_zeroed_page(GFP_KERNEL); + if (mem == NULL) { dprintk(1, KERN_ERR "%s: jpg_fbuffer_alloc() - get_zeroed_page failed for buffer %d\n", @@ -364,25 +372,23 @@ jpg_fbuffer_alloc (struct file *file) return -ENOBUFS; } - fh->jpg_buffers.buffer[i].frag_tab[2 * j] = - cpu_to_le32(virt_to_bus((void *) mem)); - fh->jpg_buffers.buffer[i].frag_tab[2 * j + - 1] = - cpu_to_le32((PAGE_SIZE / 4) << 1); + fh->buffers.buffer[i].jpg.frag_tab[2 * j] = + cpu_to_le32(virt_to_bus(mem)); + fh->buffers.buffer[i].jpg.frag_tab[2 * j + 1] = + cpu_to_le32((PAGE_SIZE >> 2) << 1); SetPageReserved(virt_to_page(mem)); } - fh->jpg_buffers.buffer[i].frag_tab[2 * j - 1] |= cpu_to_le32(1); + fh->buffers.buffer[i].jpg.frag_tab[2 * j - 1] |= cpu_to_le32(1); } } dprintk(4, KERN_DEBUG "%s: jpg_fbuffer_alloc() - %d KB allocated\n", ZR_DEVNAME(zr), - (fh->jpg_buffers.num_buffers * - fh->jpg_buffers.buffer_size) >> 10); + (fh->buffers.num_buffers * fh->buffers.buffer_size) >> 10); - fh->jpg_buffers.allocated = 1; + fh->buffers.allocated = 1; return 0; } @@ -396,42 +402,44 @@ jpg_fbuffer_free (struct file *file) int i, j, off; unsigned char *mem; __le32 frag_tab; + struct zoran_buffer *buffer; dprintk(4, KERN_DEBUG "%s: jpg_fbuffer_free()\n", ZR_DEVNAME(zr)); - for (i = 0; i < fh->jpg_buffers.num_buffers; i++) { - if (!fh->jpg_buffers.buffer[i].frag_tab) + for (i = 0, buffer = &fh->buffers.buffer[0]; + i < fh->buffers.num_buffers; i++, buffer++) { + if (!buffer->jpg.frag_tab) continue; - if (fh->jpg_buffers.need_contiguous) { - frag_tab = fh->jpg_buffers.buffer[i].frag_tab[0]; + if (fh->buffers.need_contiguous) { + frag_tab = buffer->jpg.frag_tab[0]; if (frag_tab) { - mem = (unsigned char *)bus_to_virt(le32_to_cpu(frag_tab)); - for (off = 0; off < fh->jpg_buffers.buffer_size; off += PAGE_SIZE) + mem = bus_to_virt(le32_to_cpu(frag_tab)); + for (off = 0; off < fh->buffers.buffer_size; off += PAGE_SIZE) ClearPageReserved(virt_to_page(mem + off)); kfree(mem); - fh->jpg_buffers.buffer[i].frag_tab[0] = 0; - fh->jpg_buffers.buffer[i].frag_tab[1] = 0; + buffer->jpg.frag_tab[0] = 0; + buffer->jpg.frag_tab[1] = 0; } } else { - for (j = 0; j < fh->jpg_buffers.buffer_size / PAGE_SIZE; j++) { - frag_tab = fh->jpg_buffers.buffer[i].frag_tab[2 * j]; + for (j = 0; j < fh->buffers.buffer_size / PAGE_SIZE; j++) { + frag_tab = buffer->jpg.frag_tab[2 * j]; if (!frag_tab) break; ClearPageReserved(virt_to_page(bus_to_virt(le32_to_cpu(frag_tab)))); free_page((unsigned long)bus_to_virt(le32_to_cpu(frag_tab))); - fh->jpg_buffers.buffer[i].frag_tab[2 * j] = 0; - fh->jpg_buffers.buffer[i].frag_tab[2 * j + 1] = 0; + buffer->jpg.frag_tab[2 * j] = 0; + buffer->jpg.frag_tab[2 * j + 1] = 0; } } - free_page((unsigned long)fh->jpg_buffers.buffer[i].frag_tab); - fh->jpg_buffers.buffer[i].frag_tab = NULL; + free_page((unsigned long)buffer->jpg.frag_tab); + buffer->jpg.frag_tab = NULL; } - fh->jpg_buffers.allocated = 0; + fh->buffers.allocated = 0; } /* @@ -439,12 +447,11 @@ jpg_fbuffer_free (struct file *file) */ static int -zoran_v4l_set_format (struct file *file, +zoran_v4l_set_format (struct zoran_fh *fh, int width, int height, const struct zoran_format *format) { - struct zoran_fh *fh = file->private_data; struct zoran *zr = fh->zr; int bpp; @@ -462,11 +469,11 @@ zoran_v4l_set_format (struct file *file, bpp = (format->depth + 7) / 8; /* Check against available buffer size */ - if (height * width * bpp > fh->v4l_buffers.buffer_size) { + if (height * width * bpp > fh->buffers.buffer_size) { dprintk(1, KERN_ERR "%s: v4l_set_format() - video buffer size (%d kB) is too small\n", - ZR_DEVNAME(zr), fh->v4l_buffers.buffer_size >> 10); + ZR_DEVNAME(zr), fh->buffers.buffer_size >> 10); return -EINVAL; } @@ -497,7 +504,7 @@ zoran_v4l_queue_frame (struct file *file, unsigned long flags; int res = 0; - if (!fh->v4l_buffers.allocated) { + if (!fh->buffers.allocated) { dprintk(1, KERN_ERR "%s: v4l_queue_frame() - buffers not yet allocated\n", @@ -506,7 +513,7 @@ zoran_v4l_queue_frame (struct file *file, } /* No grabbing outside the buffer range! */ - if (num >= fh->v4l_buffers.num_buffers || num < 0) { + if (num >= fh->buffers.num_buffers || num < 0) { dprintk(1, KERN_ERR "%s: v4l_queue_frame() - buffer %d is out of range\n", @@ -516,10 +523,10 @@ zoran_v4l_queue_frame (struct file *file, spin_lock_irqsave(&zr->spinlock, flags); - if (fh->v4l_buffers.active == ZORAN_FREE) { + if (fh->buffers.active == ZORAN_FREE) { if (zr->v4l_buffers.active == ZORAN_FREE) { - zr->v4l_buffers = fh->v4l_buffers; - fh->v4l_buffers.active = ZORAN_ACTIVE; + zr->v4l_buffers = fh->buffers; + fh->buffers.active = ZORAN_ACTIVE; } else { dprintk(1, KERN_ERR @@ -535,7 +542,7 @@ zoran_v4l_queue_frame (struct file *file, default: case BUZ_STATE_PEND: if (zr->v4l_buffers.active == ZORAN_FREE) { - fh->v4l_buffers.active = ZORAN_FREE; + fh->buffers.active = ZORAN_FREE; zr->v4l_buffers.allocated = 0; } res = -EBUSY; /* what are you doing? */ @@ -548,14 +555,12 @@ zoran_v4l_queue_frame (struct file *file, case BUZ_STATE_USER: /* since there is at least one unused buffer there's room for at least * one more pend[] entry */ - zr->v4l_pend[zr->v4l_pend_head++ & - V4L_MASK_FRAME] = num; + zr->v4l_pend[zr->v4l_pend_head++ & V4L_MASK_FRAME] = num; zr->v4l_buffers.buffer[num].state = BUZ_STATE_PEND; zr->v4l_buffers.buffer[num].bs.length = fh->v4l_settings.bytesperline * zr->v4l_settings.height; - fh->v4l_buffers.buffer[num] = - zr->v4l_buffers.buffer[num]; + fh->buffers.buffer[num] = zr->v4l_buffers.buffer[num]; break; } } @@ -563,7 +568,7 @@ zoran_v4l_queue_frame (struct file *file, spin_unlock_irqrestore(&zr->spinlock, flags); if (!res && zr->v4l_buffers.active == ZORAN_FREE) - zr->v4l_buffers.active = fh->v4l_buffers.active; + zr->v4l_buffers.active = fh->buffers.active; return res; } @@ -580,7 +585,7 @@ v4l_sync (struct file *file, struct zoran *zr = fh->zr; unsigned long flags; - if (fh->v4l_buffers.active == ZORAN_FREE) { + if (fh->buffers.active == ZORAN_FREE) { dprintk(1, KERN_ERR "%s: v4l_sync() - no grab active for this session\n", @@ -589,7 +594,7 @@ v4l_sync (struct file *file, } /* check passed-in frame number */ - if (frame >= fh->v4l_buffers.num_buffers || frame < 0) { + if (frame >= fh->buffers.num_buffers || frame < 0) { dprintk(1, KERN_ERR "%s: v4l_sync() - frame %d is invalid\n", ZR_DEVNAME(zr), frame); @@ -607,8 +612,7 @@ v4l_sync (struct file *file, /* wait on this buffer to get ready */ if (!wait_event_interruptible_timeout(zr->v4l_capq, - (zr->v4l_buffers.buffer[frame].state != BUZ_STATE_PEND), - 10*HZ)) + (zr->v4l_buffers.buffer[frame].state != BUZ_STATE_PEND), 10*HZ)) return -ETIME; if (signal_pending(current)) return -ERESTARTSYS; @@ -620,7 +624,7 @@ v4l_sync (struct file *file, ZR_DEVNAME(zr)); zr->v4l_buffers.buffer[frame].state = BUZ_STATE_USER; - fh->v4l_buffers.buffer[frame] = zr->v4l_buffers.buffer[frame]; + fh->buffers.buffer[frame] = zr->v4l_buffers.buffer[frame]; spin_lock_irqsave(&zr->spinlock, flags); @@ -628,8 +632,7 @@ v4l_sync (struct file *file, if (zr->v4l_pend_tail == zr->v4l_pend_head) { zr36057_set_memgrab(zr, 0); if (zr->v4l_buffers.active == ZORAN_ACTIVE) { - fh->v4l_buffers.active = zr->v4l_buffers.active = - ZORAN_FREE; + fh->buffers.active = zr->v4l_buffers.active = ZORAN_FREE; zr->v4l_buffers.allocated = 0; } } @@ -654,7 +657,7 @@ zoran_jpg_queue_frame (struct file *file, int res = 0; /* Check if buffers are allocated */ - if (!fh->jpg_buffers.allocated) { + if (!fh->buffers.allocated) { dprintk(1, KERN_ERR "%s: jpg_queue_frame() - buffers not yet allocated\n", @@ -663,7 +666,7 @@ zoran_jpg_queue_frame (struct file *file, } /* No grabbing outside the buffer range! */ - if (num >= fh->jpg_buffers.num_buffers || num < 0) { + if (num >= fh->buffers.num_buffers || num < 0) { dprintk(1, KERN_ERR "%s: jpg_queue_frame() - buffer %d out of range\n", @@ -683,10 +686,10 @@ zoran_jpg_queue_frame (struct file *file, return -EINVAL; } - if (fh->jpg_buffers.active == ZORAN_FREE) { + if (fh->buffers.active == ZORAN_FREE) { if (zr->jpg_buffers.active == ZORAN_FREE) { - zr->jpg_buffers = fh->jpg_buffers; - fh->jpg_buffers.active = ZORAN_ACTIVE; + zr->jpg_buffers = fh->buffers; + fh->buffers.active = ZORAN_ACTIVE; } else { dprintk(1, KERN_ERR @@ -713,18 +716,16 @@ zoran_jpg_queue_frame (struct file *file, case BUZ_STATE_USER: /* since there is at least one unused buffer there's room for at *least one more pend[] entry */ - zr->jpg_pend[zr->jpg_que_head++ & BUZ_MASK_FRAME] = - num; + zr->jpg_pend[zr->jpg_que_head++ & BUZ_MASK_FRAME] = num; zr->jpg_buffers.buffer[num].state = BUZ_STATE_PEND; - fh->jpg_buffers.buffer[num] = - zr->jpg_buffers.buffer[num]; + fh->buffers.buffer[num] = zr->jpg_buffers.buffer[num]; zoran_feed_stat_com(zr); break; default: case BUZ_STATE_DMA: case BUZ_STATE_PEND: if (zr->jpg_buffers.active == ZORAN_FREE) { - fh->jpg_buffers.active = ZORAN_FREE; + fh->buffers.active = ZORAN_FREE; zr->jpg_buffers.allocated = 0; } res = -EBUSY; /* what are you doing? */ @@ -734,9 +735,8 @@ zoran_jpg_queue_frame (struct file *file, spin_unlock_irqrestore(&zr->spinlock, flags); - if (!res && zr->jpg_buffers.active == ZORAN_FREE) { - zr->jpg_buffers.active = fh->jpg_buffers.active; - } + if (!res && zr->jpg_buffers.active == ZORAN_FREE) + zr->jpg_buffers.active = fh->buffers.active; return res; } @@ -753,15 +753,14 @@ jpg_qbuf (struct file *file, /* Does the user want to stop streaming? */ if (frame < 0) { if (zr->codec_mode == mode) { - if (fh->jpg_buffers.active == ZORAN_FREE) { + if (fh->buffers.active == ZORAN_FREE) { dprintk(1, KERN_ERR "%s: jpg_qbuf(-1) - session not active\n", ZR_DEVNAME(zr)); return -EINVAL; } - fh->jpg_buffers.active = zr->jpg_buffers.active = - ZORAN_FREE; + fh->buffers.active = zr->jpg_buffers.active = ZORAN_FREE; zr->jpg_buffers.allocated = 0; zr36057_enable_jpg(zr, BUZ_MODE_IDLE); return 0; @@ -797,7 +796,7 @@ jpg_sync (struct file *file, unsigned long flags; int frame; - if (fh->jpg_buffers.active == ZORAN_FREE) { + if (fh->buffers.active == ZORAN_FREE) { dprintk(1, KERN_ERR "%s: jpg_sync() - capture is not currently active\n", @@ -849,7 +848,7 @@ jpg_sync (struct file *file, *bs = zr->jpg_buffers.buffer[frame].bs; bs->frame = frame; zr->jpg_buffers.buffer[frame].state = BUZ_STATE_USER; - fh->jpg_buffers.buffer[frame] = zr->jpg_buffers.buffer[frame]; + fh->buffers.buffer[frame] = zr->jpg_buffers.buffer[frame]; spin_unlock_irqrestore(&zr->spinlock, flags); @@ -864,7 +863,7 @@ zoran_open_init_session (struct file *file) struct zoran *zr = fh->zr; /* Per default, map the V4L Buffers */ - fh->map_mode = ZORAN_MAP_MODE_RAW; + map_mode_raw(fh); /* take over the card's current settings */ fh->overlay_settings = zr->overlay_settings; @@ -874,32 +873,17 @@ zoran_open_init_session (struct file *file) /* v4l settings */ fh->v4l_settings = zr->v4l_settings; - - /* v4l_buffers */ - memset(&fh->v4l_buffers, 0, sizeof(struct zoran_v4l_struct)); - for (i = 0; i < VIDEO_MAX_FRAME; i++) { - fh->v4l_buffers.buffer[i].state = BUZ_STATE_USER; /* nothing going on */ - fh->v4l_buffers.buffer[i].bs.frame = i; - } - fh->v4l_buffers.allocated = 0; - fh->v4l_buffers.active = ZORAN_FREE; - fh->v4l_buffers.buffer_size = v4l_bufsize; - fh->v4l_buffers.num_buffers = v4l_nbufs; - /* jpg settings */ fh->jpg_settings = zr->jpg_settings; - /* jpg_buffers */ - memset(&fh->jpg_buffers, 0, sizeof(struct zoran_jpg_struct)); - for (i = 0; i < BUZ_MAX_FRAME; i++) { - fh->jpg_buffers.buffer[i].state = BUZ_STATE_USER; /* nothing going on */ - fh->jpg_buffers.buffer[i].bs.frame = i; + /* buffers */ + memset(&fh->buffers, 0, sizeof(fh->buffers)); + for (i = 0; i < MAX_FRAME; i++) { + fh->buffers.buffer[i].state = BUZ_STATE_USER; /* nothing going on */ + fh->buffers.buffer[i].bs.frame = i; } - fh->jpg_buffers.need_contiguous = zr->jpg_buffers.need_contiguous; - fh->jpg_buffers.allocated = 0; - fh->jpg_buffers.active = ZORAN_FREE; - fh->jpg_buffers.buffer_size = jpg_bufsize; - fh->jpg_buffers.num_buffers = jpg_nbufs; + fh->buffers.allocated = 0; + fh->buffers.active = ZORAN_FREE; } static void @@ -917,33 +901,33 @@ zoran_close_end_session (struct file *file) zr->overlay_mask = NULL; } - /* v4l capture */ - if (fh->v4l_buffers.active != ZORAN_FREE) { - unsigned long flags; + if (fh->map_mode == ZORAN_MAP_MODE_RAW) { + /* v4l capture */ + if (fh->buffers.active != ZORAN_FREE) { + unsigned long flags; - spin_lock_irqsave(&zr->spinlock, flags); - zr36057_set_memgrab(zr, 0); - zr->v4l_buffers.allocated = 0; - zr->v4l_buffers.active = fh->v4l_buffers.active = - ZORAN_FREE; - spin_unlock_irqrestore(&zr->spinlock, flags); - } + spin_lock_irqsave(&zr->spinlock, flags); + zr36057_set_memgrab(zr, 0); + zr->v4l_buffers.allocated = 0; + zr->v4l_buffers.active = fh->buffers.active = ZORAN_FREE; + spin_unlock_irqrestore(&zr->spinlock, flags); + } - /* v4l buffers */ - if (fh->v4l_buffers.allocated) - v4l_fbuffer_free(file); + /* v4l buffers */ + if (fh->buffers.allocated) + v4l_fbuffer_free(file); + } else { + /* jpg capture */ + if (fh->buffers.active != ZORAN_FREE) { + zr36057_enable_jpg(zr, BUZ_MODE_IDLE); + zr->jpg_buffers.allocated = 0; + zr->jpg_buffers.active = fh->buffers.active = ZORAN_FREE; + } - /* jpg capture */ - if (fh->jpg_buffers.active != ZORAN_FREE) { - zr36057_enable_jpg(zr, BUZ_MODE_IDLE); - zr->jpg_buffers.allocated = 0; - zr->jpg_buffers.active = fh->jpg_buffers.active = - ZORAN_FREE; + /* jpg buffers */ + if (fh->buffers.allocated) + jpg_fbuffer_free(file); } - - /* jpg buffers */ - if (fh->jpg_buffers.allocated) - jpg_fbuffer_free(file); } /* @@ -1382,15 +1366,15 @@ zoran_v4l2_buffer_status (struct zoran_fh *fh, int num) { struct zoran *zr = fh->zr; + unsigned long flags; buf->flags = V4L2_BUF_FLAG_MAPPED; switch (fh->map_mode) { case ZORAN_MAP_MODE_RAW: - /* check range */ - if (num < 0 || num >= fh->v4l_buffers.num_buffers || - !fh->v4l_buffers.allocated) { + if (num < 0 || num >= fh->buffers.num_buffers || + !fh->buffers.allocated) { dprintk(1, KERN_ERR "%s: v4l2_buffer_status() - wrong number or buffers not allocated\n", @@ -1398,17 +1382,26 @@ zoran_v4l2_buffer_status (struct zoran_fh *fh, return -EINVAL; } + spin_lock_irqsave(&zr->spinlock, flags); + dprintk(3, + KERN_DEBUG + "%s: %s() - raw active=%c, buffer %d: state=%c, map=%c\n", + ZR_DEVNAME(zr), __func__, + "FAL"[fh->buffers.active], num, + "UPMD"[zr->v4l_buffers.buffer[num].state], + fh->buffers.buffer[num].map ? 'Y' : 'N'); + spin_unlock_irqrestore(&zr->spinlock, flags); + buf->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - buf->length = fh->v4l_buffers.buffer_size; + buf->length = fh->buffers.buffer_size; /* get buffer */ - buf->bytesused = fh->v4l_buffers.buffer[num].bs.length; - if (fh->v4l_buffers.buffer[num].state == BUZ_STATE_DONE || - fh->v4l_buffers.buffer[num].state == BUZ_STATE_USER) { - buf->sequence = fh->v4l_buffers.buffer[num].bs.seq; + buf->bytesused = fh->buffers.buffer[num].bs.length; + if (fh->buffers.buffer[num].state == BUZ_STATE_DONE || + fh->buffers.buffer[num].state == BUZ_STATE_USER) { + buf->sequence = fh->buffers.buffer[num].bs.seq; buf->flags |= V4L2_BUF_FLAG_DONE; - buf->timestamp = - fh->v4l_buffers.buffer[num].bs.timestamp; + buf->timestamp = fh->buffers.buffer[num].bs.timestamp; } else { buf->flags |= V4L2_BUF_FLAG_QUEUED; } @@ -1424,8 +1417,8 @@ zoran_v4l2_buffer_status (struct zoran_fh *fh, case ZORAN_MAP_MODE_JPG_PLAY: /* check range */ - if (num < 0 || num >= fh->jpg_buffers.num_buffers || - !fh->jpg_buffers.allocated) { + if (num < 0 || num >= fh->buffers.num_buffers || + !fh->buffers.allocated) { dprintk(1, KERN_ERR "%s: v4l2_buffer_status() - wrong number or buffers not allocated\n", @@ -1436,16 +1429,14 @@ zoran_v4l2_buffer_status (struct zoran_fh *fh, buf->type = (fh->map_mode == ZORAN_MAP_MODE_JPG_REC) ? V4L2_BUF_TYPE_VIDEO_CAPTURE : V4L2_BUF_TYPE_VIDEO_OUTPUT; - buf->length = fh->jpg_buffers.buffer_size; + buf->length = fh->buffers.buffer_size; /* these variables are only written after frame has been captured */ - if (fh->jpg_buffers.buffer[num].state == BUZ_STATE_DONE || - fh->jpg_buffers.buffer[num].state == BUZ_STATE_USER) { - buf->sequence = fh->jpg_buffers.buffer[num].bs.seq; - buf->timestamp = - fh->jpg_buffers.buffer[num].bs.timestamp; - buf->bytesused = - fh->jpg_buffers.buffer[num].bs.length; + if (fh->buffers.buffer[num].state == BUZ_STATE_DONE || + fh->buffers.buffer[num].state == BUZ_STATE_USER) { + buf->sequence = fh->buffers.buffer[num].bs.seq; + buf->timestamp = fh->buffers.buffer[num].bs.timestamp; + buf->bytesused = fh->buffers.buffer[num].bs.length; buf->flags |= V4L2_BUF_FLAG_DONE; } else { buf->flags |= V4L2_BUF_FLAG_QUEUED; @@ -1453,14 +1444,11 @@ zoran_v4l2_buffer_status (struct zoran_fh *fh, /* which fields are these? */ if (fh->jpg_settings.TmpDcm != 1) - buf->field = - fh->jpg_settings. - odd_even ? V4L2_FIELD_TOP : V4L2_FIELD_BOTTOM; + buf->field = fh->jpg_settings.odd_even ? + V4L2_FIELD_TOP : V4L2_FIELD_BOTTOM; else - buf->field = - fh->jpg_settings. - odd_even ? V4L2_FIELD_SEQ_TB : - V4L2_FIELD_SEQ_BT; + buf->field = fh->jpg_settings.odd_even ? + V4L2_FIELD_SEQ_TB : V4L2_FIELD_SEQ_BT; break; @@ -1743,7 +1731,7 @@ sparams_unlock_and_return: mutex_lock(&zr->resource_lock); - if (fh->jpg_buffers.allocated || fh->v4l_buffers.allocated) { + if (fh->buffers.allocated) { dprintk(1, KERN_ERR "%s: BUZIOC_REQBUFS - buffers already allocated\n", @@ -1752,17 +1740,17 @@ sparams_unlock_and_return: goto jpgreqbuf_unlock_and_return; } - fh->jpg_buffers.num_buffers = breq->count; - fh->jpg_buffers.buffer_size = breq->size; + /* The next mmap will map the MJPEG buffers - could + * also be *_PLAY, but it doesn't matter here */ + map_mode_jpg(fh, 0); + fh->buffers.num_buffers = breq->count; + fh->buffers.buffer_size = breq->size; if (jpg_fbuffer_alloc(file)) { res = -ENOMEM; goto jpgreqbuf_unlock_and_return; } - /* The next mmap will map the MJPEG buffers - could - * also be *_PLAY, but it doesn't matter here */ - fh->map_mode = ZORAN_MAP_MODE_JPG_REC; jpgreqbuf_unlock_and_return: mutex_unlock(&zr->resource_lock); @@ -1805,7 +1793,15 @@ jpgreqbuf_unlock_and_return: dprintk(3, KERN_DEBUG "%s: BUZIOC_SYNC\n", ZR_DEVNAME(zr)); mutex_lock(&zr->resource_lock); - res = jpg_sync(file, bsync); + + if (fh->map_mode == ZORAN_MAP_MODE_RAW) { + dprintk(2, KERN_WARNING + "%s: %s - not in jpg capture mode\n", + ZR_DEVNAME(zr), __func__); + res = -EINVAL; + } else { + res = jpg_sync(file, bsync); + } mutex_unlock(&zr->resource_lock); return res; @@ -1884,18 +1880,10 @@ static int zoran_vidiocgmbuf(struct file *file, void *__fh, struct video_mbuf *v struct zoran *zr = fh->zr; int i, res = 0; - vmbuf->size = - fh->v4l_buffers.num_buffers * - fh->v4l_buffers.buffer_size; - vmbuf->frames = fh->v4l_buffers.num_buffers; - for (i = 0; i < vmbuf->frames; i++) { - vmbuf->offsets[i] = - i * fh->v4l_buffers.buffer_size; - } mutex_lock(&zr->resource_lock); - if (fh->jpg_buffers.allocated || fh->v4l_buffers.allocated) { + if (fh->buffers.allocated) { dprintk(1, KERN_ERR "%s: VIDIOCGMBUF - buffers already allocated\n", @@ -1904,13 +1892,19 @@ static int zoran_vidiocgmbuf(struct file *file, void *__fh, struct video_mbuf *v goto v4l1reqbuf_unlock_and_return; } + /* The next mmap will map the V4L buffers */ + map_mode_raw(fh); + if (v4l_fbuffer_alloc(file)) { res = -ENOMEM; goto v4l1reqbuf_unlock_and_return; } - /* The next mmap will map the V4L buffers */ - fh->map_mode = ZORAN_MAP_MODE_RAW; + vmbuf->size = fh->buffers.num_buffers * fh->buffers.buffer_size; + vmbuf->frames = fh->buffers.num_buffers; + for (i = 0; i < vmbuf->frames; i++) + vmbuf->offsets[i] = i * fh->buffers.buffer_size; + v4l1reqbuf_unlock_and_return: mutex_unlock(&zr->resource_lock); @@ -2223,15 +2217,15 @@ static int zoran_s_fmt_vid_out(struct file *file, void *__fh, mutex_lock(&zr->resource_lock); - settings = fh->jpg_settings; - - if (fh->v4l_buffers.allocated || fh->jpg_buffers.allocated) { + if (fh->buffers.allocated) { dprintk(1, KERN_ERR "%s: VIDIOC_S_FMT - cannot change capture mode\n", - ZR_DEVNAME(zr)); + ZR_DEVNAME(zr)); res = -EBUSY; goto sfmtjpg_unlock_and_return; } + settings = fh->jpg_settings; + /* we actually need to set 'real' parameters now */ if (fmt->fmt.pix.height * 2 > BUZ_MAX_HEIGHT) settings.TmpDcm = 1; @@ -2269,6 +2263,9 @@ static int zoran_s_fmt_vid_out(struct file *file, void *__fh, /* it's ok, so set them */ fh->jpg_settings = settings; + map_mode_jpg(fh, fmt->type == V4L2_BUF_TYPE_VIDEO_OUTPUT); + fh->buffers.buffer_size = zoran_v4l2_calc_bufsize(&fh->jpg_settings); + /* tell the user what we actually did */ fmt->fmt.pix.width = settings.img_width / settings.HorDcm; fmt->fmt.pix.height = settings.img_height * 2 / @@ -2279,15 +2276,10 @@ static int zoran_s_fmt_vid_out(struct file *file, void *__fh, else fmt->fmt.pix.field = (fh->jpg_settings.odd_even ? V4L2_FIELD_TOP : V4L2_FIELD_BOTTOM); - fh->jpg_buffers.buffer_size = zoran_v4l2_calc_bufsize(&fh->jpg_settings); fmt->fmt.pix.bytesperline = 0; - fmt->fmt.pix.sizeimage = fh->jpg_buffers.buffer_size; + fmt->fmt.pix.sizeimage = fh->buffers.buffer_size; fmt->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; - /* we hereby abuse this variable to show that - * we're gonna do mjpeg capture */ - fh->map_mode = (fmt->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) ? - ZORAN_MAP_MODE_JPG_REC : ZORAN_MAP_MODE_JPG_PLAY; sfmtjpg_unlock_and_return: mutex_unlock(&zr->resource_lock); return res; @@ -2312,9 +2304,11 @@ static int zoran_s_fmt_vid_cap(struct file *file, void *__fh, ZR_DEVNAME(zr), fmt->fmt.pix.pixelformat); return -EINVAL; } + mutex_lock(&zr->resource_lock); - if (fh->jpg_buffers.allocated || - (fh->v4l_buffers.allocated && fh->v4l_buffers.active != ZORAN_FREE)) { + + if ((fh->map_mode != ZORAN_MAP_MODE_RAW && fh->buffers.allocated) || + fh->buffers.active != ZORAN_FREE) { dprintk(1, KERN_ERR "%s: VIDIOC_S_FMT - cannot change capture mode\n", ZR_DEVNAME(zr)); res = -EBUSY; @@ -2325,13 +2319,14 @@ static int zoran_s_fmt_vid_cap(struct file *file, void *__fh, if (fmt->fmt.pix.width > BUZ_MAX_WIDTH) fmt->fmt.pix.width = BUZ_MAX_WIDTH; - res = zoran_v4l_set_format(file, fmt->fmt.pix.width, - fmt->fmt.pix.height, &zoran_formats[i]); + map_mode_raw(fh); + + res = zoran_v4l_set_format(fh, fmt->fmt.pix.width, fmt->fmt.pix.height, + &zoran_formats[i]); if (res) goto sfmtv4l_unlock_and_return; - /* tell the user the - * results/missing stuff */ + /* tell the user the results/missing stuff */ fmt->fmt.pix.bytesperline = fh->v4l_settings.bytesperline; fmt->fmt.pix.sizeimage = fh->v4l_settings.height * fh->v4l_settings.bytesperline; fmt->fmt.pix.colorspace = fh->v4l_settings.format->colorspace; @@ -2340,7 +2335,6 @@ static int zoran_s_fmt_vid_cap(struct file *file, void *__fh, else fmt->fmt.pix.field = V4L2_FIELD_TOP; - fh->map_mode = ZORAN_MAP_MODE_RAW; sfmtv4l_unlock_and_return: mutex_unlock(&zr->resource_lock); return res; @@ -2429,7 +2423,7 @@ static int zoran_reqbufs(struct file *file, void *__fh, struct v4l2_requestbuffe return zoran_streamoff(file, fh, req->type); mutex_lock(&zr->resource_lock); - if (fh->v4l_buffers.allocated || fh->jpg_buffers.allocated) { + if (fh->buffers.allocated) { dprintk(2, KERN_ERR "%s: VIDIOC_REQBUFS - buffers already allocated\n", @@ -2439,46 +2433,38 @@ static int zoran_reqbufs(struct file *file, void *__fh, struct v4l2_requestbuffe } if (fh->map_mode == ZORAN_MAP_MODE_RAW && - req->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) { - + req->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) { /* control user input */ if (req->count < 2) req->count = 2; if (req->count > v4l_nbufs) req->count = v4l_nbufs; - fh->v4l_buffers.num_buffers = req->count; + + /* The next mmap will map the V4L buffers */ + map_mode_raw(fh); + fh->buffers.num_buffers = req->count; if (v4l_fbuffer_alloc(file)) { res = -ENOMEM; goto v4l2reqbuf_unlock_and_return; } - - /* The next mmap will map the V4L buffers */ - fh->map_mode = ZORAN_MAP_MODE_RAW; - } else if (fh->map_mode == ZORAN_MAP_MODE_JPG_REC || - fh->map_mode == ZORAN_MAP_MODE_JPG_PLAY) { - + fh->map_mode == ZORAN_MAP_MODE_JPG_PLAY) { /* we need to calculate size ourselves now */ if (req->count < 4) req->count = 4; if (req->count > jpg_nbufs) req->count = jpg_nbufs; - fh->jpg_buffers.num_buffers = req->count; - fh->jpg_buffers.buffer_size = - zoran_v4l2_calc_bufsize(&fh->jpg_settings); + + /* The next mmap will map the MJPEG buffers */ + map_mode_jpg(fh, req->type == V4L2_BUF_TYPE_VIDEO_OUTPUT); + fh->buffers.num_buffers = req->count; + fh->buffers.buffer_size = zoran_v4l2_calc_bufsize(&fh->jpg_settings); if (jpg_fbuffer_alloc(file)) { res = -ENOMEM; goto v4l2reqbuf_unlock_and_return; } - - /* The next mmap will map the MJPEG buffers */ - if (req->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) - fh->map_mode = ZORAN_MAP_MODE_JPG_REC; - else - fh->map_mode = ZORAN_MAP_MODE_JPG_PLAY; - } else { dprintk(1, KERN_ERR @@ -2527,8 +2513,7 @@ static int zoran_qbuf(struct file *file, void *__fh, struct v4l2_buffer *buf) res = zoran_v4l_queue_frame(file, buf->index); if (res) goto qbuf_unlock_and_return; - if (!zr->v4l_memgrab_active && - fh->v4l_buffers.active == ZORAN_LOCKED) + if (!zr->v4l_memgrab_active && fh->buffers.active == ZORAN_LOCKED) zr36057_set_memgrab(zr, 1); break; @@ -2555,9 +2540,9 @@ static int zoran_qbuf(struct file *file, void *__fh, struct v4l2_buffer *buf) if (res != 0) goto qbuf_unlock_and_return; if (zr->codec_mode == BUZ_MODE_IDLE && - fh->jpg_buffers.active == ZORAN_LOCKED) { + fh->buffers.active == ZORAN_LOCKED) zr36057_enable_jpg(zr, codec_mode); - } + break; default: @@ -2660,12 +2645,12 @@ static int zoran_streamon(struct file *file, void *__fh, enum v4l2_buf_type type switch (fh->map_mode) { case ZORAN_MAP_MODE_RAW: /* raw capture */ if (zr->v4l_buffers.active != ZORAN_ACTIVE || - fh->v4l_buffers.active != ZORAN_ACTIVE) { + fh->buffers.active != ZORAN_ACTIVE) { res = -EBUSY; goto strmon_unlock_and_return; } - zr->v4l_buffers.active = fh->v4l_buffers.active = ZORAN_LOCKED; + zr->v4l_buffers.active = fh->buffers.active = ZORAN_LOCKED; zr->v4l_settings = fh->v4l_settings; zr->v4l_sync_tail = zr->v4l_pend_tail; @@ -2679,12 +2664,12 @@ static int zoran_streamon(struct file *file, void *__fh, enum v4l2_buf_type type case ZORAN_MAP_MODE_JPG_PLAY: /* what is the codec mode right now? */ if (zr->jpg_buffers.active != ZORAN_ACTIVE || - fh->jpg_buffers.active != ZORAN_ACTIVE) { + fh->buffers.active != ZORAN_ACTIVE) { res = -EBUSY; goto strmon_unlock_and_return; } - zr->jpg_buffers.active = fh->jpg_buffers.active = ZORAN_LOCKED; + zr->jpg_buffers.active = fh->buffers.active = ZORAN_LOCKED; if (zr->jpg_que_head != zr->jpg_que_tail) { /* Start the jpeg codec when the first frame is queued */ @@ -2711,12 +2696,13 @@ static int zoran_streamoff(struct file *file, void *__fh, enum v4l2_buf_type typ struct zoran_fh *fh = __fh; struct zoran *zr = fh->zr; int i, res = 0; + unsigned long flags; mutex_lock(&zr->resource_lock); switch (fh->map_mode) { case ZORAN_MAP_MODE_RAW: /* raw capture */ - if (fh->v4l_buffers.active == ZORAN_FREE && + if (fh->buffers.active == ZORAN_FREE && zr->v4l_buffers.active != ZORAN_FREE) { res = -EPERM; /* stay off other's settings! */ goto strmoff_unlock_and_return; @@ -2724,30 +2710,30 @@ static int zoran_streamoff(struct file *file, void *__fh, enum v4l2_buf_type typ if (zr->v4l_buffers.active == ZORAN_FREE) goto strmoff_unlock_and_return; + spin_lock_irqsave(&zr->spinlock, flags); /* unload capture */ if (zr->v4l_memgrab_active) { - unsigned long flags; - spin_lock_irqsave(&zr->spinlock, flags); zr36057_set_memgrab(zr, 0); - spin_unlock_irqrestore(&zr->spinlock, flags); } - for (i = 0; i < fh->v4l_buffers.num_buffers; i++) + for (i = 0; i < fh->buffers.num_buffers; i++) zr->v4l_buffers.buffer[i].state = BUZ_STATE_USER; - fh->v4l_buffers = zr->v4l_buffers; + fh->buffers = zr->v4l_buffers; - zr->v4l_buffers.active = fh->v4l_buffers.active = ZORAN_FREE; + zr->v4l_buffers.active = fh->buffers.active = ZORAN_FREE; zr->v4l_grab_seq = 0; zr->v4l_pend_head = zr->v4l_pend_tail = 0; zr->v4l_sync_tail = 0; + spin_unlock_irqrestore(&zr->spinlock, flags); + break; case ZORAN_MAP_MODE_JPG_REC: case ZORAN_MAP_MODE_JPG_PLAY: - if (fh->jpg_buffers.active == ZORAN_FREE && + if (fh->buffers.active == ZORAN_FREE && zr->jpg_buffers.active != ZORAN_FREE) { res = -EPERM; /* stay off other's settings! */ goto strmoff_unlock_and_return; @@ -3016,7 +3002,7 @@ static int zoran_s_crop(struct file *file, void *__fh, struct v4l2_crop *crop) mutex_lock(&zr->resource_lock); - if (fh->jpg_buffers.allocated || fh->v4l_buffers.allocated) { + if (fh->buffers.allocated) { dprintk(1, KERN_ERR "%s: VIDIOC_S_CROP - cannot change settings while active\n", ZR_DEVNAME(zr)); @@ -3094,8 +3080,7 @@ static int zoran_s_jpegcomp(struct file *file, void *__fh, mutex_lock(&zr->resource_lock); - if (fh->v4l_buffers.active != ZORAN_FREE || - fh->jpg_buffers.active != ZORAN_FREE) { + if (fh->buffers.active != ZORAN_FREE) { dprintk(1, KERN_WARNING "%s: VIDIOC_S_JPEGCOMP called while in playback/capture mode\n", ZR_DEVNAME(zr)); @@ -3106,9 +3091,9 @@ static int zoran_s_jpegcomp(struct file *file, void *__fh, res = zoran_check_jpg_settings(zr, &settings, 0); if (res) goto sjpegc_unlock_and_return; - if (!fh->jpg_buffers.allocated) - fh->jpg_buffers.buffer_size = - zoran_v4l2_calc_bufsize(&fh->jpg_settings); + if (!fh->buffers.allocated) + fh->buffers.buffer_size = + zoran_v4l2_calc_bufsize(&fh->jpg_settings); fh->jpg_settings.jpg_comp = *params = settings.jpg_comp; sjpegc_unlock_and_return: mutex_unlock(&zr->resource_lock); @@ -3145,11 +3130,11 @@ zoran_poll (struct file *file, KERN_DEBUG "%s: %s() raw - active=%c, sync_tail=%lu/%c, pend_tail=%lu, pend_head=%lu\n", ZR_DEVNAME(zr), __func__, - "FAL"[fh->v4l_buffers.active], zr->v4l_sync_tail, + "FAL"[fh->buffers.active], zr->v4l_sync_tail, "UPMD"[zr->v4l_buffers.buffer[frame].state], zr->v4l_pend_tail, zr->v4l_pend_head); /* Process is the one capturing? */ - if (fh->v4l_buffers.active != ZORAN_FREE && + if (fh->buffers.active != ZORAN_FREE && /* Buffer ready to DQBUF? */ zr->v4l_buffers.buffer[frame].state == BUZ_STATE_DONE) res = POLLIN | POLLRDNORM; @@ -3167,10 +3152,10 @@ zoran_poll (struct file *file, KERN_DEBUG "%s: %s() jpg - active=%c, que_tail=%lu/%c, que_head=%lu, dma=%lu/%lu\n", ZR_DEVNAME(zr), __func__, - "FAL"[fh->jpg_buffers.active], zr->jpg_que_tail, + "FAL"[fh->buffers.active], zr->jpg_que_tail, "UPMD"[zr->jpg_buffers.buffer[frame].state], zr->jpg_que_head, zr->jpg_dma_tail, zr->jpg_dma_head); - if (fh->jpg_buffers.active != ZORAN_FREE && + if (fh->buffers.active != ZORAN_FREE && zr->jpg_buffers.buffer[frame].state == BUZ_STATE_DONE) { if (fh->map_mode == ZORAN_MAP_MODE_JPG_REC) res = POLLIN | POLLRDNORM; @@ -3224,87 +3209,49 @@ zoran_vm_close (struct vm_area_struct *vma) struct zoran *zr = fh->zr; int i; - map->count--; - if (map->count == 0) { - switch (fh->map_mode) { - case ZORAN_MAP_MODE_JPG_REC: - case ZORAN_MAP_MODE_JPG_PLAY: - - dprintk(3, KERN_INFO "%s: munmap(MJPEG)\n", - ZR_DEVNAME(zr)); - - for (i = 0; i < fh->jpg_buffers.num_buffers; i++) { - if (fh->jpg_buffers.buffer[i].map == map) { - fh->jpg_buffers.buffer[i].map = - NULL; - } - } - kfree(map); - - for (i = 0; i < fh->jpg_buffers.num_buffers; i++) - if (fh->jpg_buffers.buffer[i].map) - break; - if (i == fh->jpg_buffers.num_buffers) { - mutex_lock(&zr->resource_lock); - - if (fh->jpg_buffers.active != ZORAN_FREE) { - jpg_qbuf(file, -1, zr->codec_mode); - zr->jpg_buffers.allocated = 0; - zr->jpg_buffers.active = - fh->jpg_buffers.active = - ZORAN_FREE; - } - jpg_fbuffer_free(file); - mutex_unlock(&zr->resource_lock); - } + if (--map->count > 0) + return; - break; + dprintk(3, KERN_INFO "%s: %s - munmap(%s)\n", ZR_DEVNAME(zr), + __func__, mode_name(fh->map_mode)); - case ZORAN_MAP_MODE_RAW: + for (i = 0; i < fh->buffers.num_buffers; i++) { + if (fh->buffers.buffer[i].map == map) + fh->buffers.buffer[i].map = NULL; + } + kfree(map); - dprintk(3, KERN_INFO "%s: munmap(V4L)\n", - ZR_DEVNAME(zr)); + /* Any buffers still mapped? */ + for (i = 0; i < fh->buffers.num_buffers; i++) + if (fh->buffers.buffer[i].map) + return; - for (i = 0; i < fh->v4l_buffers.num_buffers; i++) { - if (fh->v4l_buffers.buffer[i].map == map) { - /* unqueue/unmap */ - fh->v4l_buffers.buffer[i].map = - NULL; - } - } - kfree(map); + dprintk(3, KERN_INFO "%s: %s - free %s buffers\n", ZR_DEVNAME(zr), + __func__, mode_name(fh->map_mode)); - for (i = 0; i < fh->v4l_buffers.num_buffers; i++) - if (fh->v4l_buffers.buffer[i].map) - break; - if (i == fh->v4l_buffers.num_buffers) { - mutex_lock(&zr->resource_lock); - - if (fh->v4l_buffers.active != ZORAN_FREE) { - unsigned long flags; - - spin_lock_irqsave(&zr->spinlock, flags); - zr36057_set_memgrab(zr, 0); - zr->v4l_buffers.allocated = 0; - zr->v4l_buffers.active = - fh->v4l_buffers.active = - ZORAN_FREE; - spin_unlock_irqrestore(&zr->spinlock, flags); - } - v4l_fbuffer_free(file); - mutex_unlock(&zr->resource_lock); - } - - break; + mutex_lock(&zr->resource_lock); - default: - printk(KERN_ERR - "%s: munmap() - internal error - unknown map mode %d\n", - ZR_DEVNAME(zr), fh->map_mode); - break; + if (fh->map_mode == ZORAN_MAP_MODE_RAW) { + if (fh->buffers.active != ZORAN_FREE) { + unsigned long flags; + spin_lock_irqsave(&zr->spinlock, flags); + zr36057_set_memgrab(zr, 0); + zr->v4l_buffers.allocated = 0; + zr->v4l_buffers.active = fh->buffers.active = ZORAN_FREE; + spin_unlock_irqrestore(&zr->spinlock, flags); + } + v4l_fbuffer_free(file); + } else { + if (fh->buffers.active != ZORAN_FREE) { + jpg_qbuf(file, -1, zr->codec_mode); + zr->jpg_buffers.allocated = 0; + zr->jpg_buffers.active = fh->buffers.active = ZORAN_FREE; } + jpg_fbuffer_free(file); } + + mutex_unlock(&zr->resource_lock); } static struct vm_operations_struct zoran_vm_ops = { @@ -3329,8 +3276,7 @@ zoran_mmap (struct file *file, dprintk(3, KERN_INFO "%s: mmap(%s) of 0x%08lx-0x%08lx (size=%lu)\n", ZR_DEVNAME(zr), - fh->map_mode == ZORAN_MAP_MODE_RAW ? "V4L" : "MJPEG", - vma->vm_start, vma->vm_end, size); + mode_name(fh->map_mode), vma->vm_start, vma->vm_end, size); if (!(vma->vm_flags & VM_SHARED) || !(vma->vm_flags & VM_READ) || !(vma->vm_flags & VM_WRITE)) { @@ -3341,76 +3287,93 @@ zoran_mmap (struct file *file, return -EINVAL; } - switch (fh->map_mode) { + mutex_lock(&zr->resource_lock); - case ZORAN_MAP_MODE_JPG_REC: - case ZORAN_MAP_MODE_JPG_PLAY: + if (!fh->buffers.allocated) { + dprintk(1, + KERN_ERR + "%s: zoran_mmap(%s) - buffers not yet allocated\n", + ZR_DEVNAME(zr), mode_name(fh->map_mode)); + res = -ENOMEM; + goto mmap_unlock_and_return; + } - /* lock */ - mutex_lock(&zr->resource_lock); + first = offset / fh->buffers.buffer_size; + last = first - 1 + size / fh->buffers.buffer_size; + if (offset % fh->buffers.buffer_size != 0 || + size % fh->buffers.buffer_size != 0 || first < 0 || + last < 0 || first >= fh->buffers.num_buffers || + last >= fh->buffers.buffer_size) { + dprintk(1, + KERN_ERR + "%s: mmap(%s) - offset=%lu or size=%lu invalid for bufsize=%d and numbufs=%d\n", + ZR_DEVNAME(zr), mode_name(fh->map_mode), offset, size, + fh->buffers.buffer_size, + fh->buffers.num_buffers); + res = -EINVAL; + goto mmap_unlock_and_return; + } - /* Map the MJPEG buffers */ - if (!fh->jpg_buffers.allocated) { + /* Check if any buffers are already mapped */ + for (i = first; i <= last; i++) { + if (fh->buffers.buffer[i].map) { dprintk(1, KERN_ERR - "%s: zoran_mmap(MJPEG) - buffers not yet allocated\n", - ZR_DEVNAME(zr)); - res = -ENOMEM; - goto jpg_mmap_unlock_and_return; + "%s: mmap(%s) - buffer %d already mapped\n", + ZR_DEVNAME(zr), mode_name(fh->map_mode), i); + res = -EBUSY; + goto mmap_unlock_and_return; } + } - first = offset / fh->jpg_buffers.buffer_size; - last = first - 1 + size / fh->jpg_buffers.buffer_size; - if (offset % fh->jpg_buffers.buffer_size != 0 || - size % fh->jpg_buffers.buffer_size != 0 || first < 0 || - last < 0 || first >= fh->jpg_buffers.num_buffers || - last >= fh->jpg_buffers.num_buffers) { - dprintk(1, - KERN_ERR - "%s: mmap(MJPEG) - offset=%lu or size=%lu invalid for bufsize=%d and numbufs=%d\n", - ZR_DEVNAME(zr), offset, size, - fh->jpg_buffers.buffer_size, - fh->jpg_buffers.num_buffers); - res = -EINVAL; - goto jpg_mmap_unlock_and_return; - } + /* map these buffers */ + map = kmalloc(sizeof(struct zoran_mapping), GFP_KERNEL); + if (!map) { + res = -ENOMEM; + goto mmap_unlock_and_return; + } + map->file = file; + map->count = 1; + + vma->vm_ops = &zoran_vm_ops; + vma->vm_flags |= VM_DONTEXPAND; + vma->vm_private_data = map; + + if (fh->map_mode == ZORAN_MAP_MODE_RAW) { for (i = first; i <= last; i++) { - if (fh->jpg_buffers.buffer[i].map) { + todo = size; + if (todo > fh->buffers.buffer_size) + todo = fh->buffers.buffer_size; + page = fh->buffers.buffer[i].v4l.fbuffer_phys; + if (remap_pfn_range(vma, start, page >> PAGE_SHIFT, + todo, PAGE_SHARED)) { dprintk(1, KERN_ERR - "%s: mmap(MJPEG) - buffer %d already mapped\n", - ZR_DEVNAME(zr), i); - res = -EBUSY; - goto jpg_mmap_unlock_and_return; + "%s: zoran_mmap(V4L) - remap_pfn_range failed\n", + ZR_DEVNAME(zr)); + res = -EAGAIN; + goto mmap_unlock_and_return; } + size -= todo; + start += todo; + fh->buffers.buffer[i].map = map; + if (size == 0) + break; } - - /* map these buffers (v4l_buffers[i]) */ - map = kmalloc(sizeof(struct zoran_mapping), GFP_KERNEL); - if (!map) { - res = -ENOMEM; - goto jpg_mmap_unlock_and_return; - } - map->file = file; - map->count = 1; - - vma->vm_ops = &zoran_vm_ops; - vma->vm_flags |= VM_DONTEXPAND; - vma->vm_private_data = map; - + } else { for (i = first; i <= last; i++) { for (j = 0; - j < fh->jpg_buffers.buffer_size / PAGE_SIZE; + j < fh->buffers.buffer_size / PAGE_SIZE; j++) { fraglen = - (le32_to_cpu(fh->jpg_buffers.buffer[i]. + (le32_to_cpu(fh->buffers.buffer[i].jpg. frag_tab[2 * j + 1]) & ~1) << 1; todo = size; if (todo > fraglen) todo = fraglen; pos = - le32_to_cpu(fh->jpg_buffers. - buffer[i].frag_tab[2 * j]); + le32_to_cpu(fh->buffers. + buffer[i].jpg.frag_tab[2 * j]); /* should just be pos on i386 */ page = virt_to_phys(bus_to_virt(pos)) >> PAGE_SHIFT; @@ -3421,112 +3384,26 @@ zoran_mmap (struct file *file, "%s: zoran_mmap(V4L) - remap_pfn_range failed\n", ZR_DEVNAME(zr)); res = -EAGAIN; - goto jpg_mmap_unlock_and_return; + goto mmap_unlock_and_return; } size -= todo; start += todo; if (size == 0) break; - if (le32_to_cpu(fh->jpg_buffers.buffer[i]. + if (le32_to_cpu(fh->buffers.buffer[i].jpg. frag_tab[2 * j + 1]) & 1) break; /* was last fragment */ } - fh->jpg_buffers.buffer[i].map = map; + fh->buffers.buffer[i].map = map; if (size == 0) break; } - jpg_mmap_unlock_and_return: - mutex_unlock(&zr->resource_lock); - - break; - - case ZORAN_MAP_MODE_RAW: - - mutex_lock(&zr->resource_lock); - - /* Map the V4L buffers */ - if (!fh->v4l_buffers.allocated) { - dprintk(1, - KERN_ERR - "%s: zoran_mmap(V4L) - buffers not yet allocated\n", - ZR_DEVNAME(zr)); - res = -ENOMEM; - goto v4l_mmap_unlock_and_return; - } - - first = offset / fh->v4l_buffers.buffer_size; - last = first - 1 + size / fh->v4l_buffers.buffer_size; - if (offset % fh->v4l_buffers.buffer_size != 0 || - size % fh->v4l_buffers.buffer_size != 0 || first < 0 || - last < 0 || first >= fh->v4l_buffers.num_buffers || - last >= fh->v4l_buffers.buffer_size) { - dprintk(1, - KERN_ERR - "%s: mmap(V4L) - offset=%lu or size=%lu invalid for bufsize=%d and numbufs=%d\n", - ZR_DEVNAME(zr), offset, size, - fh->v4l_buffers.buffer_size, - fh->v4l_buffers.num_buffers); - res = -EINVAL; - goto v4l_mmap_unlock_and_return; - } - for (i = first; i <= last; i++) { - if (fh->v4l_buffers.buffer[i].map) { - dprintk(1, - KERN_ERR - "%s: mmap(V4L) - buffer %d already mapped\n", - ZR_DEVNAME(zr), i); - res = -EBUSY; - goto v4l_mmap_unlock_and_return; - } - } - - /* map these buffers (v4l_buffers[i]) */ - map = kmalloc(sizeof(struct zoran_mapping), GFP_KERNEL); - if (!map) { - res = -ENOMEM; - goto v4l_mmap_unlock_and_return; - } - map->file = file; - map->count = 1; - - vma->vm_ops = &zoran_vm_ops; - vma->vm_flags |= VM_DONTEXPAND; - vma->vm_private_data = map; - - for (i = first; i <= last; i++) { - todo = size; - if (todo > fh->v4l_buffers.buffer_size) - todo = fh->v4l_buffers.buffer_size; - page = fh->v4l_buffers.buffer[i].fbuffer_phys; - if (remap_pfn_range(vma, start, page >> PAGE_SHIFT, - todo, PAGE_SHARED)) { - dprintk(1, - KERN_ERR - "%s: zoran_mmap(V4L)i - remap_pfn_range failed\n", - ZR_DEVNAME(zr)); - res = -EAGAIN; - goto v4l_mmap_unlock_and_return; - } - size -= todo; - start += todo; - fh->v4l_buffers.buffer[i].map = map; - if (size == 0) - break; - } - v4l_mmap_unlock_and_return: - mutex_unlock(&zr->resource_lock); - - break; - - default: - dprintk(1, - KERN_ERR - "%s: zoran_mmap() - internal error - unknown map mode %d\n", - ZR_DEVNAME(zr), fh->map_mode); - break; } +mmap_unlock_and_return: + mutex_unlock(&zr->resource_lock); + return 0; } -- cgit v1.2.3 From 4dbf46a0485a5b0704e1c4b55a173128fbaedec9 Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Tue, 10 Mar 2009 23:28:17 -0300 Subject: V4L/DVB (10931): zoran: Drop the lock_norm module parameter The lock_norm module parameter doesn't look terribly useful. If you don't want to change the norm, just don't change it. As a matter of fact, no other v4l driver has such a parameter. Cc: Hans Verkuil Signed-off-by: Jean Delvare Signed-off-by: Trent Piepho Signed-off-by: Mauro Carvalho Chehab --- Documentation/video4linux/Zoran | 3 +-- drivers/media/video/zoran/zoran_driver.c | 20 -------------------- 2 files changed, 1 insertion(+), 22 deletions(-) (limited to 'drivers/media/video') diff --git a/Documentation/video4linux/Zoran b/Documentation/video4linux/Zoran index 295462b2317a..0e89e7676298 100644 --- a/Documentation/video4linux/Zoran +++ b/Documentation/video4linux/Zoran @@ -401,8 +401,7 @@ Additional notes for software developers: first set the correct norm. Well, it seems logically correct: TV standard is "more constant" for current country than geometry settings of a variety of TV capture cards which may work in ITU or - square pixel format. Remember that users now can lock the norm to - avoid any ambiguity. + square pixel format. -- Please note that lavplay/lavrec are also included in the MJPEG-tools (http://mjpeg.sf.net/). diff --git a/drivers/media/video/zoran/zoran_driver.c b/drivers/media/video/zoran/zoran_driver.c index 26be1a8908a3..1869d307a59d 100644 --- a/drivers/media/video/zoran/zoran_driver.c +++ b/drivers/media/video/zoran/zoran_driver.c @@ -162,10 +162,6 @@ const struct zoran_format zoran_formats[] = { }; #define NUM_FORMATS ARRAY_SIZE(zoran_formats) -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)"); - /* small helper function for calculating buffersizes for v4l2 * we calculate the nearest higher power-of-two, which * will be the recommended buffersize */ @@ -1483,22 +1479,6 @@ zoran_set_norm (struct zoran *zr, return -EBUSY; } - if (lock_norm && norm != zr->norm) { - if (lock_norm > 1) { - dprintk(1, - KERN_WARNING - "%s: set_norm() - TV standard is locked, can not switch norm\n", - ZR_DEVNAME(zr)); - return -EPERM; - } else { - dprintk(1, - KERN_WARNING - "%s: set_norm() - TV standard is locked, norm was not changed\n", - ZR_DEVNAME(zr)); - norm = zr->norm; - } - } - if (!(norm & zr->card.norms)) { dprintk(1, KERN_ERR "%s: set_norm() - unsupported norm %llx\n", -- cgit v1.2.3 From ee9a9d661d96e29d93859d20125bc7e4cc75309b Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Tue, 10 Mar 2009 23:28:20 -0300 Subject: V4L/DVB (10932): zoran: Don't frighten users with failed buffer allocation kmalloc() can fail for large video buffers. By default the kernel complains loudly about allocation failures, but we don't want to frighten the user, so ask kmalloc() to keep quiet on such failures. Cc: Hans Verkuil Signed-off-by: Jean Delvare Signed-off-by: Trent Piepho Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/zoran/zoran_driver.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/zoran/zoran_driver.c b/drivers/media/video/zoran/zoran_driver.c index 1869d307a59d..e22378a4598b 100644 --- a/drivers/media/video/zoran/zoran_driver.c +++ b/drivers/media/video/zoran/zoran_driver.c @@ -229,7 +229,8 @@ v4l_fbuffer_alloc (struct file *file) ZR_DEVNAME(zr), i); //udelay(20); - mem = kmalloc(fh->buffers.buffer_size, GFP_KERNEL); + mem = kmalloc(fh->buffers.buffer_size, + GFP_KERNEL | __GFP_NOWARN); if (!mem) { dprintk(1, KERN_ERR -- cgit v1.2.3 From e5ee3f643dd6d25c73cfd1e943abc9b529d63697 Mon Sep 17 00:00:00 2001 From: Trent Piepho Date: Tue, 10 Mar 2009 23:28:31 -0300 Subject: V4L/DVB (10933): zoran: Pass zoran_fh pointers instead of file pointers Many functions had a struct file pointer argument, but all they wants is the struct zoran_fh pointer from the file's private data. Since every caller of those functions already has the zoran_fh, just pass the that instead. This saves a dereference in each function change. While I'm at it, change the code formatting of affected functions to be kernel standard style. Signed-off-by: Trent Piepho Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/zoran/zoran_device.c | 6 +- drivers/media/video/zoran/zoran_device.h | 2 +- drivers/media/video/zoran/zoran_driver.c | 158 +++++++++++-------------------- 3 files changed, 56 insertions(+), 110 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/zoran/zoran_device.c b/drivers/media/video/zoran/zoran_device.c index 4dc951322ef4..f8bcd1a248c2 100644 --- a/drivers/media/video/zoran/zoran_device.c +++ b/drivers/media/video/zoran/zoran_device.c @@ -535,12 +535,8 @@ zr36057_overlay (struct zoran *zr, * and the maximum window size is BUZ_MAX_WIDTH * BUZ_MAX_HEIGHT pixels. */ -void -write_overlay_mask (struct file *file, - struct v4l2_clip *vp, - int count) +void write_overlay_mask(struct zoran_fh *fh, struct v4l2_clip *vp, int count) { - struct zoran_fh *fh = file->private_data; struct zoran *zr = fh->zr; unsigned mask_line_size = (BUZ_MAX_WIDTH + 31) / 32; u32 *mask; diff --git a/drivers/media/video/zoran/zoran_device.h b/drivers/media/video/zoran/zoran_device.h index 3520bd54c8bd..85414e17524e 100644 --- a/drivers/media/video/zoran/zoran_device.h +++ b/drivers/media/video/zoran/zoran_device.h @@ -54,7 +54,7 @@ extern int jpeg_codec_reset(struct zoran *zr); /* zr360x7 access to raw capture */ extern void zr36057_overlay(struct zoran *zr, int on); -extern void write_overlay_mask(struct file *file, +extern void write_overlay_mask(struct zoran_fh *fh, struct v4l2_clip *vp, int count); extern void zr36057_set_memgrab(struct zoran *zr, diff --git a/drivers/media/video/zoran/zoran_driver.c b/drivers/media/video/zoran/zoran_driver.c index e22378a4598b..5343a8aeb64a 100644 --- a/drivers/media/video/zoran/zoran_driver.c +++ b/drivers/media/video/zoran/zoran_driver.c @@ -186,8 +186,8 @@ zoran_v4l2_calc_bufsize (struct zoran_jpg_settings *settings) } /* forward references */ -static void v4l_fbuffer_free(struct file *file); -static void jpg_fbuffer_free(struct file *file); +static void v4l_fbuffer_free(struct zoran_fh *fh); +static void jpg_fbuffer_free(struct zoran_fh *fh); /* Set mapping mode */ static void map_mode_raw(struct zoran_fh *fh) @@ -213,10 +213,8 @@ static inline const char *mode_name(enum zoran_map_mode mode) * These have to be pysically contiguous. */ -static int -v4l_fbuffer_alloc (struct file *file) +static int v4l_fbuffer_alloc(struct zoran_fh *fh) { - struct zoran_fh *fh = file->private_data; struct zoran *zr = fh->zr; int i, off; unsigned char *mem; @@ -236,7 +234,7 @@ v4l_fbuffer_alloc (struct file *file) KERN_ERR "%s: v4l_fbuffer_alloc() - kmalloc for V4L buf %d failed\n", ZR_DEVNAME(zr), i); - v4l_fbuffer_free(file); + v4l_fbuffer_free(fh); return -ENOBUFS; } fh->buffers.buffer[i].v4l.fbuffer = mem; @@ -258,10 +256,8 @@ v4l_fbuffer_alloc (struct file *file) } /* free the V4L grab buffers */ -static void -v4l_fbuffer_free (struct file *file) +static void v4l_fbuffer_free(struct zoran_fh *fh) { - struct zoran_fh *fh = file->private_data; struct zoran *zr = fh->zr; int i, off; unsigned char *mem; @@ -311,10 +307,8 @@ v4l_fbuffer_free (struct file *file) * and fragment buffers are not little-endian. */ -static int -jpg_fbuffer_alloc (struct file *file) +static int jpg_fbuffer_alloc(struct zoran_fh *fh) { - struct zoran_fh *fh = file->private_data; struct zoran *zr = fh->zr; int i, j, off; u8 *mem; @@ -334,7 +328,7 @@ jpg_fbuffer_alloc (struct file *file) KERN_ERR "%s: jpg_fbuffer_alloc() - get_zeroed_page (frag_tab) failed for buffer %d\n", ZR_DEVNAME(zr), i); - jpg_fbuffer_free(file); + jpg_fbuffer_free(fh); return -ENOBUFS; } fh->buffers.buffer[i].jpg.frag_tab = (__le32 *)mem; @@ -347,7 +341,7 @@ jpg_fbuffer_alloc (struct file *file) KERN_ERR "%s: jpg_fbuffer_alloc() - kmalloc failed for buffer %d\n", ZR_DEVNAME(zr), i); - jpg_fbuffer_free(file); + jpg_fbuffer_free(fh); return -ENOBUFS; } fh->buffers.buffer[i].jpg.frag_tab[0] = @@ -365,7 +359,7 @@ jpg_fbuffer_alloc (struct file *file) KERN_ERR "%s: jpg_fbuffer_alloc() - get_zeroed_page failed for buffer %d\n", ZR_DEVNAME(zr), i); - jpg_fbuffer_free(file); + jpg_fbuffer_free(fh); return -ENOBUFS; } @@ -391,10 +385,8 @@ jpg_fbuffer_alloc (struct file *file) } /* free the MJPEG grab buffers */ -static void -jpg_fbuffer_free (struct file *file) +static void jpg_fbuffer_free(struct zoran_fh *fh) { - struct zoran_fh *fh = file->private_data; struct zoran *zr = fh->zr; int i, j, off; unsigned char *mem; @@ -492,11 +484,8 @@ zoran_v4l_set_format (struct zoran_fh *fh, return 0; } -static int -zoran_v4l_queue_frame (struct file *file, - int num) +static int zoran_v4l_queue_frame(struct zoran_fh *fh, int num) { - struct zoran_fh *fh = file->private_data; struct zoran *zr = fh->zr; unsigned long flags; int res = 0; @@ -574,11 +563,8 @@ zoran_v4l_queue_frame (struct file *file, * Sync on a V4L buffer */ -static int -v4l_sync (struct file *file, - int frame) +static int v4l_sync(struct zoran_fh *fh, int frame) { - struct zoran_fh *fh = file->private_data; struct zoran *zr = fh->zr; unsigned long flags; @@ -643,12 +629,9 @@ v4l_sync (struct file *file, * Queue a MJPEG buffer for capture/playback */ -static int -zoran_jpg_queue_frame (struct file *file, - int num, - enum zoran_codec_mode mode) +static int zoran_jpg_queue_frame(struct zoran_fh *fh, int num, + enum zoran_codec_mode mode) { - struct zoran_fh *fh = file->private_data; struct zoran *zr = fh->zr; unsigned long flags; int res = 0; @@ -738,12 +721,8 @@ zoran_jpg_queue_frame (struct file *file, return res; } -static int -jpg_qbuf (struct file *file, - int frame, - enum zoran_codec_mode mode) +static int jpg_qbuf(struct zoran_fh *fh, int frame, enum zoran_codec_mode mode) { - struct zoran_fh *fh = file->private_data; struct zoran *zr = fh->zr; int res = 0; @@ -770,7 +749,7 @@ jpg_qbuf (struct file *file, } } - if ((res = zoran_jpg_queue_frame(file, frame, mode))) + if ((res = zoran_jpg_queue_frame(fh, frame, mode))) return res; /* Start the jpeg codec when the first frame is queued */ @@ -784,11 +763,8 @@ jpg_qbuf (struct file *file, * Sync on a MJPEG buffer */ -static int -jpg_sync (struct file *file, - struct zoran_sync *bs) +static int jpg_sync(struct zoran_fh *fh, struct zoran_sync *bs) { - struct zoran_fh *fh = file->private_data; struct zoran *zr = fh->zr; unsigned long flags; int frame; @@ -852,11 +828,9 @@ jpg_sync (struct file *file, return 0; } -static void -zoran_open_init_session (struct file *file) +static void zoran_open_init_session(struct zoran_fh *fh) { int i; - struct zoran_fh *fh = file->private_data; struct zoran *zr = fh->zr; /* Per default, map the V4L Buffers */ @@ -883,10 +857,8 @@ zoran_open_init_session (struct file *file) fh->buffers.active = ZORAN_FREE; } -static void -zoran_close_end_session (struct file *file) +static void zoran_close_end_session(struct zoran_fh *fh) { - struct zoran_fh *fh = file->private_data; struct zoran *zr = fh->zr; /* overlay */ @@ -912,7 +884,7 @@ zoran_close_end_session (struct file *file) /* v4l buffers */ if (fh->buffers.allocated) - v4l_fbuffer_free(file); + v4l_fbuffer_free(fh); } else { /* jpg capture */ if (fh->buffers.active != ZORAN_FREE) { @@ -923,7 +895,7 @@ zoran_close_end_session (struct file *file) /* jpg buffers */ if (fh->buffers.allocated) - jpg_fbuffer_free(file); + jpg_fbuffer_free(fh); } } @@ -989,7 +961,7 @@ static int zoran_open(struct file *file) /* set file_ops stuff */ file->private_data = fh; fh->zr = zr; - zoran_open_init_session(file); + zoran_open_init_session(fh); unlock_kernel(); return 0; @@ -1018,7 +990,7 @@ zoran_close(struct file *file) * (prevents deadlocks) */ /*mutex_lock(&zr->resource_lock);*/ - zoran_close_end_session(file); + zoran_close_end_session(fh); if (zr->user-- == 1) { /* Last process */ /* Clean up JPEG process */ @@ -1085,15 +1057,13 @@ zoran_write (struct file *file, return -EINVAL; } -static int -setup_fbuffer (struct file *file, +static int setup_fbuffer(struct zoran_fh *fh, void *base, const struct zoran_format *fmt, int width, int height, int bytesperline) { - struct zoran_fh *fh = file->private_data; struct zoran *zr = fh->zr; /* (Ronald) v4l/v4l2 guidelines */ @@ -1163,17 +1133,9 @@ setup_fbuffer (struct file *file, } -static int -setup_window (struct file *file, - int x, - int y, - int width, - int height, - struct v4l2_clip __user *clips, - int clipcount, - void __user *bitmap) +static int setup_window(struct zoran_fh *fh, int x, int y, int width, int height, + struct v4l2_clip __user *clips, int clipcount, void __user *bitmap) { - struct zoran_fh *fh = file->private_data; struct zoran *zr = fh->zr; struct v4l2_clip *vcp = NULL; int on, end; @@ -1273,7 +1235,7 @@ setup_window (struct file *file, vfree(vcp); return -EFAULT; } - write_overlay_mask(file, vcp, clipcount); + write_overlay_mask(fh, vcp, clipcount); vfree(vcp); } @@ -1289,11 +1251,8 @@ setup_window (struct file *file, return wait_grab_pending(zr); } -static int -setup_overlay (struct file *file, - int on) +static int setup_overlay(struct zoran_fh *fh, int on) { - struct zoran_fh *fh = file->private_data; struct zoran *zr = fh->zr; /* If there is nothing to do, return immediatly */ @@ -1356,11 +1315,9 @@ setup_overlay (struct file *file, return wait_grab_pending(zr); } - /* get the status of a buffer in the clients buffer queue */ -static int -zoran_v4l2_buffer_status (struct zoran_fh *fh, - struct v4l2_buffer *buf, - int num) +/* get the status of a buffer in the clients buffer queue */ +static int zoran_v4l2_buffer_status(struct zoran_fh *fh, + struct v4l2_buffer *buf, int num) { struct zoran *zr = fh->zr; unsigned long flags; @@ -1727,7 +1684,7 @@ sparams_unlock_and_return: fh->buffers.num_buffers = breq->count; fh->buffers.buffer_size = breq->size; - if (jpg_fbuffer_alloc(file)) { + if (jpg_fbuffer_alloc(fh)) { res = -ENOMEM; goto jpgreqbuf_unlock_and_return; } @@ -1746,7 +1703,7 @@ jpgreqbuf_unlock_and_return: ZR_DEVNAME(zr), *frame); mutex_lock(&zr->resource_lock); - res = jpg_qbuf(file, *frame, BUZ_MODE_MOTION_COMPRESS); + res = jpg_qbuf(fh, *frame, BUZ_MODE_MOTION_COMPRESS); mutex_unlock(&zr->resource_lock); return res; @@ -1760,7 +1717,7 @@ jpgreqbuf_unlock_and_return: ZR_DEVNAME(zr), *frame); mutex_lock(&zr->resource_lock); - res = jpg_qbuf(file, *frame, BUZ_MODE_MOTION_DECOMPRESS); + res = jpg_qbuf(fh, *frame, BUZ_MODE_MOTION_DECOMPRESS); mutex_unlock(&zr->resource_lock); return res; @@ -1781,7 +1738,7 @@ jpgreqbuf_unlock_and_return: ZR_DEVNAME(zr), __func__); res = -EINVAL; } else { - res = jpg_sync(file, bsync); + res = jpg_sync(fh, bsync); } mutex_unlock(&zr->resource_lock); @@ -1876,7 +1833,7 @@ static int zoran_vidiocgmbuf(struct file *file, void *__fh, struct video_mbuf *v /* The next mmap will map the V4L buffers */ map_mode_raw(fh); - if (v4l_fbuffer_alloc(file)) { + if (v4l_fbuffer_alloc(fh)) { res = -ENOMEM; goto v4l1reqbuf_unlock_and_return; } @@ -2168,14 +2125,10 @@ static int zoran_s_fmt_vid_overlay(struct file *file, void *__fh, fmt->fmt.win.clipcount, fmt->fmt.win.bitmap); mutex_lock(&zr->resource_lock); - res = setup_window(file, fmt->fmt.win.w.left, - fmt->fmt.win.w.top, - fmt->fmt.win.w.width, - fmt->fmt.win.w.height, - (struct v4l2_clip __user *) - fmt->fmt.win.clips, - fmt->fmt.win.clipcount, - fmt->fmt.win.bitmap); + res = setup_window(fh, fmt->fmt.win.w.left, fmt->fmt.win.w.top, + fmt->fmt.win.w.width, fmt->fmt.win.w.height, + (struct v4l2_clip __user *)fmt->fmt.win.clips, + fmt->fmt.win.clipcount, fmt->fmt.win.bitmap); mutex_unlock(&zr->resource_lock); return res; } @@ -2363,9 +2316,8 @@ static int zoran_s_fbuf(struct file *file, void *__fh, } mutex_lock(&zr->resource_lock); - res = setup_fbuffer(file, fb->base, &zoran_formats[i], - fb->fmt.width, fb->fmt.height, - fb->fmt.bytesperline); + res = setup_fbuffer(fh, fb->base, &zoran_formats[i], fb->fmt.width, + fb->fmt.height, fb->fmt.bytesperline); mutex_unlock(&zr->resource_lock); return res; @@ -2378,7 +2330,7 @@ static int zoran_overlay(struct file *file, void *__fh, unsigned int on) int res; mutex_lock(&zr->resource_lock); - res = setup_overlay(file, on); + res = setup_overlay(fh, on); mutex_unlock(&zr->resource_lock); return res; @@ -2425,7 +2377,7 @@ static int zoran_reqbufs(struct file *file, void *__fh, struct v4l2_requestbuffe map_mode_raw(fh); fh->buffers.num_buffers = req->count; - if (v4l_fbuffer_alloc(file)) { + if (v4l_fbuffer_alloc(fh)) { res = -ENOMEM; goto v4l2reqbuf_unlock_and_return; } @@ -2442,7 +2394,7 @@ static int zoran_reqbufs(struct file *file, void *__fh, struct v4l2_requestbuffe fh->buffers.num_buffers = req->count; fh->buffers.buffer_size = zoran_v4l2_calc_bufsize(&fh->jpg_settings); - if (jpg_fbuffer_alloc(file)) { + if (jpg_fbuffer_alloc(fh)) { res = -ENOMEM; goto v4l2reqbuf_unlock_and_return; } @@ -2491,7 +2443,7 @@ static int zoran_qbuf(struct file *file, void *__fh, struct v4l2_buffer *buf) goto qbuf_unlock_and_return; } - res = zoran_v4l_queue_frame(file, buf->index); + res = zoran_v4l_queue_frame(fh, buf->index); if (res) goto qbuf_unlock_and_return; if (!zr->v4l_memgrab_active && fh->buffers.active == ZORAN_LOCKED) @@ -2516,8 +2468,7 @@ static int zoran_qbuf(struct file *file, void *__fh, struct v4l2_buffer *buf) goto qbuf_unlock_and_return; } - res = zoran_jpg_queue_frame(file, buf->index, - codec_mode); + res = zoran_jpg_queue_frame(fh, buf->index, codec_mode); if (res != 0) goto qbuf_unlock_and_return; if (zr->codec_mode == BUZ_MODE_IDLE && @@ -2563,7 +2514,7 @@ static int zoran_dqbuf(struct file *file, void *__fh, struct v4l2_buffer *buf) res = -EAGAIN; goto dqbuf_unlock_and_return; } - res = v4l_sync(file, num); + res = v4l_sync(fh, num); if (res) goto dqbuf_unlock_and_return; zr->v4l_sync_tail++; @@ -2595,7 +2546,7 @@ static int zoran_dqbuf(struct file *file, void *__fh, struct v4l2_buffer *buf) res = -EAGAIN; goto dqbuf_unlock_and_return; } - res = jpg_sync(file, &bs); + res = jpg_sync(fh, &bs); if (res) goto dqbuf_unlock_and_return; res = zoran_v4l2_buffer_status(fh, buf, bs.frame); @@ -2722,7 +2673,7 @@ static int zoran_streamoff(struct file *file, void *__fh, enum v4l2_buf_type typ if (zr->jpg_buffers.active == ZORAN_FREE) goto strmoff_unlock_and_return; - res = jpg_qbuf(file, -1, + res = jpg_qbuf(fh, -1, (fh->map_mode == ZORAN_MAP_MODE_JPG_REC) ? BUZ_MODE_MOTION_COMPRESS : BUZ_MODE_MOTION_DECOMPRESS); @@ -3185,8 +3136,7 @@ static void zoran_vm_close (struct vm_area_struct *vma) { struct zoran_mapping *map = vma->vm_private_data; - struct file *file = map->file; - struct zoran_fh *fh = file->private_data; + struct zoran_fh *fh = map->file->private_data; struct zoran *zr = fh->zr; int i; @@ -3222,14 +3172,14 @@ zoran_vm_close (struct vm_area_struct *vma) zr->v4l_buffers.active = fh->buffers.active = ZORAN_FREE; spin_unlock_irqrestore(&zr->spinlock, flags); } - v4l_fbuffer_free(file); + v4l_fbuffer_free(fh); } else { if (fh->buffers.active != ZORAN_FREE) { - jpg_qbuf(file, -1, zr->codec_mode); + jpg_qbuf(fh, -1, zr->codec_mode); zr->jpg_buffers.allocated = 0; zr->jpg_buffers.active = fh->buffers.active = ZORAN_FREE; } - jpg_fbuffer_free(file); + jpg_fbuffer_free(fh); } mutex_unlock(&zr->resource_lock); -- cgit v1.2.3 From c61402bae843f1f7ec29a6fe81681be21c3d201c Mon Sep 17 00:00:00 2001 From: Trent Piepho Date: Tue, 10 Mar 2009 23:28:33 -0300 Subject: V4L/DVB (10934): zoran: replace functions names in strings with __func__ It reduces the size of the driver over all, and the function names in strings need to be manually kept up to date while __func__ doesn't. Signed-off-by: Trent Piepho Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/zoran/zoran_card.c | 115 ++++++-------- drivers/media/video/zoran/zoran_driver.c | 254 +++++++++++++++---------------- 2 files changed, 173 insertions(+), 196 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/zoran/zoran_card.c b/drivers/media/video/zoran/zoran_card.c index 3ffdbe34ecc1..b5d228d91b06 100644 --- a/drivers/media/video/zoran/zoran_card.c +++ b/drivers/media/video/zoran/zoran_card.c @@ -254,7 +254,7 @@ zr36016_write (struct videocodec *codec, static void dc10_init (struct zoran *zr) { - dprintk(3, KERN_DEBUG "%s: dc10_init()\n", ZR_DEVNAME(zr)); + dprintk(3, KERN_DEBUG "%s: %s\n", ZR_DEVNAME(zr), __func__); /* Pixel clock selection */ GPIO(zr, 4, 0); @@ -266,13 +266,13 @@ dc10_init (struct zoran *zr) static void dc10plus_init (struct zoran *zr) { - dprintk(3, KERN_DEBUG "%s: dc10plus_init()\n", ZR_DEVNAME(zr)); + dprintk(3, KERN_DEBUG "%s: %s\n", ZR_DEVNAME(zr), __func__); } static void buz_init (struct zoran *zr) { - dprintk(3, KERN_DEBUG "%s: buz_init()\n", ZR_DEVNAME(zr)); + dprintk(3, KERN_DEBUG "%s: %s\n", ZR_DEVNAME(zr), __func__); /* some stuff from Iomega */ pci_write_config_dword(zr->pci_dev, 0xfc, 0x90680f15); @@ -283,7 +283,7 @@ buz_init (struct zoran *zr) static void lml33_init (struct zoran *zr) { - dprintk(3, KERN_DEBUG "%s: lml33_init()\n", ZR_DEVNAME(zr)); + dprintk(3, KERN_DEBUG "%s: %s\n", ZR_DEVNAME(zr), __func__); GPIO(zr, 2, 1); // Set Composite input/output } @@ -758,13 +758,13 @@ zoran_check_jpg_settings (struct zoran *zr, dprintk(4, KERN_DEBUG - "%s: check_jpg_settings() - dec: %d, Hdcm: %d, Vdcm: %d, Tdcm: %d\n", - ZR_DEVNAME(zr), settings->decimation, settings->HorDcm, + "%s: %s - dec: %d, Hdcm: %d, Vdcm: %d, Tdcm: %d\n", + ZR_DEVNAME(zr), __func__, settings->decimation, settings->HorDcm, settings->VerDcm, settings->TmpDcm); dprintk(4, KERN_DEBUG - "%s: check_jpg_settings() - x: %d, y: %d, w: %d, y: %d\n", - ZR_DEVNAME(zr), settings->img_x, settings->img_y, + "%s: %s - x: %d, y: %d, w: %d, y: %d\n", + ZR_DEVNAME(zr), __func__, settings->img_x, settings->img_y, settings->img_width, settings->img_height); /* Check decimation, set default values for decimation = 1, 2, 4 */ switch (settings->decimation) { @@ -796,8 +796,8 @@ zoran_check_jpg_settings (struct zoran *zr, if (zr->card.type == DC10_new) { dprintk(1, KERN_DEBUG - "%s: check_jpg_settings() - HDec by 4 is not supported on the DC10\n", - ZR_DEVNAME(zr)); + "%s: %s - HDec by 4 is not supported on the DC10\n", + ZR_DEVNAME(zr), __func__); err0++; break; } @@ -874,16 +874,16 @@ zoran_check_jpg_settings (struct zoran *zr, if (!try && err0) { dprintk(1, KERN_ERR - "%s: check_jpg_settings() - error in params for decimation = 0\n", - ZR_DEVNAME(zr)); + "%s: %s - error in params for decimation = 0\n", + ZR_DEVNAME(zr), __func__); err++; } break; default: dprintk(1, KERN_ERR - "%s: check_jpg_settings() - decimation = %d, must be 0, 1, 2 or 4\n", - ZR_DEVNAME(zr), settings->decimation); + "%s: %s - decimation = %d, must be 0, 1, 2 or 4\n", + ZR_DEVNAME(zr), __func__, settings->decimation); err++; break; } @@ -963,10 +963,8 @@ zoran_open_init_params (struct zoran *zr) JPEG_MARKER_DHT | JPEG_MARKER_DQT; i = zoran_check_jpg_settings(zr, &zr->jpg_settings, 0); if (i) - dprintk(1, - KERN_ERR - "%s: zoran_open_init_params() internal error\n", - ZR_DEVNAME(zr)); + dprintk(1, KERN_ERR "%s: %s internal error\n", + ZR_DEVNAME(zr), __func__); clear_interrupt_counters(zr); zr->testing = 0; @@ -1005,8 +1003,8 @@ zr36057_init (struct zoran *zr) dprintk(1, KERN_INFO - "%s: zr36057_init() - initializing card[%d], zr=%p\n", - ZR_DEVNAME(zr), zr->id, zr); + "%s: %s - initializing card[%d], zr=%p\n", + ZR_DEVNAME(zr), __func__, zr->id, zr); /* default setup of all parameters which will persist between opens */ zr->user = 0; @@ -1039,8 +1037,8 @@ zr36057_init (struct zoran *zr) if (zr->timing == NULL) { dprintk(1, KERN_WARNING - "%s: zr36057_init() - default TV standard not supported by hardware. PAL will be used.\n", - ZR_DEVNAME(zr)); + "%s: %s - default TV standard not supported by hardware. PAL will be used.\n", + ZR_DEVNAME(zr), __func__); zr->norm = V4L2_STD_PAL; zr->timing = zr->card.tvn[0]; } @@ -1064,8 +1062,8 @@ zr36057_init (struct zoran *zr) if (!zr->stat_com || !zr->video_dev) { dprintk(1, KERN_ERR - "%s: zr36057_init() - kmalloc (STAT_COM) failed\n", - ZR_DEVNAME(zr)); + "%s: %s - kmalloc (STAT_COM) failed\n", + ZR_DEVNAME(zr), __func__); err = -ENOMEM; goto exit_free; } @@ -1159,10 +1157,8 @@ zoran_setup_videocodec (struct zoran *zr, m = kmalloc(sizeof(struct videocodec_master), GFP_KERNEL); if (!m) { - dprintk(1, - KERN_ERR - "%s: zoran_setup_videocodec() - no memory\n", - ZR_DEVNAME(zr)); + dprintk(1, KERN_ERR "%s: %s - no memory\n", + ZR_DEVNAME(zr), __func__); return m; } @@ -1219,19 +1215,15 @@ static int __devinit zoran_probe(struct pci_dev *pdev, nr = zoran_num++; if (nr >= BUZ_MAX) { - dprintk(1, - KERN_ERR - "%s: driver limited to %d card(s) maximum\n", + dprintk(1, KERN_ERR "%s: driver limited to %d card(s) maximum\n", ZORAN_NAME, BUZ_MAX); return -ENOENT; } zr = kzalloc(sizeof(struct zoran), GFP_KERNEL); if (!zr) { - dprintk(1, - KERN_ERR - "%s: find_zr36057() - kzalloc failed\n", - ZORAN_NAME); + dprintk(1, KERN_ERR "%s: %s - kzalloc failed\n", + ZORAN_NAME, __func__); return -ENOMEM; } if (v4l2_device_register(&pdev->dev, &zr->v4l2_dev)) @@ -1306,9 +1298,7 @@ static int __devinit zoran_probe(struct pci_dev *pdev, zr->zr36057_mem = pci_ioremap_bar(zr->pci_dev, 0); if (!zr->zr36057_mem) { - dprintk(1, - KERN_ERR - "%s: %s() - ioremap failed\n", + dprintk(1, KERN_ERR "%s: %s() - ioremap failed\n", ZR_DEVNAME(zr), __func__); goto zr_unreg; } @@ -1319,18 +1309,18 @@ static int __devinit zoran_probe(struct pci_dev *pdev, if (result == -EINVAL) { dprintk(1, KERN_ERR - "%s: find_zr36057() - bad irq number or handler\n", - ZR_DEVNAME(zr)); + "%s: %s - bad irq number or handler\n", + ZR_DEVNAME(zr), __func__); } else if (result == -EBUSY) { dprintk(1, KERN_ERR - "%s: find_zr36057() - IRQ %d busy, change your PnP config in BIOS\n", - ZR_DEVNAME(zr), zr->pci_dev->irq); + "%s: %s - IRQ %d busy, change your PnP config in BIOS\n", + ZR_DEVNAME(zr), __func__, zr->pci_dev->irq); } else { dprintk(1, KERN_ERR - "%s: find_zr36057() - can't assign irq, error code %d\n", - ZR_DEVNAME(zr), result); + "%s: %s - can't assign irq, error code %d\n", + ZR_DEVNAME(zr), __func__, result); } goto zr_unmap; } @@ -1340,9 +1330,7 @@ static int __devinit zoran_probe(struct pci_dev *pdev, &latency); need_latency = zr->revision > 1 ? 32 : 48; if (latency != need_latency) { - dprintk(2, - KERN_INFO - "%s: Changing PCI latency from %d to %d\n", + dprintk(2, KERN_INFO "%s: Changing PCI latency from %d to %d\n", ZR_DEVNAME(zr), latency, need_latency); pci_write_config_byte(zr->pci_dev, PCI_LATENCY_TIMER, need_latency); @@ -1354,10 +1342,8 @@ static int __devinit zoran_probe(struct pci_dev *pdev, ZR_DEVNAME(zr)); if (zoran_register_i2c(zr) < 0) { - dprintk(1, - KERN_ERR - "%s: find_zr36057() - can't initialize i2c bus\n", - ZR_DEVNAME(zr)); + dprintk(1, KERN_ERR "%s: %s - can't initialize i2c bus\n", + ZR_DEVNAME(zr), __func__); goto zr_free_irq; } @@ -1409,17 +1395,13 @@ static int __devinit zoran_probe(struct pci_dev *pdev, goto zr_unreg_i2c; zr->codec = videocodec_attach(master_codec); if (!zr->codec) { - dprintk(1, - KERN_ERR - "%s: find_zr36057() - no codec found\n", - ZR_DEVNAME(zr)); + dprintk(1, KERN_ERR "%s: %s - no codec found\n", + ZR_DEVNAME(zr), __func__); goto zr_free_codec; } if (zr->codec->type != zr->card.video_codec) { - dprintk(1, - KERN_ERR - "%s: find_zr36057() - wrong codec\n", - ZR_DEVNAME(zr)); + dprintk(1, KERN_ERR "%s: %s - wrong codec\n", + ZR_DEVNAME(zr), __func__); goto zr_detach_codec; } } @@ -1429,17 +1411,13 @@ static int __devinit zoran_probe(struct pci_dev *pdev, goto zr_detach_codec; zr->vfe = videocodec_attach(master_vfe); if (!zr->vfe) { - dprintk(1, - KERN_ERR - "%s: find_zr36057() - no VFE found\n", - ZR_DEVNAME(zr)); + dprintk(1, KERN_ERR "%s: %s - no VFE found\n", + ZR_DEVNAME(zr), __func__); goto zr_free_vfe; } if (zr->vfe->type != zr->card.video_vfe) { - dprintk(1, - KERN_ERR - "%s: find_zr36057() = wrong VFE\n", - ZR_DEVNAME(zr)); + dprintk(1, KERN_ERR "%s: %s = wrong VFE\n", + ZR_DEVNAME(zr), __func__); goto zr_detach_vfe; } } @@ -1447,8 +1425,7 @@ static int __devinit zoran_probe(struct pci_dev *pdev, /* take care of Natoma chipset and a revision 1 zr36057 */ if ((pci_pci_problems & PCIPCI_NATOMA) && zr->revision <= 1) { zr->jpg_buffers.need_contiguous = 1; - dprintk(1, - KERN_INFO + dprintk(1, KERN_INFO "%s: ZR36057/Natoma bug, max. buffer size is 128K\n", ZR_DEVNAME(zr)); } diff --git a/drivers/media/video/zoran/zoran_driver.c b/drivers/media/video/zoran/zoran_driver.c index 5343a8aeb64a..60501f256b28 100644 --- a/drivers/media/video/zoran/zoran_driver.c +++ b/drivers/media/video/zoran/zoran_driver.c @@ -223,8 +223,8 @@ static int v4l_fbuffer_alloc(struct zoran_fh *fh) if (fh->buffers.buffer[i].v4l.fbuffer) dprintk(2, KERN_WARNING - "%s: v4l_fbuffer_alloc() - buffer %d already allocated!?\n", - ZR_DEVNAME(zr), i); + "%s: %s - buffer %d already allocated!?\n", + ZR_DEVNAME(zr), __func__, i); //udelay(20); mem = kmalloc(fh->buffers.buffer_size, @@ -232,8 +232,8 @@ static int v4l_fbuffer_alloc(struct zoran_fh *fh) if (!mem) { dprintk(1, KERN_ERR - "%s: v4l_fbuffer_alloc() - kmalloc for V4L buf %d failed\n", - ZR_DEVNAME(zr), i); + "%s: %s - kmalloc for V4L buf %d failed\n", + ZR_DEVNAME(zr), __func__, i); v4l_fbuffer_free(fh); return -ENOBUFS; } @@ -245,8 +245,8 @@ static int v4l_fbuffer_alloc(struct zoran_fh *fh) SetPageReserved(virt_to_page(mem + off)); dprintk(4, KERN_INFO - "%s: v4l_fbuffer_alloc() - V4L frame %d mem 0x%lx (bus: 0x%lx)\n", - ZR_DEVNAME(zr), i, (unsigned long) mem, + "%s: %s - V4L frame %d mem 0x%lx (bus: 0x%lx)\n", + ZR_DEVNAME(zr), __func__, i, (unsigned long) mem, virt_to_bus(mem)); } @@ -262,7 +262,7 @@ static void v4l_fbuffer_free(struct zoran_fh *fh) int i, off; unsigned char *mem; - dprintk(4, KERN_INFO "%s: v4l_fbuffer_free()\n", ZR_DEVNAME(zr)); + dprintk(4, KERN_INFO "%s: %s\n", ZR_DEVNAME(zr), __func__); for (i = 0; i < fh->buffers.num_buffers; i++) { if (!fh->buffers.buffer[i].v4l.fbuffer) @@ -317,8 +317,8 @@ static int jpg_fbuffer_alloc(struct zoran_fh *fh) if (fh->buffers.buffer[i].jpg.frag_tab) dprintk(2, KERN_WARNING - "%s: jpg_fbuffer_alloc() - buffer %d already allocated!?\n", - ZR_DEVNAME(zr), i); + "%s: %s - buffer %d already allocated!?\n", + ZR_DEVNAME(zr), __func__, i); /* Allocate fragment table for this buffer */ @@ -326,8 +326,8 @@ static int jpg_fbuffer_alloc(struct zoran_fh *fh) if (mem == 0) { dprintk(1, KERN_ERR - "%s: jpg_fbuffer_alloc() - get_zeroed_page (frag_tab) failed for buffer %d\n", - ZR_DEVNAME(zr), i); + "%s: %s - get_zeroed_page (frag_tab) failed for buffer %d\n", + ZR_DEVNAME(zr), __func__, i); jpg_fbuffer_free(fh); return -ENOBUFS; } @@ -339,8 +339,8 @@ static int jpg_fbuffer_alloc(struct zoran_fh *fh) if (mem == NULL) { dprintk(1, KERN_ERR - "%s: jpg_fbuffer_alloc() - kmalloc failed for buffer %d\n", - ZR_DEVNAME(zr), i); + "%s: %s - kmalloc failed for buffer %d\n", + ZR_DEVNAME(zr), __func__, i); jpg_fbuffer_free(fh); return -ENOBUFS; } @@ -357,8 +357,8 @@ static int jpg_fbuffer_alloc(struct zoran_fh *fh) if (mem == NULL) { dprintk(1, KERN_ERR - "%s: jpg_fbuffer_alloc() - get_zeroed_page failed for buffer %d\n", - ZR_DEVNAME(zr), i); + "%s: %s - get_zeroed_page failed for buffer %d\n", + ZR_DEVNAME(zr), __func__, i); jpg_fbuffer_free(fh); return -ENOBUFS; } @@ -375,8 +375,8 @@ static int jpg_fbuffer_alloc(struct zoran_fh *fh) } dprintk(4, - KERN_DEBUG "%s: jpg_fbuffer_alloc() - %d KB allocated\n", - ZR_DEVNAME(zr), + KERN_DEBUG "%s: %s - %d KB allocated\n", + ZR_DEVNAME(zr), __func__, (fh->buffers.num_buffers * fh->buffers.buffer_size) >> 10); fh->buffers.allocated = 1; @@ -393,7 +393,7 @@ static void jpg_fbuffer_free(struct zoran_fh *fh) __le32 frag_tab; struct zoran_buffer *buffer; - dprintk(4, KERN_DEBUG "%s: jpg_fbuffer_free()\n", ZR_DEVNAME(zr)); + dprintk(4, KERN_DEBUG "%s: %s\n", ZR_DEVNAME(zr), __func__); for (i = 0, buffer = &fh->buffers.buffer[0]; i < fh->buffers.num_buffers; i++, buffer++) { @@ -450,8 +450,8 @@ zoran_v4l_set_format (struct zoran_fh *fh, height > BUZ_MAX_HEIGHT || width > BUZ_MAX_WIDTH) { dprintk(1, KERN_ERR - "%s: v4l_set_format() - wrong frame size (%dx%d)\n", - ZR_DEVNAME(zr), width, height); + "%s: %s - wrong frame size (%dx%d)\n", + ZR_DEVNAME(zr), __func__, width, height); return -EINVAL; } @@ -461,8 +461,8 @@ zoran_v4l_set_format (struct zoran_fh *fh, if (height * width * bpp > fh->buffers.buffer_size) { dprintk(1, KERN_ERR - "%s: v4l_set_format() - video buffer size (%d kB) is too small\n", - ZR_DEVNAME(zr), fh->buffers.buffer_size >> 10); + "%s: %s - video buffer size (%d kB) is too small\n", + ZR_DEVNAME(zr), __func__, fh->buffers.buffer_size >> 10); return -EINVAL; } @@ -471,8 +471,8 @@ zoran_v4l_set_format (struct zoran_fh *fh, if ((bpp == 2 && (width & 1)) || (bpp == 3 && (width & 3))) { dprintk(1, KERN_ERR - "%s: v4l_set_format() - wrong frame alignment\n", - ZR_DEVNAME(zr)); + "%s: %s - wrong frame alignment\n", + ZR_DEVNAME(zr), __func__); return -EINVAL; } @@ -493,8 +493,8 @@ static int zoran_v4l_queue_frame(struct zoran_fh *fh, int num) if (!fh->buffers.allocated) { dprintk(1, KERN_ERR - "%s: v4l_queue_frame() - buffers not yet allocated\n", - ZR_DEVNAME(zr)); + "%s: %s - buffers not yet allocated\n", + ZR_DEVNAME(zr), __func__); res = -ENOMEM; } @@ -502,8 +502,8 @@ static int zoran_v4l_queue_frame(struct zoran_fh *fh, int num) if (num >= fh->buffers.num_buffers || num < 0) { dprintk(1, KERN_ERR - "%s: v4l_queue_frame() - buffer %d is out of range\n", - ZR_DEVNAME(zr), num); + "%s: %s - buffer %d is out of range\n", + ZR_DEVNAME(zr), __func__, num); res = -EINVAL; } @@ -516,8 +516,8 @@ static int zoran_v4l_queue_frame(struct zoran_fh *fh, int num) } else { dprintk(1, KERN_ERR - "%s: v4l_queue_frame() - another session is already capturing\n", - ZR_DEVNAME(zr)); + "%s: %s - another session is already capturing\n", + ZR_DEVNAME(zr), __func__); res = -EBUSY; } } @@ -536,8 +536,8 @@ static int zoran_v4l_queue_frame(struct zoran_fh *fh, int num) case BUZ_STATE_DONE: dprintk(2, KERN_WARNING - "%s: v4l_queue_frame() - queueing buffer %d in state DONE!?\n", - ZR_DEVNAME(zr), num); + "%s: %s - queueing buffer %d in state DONE!?\n", + ZR_DEVNAME(zr), __func__, num); case BUZ_STATE_USER: /* since there is at least one unused buffer there's room for at least * one more pend[] entry */ @@ -571,16 +571,16 @@ static int v4l_sync(struct zoran_fh *fh, int frame) if (fh->buffers.active == ZORAN_FREE) { dprintk(1, KERN_ERR - "%s: v4l_sync() - no grab active for this session\n", - ZR_DEVNAME(zr)); + "%s: %s - no grab active for this session\n", + ZR_DEVNAME(zr), __func__); return -EINVAL; } /* check passed-in frame number */ if (frame >= fh->buffers.num_buffers || frame < 0) { dprintk(1, - KERN_ERR "%s: v4l_sync() - frame %d is invalid\n", - ZR_DEVNAME(zr), frame); + KERN_ERR "%s: %s - frame %d is invalid\n", + ZR_DEVNAME(zr), __func__, frame); return -EINVAL; } @@ -588,8 +588,8 @@ static int v4l_sync(struct zoran_fh *fh, int frame) if (zr->v4l_buffers.buffer[frame].state == BUZ_STATE_USER) { dprintk(1, KERN_ERR - "%s: v4l_sync() - attempt to sync on a buffer which was not queued?\n", - ZR_DEVNAME(zr)); + "%s: %s - attempt to sync on a buffer which was not queued?\n", + ZR_DEVNAME(zr), __func__); return -EPROTO; } @@ -603,8 +603,8 @@ static int v4l_sync(struct zoran_fh *fh, int frame) /* buffer should now be in BUZ_STATE_DONE */ if (zr->v4l_buffers.buffer[frame].state != BUZ_STATE_DONE) dprintk(2, - KERN_ERR "%s: v4l_sync() - internal state error\n", - ZR_DEVNAME(zr)); + KERN_ERR "%s: %s - internal state error\n", + ZR_DEVNAME(zr), __func__); zr->v4l_buffers.buffer[frame].state = BUZ_STATE_USER; fh->buffers.buffer[frame] = zr->v4l_buffers.buffer[frame]; @@ -640,8 +640,8 @@ static int zoran_jpg_queue_frame(struct zoran_fh *fh, int num, if (!fh->buffers.allocated) { dprintk(1, KERN_ERR - "%s: jpg_queue_frame() - buffers not yet allocated\n", - ZR_DEVNAME(zr)); + "%s: %s - buffers not yet allocated\n", + ZR_DEVNAME(zr), __func__); return -ENOMEM; } @@ -649,8 +649,8 @@ static int zoran_jpg_queue_frame(struct zoran_fh *fh, int num, if (num >= fh->buffers.num_buffers || num < 0) { dprintk(1, KERN_ERR - "%s: jpg_queue_frame() - buffer %d out of range\n", - ZR_DEVNAME(zr), num); + "%s: %s - buffer %d out of range\n", + ZR_DEVNAME(zr), __func__, num); return -EINVAL; } @@ -661,8 +661,8 @@ static int zoran_jpg_queue_frame(struct zoran_fh *fh, int num, /* wrong codec mode active - invalid */ dprintk(1, KERN_ERR - "%s: jpg_queue_frame() - codec in wrong mode\n", - ZR_DEVNAME(zr)); + "%s: %s - codec in wrong mode\n", + ZR_DEVNAME(zr), __func__); return -EINVAL; } @@ -673,8 +673,8 @@ static int zoran_jpg_queue_frame(struct zoran_fh *fh, int num, } else { dprintk(1, KERN_ERR - "%s: jpg_queue_frame() - another session is already capturing\n", - ZR_DEVNAME(zr)); + "%s: %s - another session is already capturing\n", + ZR_DEVNAME(zr), __func__); res = -EBUSY; } } @@ -691,8 +691,8 @@ static int zoran_jpg_queue_frame(struct zoran_fh *fh, int num, case BUZ_STATE_DONE: dprintk(2, KERN_WARNING - "%s: jpg_queue_frame() - queing frame in BUZ_STATE_DONE state!?\n", - ZR_DEVNAME(zr)); + "%s: %s - queing frame in BUZ_STATE_DONE state!?\n", + ZR_DEVNAME(zr), __func__); case BUZ_STATE_USER: /* since there is at least one unused buffer there's room for at *least one more pend[] entry */ @@ -732,8 +732,8 @@ static int jpg_qbuf(struct zoran_fh *fh, int frame, enum zoran_codec_mode mode) if (fh->buffers.active == ZORAN_FREE) { dprintk(1, KERN_ERR - "%s: jpg_qbuf(-1) - session not active\n", - ZR_DEVNAME(zr)); + "%s: %s(-1) - session not active\n", + ZR_DEVNAME(zr), __func__); return -EINVAL; } fh->buffers.active = zr->jpg_buffers.active = ZORAN_FREE; @@ -743,8 +743,8 @@ static int jpg_qbuf(struct zoran_fh *fh, int frame, enum zoran_codec_mode mode) } else { dprintk(1, KERN_ERR - "%s: jpg_qbuf() - stop streaming but not in streaming mode\n", - ZR_DEVNAME(zr)); + "%s: %s - stop streaming but not in streaming mode\n", + ZR_DEVNAME(zr), __func__); return -EINVAL; } } @@ -772,16 +772,16 @@ static int jpg_sync(struct zoran_fh *fh, struct zoran_sync *bs) if (fh->buffers.active == ZORAN_FREE) { dprintk(1, KERN_ERR - "%s: jpg_sync() - capture is not currently active\n", - ZR_DEVNAME(zr)); + "%s: %s - capture is not currently active\n", + ZR_DEVNAME(zr), __func__); return -EINVAL; } if (zr->codec_mode != BUZ_MODE_MOTION_DECOMPRESS && zr->codec_mode != BUZ_MODE_MOTION_COMPRESS) { dprintk(1, KERN_ERR - "%s: jpg_sync() - codec not in streaming mode\n", - ZR_DEVNAME(zr)); + "%s: %s - codec not in streaming mode\n", + ZR_DEVNAME(zr), __func__); return -EINVAL; } if (!wait_event_interruptible_timeout(zr->jpg_capq, @@ -796,8 +796,8 @@ static int jpg_sync(struct zoran_fh *fh, struct zoran_sync *bs) sizeof(isr), &isr); dprintk(1, KERN_ERR - "%s: jpg_sync() - timeout: codec isr=0x%02x\n", - ZR_DEVNAME(zr), isr); + "%s: %s - timeout: codec isr=0x%02x\n", + ZR_DEVNAME(zr), __func__, isr); return -ETIME; @@ -815,8 +815,8 @@ static int jpg_sync(struct zoran_fh *fh, struct zoran_sync *bs) /* buffer should now be in BUZ_STATE_DONE */ if (zr->jpg_buffers.buffer[frame].state != BUZ_STATE_DONE) dprintk(2, - KERN_ERR "%s: jpg_sync() - internal state error\n", - ZR_DEVNAME(zr)); + KERN_ERR "%s: %s - internal state error\n", + ZR_DEVNAME(zr), __func__); *bs = zr->jpg_buffers.buffer[frame].bs; bs->frame = frame; @@ -909,8 +909,8 @@ static int zoran_open(struct file *file) struct zoran_fh *fh; int res, first_open = 0; - dprintk(2, KERN_INFO "%s: zoran_open(%s, pid=[%d]), users(-)=%d\n", - ZR_DEVNAME(zr), current->comm, task_pid_nr(current), zr->user + 1); + dprintk(2, KERN_INFO "%s: %s(%s, pid=[%d]), users(-)=%d\n", + ZR_DEVNAME(zr), __func__, current->comm, task_pid_nr(current), zr->user + 1); lock_kernel(); @@ -926,8 +926,8 @@ static int zoran_open(struct file *file) if (!fh) { dprintk(1, KERN_ERR - "%s: zoran_open() - allocation of zoran_fh failed\n", - ZR_DEVNAME(zr)); + "%s: %s - allocation of zoran_fh failed\n", + ZR_DEVNAME(zr), __func__); res = -ENOMEM; goto fail_unlock; } @@ -938,8 +938,8 @@ static int zoran_open(struct file *file) if (!fh->overlay_mask) { dprintk(1, KERN_ERR - "%s: zoran_open() - allocation of overlay_mask failed\n", - ZR_DEVNAME(zr)); + "%s: %s - allocation of overlay_mask failed\n", + ZR_DEVNAME(zr), __func__); res = -ENOMEM; goto fail_fh; } @@ -983,8 +983,8 @@ zoran_close(struct file *file) struct zoran_fh *fh = file->private_data; struct zoran *zr = fh->zr; - dprintk(2, KERN_INFO "%s: zoran_close(%s, pid=[%d]), users(+)=%d\n", - ZR_DEVNAME(zr), current->comm, task_pid_nr(current), zr->user - 1); + dprintk(2, KERN_INFO "%s: %s(%s, pid=[%d]), users(+)=%d\n", + ZR_DEVNAME(zr), __func__, current->comm, task_pid_nr(current), zr->user - 1); /* kernel locks (fs/device.c), so don't do that ourselves * (prevents deadlocks) */ @@ -1029,7 +1029,7 @@ zoran_close(struct file *file) kfree(fh->overlay_mask); kfree(fh); - dprintk(4, KERN_INFO "%s: zoran_close() done\n", ZR_DEVNAME(zr)); + dprintk(4, KERN_INFO "%s: %s done\n", ZR_DEVNAME(zr), __func__); return 0; } @@ -1091,8 +1091,8 @@ static int setup_fbuffer(struct zoran_fh *fh, * friendly and silently do as if nothing went wrong */ dprintk(3, KERN_ERR - "%s: setup_fbuffer() - forced overlay turnoff because framebuffer changed\n", - ZR_DEVNAME(zr)); + "%s: %s - forced overlay turnoff because framebuffer changed\n", + ZR_DEVNAME(zr), __func__); zr36057_overlay(zr, 0); } #endif @@ -1100,22 +1100,22 @@ static int setup_fbuffer(struct zoran_fh *fh, if (!(fmt->flags & ZORAN_FORMAT_OVERLAY)) { dprintk(1, KERN_ERR - "%s: setup_fbuffer() - no valid overlay format given\n", - ZR_DEVNAME(zr)); + "%s: %s - no valid overlay format given\n", + ZR_DEVNAME(zr), __func__); return -EINVAL; } if (height <= 0 || width <= 0 || bytesperline <= 0) { dprintk(1, KERN_ERR - "%s: setup_fbuffer() - invalid height/width/bpl value (%d|%d|%d)\n", - ZR_DEVNAME(zr), width, height, bytesperline); + "%s: %s - invalid height/width/bpl value (%d|%d|%d)\n", + ZR_DEVNAME(zr), __func__, width, height, bytesperline); return -EINVAL; } if (bytesperline & 3) { dprintk(1, KERN_ERR - "%s: setup_fbuffer() - bytesperline (%d) must be 4-byte aligned\n", - ZR_DEVNAME(zr), bytesperline); + "%s: %s - bytesperline (%d) must be 4-byte aligned\n", + ZR_DEVNAME(zr), __func__, bytesperline); return -EINVAL; } @@ -1144,16 +1144,16 @@ static int setup_window(struct zoran_fh *fh, int x, int y, int width, int height if (!zr->vbuf_base) { dprintk(1, KERN_ERR - "%s: setup_window() - frame buffer has to be set first\n", - ZR_DEVNAME(zr)); + "%s: %s - frame buffer has to be set first\n", + ZR_DEVNAME(zr), __func__); return -EINVAL; } if (!fh->overlay_settings.format) { dprintk(1, KERN_ERR - "%s: setup_window() - no overlay format set\n", - ZR_DEVNAME(zr)); + "%s: %s - no overlay format set\n", + ZR_DEVNAME(zr), __func__); return -EINVAL; } @@ -1183,8 +1183,8 @@ static int setup_window(struct zoran_fh *fh, int x, int y, int width, int height width > BUZ_MAX_WIDTH || height > BUZ_MAX_HEIGHT) { dprintk(1, KERN_ERR - "%s: setup_window() - width = %d or height = %d invalid\n", - ZR_DEVNAME(zr), width, height); + "%s: %s - width = %d or height = %d invalid\n", + ZR_DEVNAME(zr), __func__, width, height); return -EINVAL; } @@ -1226,8 +1226,8 @@ static int setup_window(struct zoran_fh *fh, int x, int y, int width, int height if (vcp == NULL) { dprintk(1, KERN_ERR - "%s: setup_window() - Alloc of clip mask failed\n", - ZR_DEVNAME(zr)); + "%s: %s - Alloc of clip mask failed\n", + ZR_DEVNAME(zr), __func__); return -ENOMEM; } if (copy_from_user @@ -1265,16 +1265,16 @@ static int setup_overlay(struct zoran_fh *fh, int on) fh->overlay_active == ZORAN_FREE) { dprintk(1, KERN_ERR - "%s: setup_overlay() - overlay is already active for another session\n", - ZR_DEVNAME(zr)); + "%s: %s - overlay is already active for another session\n", + ZR_DEVNAME(zr), __func__); return -EBUSY; } if (!on && zr->overlay_active != ZORAN_FREE && fh->overlay_active == ZORAN_FREE) { dprintk(1, KERN_ERR - "%s: setup_overlay() - you cannot cancel someone else's session\n", - ZR_DEVNAME(zr)); + "%s: %s - you cannot cancel someone else's session\n", + ZR_DEVNAME(zr), __func__); return -EPERM; } @@ -1290,15 +1290,15 @@ static int setup_overlay(struct zoran_fh *fh, int on) if (!zr->vbuf_base || !fh->overlay_settings.is_set) { dprintk(1, KERN_ERR - "%s: setup_overlay() - buffer or window not set\n", - ZR_DEVNAME(zr)); + "%s: %s - buffer or window not set\n", + ZR_DEVNAME(zr), __func__); return -EINVAL; } if (!fh->overlay_settings.format) { dprintk(1, KERN_ERR - "%s: setup_overlay() - no overlay format set\n", - ZR_DEVNAME(zr)); + "%s: %s - no overlay format set\n", + ZR_DEVNAME(zr), __func__); return -EINVAL; } zr->overlay_active = fh->overlay_active = ZORAN_LOCKED; @@ -1331,8 +1331,8 @@ static int zoran_v4l2_buffer_status(struct zoran_fh *fh, !fh->buffers.allocated) { dprintk(1, KERN_ERR - "%s: v4l2_buffer_status() - wrong number or buffers not allocated\n", - ZR_DEVNAME(zr)); + "%s: %s - wrong number or buffers not allocated\n", + ZR_DEVNAME(zr), __func__); return -EINVAL; } @@ -1375,8 +1375,8 @@ static int zoran_v4l2_buffer_status(struct zoran_fh *fh, !fh->buffers.allocated) { dprintk(1, KERN_ERR - "%s: v4l2_buffer_status() - wrong number or buffers not allocated\n", - ZR_DEVNAME(zr)); + "%s: %s - wrong number or buffers not allocated\n", + ZR_DEVNAME(zr), __func__); return -EINVAL; } @@ -1410,8 +1410,8 @@ static int zoran_v4l2_buffer_status(struct zoran_fh *fh, dprintk(5, KERN_ERR - "%s: v4l2_buffer_status() - invalid buffer type|map_mode (%d|%d)\n", - ZR_DEVNAME(zr), buf->type, fh->map_mode); + "%s: %s - invalid buffer type|map_mode (%d|%d)\n", + ZR_DEVNAME(zr), __func__, buf->type, fh->map_mode); return -EINVAL; } @@ -1432,15 +1432,15 @@ zoran_set_norm (struct zoran *zr, zr->jpg_buffers.active != ZORAN_FREE) { dprintk(1, KERN_WARNING - "%s: set_norm() called while in playback/capture mode\n", - ZR_DEVNAME(zr)); + "%s: %s called while in playback/capture mode\n", + ZR_DEVNAME(zr), __func__); return -EBUSY; } if (!(norm & zr->card.norms)) { dprintk(1, - KERN_ERR "%s: set_norm() - unsupported norm %llx\n", - ZR_DEVNAME(zr), norm); + KERN_ERR "%s: %s - unsupported norm %llx\n", + ZR_DEVNAME(zr), __func__, norm); return -EINVAL; } @@ -1458,8 +1458,8 @@ zoran_set_norm (struct zoran *zr, if (status & V4L2_IN_ST_NO_SIGNAL) { dprintk(1, KERN_ERR - "%s: set_norm() - no norm detected\n", - ZR_DEVNAME(zr)); + "%s: %s - no norm detected\n", + ZR_DEVNAME(zr), __func__); /* reset norm */ decoder_s_std(zr, zr->norm); return -EIO; @@ -1506,16 +1506,16 @@ zoran_set_input (struct zoran *zr, zr->jpg_buffers.active != ZORAN_FREE) { dprintk(1, KERN_WARNING - "%s: set_input() called while in playback/capture mode\n", - ZR_DEVNAME(zr)); + "%s: %s called while in playback/capture mode\n", + ZR_DEVNAME(zr), __func__); return -EBUSY; } if (input < 0 || input >= zr->card.inputs) { dprintk(1, KERN_ERR - "%s: set_input() - unnsupported input %d\n", - ZR_DEVNAME(zr), input); + "%s: %s - unnsupported input %d\n", + ZR_DEVNAME(zr), __func__, input); return -EINVAL; } @@ -3101,8 +3101,8 @@ zoran_poll (struct file *file, default: dprintk(1, KERN_ERR - "%s: zoran_poll() - internal error, unknown map_mode=%d\n", - ZR_DEVNAME(zr), fh->map_mode); + "%s: %s - internal error, unknown map_mode=%d\n", + ZR_DEVNAME(zr), __func__, fh->map_mode); res = POLLNVAL; } @@ -3205,16 +3205,16 @@ zoran_mmap (struct file *file, int res = 0; dprintk(3, - KERN_INFO "%s: mmap(%s) of 0x%08lx-0x%08lx (size=%lu)\n", - ZR_DEVNAME(zr), + KERN_INFO "%s: %s(%s) of 0x%08lx-0x%08lx (size=%lu)\n", + ZR_DEVNAME(zr), __func__, mode_name(fh->map_mode), vma->vm_start, vma->vm_end, size); if (!(vma->vm_flags & VM_SHARED) || !(vma->vm_flags & VM_READ) || !(vma->vm_flags & VM_WRITE)) { dprintk(1, KERN_ERR - "%s: mmap() - no MAP_SHARED/PROT_{READ,WRITE} given\n", - ZR_DEVNAME(zr)); + "%s: %s - no MAP_SHARED/PROT_{READ,WRITE} given\n", + ZR_DEVNAME(zr), __func__); return -EINVAL; } @@ -3223,8 +3223,8 @@ zoran_mmap (struct file *file, if (!fh->buffers.allocated) { dprintk(1, KERN_ERR - "%s: zoran_mmap(%s) - buffers not yet allocated\n", - ZR_DEVNAME(zr), mode_name(fh->map_mode)); + "%s: %s(%s) - buffers not yet allocated\n", + ZR_DEVNAME(zr), __func__, mode_name(fh->map_mode)); res = -ENOMEM; goto mmap_unlock_and_return; } @@ -3237,8 +3237,8 @@ zoran_mmap (struct file *file, last >= fh->buffers.buffer_size) { dprintk(1, KERN_ERR - "%s: mmap(%s) - offset=%lu or size=%lu invalid for bufsize=%d and numbufs=%d\n", - ZR_DEVNAME(zr), mode_name(fh->map_mode), offset, size, + "%s: %s(%s) - offset=%lu or size=%lu invalid for bufsize=%d and numbufs=%d\n", + ZR_DEVNAME(zr), __func__, mode_name(fh->map_mode), offset, size, fh->buffers.buffer_size, fh->buffers.num_buffers); res = -EINVAL; @@ -3250,8 +3250,8 @@ zoran_mmap (struct file *file, if (fh->buffers.buffer[i].map) { dprintk(1, KERN_ERR - "%s: mmap(%s) - buffer %d already mapped\n", - ZR_DEVNAME(zr), mode_name(fh->map_mode), i); + "%s: %s(%s) - buffer %d already mapped\n", + ZR_DEVNAME(zr), __func__, mode_name(fh->map_mode), i); res = -EBUSY; goto mmap_unlock_and_return; } @@ -3280,8 +3280,8 @@ zoran_mmap (struct file *file, todo, PAGE_SHARED)) { dprintk(1, KERN_ERR - "%s: zoran_mmap(V4L) - remap_pfn_range failed\n", - ZR_DEVNAME(zr)); + "%s: %s(V4L) - remap_pfn_range failed\n", + ZR_DEVNAME(zr), __func__); res = -EAGAIN; goto mmap_unlock_and_return; } @@ -3312,8 +3312,8 @@ zoran_mmap (struct file *file, todo, PAGE_SHARED)) { dprintk(1, KERN_ERR - "%s: zoran_mmap(V4L) - remap_pfn_range failed\n", - ZR_DEVNAME(zr)); + "%s: %s(V4L) - remap_pfn_range failed\n", + ZR_DEVNAME(zr), __func__); res = -EAGAIN; goto mmap_unlock_and_return; } -- cgit v1.2.3 From f263bac9f7181df80b732b7bc11a7a4e38ca962f Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Sat, 7 Mar 2009 07:43:01 -0300 Subject: V4L/DVB (10938): em28xx: Prevent general protection fault on rmmod The removal of the timer which polls the infrared input is racy. Replacing the timer with a delayed work solves the problem. Signed-off-by: Jean Delvare Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/em28xx/em28xx-input.c | 22 ++++++---------------- 1 file changed, 6 insertions(+), 16 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/em28xx/em28xx-input.c b/drivers/media/video/em28xx/em28xx-input.c index 0443afe09ff8..a5abfd7a19f5 100644 --- a/drivers/media/video/em28xx/em28xx-input.c +++ b/drivers/media/video/em28xx/em28xx-input.c @@ -68,8 +68,7 @@ struct em28xx_IR { /* poll external decoder */ int polling; - struct work_struct work; - struct timer_list timer; + struct delayed_work work; unsigned int last_toggle:1; unsigned int last_readcount; unsigned int repeat_interval; @@ -292,32 +291,23 @@ static void em28xx_ir_handle_key(struct em28xx_IR *ir) return; } -static void ir_timer(unsigned long data) -{ - struct em28xx_IR *ir = (struct em28xx_IR *)data; - - schedule_work(&ir->work); -} - static void em28xx_ir_work(struct work_struct *work) { - struct em28xx_IR *ir = container_of(work, struct em28xx_IR, work); + struct em28xx_IR *ir = container_of(work, struct em28xx_IR, work.work); em28xx_ir_handle_key(ir); - mod_timer(&ir->timer, jiffies + msecs_to_jiffies(ir->polling)); + schedule_delayed_work(&ir->work, msecs_to_jiffies(ir->polling)); } static void em28xx_ir_start(struct em28xx_IR *ir) { - setup_timer(&ir->timer, ir_timer, (unsigned long)ir); - INIT_WORK(&ir->work, em28xx_ir_work); - schedule_work(&ir->work); + INIT_DELAYED_WORK(&ir->work, em28xx_ir_work); + schedule_delayed_work(&ir->work, 0); } static void em28xx_ir_stop(struct em28xx_IR *ir) { - del_timer_sync(&ir->timer); - flush_scheduled_work(); + cancel_delayed_work_sync(&ir->work); } int em28xx_ir_init(struct em28xx *dev) -- cgit v1.2.3 From c1089bdc07f06b90f0bc50d0789c2a4833097df7 Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Sat, 7 Mar 2009 07:43:43 -0300 Subject: V4L/DVB (10939): ir-kbd-i2c: Prevent general protection fault on rmmod The removal of the timer which polls the infrared input is racy. Replacing the timer with a delayed work solves the problem. Signed-off-by: Jean Delvare Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/ir-kbd-i2c.c | 20 +++++--------------- include/media/ir-kbd-i2c.h | 3 +-- 2 files changed, 6 insertions(+), 17 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/ir-kbd-i2c.c b/drivers/media/video/ir-kbd-i2c.c index 2ee49b7ddcf0..092c7da0f37a 100644 --- a/drivers/media/video/ir-kbd-i2c.c +++ b/drivers/media/video/ir-kbd-i2c.c @@ -279,15 +279,9 @@ static void ir_key_poll(struct IR_i2c *ir) } } -static void ir_timer(unsigned long data) -{ - struct IR_i2c *ir = (struct IR_i2c*)data; - schedule_work(&ir->work); -} - static void ir_work(struct work_struct *work) { - struct IR_i2c *ir = container_of(work, struct IR_i2c, work); + struct IR_i2c *ir = container_of(work, struct IR_i2c, work.work); int polling_interval = 100; /* MSI TV@nywhere Plus requires more frequent polling @@ -296,7 +290,7 @@ static void ir_work(struct work_struct *work) polling_interval = 50; ir_key_poll(ir); - mod_timer(&ir->timer, jiffies + msecs_to_jiffies(polling_interval)); + schedule_delayed_work(&ir->work, msecs_to_jiffies(polling_interval)); } /* ----------------------------------------------------------------------- */ @@ -452,11 +446,8 @@ static int ir_attach(struct i2c_adapter *adap, int addr, ir->input->name, ir->input->phys, adap->name); /* start polling via eventd */ - INIT_WORK(&ir->work, ir_work); - init_timer(&ir->timer); - ir->timer.function = ir_timer; - ir->timer.data = (unsigned long)ir; - schedule_work(&ir->work); + INIT_DELAYED_WORK(&ir->work, ir_work); + schedule_delayed_work(&ir->work, 0); return 0; @@ -473,8 +464,7 @@ static int ir_detach(struct i2c_client *client) struct IR_i2c *ir = i2c_get_clientdata(client); /* kill outstanding polls */ - del_timer_sync(&ir->timer); - flush_scheduled_work(); + cancel_delayed_work_sync(&ir->work); /* unregister devices */ input_unregister_device(ir->input); diff --git a/include/media/ir-kbd-i2c.h b/include/media/ir-kbd-i2c.h index 00fa57eb9fde..07963d705400 100644 --- a/include/media/ir-kbd-i2c.h +++ b/include/media/ir-kbd-i2c.h @@ -14,8 +14,7 @@ struct IR_i2c { /* Used to avoid fast repeating */ unsigned char old; - struct work_struct work; - struct timer_list timer; + struct delayed_work work; char phys[32]; int (*get_key)(struct IR_i2c*, u32*, u32*); }; -- cgit v1.2.3 From fb6991d417a9f06978119ea597dc5955b3eb784d Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Sat, 7 Mar 2009 07:44:12 -0300 Subject: V4L/DVB (10940): saa6588: Prevent general protection fault on rmmod The removal of the timer which polls the infrared input is racy. Replacing the timer with a delayed work solves the problem. Signed-off-by: Jean Delvare Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/saa6588.c | 24 ++++++------------------ 1 file changed, 6 insertions(+), 18 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/saa6588.c b/drivers/media/video/saa6588.c index 0067b281d503..2ce758c1ebb1 100644 --- a/drivers/media/video/saa6588.c +++ b/drivers/media/video/saa6588.c @@ -76,8 +76,7 @@ MODULE_LICENSE("GPL"); struct saa6588 { struct v4l2_subdev sd; - struct work_struct work; - struct timer_list timer; + struct delayed_work work; spinlock_t lock; unsigned char *buffer; unsigned int buf_size; @@ -322,19 +321,12 @@ static void saa6588_i2c_poll(struct saa6588 *s) wake_up_interruptible(&s->read_queue); } -static void saa6588_timer(unsigned long data) -{ - struct saa6588 *s = (struct saa6588 *)data; - - schedule_work(&s->work); -} - static void saa6588_work(struct work_struct *work) { - struct saa6588 *s = container_of(work, struct saa6588, work); + struct saa6588 *s = container_of(work, struct saa6588, work.work); saa6588_i2c_poll(s); - mod_timer(&s->timer, jiffies + msecs_to_jiffies(20)); + schedule_delayed_work(&s->work, msecs_to_jiffies(20)); } static int saa6588_configure(struct saa6588 *s) @@ -490,11 +482,8 @@ static int saa6588_probe(struct i2c_client *client, saa6588_configure(s); /* start polling via eventd */ - INIT_WORK(&s->work, saa6588_work); - init_timer(&s->timer); - s->timer.function = saa6588_timer; - s->timer.data = (unsigned long)s; - schedule_work(&s->work); + INIT_DELAYED_WORK(&s->work, saa6588_work); + schedule_delayed_work(&s->work, 0); return 0; } @@ -505,8 +494,7 @@ static int saa6588_remove(struct i2c_client *client) v4l2_device_unregister_subdev(sd); - del_timer_sync(&s->timer); - flush_scheduled_work(); + cancel_delayed_work_sync(&s->work); kfree(s->buffer); kfree(s); -- cgit v1.2.3 From 569b7ec73abf576f9a9e4070d213aadf2cce73cb Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Sat, 7 Mar 2009 07:42:12 -0300 Subject: V4L/DVB (10943): cx88: Prevent general protection fault on rmmod When unloading the cx8800 driver I sometimes get a general protection fault. Analysis revealed a race in cx88_ir_stop(). It can be solved by using a delayed work instead of a timer for infrared input polling. Signed-off-by: Jean Delvare Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx88/cx88-input.c | 25 +++++++------------------ 1 file changed, 7 insertions(+), 18 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/cx88/cx88-input.c b/drivers/media/video/cx88/cx88-input.c index ad0842136d8d..ec05312a9b62 100644 --- a/drivers/media/video/cx88/cx88-input.c +++ b/drivers/media/video/cx88/cx88-input.c @@ -48,8 +48,7 @@ struct cx88_IR { /* poll external decoder */ int polling; - struct work_struct work; - struct timer_list timer; + struct delayed_work work; u32 gpio_addr; u32 last_gpio; u32 mask_keycode; @@ -143,27 +142,19 @@ static void cx88_ir_handle_key(struct cx88_IR *ir) } } -static void ir_timer(unsigned long data) -{ - struct cx88_IR *ir = (struct cx88_IR *)data; - - schedule_work(&ir->work); -} - static void cx88_ir_work(struct work_struct *work) { - struct cx88_IR *ir = container_of(work, struct cx88_IR, work); + struct cx88_IR *ir = container_of(work, struct cx88_IR, work.work); cx88_ir_handle_key(ir); - mod_timer(&ir->timer, jiffies + msecs_to_jiffies(ir->polling)); + schedule_delayed_work(&ir->work, msecs_to_jiffies(ir->polling)); } void cx88_ir_start(struct cx88_core *core, struct cx88_IR *ir) { if (ir->polling) { - setup_timer(&ir->timer, ir_timer, (unsigned long)ir); - INIT_WORK(&ir->work, cx88_ir_work); - schedule_work(&ir->work); + INIT_DELAYED_WORK(&ir->work, cx88_ir_work); + schedule_delayed_work(&ir->work, 0); } if (ir->sampling) { core->pci_irqmask |= PCI_INT_IR_SMPINT; @@ -179,10 +170,8 @@ void cx88_ir_stop(struct cx88_core *core, struct cx88_IR *ir) core->pci_irqmask &= ~PCI_INT_IR_SMPINT; } - if (ir->polling) { - del_timer_sync(&ir->timer); - flush_scheduled_work(); - } + if (ir->polling) + cancel_delayed_work_sync(&ir->work); } /* ---------------------------------------------------------------------- */ -- cgit v1.2.3 From 76ecf4599e55fd16bdb333a737c6243105c916e6 Mon Sep 17 00:00:00 2001 From: Robert Millan Date: Wed, 11 Mar 2009 08:18:53 -0300 Subject: V4L/DVB (10944): Conceptronic CTVFMI2 PCI Id My BTTV_BOARD_CONCEPTRONIC_CTVFMI2 card wasn't auto-detected, here's a patch that adds its PCI id. lspci -nnv output: 05:06.0 Multimedia video controller [0400]: Brooktree Corporation Bt878 Video Capture [109e:036e] (rev 11) 05:06.1 Multimedia controller [0480]: Brooktree Corporation Bt878 Audio Capture [109e:0878] (rev 11) Press within 3 seconds if this is wrong. Signed-off-by: Mauro Carvalho Chehab --- Documentation/video4linux/CARDLIST.bttv | 2 +- drivers/media/video/bt8xx/bttv-cards.c | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers/media/video') diff --git a/Documentation/video4linux/CARDLIST.bttv b/Documentation/video4linux/CARDLIST.bttv index 1da2c62715ae..e17750473e08 100644 --- a/Documentation/video4linux/CARDLIST.bttv +++ b/Documentation/video4linux/CARDLIST.bttv @@ -135,7 +135,7 @@ 134 -> Adlink RTV24 135 -> DViCO FusionHDTV 5 Lite [18ac:d500] 136 -> Acorp Y878F [9511:1540] -137 -> Conceptronic CTVFMi v2 +137 -> Conceptronic CTVFMi v2 [036e:109e] 138 -> Prolink Pixelview PV-BT878P+ (Rev.2E) 139 -> Prolink PixelView PlayTV MPEG2 PV-M4900 140 -> Osprey 440 [0070:ff07] diff --git a/drivers/media/video/bt8xx/bttv-cards.c b/drivers/media/video/bt8xx/bttv-cards.c index fbeb396dc1c5..187ed4ef3993 100644 --- a/drivers/media/video/bt8xx/bttv-cards.c +++ b/drivers/media/video/bt8xx/bttv-cards.c @@ -298,6 +298,8 @@ static struct CARD { /* Duplicate PCI ID, reconfigure for this board during the eeprom read. * { 0x13eb0070, BTTV_BOARD_HAUPPAUGE_IMPACTVCB, "Hauppauge ImpactVCB" }, */ + { 0x109e036e, BTTV_BOARD_CONCEPTRONIC_CTVFMI2, "Conceptronic CTVFMi v2"}, + /* DVB cards (using pci function .1 for mpeg data xfer) */ { 0x001c11bd, BTTV_BOARD_PINNACLESAT, "Pinnacle PCTV Sat" }, { 0x01010071, BTTV_BOARD_NEBULA_DIGITV, "Nebula Electronics DigiTV" }, -- cgit v1.2.3 From 5c8e2403ba06d39f04f6ae62f3afe5542e0eb533 Mon Sep 17 00:00:00 2001 From: Martin Fuzzey Date: Mon, 9 Mar 2009 20:16:00 -0300 Subject: V4L/DVB (10945): pwc : fix LED and power setup for first open Call pwc_construct before trying to talk to device to obtain vc interface so that LED and power setup works the first time the video device is opened. Signed-off-by: Martin Fuzzey Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/pwc/pwc-if.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/pwc/pwc-if.c b/drivers/media/video/pwc/pwc-if.c index a7c2e7284c20..7c542caf248e 100644 --- a/drivers/media/video/pwc/pwc-if.c +++ b/drivers/media/video/pwc/pwc-if.c @@ -1125,6 +1125,7 @@ static int pwc_video_open(struct file *file) } mutex_lock(&pdev->modlock); + pwc_construct(pdev); /* set min/max sizes correct */ if (!pdev->usb_init) { PWC_DEBUG_OPEN("Doing first time initialization.\n"); pdev->usb_init = 1; @@ -1149,7 +1150,6 @@ static int pwc_video_open(struct file *file) if (pwc_set_leds(pdev, led_on, led_off) < 0) PWC_DEBUG_OPEN("Failed to set LED on/off time.\n"); - pwc_construct(pdev); /* set min/max sizes correct */ /* So far, so good. Allocate memory. */ i = pwc_allocate_buffers(pdev); -- cgit v1.2.3 From cbb72b0f690b138bdc0c934b533390bf1ec59a04 Mon Sep 17 00:00:00 2001 From: Scott James Remnant Date: Mon, 2 Mar 2009 15:40:57 -0300 Subject: V4L/DVB (10947): Auto-load videodev module when device opened. The videodev module is missing the char-major-81-* alias that would cause it to be auto-loaded when a device of that type is opened. This patch adds the alias. Signed-off-by: Scott James Remnant Signed-off-by: Tim Gardner Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/v4l2-dev.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/media/video') diff --git a/drivers/media/video/v4l2-dev.c b/drivers/media/video/v4l2-dev.c index 231f5dbb18b4..64c638ecdd4b 100644 --- a/drivers/media/video/v4l2-dev.c +++ b/drivers/media/video/v4l2-dev.c @@ -582,6 +582,7 @@ module_exit(videodev_exit) MODULE_AUTHOR("Alan Cox, Mauro Carvalho Chehab "); MODULE_DESCRIPTION("Device registrar for Video4Linux drivers v2"); MODULE_LICENSE("GPL"); +MODULE_ALIAS_CHARDEV_MAJOR(VIDEO_MAJOR); /* -- cgit v1.2.3 From 70101a2785598f1a743c1e0fb65264c55bf5a29f Mon Sep 17 00:00:00 2001 From: Stephan Wienczny Date: Tue, 10 Mar 2009 19:08:06 -0300 Subject: V4L/DVB (10949): Add support for Terratec Cinergy HT PCI MKII This patch adds support for Terratec Cinergy HT PCI MKII with card id 79. Its more or less a copy of Pinnacle Hybrid PCTV. Thanks to k1ngf1sher on forum.ubuntuusers.de for the idea to copy that card. Signed-off-by: Stephan Wienczny Signed-off-by: Mauro Carvalho Chehab --- Documentation/video4linux/CARDLIST.cx88 | 1 + drivers/media/video/cx88/cx88-cards.c | 38 +++++++++++++++++++++++++++++++++ drivers/media/video/cx88/cx88-dvb.c | 16 ++++++++++++++ drivers/media/video/cx88/cx88.h | 1 + 4 files changed, 56 insertions(+) (limited to 'drivers/media/video') diff --git a/Documentation/video4linux/CARDLIST.cx88 b/Documentation/video4linux/CARDLIST.cx88 index 0d08f1edcf6d..71e9db0b26f7 100644 --- a/Documentation/video4linux/CARDLIST.cx88 +++ b/Documentation/video4linux/CARDLIST.cx88 @@ -77,3 +77,4 @@ 76 -> SATTRADE ST4200 DVB-S/S2 [b200:4200] 77 -> TBS 8910 DVB-S [8910:8888] 78 -> Prof 6200 DVB-S [b022:3022] + 79 -> Terratec Cinergy HT PCI MKII [153b:1177] diff --git a/drivers/media/video/cx88/cx88-cards.c b/drivers/media/video/cx88/cx88-cards.c index 733ede34f93a..1d7e3a562995 100644 --- a/drivers/media/video/cx88/cx88-cards.c +++ b/drivers/media/video/cx88/cx88-cards.c @@ -1934,6 +1934,39 @@ static const struct cx88_board cx88_boards[] = { } }, .mpeg = CX88_MPEG_DVB, }, + [CX88_BOARD_TERRATEC_CINERGY_HT_PCI_MKII] = { + .name = "Terratec Cinergy HT PCI MKII", + .tuner_type = TUNER_XC2028, + .tuner_addr = 0x61, + .radio_type = TUNER_XC2028, + .radio_addr = 0x61, + .input = { { + .type = CX88_VMUX_TELEVISION, + .vmux = 0, + .gpio0 = 0x004ff, + .gpio1 = 0x010ff, + .gpio2 = 0x00001, + }, { + .type = CX88_VMUX_COMPOSITE1, + .vmux = 1, + .gpio0 = 0x004fb, + .gpio1 = 0x010ef, + .audioroute = 1, + }, { + .type = CX88_VMUX_SVIDEO, + .vmux = 2, + .gpio0 = 0x004fb, + .gpio1 = 0x010ef, + .audioroute = 1, + } }, + .radio = { + .type = CX88_RADIO, + .gpio0 = 0x004ff, + .gpio1 = 0x010ff, + .gpio2 = 0x0ff, + }, + .mpeg = CX88_MPEG_DVB, + }, }; /* ------------------------------------------------------------------ */ @@ -2343,6 +2376,10 @@ static const struct cx88_subid cx88_subids[] = { .subvendor = 0xb200, .subdevice = 0x4200, .card = CX88_BOARD_SATTRADE_ST4200, + }, { + .subvendor = 0x153b, + .subdevice = 0x1177, + .card = CX88_BOARD_TERRATEC_CINERGY_HT_PCI_MKII, }, }; @@ -2819,6 +2856,7 @@ void cx88_setup_xc3028(struct cx88_core *core, struct xc2028_ctrl *ctl) */ break; case CX88_BOARD_PINNACLE_HYBRID_PCTV: + case CX88_BOARD_TERRATEC_CINERGY_HT_PCI_MKII: ctl->demod = XC3028_FE_ZARLINK456; ctl->mts = 1; break; diff --git a/drivers/media/video/cx88/cx88-dvb.c b/drivers/media/video/cx88/cx88-dvb.c index aef5297534af..08346fa05cd7 100644 --- a/drivers/media/video/cx88/cx88-dvb.c +++ b/drivers/media/video/cx88/cx88-dvb.c @@ -241,6 +241,12 @@ static struct mt352_config dvico_fusionhdtv_dual = { .demod_init = dvico_dual_demod_init, }; +static struct zl10353_config cx88_terratec_cinergy_ht_pci_mkii_config = { + .demod_address = (0x1e >> 1), + .no_tuner = 1, + .if2 = 45600, +}; + #if defined(CONFIG_VIDEO_CX88_VP3054) || (defined(CONFIG_VIDEO_CX88_VP3054_MODULE) && defined(MODULE)) static int dntv_live_dvbt_pro_demod_init(struct dvb_frontend* fe) { @@ -1131,6 +1137,16 @@ static int dvb_register(struct cx8802_dev *dev) if (fe0->dvb.frontend != NULL) fe0->dvb.frontend->ops.set_voltage = tevii_dvbs_set_voltage; break; + case CX88_BOARD_TERRATEC_CINERGY_HT_PCI_MKII: + fe0->dvb.frontend = dvb_attach(zl10353_attach, + &cx88_terratec_cinergy_ht_pci_mkii_config, + &core->i2c_adap); + if (fe0->dvb.frontend) { + fe0->dvb.frontend->ops.i2c_gate_ctrl = NULL; + if (attach_xc3028(0x61, dev) < 0) + goto frontend_detach; + } + break; default: printk(KERN_ERR "%s/2: The frontend of your DVB/ATSC card isn't supported yet\n", core->name); diff --git a/drivers/media/video/cx88/cx88.h b/drivers/media/video/cx88/cx88.h index 3542061c7329..303d8d20fc91 100644 --- a/drivers/media/video/cx88/cx88.h +++ b/drivers/media/video/cx88/cx88.h @@ -231,6 +231,7 @@ extern struct sram_channel cx88_sram_channels[]; #define CX88_BOARD_SATTRADE_ST4200 76 #define CX88_BOARD_TBS_8910 77 #define CX88_BOARD_PROF_6200 78 +#define CX88_BOARD_TERRATEC_CINERGY_HT_PCI_MKII 79 enum cx88_itype { CX88_VMUX_COMPOSITE1 = 1, -- cgit v1.2.3 From d8cd5e6c240bb3ff55e42afaa446c178ef8bb403 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 11 Mar 2009 04:34:09 -0300 Subject: V4L/DVB (10960): omap24xxcam: don't set vfl_type. The vfl_type field is set by the core, so anything you fill in here will be overwritten. And it will be set to a VFL_TYPE_ value, not a VID_TYPE_ value which is an obsolete V4L1 type. Since these V4L1 types have been made unavailable for V4L2 drivers, this driver stopped compiling. In this case the fix is just removing this assignment. Cc: Sakari Ailus Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/omap24xxcam.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/omap24xxcam.c b/drivers/media/video/omap24xxcam.c index 805faaea6449..2cea7fee9b51 100644 --- a/drivers/media/video/omap24xxcam.c +++ b/drivers/media/video/omap24xxcam.c @@ -1665,7 +1665,6 @@ static int omap24xxcam_device_register(struct v4l2_int_device *s) vfd->parent = cam->dev; strlcpy(vfd->name, CAM_NAME, sizeof(vfd->name)); - vfd->vfl_type = VID_TYPE_CAPTURE | VID_TYPE_CHROMAKEY; vfd->fops = &omap24xxcam_fops; vfd->minor = -1; vfd->ioctl_ops = &omap24xxcam_ioctl_fops; -- cgit v1.2.3 From c019f90ae9aa8b9c728321f886002b06dc2cf0cf Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 11 Mar 2009 18:50:04 -0300 Subject: V4L/DVB (10965): ivtv: bump version Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/ivtv/ivtv-version.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/ivtv/ivtv-version.h b/drivers/media/video/ivtv/ivtv-version.h index 8cd753d30bf7..b530dec399d3 100644 --- a/drivers/media/video/ivtv/ivtv-version.h +++ b/drivers/media/video/ivtv/ivtv-version.h @@ -23,7 +23,7 @@ #define IVTV_DRIVER_NAME "ivtv" #define IVTV_DRIVER_VERSION_MAJOR 1 #define IVTV_DRIVER_VERSION_MINOR 4 -#define IVTV_DRIVER_VERSION_PATCHLEVEL 0 +#define IVTV_DRIVER_VERSION_PATCHLEVEL 1 #define IVTV_VERSION __stringify(IVTV_DRIVER_VERSION_MAJOR) "." __stringify(IVTV_DRIVER_VERSION_MINOR) "." __stringify(IVTV_DRIVER_VERSION_PATCHLEVEL) #define IVTV_DRIVER_VERSION KERNEL_VERSION(IVTV_DRIVER_VERSION_MAJOR,IVTV_DRIVER_VERSION_MINOR,IVTV_DRIVER_VERSION_PATCHLEVEL) -- cgit v1.2.3 From 7c026c35114d169d77c2543fdf4d5689a1c9a51d Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Thu, 12 Mar 2009 18:56:15 -0300 Subject: V4L/DVB (10983): v4l2-common: add missing i2c_unregister_device. If the i2c sub-device cannot be found, then we must unregister the i2c_client. Otherwise this will prevent a possible probe for a different device on that same address. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/v4l2-common.c | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/v4l2-common.c b/drivers/media/video/v4l2-common.c index dbced906aa06..49aad1ed0b26 100644 --- a/drivers/media/video/v4l2-common.c +++ b/drivers/media/video/v4l2-common.c @@ -813,11 +813,11 @@ struct v4l2_subdev *v4l2_i2c_new_subdev(struct i2c_adapter *adapter, We need better support from the kernel so that we can easily wait for the load to finish. */ if (client == NULL || client->driver == NULL) - return NULL; + goto error; /* Lock the module so we can safely get the v4l2_subdev pointer */ if (!try_module_get(client->driver->driver.owner)) - return NULL; + goto error; sd = i2c_get_clientdata(client); /* Register with the v4l2_device which increases the module's @@ -826,8 +826,13 @@ struct v4l2_subdev *v4l2_i2c_new_subdev(struct i2c_adapter *adapter, sd = NULL; /* Decrease the module use count to match the first try_module_get. */ module_put(client->driver->driver.owner); - return sd; +error: + /* If we have a client but no subdev, then something went wrong and + we must unregister the client. */ + if (client && sd == NULL) + i2c_unregister_device(client); + return sd; } EXPORT_SYMBOL_GPL(v4l2_i2c_new_subdev); @@ -860,11 +865,11 @@ struct v4l2_subdev *v4l2_i2c_new_probed_subdev(struct i2c_adapter *adapter, We need better support from the kernel so that we can easily wait for the load to finish. */ if (client == NULL || client->driver == NULL) - return NULL; + goto error; /* Lock the module so we can safely get the v4l2_subdev pointer */ if (!try_module_get(client->driver->driver.owner)) - return NULL; + goto error; sd = i2c_get_clientdata(client); /* Register with the v4l2_device which increases the module's @@ -873,6 +878,12 @@ struct v4l2_subdev *v4l2_i2c_new_probed_subdev(struct i2c_adapter *adapter, sd = NULL; /* Decrease the module use count to match the first try_module_get. */ module_put(client->driver->driver.owner); + +error: + /* If we have a client but no subdev, then something went wrong and + we must unregister the client. */ + if (client && sd == NULL) + i2c_unregister_device(client); return sd; } EXPORT_SYMBOL_GPL(v4l2_i2c_new_probed_subdev); -- cgit v1.2.3 From 9832d765f82769799ba15ac9d2e8edf8f7de6898 Mon Sep 17 00:00:00 2001 From: Theodore Kilgore Date: Fri, 13 Mar 2009 13:04:31 -0300 Subject: V4L/DVB (10986): mr97310a: don't discard frame headers on stream output Fix a bug where all frame headers were being discarded, instead of being part of the stream output, on MR97310A cameras. The frame headers contain information which may be useful in processing the video output and therefore should be kept and not discarded. A corresponding patch to the decompression algorithm in libv4lconvert/mr97310a.c corrects the change in frame offset. Signed-off-by: Theodore Kilgore Signed-off-by: Hans de Goede Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/mr97310a.c | 22 +++------------------- 1 file changed, 3 insertions(+), 19 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/gspca/mr97310a.c b/drivers/media/video/gspca/mr97310a.c index 5ec5ce6e3ed9..2a901a4a6f00 100644 --- a/drivers/media/video/gspca/mr97310a.c +++ b/drivers/media/video/gspca/mr97310a.c @@ -29,9 +29,7 @@ MODULE_LICENSE("GPL"); /* specific webcam descriptor */ struct sd { struct gspca_dev gspca_dev; /* !! must be the first item */ - u8 sof_read; - u8 header_read; }; /* V4L2 controls supported by the driver */ @@ -285,7 +283,6 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, __u8 *data, /* isoc packet */ int len) /* iso packet length */ { - struct sd *sd = (struct sd *) gspca_dev; unsigned char *sof; sof = pac_find_sof(gspca_dev, data, len); @@ -300,25 +297,12 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, n = 0; frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame, data, n); - sd->header_read = 0; - gspca_frame_add(gspca_dev, FIRST_PACKET, frame, NULL, 0); + /* Start next frame. */ + gspca_frame_add(gspca_dev, FIRST_PACKET, frame, + pac_sof_marker, sizeof pac_sof_marker); len -= sof - data; data = sof; } - if (sd->header_read < 7) { - int needed; - - /* skip the rest of the header */ - needed = 7 - sd->header_read; - if (len <= needed) { - sd->header_read += len; - return; - } - data += needed; - len -= needed; - sd->header_read = 7; - } - gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len); } -- cgit v1.2.3 From afd96668d8491f762e35c16ce65781da820a67fa Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 13 Mar 2009 13:24:19 -0300 Subject: V4L/DVB (10987): cx23885: fix crash on non-netup cards The new support for the CX23885_BOARD_NETUP_DUAL_DVBS2_CI board broke the existing boards. Interrupts for the netup part were enabled and handled without testing whether the current board actually had a netup -> instant and fatal crash. I've added tests to do this only for the CX23885_BOARD_NETUP_DUAL_DVBS2_CI board. Signed-off-by: Hans Verkuil Reviewed-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx23885/cx23885-core.c | 10 ++++++++-- drivers/media/video/cx23885/cx23885-dvb.c | 6 +++++- 2 files changed, 13 insertions(+), 3 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/cx23885/cx23885-core.c b/drivers/media/video/cx23885/cx23885-core.c index 1b401457d42e..d19d453cf62a 100644 --- a/drivers/media/video/cx23885/cx23885-core.c +++ b/drivers/media/video/cx23885/cx23885-core.c @@ -1699,7 +1699,8 @@ static irqreturn_t cx23885_irq(int irq, void *dev_id) PCI_MSK_GPIO1); } - if ((pci_status & PCI_MSK_GPIO0) || (pci_status & PCI_MSK_GPIO1)) + if (cx23885_boards[dev->board].cimax > 0 && + ((pci_status & PCI_MSK_GPIO0) || (pci_status & PCI_MSK_GPIO1))) /* handled += cx23885_irq_gpio(dev, pci_status); */ handled += netup_ci_slot_status(dev, pci_status); @@ -1775,7 +1776,12 @@ static int __devinit cx23885_initdev(struct pci_dev *pci_dev, } pci_set_drvdata(pci_dev, dev); - cx_set(PCI_INT_MSK, 0x01800000); /* for NetUP */ + + switch (dev->board) { + case CX23885_BOARD_NETUP_DUAL_DVBS2_CI: + cx_set(PCI_INT_MSK, 0x01800000); /* for NetUP */ + break; + } return 0; diff --git a/drivers/media/video/cx23885/cx23885-dvb.c b/drivers/media/video/cx23885/cx23885-dvb.c index 9a0bc6e84a95..8d731fffad58 100644 --- a/drivers/media/video/cx23885/cx23885-dvb.c +++ b/drivers/media/video/cx23885/cx23885-dvb.c @@ -778,7 +778,11 @@ int cx23885_dvb_unregister(struct cx23885_tsport *port) if (fe0->dvb.frontend) videobuf_dvb_unregister_bus(&port->frontends); - netup_ci_exit(port); + switch (port->dev->board) { + case CX23885_BOARD_NETUP_DUAL_DVBS2_CI: + netup_ci_exit(port); + break; + } return 0; } -- cgit v1.2.3 From 005759613b95264fba9138010f112bc138c857c2 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 13 Mar 2009 10:03:04 -0300 Subject: V4L/DVB (10988): v4l2-dev: use parent field if the v4l2_device has no parent set. Normally the parent device of v4l2_device is used as the video device node's parent. But if it was not set, then use the parent field in the video_device struct. This is needed in the cx88 driver, which has one core v4l2_device but creates multiple pci devices (one each for raw and mpeg video). So you cannot associate the core v4l2_device with a particular PCI device, but you can do that for each video_device. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- Documentation/video4linux/v4l2-framework.txt | 12 +++++++++++- drivers/media/video/v4l2-dev.c | 2 +- 2 files changed, 12 insertions(+), 2 deletions(-) (limited to 'drivers/media/video') diff --git a/Documentation/video4linux/v4l2-framework.txt b/Documentation/video4linux/v4l2-framework.txt index 51a7b6db118f..df0247ed13d8 100644 --- a/Documentation/video4linux/v4l2-framework.txt +++ b/Documentation/video4linux/v4l2-framework.txt @@ -91,7 +91,8 @@ NULL, then you *must* setup v4l2_dev->name before calling v4l2_device_register. The first 'dev' argument is normally the struct device pointer of a pci_dev, usb_device or platform_device. It is rare for dev to be NULL, but it happens -with ISA devices, for example. +with ISA devices or when one device creates multiple PCI devices, thus making +it impossible to associate v4l2_dev with a particular parent. You unregister with: @@ -414,6 +415,15 @@ You should also set these fields: - ioctl_ops: if you use the v4l2_ioctl_ops to simplify ioctl maintenance (highly recommended to use this and it might become compulsory in the future!), then set this to your v4l2_ioctl_ops struct. +- parent: you only set this if v4l2_device was registered with NULL as + the parent device struct. This only happens in cases where one hardware + device has multiple PCI devices that all share the same v4l2_device core. + + The cx88 driver is an example of this: one core v4l2_device struct, but + it is used by both an raw video PCI device (cx8800) and a MPEG PCI device + (cx8802). Since the v4l2_device cannot be associated with a particular + PCI device it is setup without a parent device. But when the struct + video_device is setup you do know which parent PCI device to use. If you use v4l2_ioctl_ops, then you should set either .unlocked_ioctl or .ioctl to video_ioctl2 in your v4l2_file_operations struct. diff --git a/drivers/media/video/v4l2-dev.c b/drivers/media/video/v4l2-dev.c index 64c638ecdd4b..cdc8ce3c4e56 100644 --- a/drivers/media/video/v4l2-dev.c +++ b/drivers/media/video/v4l2-dev.c @@ -395,7 +395,7 @@ int video_register_device_index(struct video_device *vdev, int type, int nr, vdev->vfl_type = type; vdev->cdev = NULL; - if (vdev->v4l2_dev) + if (vdev->v4l2_dev && vdev->v4l2_dev->dev) vdev->parent = vdev->v4l2_dev->dev; /* Part 2: find a free minor, kernel number and device index. */ -- cgit v1.2.3 From 1cd3c0fa927084549005fc22e54d99684b314f14 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sun, 8 Mar 2009 17:04:38 -0300 Subject: V4L/DVB (11022): zoran/bt819: use new notify functionality. Bt819 needs the parent driver to drive a GPIO pin low and high in order to reset its fifo. Use the new notify callback for this. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/bt819.c | 14 ++++++++++++- drivers/media/video/zoran/zoran_card.c | 20 +++++++++++++++--- drivers/media/video/zoran/zoran_device.c | 36 ++------------------------------ drivers/media/video/zoran/zoran_device.h | 3 --- drivers/media/video/zoran/zoran_driver.c | 12 +++++------ include/media/bt819.h | 33 +++++++++++++++++++++++++++++ 6 files changed, 71 insertions(+), 47 deletions(-) create mode 100644 include/media/bt819.h (limited to 'drivers/media/video') diff --git a/drivers/media/video/bt819.c b/drivers/media/video/bt819.c index e0d8e2b186d1..217294d56414 100644 --- a/drivers/media/video/bt819.c +++ b/drivers/media/video/bt819.c @@ -32,13 +32,14 @@ #include #include #include -#include +#include #include #include #include #include #include #include +#include MODULE_DESCRIPTION("Brooktree-819 video decoder driver"); MODULE_AUTHOR("Mike Bernson & Dave Perks"); @@ -250,7 +251,11 @@ static int bt819_s_std(struct v4l2_subdev *sd, v4l2_std_id std) v4l2_dbg(1, debug, sd, "set norm %llx\n", (unsigned long long)std); + if (sd->v4l2_dev == NULL || sd->v4l2_dev->notify == NULL) + v4l2_err(sd, "no notify found!\n"); + if (std & V4L2_STD_NTSC) { + v4l2_subdev_notify(sd, BT819_FIFO_RESET_LOW, 0); bt819_setbit(decoder, 0x01, 0, 1); bt819_setbit(decoder, 0x01, 1, 0); bt819_setbit(decoder, 0x01, 5, 0); @@ -259,6 +264,7 @@ static int bt819_s_std(struct v4l2_subdev *sd, v4l2_std_id std) /* bt819_setbit(decoder, 0x1a, 5, 1); */ timing = &timing_data[1]; } else if (std & V4L2_STD_PAL) { + v4l2_subdev_notify(sd, BT819_FIFO_RESET_LOW, 0); bt819_setbit(decoder, 0x01, 0, 1); bt819_setbit(decoder, 0x01, 1, 1); bt819_setbit(decoder, 0x01, 5, 1); @@ -283,6 +289,7 @@ static int bt819_s_std(struct v4l2_subdev *sd, v4l2_std_id std) bt819_write(decoder, 0x08, (timing->hscale >> 8) & 0xff); bt819_write(decoder, 0x09, timing->hscale & 0xff); decoder->norm = std; + v4l2_subdev_notify(sd, BT819_FIFO_RESET_HIGH, 0); return 0; } @@ -295,7 +302,11 @@ static int bt819_s_routing(struct v4l2_subdev *sd, const struct v4l2_routing *ro if (route->input < 0 || route->input > 7) return -EINVAL; + if (sd->v4l2_dev == NULL || sd->v4l2_dev->notify == NULL) + v4l2_err(sd, "no notify found!\n"); + if (decoder->input != route->input) { + v4l2_subdev_notify(sd, BT819_FIFO_RESET_LOW, 0); decoder->input = route->input; /* select mode */ if (decoder->input == 0) { @@ -305,6 +316,7 @@ static int bt819_s_routing(struct v4l2_subdev *sd, const struct v4l2_routing *ro bt819_setbit(decoder, 0x0b, 6, 1); bt819_setbit(decoder, 0x1a, 1, 0); } + v4l2_subdev_notify(sd, BT819_FIFO_RESET_HIGH, 0); } return 0; } diff --git a/drivers/media/video/zoran/zoran_card.c b/drivers/media/video/zoran/zoran_card.c index b5d228d91b06..ec9b6ef56090 100644 --- a/drivers/media/video/zoran/zoran_card.c +++ b/drivers/media/video/zoran/zoran_card.c @@ -39,7 +39,6 @@ #include #include #include -#include #include #include #include @@ -48,8 +47,9 @@ #include #include #include - -#include +#include +#include +#include #include "videocodec.h" #include "zoran.h" @@ -1196,6 +1196,19 @@ zoran_setup_videocodec (struct zoran *zr, return m; } +static int zoran_subdev_notify(struct v4l2_subdev *sd, unsigned int cmd, void *arg) +{ + struct zoran *zr = to_zoran(sd->v4l2_dev); + + /* Bt819 needs to reset its FIFO buffer using #FRST pin and + LML33 card uses GPIO(7) for that. */ + if (cmd == BT819_FIFO_RESET_LOW) + GPIO(zr, 7, 0); + else if (cmd == BT819_FIFO_RESET_HIGH) + GPIO(zr, 7, 1); + return 0; +} + /* * Scan for a Buz card (actually for the PCI controller ZR36057), * request the irq and map the io memory @@ -1226,6 +1239,7 @@ static int __devinit zoran_probe(struct pci_dev *pdev, ZORAN_NAME, __func__); return -ENOMEM; } + zr->v4l2_dev.notify = zoran_subdev_notify; if (v4l2_device_register(&pdev->dev, &zr->v4l2_dev)) goto zr_free_mem; zr->pci_dev = pdev; diff --git a/drivers/media/video/zoran/zoran_device.c b/drivers/media/video/zoran/zoran_device.c index f8bcd1a248c2..e0223deed35e 100644 --- a/drivers/media/video/zoran/zoran_device.c +++ b/drivers/media/video/zoran/zoran_device.c @@ -1584,8 +1584,8 @@ zoran_init_hardware (struct zoran *zr) route.input = zr->card.input[zr->input].muxsel; decoder_call(zr, core, init, 0); - decoder_s_std(zr, zr->norm); - decoder_s_routing(zr, &route); + decoder_call(zr, tuner, s_std, zr->norm); + decoder_call(zr, video, s_routing, &route); encoder_call(zr, core, init, 0); encoder_call(zr, video, s_std_output, zr->norm); @@ -1650,35 +1650,3 @@ zr36057_init_vfe (struct zoran *zr) reg |= ZR36057_VDCR_Triton; btwrite(reg, ZR36057_VDCR); } - -/* - * Interface to decoder and encoder chips using i2c bus - */ - -int decoder_s_std(struct zoran *zr, v4l2_std_id std) -{ - int res; - - /* Bt819 needs to reset its FIFO buffer using #FRST pin and - LML33 card uses GPIO(7) for that. */ - if (zr->card.type == LML33) - GPIO(zr, 7, 0); - res = decoder_call(zr, tuner, s_std, std); - if (zr->card.type == LML33) - GPIO(zr, 7, 1); /* Pull #FRST high. */ - return res; -} - -int decoder_s_routing(struct zoran *zr, struct v4l2_routing *route) -{ - int res; - - /* Bt819 needs to reset its FIFO buffer using #FRST pin and - LML33 card uses GPIO(7) for that. */ - if (zr->card.type == LML33) - GPIO(zr, 7, 0); - res = decoder_call(zr, video, s_routing, route); - if (zr->card.type == LML33) - GPIO(zr, 7, 1); /* Pull #FRST high. */ - return res; -} diff --git a/drivers/media/video/zoran/zoran_device.h b/drivers/media/video/zoran/zoran_device.h index 85414e17524e..07f2c23ff740 100644 --- a/drivers/media/video/zoran/zoran_device.h +++ b/drivers/media/video/zoran/zoran_device.h @@ -92,7 +92,4 @@ extern int pass_through; #define encoder_call(zr, o, f, args...) \ v4l2_subdev_call(zr->encoder, o, f, ##args) -int decoder_s_std(struct zoran *zr, v4l2_std_id std); -int decoder_s_routing(struct zoran *zr, struct v4l2_routing *route); - #endif /* __ZORAN_DEVICE_H__ */ diff --git a/drivers/media/video/zoran/zoran_driver.c b/drivers/media/video/zoran/zoran_driver.c index 60501f256b28..1e87fb9f7146 100644 --- a/drivers/media/video/zoran/zoran_driver.c +++ b/drivers/media/video/zoran/zoran_driver.c @@ -1449,7 +1449,7 @@ zoran_set_norm (struct zoran *zr, v4l2_std_id std = 0; decoder_call(zr, video, querystd, &std); - decoder_s_std(zr, std); + decoder_call(zr, tuner, s_std, std); /* let changes come into effect */ ssleep(2); @@ -1461,7 +1461,7 @@ zoran_set_norm (struct zoran *zr, "%s: %s - no norm detected\n", ZR_DEVNAME(zr), __func__); /* reset norm */ - decoder_s_std(zr, zr->norm); + decoder_call(zr, tuner, s_std, zr->norm); return -EIO; } @@ -1480,7 +1480,7 @@ zoran_set_norm (struct zoran *zr, if (on) zr36057_overlay(zr, 0); - decoder_s_std(zr, norm); + decoder_call(zr, tuner, s_std, norm); encoder_call(zr, video, s_std_output, norm); if (on) @@ -1522,7 +1522,7 @@ zoran_set_input (struct zoran *zr, route.input = zr->card.input[input].muxsel; zr->input = input; - decoder_s_routing(zr, &route); + decoder_call(zr, video, s_routing, &route); return 0; } @@ -1775,7 +1775,7 @@ jpgreqbuf_unlock_and_return: goto gstat_unlock_and_return; } - decoder_s_routing(zr, &route); + decoder_call(zr, video, s_routing, &route); /* sleep 1 second */ ssleep(1); @@ -1786,7 +1786,7 @@ jpgreqbuf_unlock_and_return: /* restore previous input and norm */ route.input = zr->card.input[zr->input].muxsel; - decoder_s_routing(zr, &route); + decoder_call(zr, video, s_routing, &route); gstat_unlock_and_return: mutex_unlock(&zr->resource_lock); diff --git a/include/media/bt819.h b/include/media/bt819.h new file mode 100644 index 000000000000..38f666bde77a --- /dev/null +++ b/include/media/bt819.h @@ -0,0 +1,33 @@ +/* + bt819.h - bt819 notifications + + Copyright (C) 2009 Hans Verkuil (hverkuil@xs4all.nl) + + 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 _BT819_H_ +#define _BT819_H_ + +#include + +/* v4l2_device notifications. */ + +/* Needed to reset the FIFO buffer when changing the input + or the video standard. */ +#define BT819_FIFO_RESET_LOW _IO('b', 0) +#define BT819_FIFO_RESET_HIGH _IO('b', 1) + +#endif -- cgit v1.2.3 From 09e231b35173313cd92e27532e5028f2042dcee4 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Fri, 13 Mar 2009 06:08:20 -0300 Subject: V4L/DVB (11024): soc-camera: separate S_FMT and S_CROP operations As host and camera drivers become more complex, differences between S_FMT and S_CROP functionality grow, this patch separates them. Signed-off-by: Guennadi Liakhovetski Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/mt9m001.c | 19 +++- drivers/media/video/mt9m111.c | 56 ++++++---- drivers/media/video/mt9t031.c | 84 +++++++++------ drivers/media/video/mt9v022.c | 62 +++++++----- drivers/media/video/mx3_camera.c | 157 ++++++++++++++++++----------- drivers/media/video/ov772x.c | 31 +++++- drivers/media/video/pxa_camera.c | 67 ++++++++---- drivers/media/video/sh_mobile_ceu_camera.c | 17 +++- drivers/media/video/soc_camera.c | 20 ++-- drivers/media/video/soc_camera_platform.c | 9 +- drivers/media/video/tw9910.c | 45 ++++++--- include/media/soc_camera.h | 6 +- 12 files changed, 381 insertions(+), 192 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/mt9m001.c b/drivers/media/video/mt9m001.c index 2d1034dad495..a6703d25227f 100644 --- a/drivers/media/video/mt9m001.c +++ b/drivers/media/video/mt9m001.c @@ -284,8 +284,8 @@ static unsigned long mt9m001_query_bus_param(struct soc_camera_device *icd) return soc_camera_apply_sensor_flags(icl, flags); } -static int mt9m001_set_fmt(struct soc_camera_device *icd, - __u32 pixfmt, struct v4l2_rect *rect) +static int mt9m001_set_crop(struct soc_camera_device *icd, + struct v4l2_rect *rect) { struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd); int ret; @@ -324,6 +324,20 @@ static int mt9m001_set_fmt(struct soc_camera_device *icd, return ret; } +static int mt9m001_set_fmt(struct soc_camera_device *icd, + struct v4l2_format *f) +{ + struct v4l2_rect rect = { + .left = icd->x_current, + .top = icd->y_current, + .width = f->fmt.pix.width, + .height = f->fmt.pix.height, + }; + + /* No support for scaling so far, just crop. TODO: use skipping */ + return mt9m001_set_crop(icd, &rect); +} + static int mt9m001_try_fmt(struct soc_camera_device *icd, struct v4l2_format *f) { @@ -449,6 +463,7 @@ static struct soc_camera_ops mt9m001_ops = { .release = mt9m001_release, .start_capture = mt9m001_start_capture, .stop_capture = mt9m001_stop_capture, + .set_crop = mt9m001_set_crop, .set_fmt = mt9m001_set_fmt, .try_fmt = mt9m001_try_fmt, .set_bus_param = mt9m001_set_bus_param, diff --git a/drivers/media/video/mt9m111.c b/drivers/media/video/mt9m111.c index 7e6be36f0855..cdd1ddb51388 100644 --- a/drivers/media/video/mt9m111.c +++ b/drivers/media/video/mt9m111.c @@ -152,7 +152,7 @@ struct mt9m111 { struct soc_camera_device icd; int model; /* V4L2_IDENT_MT9M11x* codes from v4l2-chip-ident.h */ enum mt9m111_context context; - unsigned int left, top, width, height; + struct v4l2_rect rect; u32 pixfmt; unsigned char autoexposure; unsigned char datawidth; @@ -249,12 +249,13 @@ static int mt9m111_set_context(struct soc_camera_device *icd, return reg_write(CONTEXT_CONTROL, valA); } -static int mt9m111_setup_rect(struct soc_camera_device *icd) +static int mt9m111_setup_rect(struct soc_camera_device *icd, + struct v4l2_rect *rect) { struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd); int ret, is_raw_format; - int width = mt9m111->width; - int height = mt9m111->height; + int width = rect->width; + int height = rect->height; if ((mt9m111->pixfmt == V4L2_PIX_FMT_SBGGR8) || (mt9m111->pixfmt == V4L2_PIX_FMT_SBGGR16)) @@ -262,9 +263,9 @@ static int mt9m111_setup_rect(struct soc_camera_device *icd) else is_raw_format = 0; - ret = reg_write(COLUMN_START, mt9m111->left); + ret = reg_write(COLUMN_START, rect->left); if (!ret) - ret = reg_write(ROW_START, mt9m111->top); + ret = reg_write(ROW_START, rect->top); if (is_raw_format) { if (!ret) @@ -436,6 +437,22 @@ static int mt9m111_set_bus_param(struct soc_camera_device *icd, unsigned long f) return 0; } +static int mt9m111_set_crop(struct soc_camera_device *icd, + struct v4l2_rect *rect) +{ + struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd); + int ret; + + dev_dbg(&icd->dev, "%s left=%d, top=%d, width=%d, height=%d\n", + __func__, rect->left, rect->top, rect->width, + rect->height); + + ret = mt9m111_setup_rect(icd, rect); + if (!ret) + mt9m111->rect = *rect; + return ret; +} + static int mt9m111_set_pixfmt(struct soc_camera_device *icd, u32 pixfmt) { struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd); @@ -486,23 +503,27 @@ static int mt9m111_set_pixfmt(struct soc_camera_device *icd, u32 pixfmt) } static int mt9m111_set_fmt(struct soc_camera_device *icd, - __u32 pixfmt, struct v4l2_rect *rect) + struct v4l2_format *f) { struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd); + struct v4l2_pix_format *pix = &f->fmt.pix; + struct v4l2_rect rect = { + .left = mt9m111->rect.left, + .top = mt9m111->rect.top, + .width = pix->width, + .height = pix->height, + }; int ret; - mt9m111->left = rect->left; - mt9m111->top = rect->top; - mt9m111->width = rect->width; - mt9m111->height = rect->height; - dev_dbg(&icd->dev, "%s fmt=%x left=%d, top=%d, width=%d, height=%d\n", - __func__, pixfmt, mt9m111->left, mt9m111->top, mt9m111->width, - mt9m111->height); + __func__, pix->pixelformat, rect.left, rect.top, rect.width, + rect.height); - ret = mt9m111_setup_rect(icd); + ret = mt9m111_setup_rect(icd, &rect); + if (!ret) + ret = mt9m111_set_pixfmt(icd, pix->pixelformat); if (!ret) - ret = mt9m111_set_pixfmt(icd, pixfmt); + mt9m111->rect = rect; return ret; } @@ -633,6 +654,7 @@ static struct soc_camera_ops mt9m111_ops = { .release = mt9m111_release, .start_capture = mt9m111_start_capture, .stop_capture = mt9m111_stop_capture, + .set_crop = mt9m111_set_crop, .set_fmt = mt9m111_set_fmt, .try_fmt = mt9m111_try_fmt, .query_bus_param = mt9m111_query_bus_param, @@ -817,7 +839,7 @@ static int mt9m111_restore_state(struct soc_camera_device *icd) mt9m111_set_context(icd, mt9m111->context); mt9m111_set_pixfmt(icd, mt9m111->pixfmt); - mt9m111_setup_rect(icd); + mt9m111_setup_rect(icd, &mt9m111->rect); mt9m111_set_flip(icd, mt9m111->hflip, MT9M111_RMB_MIRROR_COLS); mt9m111_set_flip(icd, mt9m111->vflip, MT9M111_RMB_MIRROR_ROWS); mt9m111_set_global_gain(icd, icd->gain); diff --git a/drivers/media/video/mt9t031.c b/drivers/media/video/mt9t031.c index acc1fa9db67d..677be18df9b3 100644 --- a/drivers/media/video/mt9t031.c +++ b/drivers/media/video/mt9t031.c @@ -213,36 +213,14 @@ static void recalculate_limits(struct soc_camera_device *icd, icd->height_max = MT9T031_MAX_HEIGHT / yskip; } -static int mt9t031_set_fmt(struct soc_camera_device *icd, - __u32 pixfmt, struct v4l2_rect *rect) +static int mt9t031_set_params(struct soc_camera_device *icd, + struct v4l2_rect *rect, u16 xskip, u16 yskip) { struct mt9t031 *mt9t031 = container_of(icd, struct mt9t031, icd); int ret; + u16 xbin, ybin, width, height, left, top; const u16 hblank = MT9T031_HORIZONTAL_BLANK, vblank = MT9T031_VERTICAL_BLANK; - u16 xbin, xskip, ybin, yskip, width, height, left, top; - - if (pixfmt) { - /* - * try_fmt has put rectangle within limits. - * S_FMT - use binning and skipping for scaling, recalculate - * limits, used for cropping - */ - /* Is this more optimal than just a division? */ - for (xskip = 8; xskip > 1; xskip--) - if (rect->width * xskip <= MT9T031_MAX_WIDTH) - break; - - for (yskip = 8; yskip > 1; yskip--) - if (rect->height * yskip <= MT9T031_MAX_HEIGHT) - break; - - recalculate_limits(icd, xskip, yskip); - } else { - /* CROP - no change in scaling, or in limits */ - xskip = mt9t031->xskip; - yskip = mt9t031->yskip; - } /* Make sure we don't exceed sensor limits */ if (rect->left + rect->width > icd->width_max) @@ -289,7 +267,7 @@ static int mt9t031_set_fmt(struct soc_camera_device *icd, if (ret >= 0) ret = reg_write(icd, MT9T031_VERTICAL_BLANKING, vblank); - if (pixfmt) { + if (yskip != mt9t031->yskip || xskip != mt9t031->xskip) { /* Binning, skipping */ if (ret >= 0) ret = reg_write(icd, MT9T031_COLUMN_ADDRESS_MODE, @@ -325,15 +303,58 @@ static int mt9t031_set_fmt(struct soc_camera_device *icd, } } - if (!ret && pixfmt) { + /* Re-enable register update, commit all changes */ + if (ret >= 0) + ret = reg_clear(icd, MT9T031_OUTPUT_CONTROL, 1); + + return ret < 0 ? ret : 0; +} + +static int mt9t031_set_crop(struct soc_camera_device *icd, + struct v4l2_rect *rect) +{ + struct mt9t031 *mt9t031 = container_of(icd, struct mt9t031, icd); + + /* CROP - no change in scaling, or in limits */ + return mt9t031_set_params(icd, rect, mt9t031->xskip, mt9t031->yskip); +} + +static int mt9t031_set_fmt(struct soc_camera_device *icd, + struct v4l2_format *f) +{ + struct mt9t031 *mt9t031 = container_of(icd, struct mt9t031, icd); + int ret; + u16 xskip, yskip; + struct v4l2_rect rect = { + .left = icd->x_current, + .top = icd->y_current, + .width = f->fmt.pix.width, + .height = f->fmt.pix.height, + }; + + /* + * try_fmt has put rectangle within limits. + * S_FMT - use binning and skipping for scaling, recalculate + * limits, used for cropping + */ + /* Is this more optimal than just a division? */ + for (xskip = 8; xskip > 1; xskip--) + if (rect.width * xskip <= MT9T031_MAX_WIDTH) + break; + + for (yskip = 8; yskip > 1; yskip--) + if (rect.height * yskip <= MT9T031_MAX_HEIGHT) + break; + + recalculate_limits(icd, xskip, yskip); + + ret = mt9t031_set_params(icd, &rect, xskip, yskip); + if (!ret) { mt9t031->xskip = xskip; mt9t031->yskip = yskip; } - /* Re-enable register update, commit all changes */ - reg_clear(icd, MT9T031_OUTPUT_CONTROL, 1); - - return ret < 0 ? ret : 0; + return ret; } static int mt9t031_try_fmt(struct soc_camera_device *icd, @@ -470,6 +491,7 @@ static struct soc_camera_ops mt9t031_ops = { .release = mt9t031_release, .start_capture = mt9t031_start_capture, .stop_capture = mt9t031_stop_capture, + .set_crop = mt9t031_set_crop, .set_fmt = mt9t031_set_fmt, .try_fmt = mt9t031_try_fmt, .set_bus_param = mt9t031_set_bus_param, diff --git a/drivers/media/video/mt9v022.c b/drivers/media/video/mt9v022.c index 6eb4b3a818d7..3871d4a2d8ff 100644 --- a/drivers/media/video/mt9v022.c +++ b/drivers/media/video/mt9v022.c @@ -340,32 +340,11 @@ static unsigned long mt9v022_query_bus_param(struct soc_camera_device *icd) width_flag; } -static int mt9v022_set_fmt(struct soc_camera_device *icd, - __u32 pixfmt, struct v4l2_rect *rect) +static int mt9v022_set_crop(struct soc_camera_device *icd, + struct v4l2_rect *rect) { - struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd); int ret; - /* The caller provides a supported format, as verified per call to - * icd->try_fmt(), 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) { @@ -403,6 +382,42 @@ static int mt9v022_set_fmt(struct soc_camera_device *icd, return 0; } +static int mt9v022_set_fmt(struct soc_camera_device *icd, + struct v4l2_format *f) +{ + struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd); + struct v4l2_pix_format *pix = &f->fmt.pix; + struct v4l2_rect rect = { + .left = icd->x_current, + .top = icd->y_current, + .width = pix->width, + .height = pix->height, + }; + + /* The caller provides a supported format, as verified per call to + * icd->try_fmt(), datawidth is from our supported format list */ + switch (pix->pixelformat) { + 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; + } + + /* No support for scaling on this camera, just crop. */ + return mt9v022_set_crop(icd, &rect); +} + static int mt9v022_try_fmt(struct soc_camera_device *icd, struct v4l2_format *f) { @@ -544,6 +559,7 @@ static struct soc_camera_ops mt9v022_ops = { .release = mt9v022_release, .start_capture = mt9v022_start_capture, .stop_capture = mt9v022_stop_capture, + .set_crop = mt9v022_set_crop, .set_fmt = mt9v022_set_fmt, .try_fmt = mt9v022_try_fmt, .set_bus_param = mt9v022_set_bus_param, diff --git a/drivers/media/video/mx3_camera.c b/drivers/media/video/mx3_camera.c index f525dc48f6ca..70629e172e65 100644 --- a/drivers/media/video/mx3_camera.c +++ b/drivers/media/video/mx3_camera.c @@ -544,16 +544,14 @@ static void mx3_camera_remove_device(struct soc_camera_device *icd) } static bool channel_change_requested(struct soc_camera_device *icd, - const struct soc_camera_format_xlate *xlate, - __u32 pixfmt, struct v4l2_rect *rect) + struct v4l2_rect *rect) { struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); struct mx3_camera_dev *mx3_cam = ici->priv; struct idmac_channel *ichan = mx3_cam->idmac_channel[0]; - /* So far only one configuration is supported */ - return pixfmt || (ichan && rect->width * rect->height > - icd->width * icd->height); + /* Do buffers have to be re-allocated or channel re-configured? */ + return ichan && rect->width * rect->height > icd->width * icd->height; } static int test_platform_param(struct mx3_camera_dev *mx3_cam, @@ -733,61 +731,10 @@ passthrough: return formats; } -static int mx3_camera_set_fmt(struct soc_camera_device *icd, - __u32 pixfmt, struct v4l2_rect *rect) +static void configure_geometry(struct mx3_camera_dev *mx3_cam, + struct v4l2_rect *rect) { - struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); - struct mx3_camera_dev *mx3_cam = ici->priv; - const struct soc_camera_format_xlate *xlate; u32 ctrl, width_field, height_field; - int ret; - - xlate = soc_camera_xlate_by_fourcc(icd, pixfmt); - if (pixfmt && !xlate) { - dev_warn(&ici->dev, "Format %x not found\n", pixfmt); - return -EINVAL; - } - - /* - * We now know pixel formats and can decide upon DMA-channel(s) - * So far only direct camera-to-memory is supported - */ - if (channel_change_requested(icd, xlate, pixfmt, rect)) { - dma_cap_mask_t mask; - struct dma_chan *chan; - struct idmac_channel **ichan = &mx3_cam->idmac_channel[0]; - /* We have to use IDMAC_IC_7 for Bayer / generic data */ - struct dma_chan_request rq = {.mx3_cam = mx3_cam, - .id = IDMAC_IC_7}; - - if (*ichan) { - struct videobuf_buffer *vb, *_vb; - dma_release_channel(&(*ichan)->dma_chan); - *ichan = NULL; - mx3_cam->active = NULL; - list_for_each_entry_safe(vb, _vb, &mx3_cam->capture, queue) { - list_del_init(&vb->queue); - vb->state = VIDEOBUF_ERROR; - wake_up(&vb->done); - } - } - - dma_cap_zero(mask); - dma_cap_set(DMA_SLAVE, mask); - dma_cap_set(DMA_PRIVATE, mask); - chan = dma_request_channel(mask, chan_filter, &rq); - if (!chan) - return -EBUSY; - - *ichan = to_idmac_chan(chan); - (*ichan)->client = mx3_cam; - } - - /* - * Might have to perform a complete interface initialisation like in - * ipu_csi_init_interface() in mxc_v4l2_s_param(). Also consider - * mxc_v4l2_s_fmt() - */ /* Setup frame size - this cannot be changed on-the-fly... */ width_field = rect->width - 1; @@ -808,9 +755,98 @@ static int mx3_camera_set_fmt(struct soc_camera_device *icd, * No need to free resources here if we fail, we'll see if we need to * do this next time we are called */ +} + +static int acquire_dma_channel(struct mx3_camera_dev *mx3_cam) +{ + dma_cap_mask_t mask; + struct dma_chan *chan; + struct idmac_channel **ichan = &mx3_cam->idmac_channel[0]; + /* We have to use IDMAC_IC_7 for Bayer / generic data */ + struct dma_chan_request rq = {.mx3_cam = mx3_cam, + .id = IDMAC_IC_7}; + + if (*ichan) { + struct videobuf_buffer *vb, *_vb; + dma_release_channel(&(*ichan)->dma_chan); + *ichan = NULL; + mx3_cam->active = NULL; + list_for_each_entry_safe(vb, _vb, &mx3_cam->capture, queue) { + list_del_init(&vb->queue); + vb->state = VIDEOBUF_ERROR; + wake_up(&vb->done); + } + } + + dma_cap_zero(mask); + dma_cap_set(DMA_SLAVE, mask); + dma_cap_set(DMA_PRIVATE, mask); + chan = dma_request_channel(mask, chan_filter, &rq); + if (!chan) + return -EBUSY; + + *ichan = to_idmac_chan(chan); + (*ichan)->client = mx3_cam; + + return 0; +} + +static int mx3_camera_set_crop(struct soc_camera_device *icd, + struct v4l2_rect *rect) +{ + struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); + struct mx3_camera_dev *mx3_cam = ici->priv; + + /* + * We now know pixel formats and can decide upon DMA-channel(s) + * So far only direct camera-to-memory is supported + */ + if (channel_change_requested(icd, rect)) { + int ret = acquire_dma_channel(mx3_cam); + if (ret < 0) + return ret; + } + + configure_geometry(mx3_cam, rect); + + return icd->ops->set_crop(icd, rect); +} + +static int mx3_camera_set_fmt(struct soc_camera_device *icd, + struct v4l2_format *f) +{ + struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); + struct mx3_camera_dev *mx3_cam = ici->priv; + const struct soc_camera_format_xlate *xlate; + struct v4l2_pix_format *pix = &f->fmt.pix; + struct v4l2_rect rect = { + .left = icd->x_current, + .top = icd->y_current, + .width = pix->width, + .height = pix->height, + }; + int ret; + + xlate = soc_camera_xlate_by_fourcc(icd, pix->pixelformat); + if (!xlate) { + dev_warn(&ici->dev, "Format %x not found\n", pix->pixelformat); + return -EINVAL; + } + + ret = acquire_dma_channel(mx3_cam); + if (ret < 0) + return ret; + + /* + * Might have to perform a complete interface initialisation like in + * ipu_csi_init_interface() in mxc_v4l2_s_param(). Also consider + * mxc_v4l2_s_fmt() + */ + + configure_geometry(mx3_cam, &rect); - ret = icd->ops->set_fmt(icd, pixfmt ? xlate->cam_fmt->fourcc : 0, rect); - if (pixfmt && !ret) { + ret = icd->ops->set_fmt(icd, f); + if (!ret) { icd->buswidth = xlate->buswidth; icd->current_fmt = xlate->host_fmt; } @@ -1031,6 +1067,7 @@ static struct soc_camera_host_ops mx3_soc_camera_host_ops = { .suspend = mx3_camera_suspend, .resume = mx3_camera_resume, #endif + .set_crop = mx3_camera_set_crop, .set_fmt = mx3_camera_set_fmt, .try_fmt = mx3_camera_try_fmt, .get_formats = mx3_camera_get_formats, diff --git a/drivers/media/video/ov772x.c b/drivers/media/video/ov772x.c index 880e51f0e9fd..8dd93b36c787 100644 --- a/drivers/media/video/ov772x.c +++ b/drivers/media/video/ov772x.c @@ -781,11 +781,9 @@ ov772x_select_win(u32 width, u32 height) return win; } -static int ov772x_set_fmt(struct soc_camera_device *icd, - __u32 pixfmt, - struct v4l2_rect *rect) +static int ov772x_set_params(struct ov772x_priv *priv, u32 width, u32 height, + u32 pixfmt) { - struct ov772x_priv *priv = container_of(icd, struct ov772x_priv, icd); int ret = -EINVAL; u8 val; int i; @@ -806,7 +804,7 @@ static int ov772x_set_fmt(struct soc_camera_device *icd, /* * select win */ - priv->win = ov772x_select_win(rect->width, rect->height); + priv->win = ov772x_select_win(width, height); /* * reset hardware @@ -870,6 +868,28 @@ ov772x_set_fmt_error: return ret; } +static int ov772x_set_crop(struct soc_camera_device *icd, + struct v4l2_rect *rect) +{ + struct ov772x_priv *priv = container_of(icd, struct ov772x_priv, icd); + + if (!priv->fmt) + return -EINVAL; + + return ov772x_set_params(priv, rect->width, rect->height, + priv->fmt->fourcc); +} + +static int ov772x_set_fmt(struct soc_camera_device *icd, + struct v4l2_format *f) +{ + struct ov772x_priv *priv = container_of(icd, struct ov772x_priv, icd); + struct v4l2_pix_format *pix = &f->fmt.pix; + + return ov772x_set_params(priv, pix->width, pix->height, + pix->pixelformat); +} + static int ov772x_try_fmt(struct soc_camera_device *icd, struct v4l2_format *f) { @@ -959,6 +979,7 @@ static struct soc_camera_ops ov772x_ops = { .release = ov772x_release, .start_capture = ov772x_start_capture, .stop_capture = ov772x_stop_capture, + .set_crop = ov772x_set_crop, .set_fmt = ov772x_set_fmt, .try_fmt = ov772x_try_fmt, .set_bus_param = ov772x_set_bus_param, diff --git a/drivers/media/video/pxa_camera.c b/drivers/media/video/pxa_camera.c index 2cc203cfbe6c..c522616ef38f 100644 --- a/drivers/media/video/pxa_camera.c +++ b/drivers/media/video/pxa_camera.c @@ -1150,8 +1150,43 @@ static int pxa_camera_get_formats(struct soc_camera_device *icd, int idx, return formats; } +static int pxa_camera_set_crop(struct soc_camera_device *icd, + struct v4l2_rect *rect) +{ + struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); + struct pxa_camera_dev *pcdev = ici->priv; + struct soc_camera_sense sense = { + .master_clock = pcdev->mclk, + .pixel_clock_max = pcdev->ciclk / 4, + }; + int ret; + + /* If PCLK is used to latch data from the sensor, check sense */ + if (pcdev->platform_flags & PXA_CAMERA_PCLK_EN) + icd->sense = &sense; + + ret = icd->ops->set_crop(icd, rect); + + icd->sense = NULL; + + if (ret < 0) { + dev_warn(&ici->dev, "Failed to crop to %ux%u@%u:%u\n", + rect->width, rect->height, rect->left, rect->top); + } else if (sense.flags & SOCAM_SENSE_PCLK_CHANGED) { + if (sense.pixel_clock > sense.pixel_clock_max) { + dev_err(&ici->dev, + "pixel clock %lu set by the camera too high!", + sense.pixel_clock); + return -EIO; + } + recalculate_fifo_timeout(pcdev, sense.pixel_clock); + } + + return ret; +} + static int pxa_camera_set_fmt(struct soc_camera_device *icd, - __u32 pixfmt, struct v4l2_rect *rect) + struct v4l2_format *f) { struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); struct pxa_camera_dev *pcdev = ici->priv; @@ -1161,35 +1196,30 @@ static int pxa_camera_set_fmt(struct soc_camera_device *icd, .master_clock = pcdev->mclk, .pixel_clock_max = pcdev->ciclk / 4, }; + struct v4l2_pix_format *pix = &f->fmt.pix; + struct v4l2_format cam_f = *f; int ret; - if (pixfmt) { - xlate = soc_camera_xlate_by_fourcc(icd, pixfmt); - if (!xlate) { - dev_warn(&ici->dev, "Format %x not found\n", pixfmt); - return -EINVAL; - } - - cam_fmt = xlate->cam_fmt; + xlate = soc_camera_xlate_by_fourcc(icd, pix->pixelformat); + if (!xlate) { + dev_warn(&ici->dev, "Format %x not found\n", pix->pixelformat); + return -EINVAL; } + cam_fmt = xlate->cam_fmt; + /* If PCLK is used to latch data from the sensor, check sense */ if (pcdev->platform_flags & PXA_CAMERA_PCLK_EN) icd->sense = &sense; - switch (pixfmt) { - case 0: /* Only geometry change */ - ret = icd->ops->set_fmt(icd, pixfmt, rect); - break; - default: - ret = icd->ops->set_fmt(icd, cam_fmt->fourcc, rect); - } + cam_f.fmt.pix.pixelformat = cam_fmt->fourcc; + ret = icd->ops->set_fmt(icd, &cam_f); icd->sense = NULL; if (ret < 0) { dev_warn(&ici->dev, "Failed to configure for format %x\n", - pixfmt); + pix->pixelformat); } else if (sense.flags & SOCAM_SENSE_PCLK_CHANGED) { if (sense.pixel_clock > sense.pixel_clock_max) { dev_err(&ici->dev, @@ -1200,7 +1230,7 @@ static int pxa_camera_set_fmt(struct soc_camera_device *icd, recalculate_fifo_timeout(pcdev, sense.pixel_clock); } - if (pixfmt && !ret) { + if (!ret) { icd->buswidth = xlate->buswidth; icd->current_fmt = xlate->host_fmt; } @@ -1364,6 +1394,7 @@ static struct soc_camera_host_ops pxa_soc_camera_host_ops = { .remove = pxa_camera_remove_device, .suspend = pxa_camera_suspend, .resume = pxa_camera_resume, + .set_crop = pxa_camera_set_crop, .get_formats = pxa_camera_get_formats, .set_fmt = pxa_camera_set_fmt, .try_fmt = pxa_camera_try_fmt, diff --git a/drivers/media/video/sh_mobile_ceu_camera.c b/drivers/media/video/sh_mobile_ceu_camera.c index ed3bfc4cf9f9..3f71cb809652 100644 --- a/drivers/media/video/sh_mobile_ceu_camera.c +++ b/drivers/media/video/sh_mobile_ceu_camera.c @@ -638,24 +638,30 @@ add_single_format: return formats; } +static int sh_mobile_ceu_set_crop(struct soc_camera_device *icd, + struct v4l2_rect *rect) +{ + return icd->ops->set_crop(icd, rect); +} + static int sh_mobile_ceu_set_fmt(struct soc_camera_device *icd, - __u32 pixfmt, struct v4l2_rect *rect) + struct v4l2_format *f) { struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); struct sh_mobile_ceu_dev *pcdev = ici->priv; + __u32 pixfmt = f->fmt.pix.pixelformat; const struct soc_camera_format_xlate *xlate; + struct v4l2_format cam_f = *f; int ret; - if (!pixfmt) - return icd->ops->set_fmt(icd, pixfmt, rect); - xlate = soc_camera_xlate_by_fourcc(icd, pixfmt); if (!xlate) { dev_warn(&ici->dev, "Format %x not found\n", pixfmt); return -EINVAL; } - ret = icd->ops->set_fmt(icd, xlate->cam_fmt->fourcc, rect); + cam_f.fmt.pix.pixelformat = xlate->cam_fmt->fourcc; + ret = icd->ops->set_fmt(icd, &cam_f); if (!ret) { icd->buswidth = xlate->buswidth; @@ -787,6 +793,7 @@ static struct soc_camera_host_ops sh_mobile_ceu_host_ops = { .add = sh_mobile_ceu_add_device, .remove = sh_mobile_ceu_remove_device, .get_formats = sh_mobile_ceu_get_formats, + .set_crop = sh_mobile_ceu_set_crop, .set_fmt = sh_mobile_ceu_set_fmt, .try_fmt = sh_mobile_ceu_try_fmt, .reqbufs = sh_mobile_ceu_reqbufs, diff --git a/drivers/media/video/soc_camera.c b/drivers/media/video/soc_camera.c index fcb05f06de8f..9939b045cb4c 100644 --- a/drivers/media/video/soc_camera.c +++ b/drivers/media/video/soc_camera.c @@ -417,9 +417,7 @@ static int soc_camera_s_fmt_vid_cap(struct file *file, void *priv, struct soc_camera_device *icd = icf->icd; struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); struct v4l2_pix_format *pix = &f->fmt.pix; - __u32 pixfmt = pix->pixelformat; int ret; - struct v4l2_rect rect; WARN_ON(priv != file->private_data); @@ -435,23 +433,19 @@ static int soc_camera_s_fmt_vid_cap(struct file *file, void *priv, goto unlock; } - rect.left = icd->x_current; - rect.top = icd->y_current; - rect.width = pix->width; - rect.height = pix->height; - ret = ici->ops->set_fmt(icd, pix->pixelformat, &rect); + ret = ici->ops->set_fmt(icd, f); if (ret < 0) { goto unlock; } else if (!icd->current_fmt || - icd->current_fmt->fourcc != pixfmt) { + icd->current_fmt->fourcc != pix->pixelformat) { dev_err(&ici->dev, "Host driver hasn't set up current format correctly!\n"); ret = -EINVAL; goto unlock; } - icd->width = rect.width; - icd->height = rect.height; + icd->width = f->fmt.pix.width; + icd->height = f->fmt.pix.height; icf->vb_vidq.field = pix->field; if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) dev_warn(&icd->dev, "Attention! Wrong buf-type %d\n", @@ -461,7 +455,7 @@ static int soc_camera_s_fmt_vid_cap(struct file *file, void *priv, icd->width, icd->height); /* set physical bus parameters */ - ret = ici->ops->set_bus_param(icd, pixfmt); + ret = ici->ops->set_bus_param(icd, pix->pixelformat); unlock: mutex_unlock(&icf->vb_vidq.vb_lock); @@ -685,7 +679,7 @@ static int soc_camera_s_crop(struct file *file, void *fh, /* Cropping is allowed during a running capture, guard consistency */ mutex_lock(&icf->vb_vidq.vb_lock); - ret = ici->ops->set_fmt(icd, 0, &a->c); + ret = ici->ops->set_crop(icd, &a->c); if (!ret) { icd->width = a->c.width; icd->height = a->c.height; @@ -918,6 +912,7 @@ int soc_camera_host_register(struct soc_camera_host *ici) if (!ici || !ici->ops || !ici->ops->try_fmt || !ici->ops->set_fmt || + !ici->ops->set_crop || !ici->ops->set_bus_param || !ici->ops->querycap || !ici->ops->init_videobuf || @@ -998,6 +993,7 @@ int soc_camera_device_register(struct soc_camera_device *icd) !icd->ops->release || !icd->ops->start_capture || !icd->ops->stop_capture || + !icd->ops->set_crop || !icd->ops->set_fmt || !icd->ops->try_fmt || !icd->ops->query_bus_param || diff --git a/drivers/media/video/soc_camera_platform.c b/drivers/media/video/soc_camera_platform.c index 013ab06e3180..c48676356ab7 100644 --- a/drivers/media/video/soc_camera_platform.c +++ b/drivers/media/video/soc_camera_platform.c @@ -79,8 +79,14 @@ soc_camera_platform_query_bus_param(struct soc_camera_device *icd) return p->bus_param; } +static int soc_camera_platform_set_crop(struct soc_camera_device *icd, + struct v4l2_rect *rect) +{ + return 0; +} + static int soc_camera_platform_set_fmt(struct soc_camera_device *icd, - __u32 pixfmt, struct v4l2_rect *rect) + struct v4l2_format *f) { return 0; } @@ -125,6 +131,7 @@ static struct soc_camera_ops soc_camera_platform_ops = { .release = soc_camera_platform_release, .start_capture = soc_camera_platform_start_capture, .stop_capture = soc_camera_platform_stop_capture, + .set_crop = soc_camera_platform_set_crop, .set_fmt = soc_camera_platform_set_fmt, .try_fmt = soc_camera_platform_try_fmt, .set_bus_param = soc_camera_platform_set_bus_param, diff --git a/drivers/media/video/tw9910.c b/drivers/media/video/tw9910.c index 0558b22fd3fb..a39947643992 100644 --- a/drivers/media/video/tw9910.c +++ b/drivers/media/video/tw9910.c @@ -641,25 +641,12 @@ static int tw9910_set_register(struct soc_camera_device *icd, } #endif -static int tw9910_set_fmt(struct soc_camera_device *icd, __u32 pixfmt, - struct v4l2_rect *rect) +static int tw9910_set_crop(struct soc_camera_device *icd, + struct v4l2_rect *rect) { struct tw9910_priv *priv = container_of(icd, struct tw9910_priv, icd); int ret = -EINVAL; u8 val; - int i; - - /* - * check color format - */ - for (i = 0 ; i < ARRAY_SIZE(tw9910_color_fmt) ; i++) { - if (pixfmt == tw9910_color_fmt[i].fourcc) { - ret = 0; - break; - } - } - if (ret < 0) - goto tw9910_set_fmt_error; /* * select suitable norm @@ -746,8 +733,33 @@ tw9910_set_fmt_error: return ret; } +static int tw9910_set_fmt(struct soc_camera_device *icd, + struct v4l2_format *f) +{ + struct v4l2_pix_format *pix = &f->fmt.pix; + struct v4l2_rect rect = { + .left = icd->x_current, + .top = icd->y_current, + .width = pix->width, + .height = pix->height, + }; + int i; + + /* + * check color format + */ + for (i = 0; i < ARRAY_SIZE(tw9910_color_fmt); i++) + if (pix->pixelformat == tw9910_color_fmt[i].fourcc) + break; + + if (i == ARRAY_SIZE(tw9910_color_fmt)) + return -EINVAL; + + return tw9910_set_crop(icd, &rect); +} + static int tw9910_try_fmt(struct soc_camera_device *icd, - struct v4l2_format *f) + struct v4l2_format *f) { struct v4l2_pix_format *pix = &f->fmt.pix; const struct tw9910_scale_ctrl *scale; @@ -835,6 +847,7 @@ static struct soc_camera_ops tw9910_ops = { .release = tw9910_release, .start_capture = tw9910_start_capture, .stop_capture = tw9910_stop_capture, + .set_crop = tw9910_set_crop, .set_fmt = tw9910_set_fmt, .try_fmt = tw9910_try_fmt, .set_bus_param = tw9910_set_bus_param, diff --git a/include/media/soc_camera.h b/include/media/soc_camera.h index c63a3409ffb7..e9eb60740aaa 100644 --- a/include/media/soc_camera.h +++ b/include/media/soc_camera.h @@ -74,7 +74,8 @@ struct soc_camera_host_ops { int (*resume)(struct soc_camera_device *); int (*get_formats)(struct soc_camera_device *, int, struct soc_camera_format_xlate *); - int (*set_fmt)(struct soc_camera_device *, __u32, struct v4l2_rect *); + int (*set_crop)(struct soc_camera_device *, struct v4l2_rect *); + int (*set_fmt)(struct soc_camera_device *, struct v4l2_format *); int (*try_fmt)(struct soc_camera_device *, struct v4l2_format *); void (*init_videobuf)(struct videobuf_queue *, struct soc_camera_device *); @@ -159,7 +160,8 @@ struct soc_camera_ops { int (*release)(struct soc_camera_device *); int (*start_capture)(struct soc_camera_device *); int (*stop_capture)(struct soc_camera_device *); - int (*set_fmt)(struct soc_camera_device *, __u32, struct v4l2_rect *); + int (*set_crop)(struct soc_camera_device *, struct v4l2_rect *); + int (*set_fmt)(struct soc_camera_device *, struct v4l2_format *); int (*try_fmt)(struct soc_camera_device *, struct v4l2_format *); unsigned long (*query_bus_param)(struct soc_camera_device *); int (*set_bus_param)(struct soc_camera_device *, unsigned long); -- cgit v1.2.3 From df2ed07025fc83f3b36470cf06d1816a5e07c90b Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Fri, 13 Mar 2009 06:08:20 -0300 Subject: V4L/DVB (11025): soc-camera: configure drivers with a default format on open Currently soc-camera doesn't set up any image format without an explicit S_FMT. It seems this should be supported, since, for example, capture-example.c from v4l2-apps by default doesn't issue an S_FMT. This patch configures a default image format on open(). Signed-off-by: Guennadi Liakhovetski Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/soc_camera.c | 100 ++++++++++++++++++++++++++------------- 1 file changed, 68 insertions(+), 32 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/soc_camera.c b/drivers/media/video/soc_camera.c index 9939b045cb4c..fcd6b2ce9c19 100644 --- a/drivers/media/video/soc_camera.c +++ b/drivers/media/video/soc_camera.c @@ -30,6 +30,10 @@ #include #include +/* Default to VGA resolution */ +#define DEFAULT_WIDTH 640 +#define DEFAULT_HEIGHT 480 + static LIST_HEAD(hosts); static LIST_HEAD(devices); static DEFINE_MUTEX(list_lock); @@ -256,6 +260,44 @@ static void soc_camera_free_user_formats(struct soc_camera_device *icd) vfree(icd->user_formats); } +/* Called with .vb_lock held */ +static int soc_camera_set_fmt(struct soc_camera_file *icf, + struct v4l2_format *f) +{ + struct soc_camera_device *icd = icf->icd; + struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); + struct v4l2_pix_format *pix = &f->fmt.pix; + int ret; + + /* We always call try_fmt() before set_fmt() or set_crop() */ + ret = ici->ops->try_fmt(icd, f); + if (ret < 0) + return ret; + + ret = ici->ops->set_fmt(icd, f); + if (ret < 0) { + return ret; + } else if (!icd->current_fmt || + icd->current_fmt->fourcc != pix->pixelformat) { + dev_err(&ici->dev, + "Host driver hasn't set up current format correctly!\n"); + return -EINVAL; + } + + icd->width = pix->width; + icd->height = pix->height; + icf->vb_vidq.field = pix->field; + if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + 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); + + /* set physical bus parameters */ + return ici->ops->set_bus_param(icd, pix->pixelformat); +} + static int soc_camera_open(struct file *file) { struct video_device *vdev; @@ -297,6 +339,15 @@ static int soc_camera_open(struct file *file) /* Now we really have to activate the camera */ if (icd->use_count == 1) { + struct v4l2_format f = { + .type = V4L2_BUF_TYPE_VIDEO_CAPTURE, + .fmt.pix = { + .width = DEFAULT_WIDTH, + .height = DEFAULT_HEIGHT, + .field = V4L2_FIELD_ANY, + }, + }; + ret = soc_camera_init_user_formats(icd); if (ret < 0) goto eiufmt; @@ -305,6 +356,14 @@ static int soc_camera_open(struct file *file) dev_err(&icd->dev, "Couldn't activate the camera: %d\n", ret); goto eiciadd; } + + f.fmt.pix.pixelformat = icd->current_fmt->fourcc; + f.fmt.pix.colorspace = icd->current_fmt->colorspace; + + /* Try to configure with default parameters */ + ret = soc_camera_set_fmt(icf, &f); + if (ret < 0) + goto esfmt; } mutex_unlock(&icd->video_lock); @@ -316,7 +375,12 @@ static int soc_camera_open(struct file *file) return 0; - /* First two errors are entered with the .video_lock held */ + /* + * First three errors are entered with the .video_lock held + * and use_count == 1 + */ +esfmt: + ici->ops->remove(icd); eiciadd: soc_camera_free_user_formats(icd); eiufmt: @@ -415,16 +479,10 @@ static int soc_camera_s_fmt_vid_cap(struct file *file, void *priv, { 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 v4l2_pix_format *pix = &f->fmt.pix; int ret; WARN_ON(priv != file->private_data); - ret = soc_camera_try_fmt_vid_cap(file, priv, f); - if (ret < 0) - return ret; - mutex_lock(&icf->vb_vidq.vb_lock); if (videobuf_queue_is_busy(&icf->vb_vidq)) { @@ -433,29 +491,7 @@ static int soc_camera_s_fmt_vid_cap(struct file *file, void *priv, goto unlock; } - ret = ici->ops->set_fmt(icd, f); - if (ret < 0) { - goto unlock; - } else if (!icd->current_fmt || - icd->current_fmt->fourcc != pix->pixelformat) { - dev_err(&ici->dev, - "Host driver hasn't set up current format correctly!\n"); - ret = -EINVAL; - goto unlock; - } - - icd->width = f->fmt.pix.width; - icd->height = f->fmt.pix.height; - icf->vb_vidq.field = pix->field; - if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - 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); - - /* set physical bus parameters */ - ret = ici->ops->set_bus_param(icd, pix->pixelformat); + ret = soc_camera_set_fmt(icf, f); unlock: mutex_unlock(&icf->vb_vidq.vb_lock); @@ -642,8 +678,8 @@ static int soc_camera_cropcap(struct file *file, void *fh, 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->defrect.width = DEFAULT_WIDTH; + a->defrect.height = DEFAULT_HEIGHT; a->pixelaspect.numerator = 1; a->pixelaspect.denominator = 1; -- cgit v1.2.3 From e802967c7079d2b4cfbd107dc90812605dbcad5a Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Fri, 13 Mar 2009 06:08:20 -0300 Subject: V4L/DVB (11026): sh-mobile-ceu-camera: set field to the value, configured at open() For the case, that we have to capture with a default format, i.e., when the user doesn't call S_FMT, we have to use the field value according to the default, configured at open() time. Signed-off-by: Guennadi Liakhovetski Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/sh_mobile_ceu_camera.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/sh_mobile_ceu_camera.c b/drivers/media/video/sh_mobile_ceu_camera.c index 3f71cb809652..55a5eae77bab 100644 --- a/drivers/media/video/sh_mobile_ceu_camera.c +++ b/drivers/media/video/sh_mobile_ceu_camera.c @@ -94,7 +94,7 @@ struct sh_mobile_ceu_dev { spinlock_t lock; struct list_head capture; struct videobuf_buffer *active; - int is_interlace; + int is_interlaced; struct sh_mobile_ceu_info *pdata; @@ -205,7 +205,7 @@ static void sh_mobile_ceu_capture(struct sh_mobile_ceu_dev *pcdev) phys_addr_top = videobuf_to_dma_contig(pcdev->active); ceu_write(pcdev, CDAYR, phys_addr_top); - if (pcdev->is_interlace) { + if (pcdev->is_interlaced) { phys_addr_bottom = phys_addr_top + icd->width; ceu_write(pcdev, CDBYR, phys_addr_bottom); } @@ -217,7 +217,7 @@ static void sh_mobile_ceu_capture(struct sh_mobile_ceu_dev *pcdev) case V4L2_PIX_FMT_NV61: phys_addr_top += icd->width * icd->height; ceu_write(pcdev, CDACR, phys_addr_top); - if (pcdev->is_interlace) { + if (pcdev->is_interlaced) { phys_addr_bottom = phys_addr_top + icd->width; ceu_write(pcdev, CDBCR, phys_addr_bottom); } @@ -481,7 +481,7 @@ static int sh_mobile_ceu_set_bus_param(struct soc_camera_device *icd, ceu_write(pcdev, CAMCR, value); ceu_write(pcdev, CAPCR, 0x00300000); - ceu_write(pcdev, CAIFR, (pcdev->is_interlace) ? 0x101 : 0); + ceu_write(pcdev, CAIFR, pcdev->is_interlaced ? 0x101 : 0); mdelay(1); @@ -497,7 +497,7 @@ static int sh_mobile_ceu_set_bus_param(struct soc_camera_device *icd, } height = icd->height; - if (pcdev->is_interlace) { + if (pcdev->is_interlaced) { height /= 2; cdwdr_width *= 2; } @@ -711,13 +711,13 @@ static int sh_mobile_ceu_try_fmt(struct soc_camera_device *icd, switch (f->fmt.pix.field) { case V4L2_FIELD_INTERLACED: - pcdev->is_interlace = 1; + pcdev->is_interlaced = 1; break; case V4L2_FIELD_ANY: f->fmt.pix.field = V4L2_FIELD_NONE; /* fall-through */ case V4L2_FIELD_NONE: - pcdev->is_interlace = 0; + pcdev->is_interlaced = 0; break; default: ret = -EINVAL; @@ -783,7 +783,8 @@ static void sh_mobile_ceu_init_videobuf(struct videobuf_queue *q, &sh_mobile_ceu_videobuf_ops, &ici->dev, &pcdev->lock, V4L2_BUF_TYPE_VIDEO_CAPTURE, - V4L2_FIELD_ANY, + pcdev->is_interlaced ? + V4L2_FIELD_INTERLACED : V4L2_FIELD_NONE, sizeof(struct sh_mobile_ceu_buffer), icd); } -- cgit v1.2.3 From 025c18a19d7d7eb8745d25986f982a5f35a85157 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Fri, 13 Mar 2009 06:08:20 -0300 Subject: V4L/DVB (11027): soc-camera: configure drivers with a default format at probe time Currently soc-camera doesn't set up any image format without an explicit S_FMT. According to the API this should be supported, for example, capture-example.c from v4l2-apps by default doesn't issue an S_FMT. This patch moves negotiating of available host-camera format translations to probe() time, and restores the state from the last close() on the next open(). This is needed for some drivers, which power down or reset hardware after the last user closes the interface. This patch also has a nice side-effect of avoiding multiple allocation anf freeing of format translation tables. Signed-off-by: Guennadi Liakhovetski Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/soc_camera.c | 39 +++++++++++++++++++++++---------------- include/media/soc_camera.h | 1 + 2 files changed, 24 insertions(+), 16 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/soc_camera.c b/drivers/media/video/soc_camera.c index fcd6b2ce9c19..6d8bfd4d97e2 100644 --- a/drivers/media/video/soc_camera.c +++ b/drivers/media/video/soc_camera.c @@ -286,7 +286,9 @@ static int soc_camera_set_fmt(struct soc_camera_file *icf, icd->width = pix->width; icd->height = pix->height; - icf->vb_vidq.field = pix->field; + icf->vb_vidq.field = + icd->field = pix->field; + if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) dev_warn(&icd->dev, "Attention! Wrong buf-type %d\n", f->type); @@ -339,27 +341,24 @@ static int soc_camera_open(struct file *file) /* Now we really have to activate the camera */ if (icd->use_count == 1) { + /* Restore parameters before the last close() per V4L2 API */ struct v4l2_format f = { .type = V4L2_BUF_TYPE_VIDEO_CAPTURE, .fmt.pix = { - .width = DEFAULT_WIDTH, - .height = DEFAULT_HEIGHT, - .field = V4L2_FIELD_ANY, + .width = icd->width, + .height = icd->height, + .field = icd->field, + .pixelformat = icd->current_fmt->fourcc, + .colorspace = icd->current_fmt->colorspace, }, }; - ret = soc_camera_init_user_formats(icd); - if (ret < 0) - goto eiufmt; ret = ici->ops->add(icd); if (ret < 0) { dev_err(&icd->dev, "Couldn't activate the camera: %d\n", ret); goto eiciadd; } - f.fmt.pix.pixelformat = icd->current_fmt->fourcc; - f.fmt.pix.colorspace = icd->current_fmt->colorspace; - /* Try to configure with default parameters */ ret = soc_camera_set_fmt(icf, &f); if (ret < 0) @@ -382,8 +381,6 @@ static int soc_camera_open(struct file *file) esfmt: ici->ops->remove(icd); eiciadd: - soc_camera_free_user_formats(icd); -eiufmt: icd->use_count--; mutex_unlock(&icd->video_lock); module_put(ici->ops->owner); @@ -403,10 +400,9 @@ static int soc_camera_close(struct file *file) mutex_lock(&icd->video_lock); icd->use_count--; - if (!icd->use_count) { + if (!icd->use_count) ici->ops->remove(icd); - soc_camera_free_user_formats(icd); - } + mutex_unlock(&icd->video_lock); module_put(icd->ops->owner); @@ -874,9 +870,18 @@ static int soc_camera_probe(struct device *dev) qctrl = soc_camera_find_qctrl(icd->ops, V4L2_CID_EXPOSURE); icd->exposure = qctrl ? qctrl->default_value : (unsigned short)~0; + + ret = soc_camera_init_user_formats(icd); + if (ret < 0) + goto eiufmt; + + icd->height = DEFAULT_HEIGHT; + icd->width = DEFAULT_WIDTH; + icd->field = V4L2_FIELD_ANY; } - ici->ops->remove(icd); +eiufmt: + ici->ops->remove(icd); eiadd: mutex_unlock(&icd->video_lock); module_put(ici->ops->owner); @@ -895,6 +900,8 @@ static int soc_camera_remove(struct device *dev) if (icd->ops->remove) icd->ops->remove(icd); + soc_camera_free_user_formats(icd); + return 0; } diff --git a/include/media/soc_camera.h b/include/media/soc_camera.h index e9eb60740aaa..013c81875d76 100644 --- a/include/media/soc_camera.h +++ b/include/media/soc_camera.h @@ -45,6 +45,7 @@ struct soc_camera_device { int num_formats; struct soc_camera_format_xlate *user_formats; int num_user_formats; + enum v4l2_field field; /* Preserve field over close() */ struct module *owner; void *host_priv; /* Per-device host private data */ /* soc_camera.c private count. Only accessed with .video_lock held */ -- cgit v1.2.3 From f340e3f6f1c2061a65fd1cbd70e9e57e27d34212 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 13 Mar 2009 06:08:20 -0300 Subject: V4L/DVB (11028): ov772x: use soft sleep mode in stop_capture Signed-off-by: Kuninori Morimoto Signed-off-by: Guennadi Liakhovetski Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/ov772x.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers/media/video') diff --git a/drivers/media/video/ov772x.c b/drivers/media/video/ov772x.c index 8dd93b36c787..84b0fc1bb237 100644 --- a/drivers/media/video/ov772x.c +++ b/drivers/media/video/ov772x.c @@ -646,6 +646,8 @@ static int ov772x_start_capture(struct soc_camera_device *icd) return -EPERM; } + ov772x_mask_set(priv->client, COM2, SOFT_SLEEP_MODE, 0); + dev_dbg(&icd->dev, "format %s, win %s\n", priv->fmt->name, priv->win->name); @@ -654,6 +656,8 @@ static int ov772x_start_capture(struct soc_camera_device *icd) static int ov772x_stop_capture(struct soc_camera_device *icd) { + struct ov772x_priv *priv = container_of(icd, struct ov772x_priv, icd); + ov772x_mask_set(priv->client, COM2, SOFT_SLEEP_MODE, SOFT_SLEEP_MODE); return 0; } -- cgit v1.2.3 From 97215cbd1bc3cc32a2a1b3a94b003c3cbcf95683 Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Fri, 13 Mar 2009 06:08:20 -0300 Subject: V4L/DVB (11029): video: use videobuf_waiton() in sh_mobile_ceu free_buffer() Make sure videobuf_waiton() is used before freeing a buffer. Without this fix we may return the buffer to the allocator before the bus mastering operation is finished. Reported-by: Matthieu CASTET Tested-by: Kuninori Morimoto Signed-off-by: Magnus Damm Signed-off-by: Guennadi Liakhovetski Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/sh_mobile_ceu_camera.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/media/video') diff --git a/drivers/media/video/sh_mobile_ceu_camera.c b/drivers/media/video/sh_mobile_ceu_camera.c index 55a5eae77bab..b5e37a530c62 100644 --- a/drivers/media/video/sh_mobile_ceu_camera.c +++ b/drivers/media/video/sh_mobile_ceu_camera.c @@ -174,6 +174,7 @@ static void free_buffer(struct videobuf_queue *vq, if (in_interrupt()) BUG(); + videobuf_waiton(&buf->vb, 0, 0); videobuf_dma_contig_free(vq, &buf->vb); dev_dbg(&icd->dev, "%s freed\n", __func__); buf->vb.state = VIDEOBUF_NEEDS_INIT; -- cgit v1.2.3 From 36034dc325ecab63c8cfb992fbf9a1a8e94738a2 Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Fri, 13 Mar 2009 06:08:20 -0300 Subject: V4L/DVB (11032): mt9m001: allow setting of bus width from board code This patch removes the phytec specific setting of the bus width and switches to the more generic query_bus_param/set_bus_param hooks Signed-off-by: Sascha Hauer Signed-off-by: Guennadi Liakhovetski Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/Kconfig | 7 --- drivers/media/video/mt9m001.c | 143 ++++++++++++------------------------------ 2 files changed, 40 insertions(+), 110 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig index 534a022c4d1b..24dfb39a6ccb 100644 --- a/drivers/media/video/Kconfig +++ b/drivers/media/video/Kconfig @@ -707,13 +707,6 @@ config SOC_CAMERA_MT9M001 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_MT9M111 tristate "mt9m111 and mt9m112 support" depends on SOC_CAMERA && I2C diff --git a/drivers/media/video/mt9m001.c b/drivers/media/video/mt9m001.c index a6703d25227f..fa7e5093edeb 100644 --- a/drivers/media/video/mt9m001.c +++ b/drivers/media/video/mt9m001.c @@ -12,7 +12,6 @@ #include #include #include -#include #include #include @@ -73,9 +72,7 @@ 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) @@ -181,92 +178,28 @@ static int mt9m001_stop_capture(struct soc_camera_device *icd) 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 bus_switch_possible(struct mt9m001 *mt9m001) -{ -#ifdef CONFIG_MT9M001_PCA9536_SWITCH - return gpio_is_valid(mt9m001->switch_gpio); -#else - return 0; -#endif -} - static int mt9m001_set_bus_param(struct soc_camera_device *icd, unsigned long flags) { struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd); - unsigned int width_flag = flags & SOCAM_DATAWIDTH_MASK; - int ret; + struct soc_camera_link *icl = mt9m001->client->dev.platform_data; + unsigned long width_flag = flags & SOCAM_DATAWIDTH_MASK; - /* Flags validity verified in test_bus_param */ + /* Only one width bit may be set */ + if (!is_power_of_2(width_flag)) + return -EINVAL; - if ((mt9m001->datawidth != 10 && (width_flag == SOCAM_DATAWIDTH_10)) || - (mt9m001->datawidth != 9 && (width_flag == SOCAM_DATAWIDTH_9)) || - (mt9m001->datawidth != 8 && (width_flag == SOCAM_DATAWIDTH_8))) { - /* Well, we actually only can do 10 or 8 bits... */ - if (width_flag == SOCAM_DATAWIDTH_9) - return -EINVAL; - ret = bus_switch_act(mt9m001, - width_flag == SOCAM_DATAWIDTH_8); - if (ret < 0) - return ret; + if (icl->set_bus_param) + return icl->set_bus_param(icl, width_flag); - mt9m001->datawidth = width_flag == SOCAM_DATAWIDTH_8 ? 8 : 10; - } + /* + * Without board specific bus width settings we only support the + * sensors native bus width + */ + if (width_flag == SOCAM_DATAWIDTH_10) + return 0; - return 0; + return -EINVAL; } static unsigned long mt9m001_query_bus_param(struct soc_camera_device *icd) @@ -274,12 +207,14 @@ static unsigned long mt9m001_query_bus_param(struct soc_camera_device *icd) struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd); struct soc_camera_link *icl = mt9m001->client->dev.platform_data; /* MT9M001 has all capture_format parameters fixed */ - unsigned long flags = SOCAM_DATAWIDTH_10 | SOCAM_PCLK_SAMPLE_RISING | + unsigned long flags = SOCAM_PCLK_SAMPLE_RISING | SOCAM_HSYNC_ACTIVE_HIGH | SOCAM_VSYNC_ACTIVE_HIGH | SOCAM_DATA_ACTIVE_HIGH | SOCAM_MASTER; - if (bus_switch_possible(mt9m001)) - flags |= SOCAM_DATAWIDTH_8; + if (icl->query_bus_param) + flags |= icl->query_bus_param(icl) & SOCAM_DATAWIDTH_MASK; + else + flags |= SOCAM_DATAWIDTH_10; return soc_camera_apply_sensor_flags(icl, flags); } @@ -598,6 +533,7 @@ static int mt9m001_video_probe(struct soc_camera_device *icd) struct soc_camera_link *icl = mt9m001->client->dev.platform_data; s32 data; int ret; + unsigned long flags; /* We must have a parent by now. And it cannot be a wrong one. * So this entire test is completely redundant. */ @@ -618,18 +554,10 @@ static int mt9m001_video_probe(struct soc_camera_device *icd) case 0x8421: mt9m001->model = V4L2_IDENT_MT9M001C12ST; icd->formats = mt9m001_colour_formats; - if (gpio_is_valid(icl->gpio)) - icd->num_formats = ARRAY_SIZE(mt9m001_colour_formats); - else - icd->num_formats = 1; break; case 0x8431: mt9m001->model = V4L2_IDENT_MT9M001C12STM; icd->formats = mt9m001_monochrome_formats; - if (gpio_is_valid(icl->gpio)) - icd->num_formats = ARRAY_SIZE(mt9m001_monochrome_formats); - else - icd->num_formats = 1; break; default: ret = -ENODEV; @@ -638,6 +566,26 @@ static int mt9m001_video_probe(struct soc_camera_device *icd) goto ei2c; } + icd->num_formats = 0; + + /* + * This is a 10bit sensor, so by default we only allow 10bit. + * The platform may support different bus widths due to + * different routing of the data lines. + */ + if (icl->query_bus_param) + flags = icl->query_bus_param(icl); + else + flags = SOCAM_DATAWIDTH_10; + + if (flags & SOCAM_DATAWIDTH_10) + icd->num_formats++; + else + icd->formats++; + + if (flags & SOCAM_DATAWIDTH_8) + icd->num_formats++; + dev_info(&icd->dev, "Detected a MT9M001 chip ID %x (%s)\n", data, data == 0x8431 ? "C12STM" : "C12ST"); @@ -703,18 +651,10 @@ static int mt9m001_probe(struct i2c_client *client, 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; @@ -722,8 +662,6 @@ static int mt9m001_probe(struct i2c_client *client, return 0; eisdr: - bus_switch_release(mt9m001); -eswinit: kfree(mt9m001); return ret; } @@ -733,7 +671,6 @@ 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; -- cgit v1.2.3 From e958e27adeade7fa085dd396a8a0dfaef7e338c1 Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Fri, 13 Mar 2009 06:08:20 -0300 Subject: V4L/DVB (11033): mt9v022: allow setting of bus width from board code This patch removes the phytec specific setting of the bus width and switches to the more generic query_bus_param/set_bus_param hooks Signed-off-by: Sascha Hauer Signed-off-by: Guennadi Liakhovetski Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/Kconfig | 7 --- drivers/media/video/mt9v022.c | 141 +++++++++++++----------------------------- 2 files changed, 42 insertions(+), 106 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig index 24dfb39a6ccb..d5ddb819a961 100644 --- a/drivers/media/video/Kconfig +++ b/drivers/media/video/Kconfig @@ -726,13 +726,6 @@ config SOC_CAMERA_MT9V022 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 SOC_CAMERA_TW9910 tristate "tw9910 support" depends on SOC_CAMERA && I2C diff --git a/drivers/media/video/mt9v022.c b/drivers/media/video/mt9v022.c index 3871d4a2d8ff..4d3b4813c322 100644 --- a/drivers/media/video/mt9v022.c +++ b/drivers/media/video/mt9v022.c @@ -13,7 +13,6 @@ #include #include #include -#include #include #include @@ -89,9 +88,7 @@ struct mt9v022 { struct i2c_client *client; struct soc_camera_device icd; int model; /* V4L2_IDENT_MT9V022* 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) @@ -209,66 +206,6 @@ static int mt9v022_stop_capture(struct soc_camera_device *icd) 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 bus_switch_possible(struct mt9v022 *mt9v022) -{ -#ifdef CONFIG_MT9V022_PCA9536_SWITCH - return gpio_is_valid(mt9v022->switch_gpio); -#else - return 0; -#endif -} - static int mt9v022_set_bus_param(struct soc_camera_device *icd, unsigned long flags) { @@ -282,19 +219,17 @@ static int mt9v022_set_bus_param(struct soc_camera_device *icd, if (!is_power_of_2(width_flag)) return -EINVAL; - if ((mt9v022->datawidth != 10 && (width_flag == SOCAM_DATAWIDTH_10)) || - (mt9v022->datawidth != 9 && (width_flag == SOCAM_DATAWIDTH_9)) || - (mt9v022->datawidth != 8 && (width_flag == SOCAM_DATAWIDTH_8))) { - /* Well, we actually only can do 10 or 8 bits... */ - if (width_flag == SOCAM_DATAWIDTH_9) - return -EINVAL; - - ret = bus_switch_act(mt9v022, - width_flag == SOCAM_DATAWIDTH_8); - if (ret < 0) + if (icl->set_bus_param) { + ret = icl->set_bus_param(icl, width_flag); + if (ret) return ret; - - mt9v022->datawidth = width_flag == SOCAM_DATAWIDTH_8 ? 8 : 10; + } else { + /* + * Without board specific bus width settings we only support the + * sensors native bus width + */ + if (width_flag != SOCAM_DATAWIDTH_10) + return -EINVAL; } flags = soc_camera_apply_sensor_flags(icl, flags); @@ -328,10 +263,14 @@ static int mt9v022_set_bus_param(struct soc_camera_device *icd, static unsigned long mt9v022_query_bus_param(struct soc_camera_device *icd) { struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd); - unsigned int width_flag = SOCAM_DATAWIDTH_10; + struct soc_camera_link *icl = mt9v022->client->dev.platform_data; + unsigned int width_flag; - if (bus_switch_possible(mt9v022)) - width_flag |= SOCAM_DATAWIDTH_8; + if (icl->query_bus_param) + width_flag = icl->query_bus_param(icl) & + SOCAM_DATAWIDTH_MASK; + else + width_flag = SOCAM_DATAWIDTH_10; return SOCAM_PCLK_SAMPLE_RISING | SOCAM_PCLK_SAMPLE_FALLING | SOCAM_HSYNC_ACTIVE_HIGH | SOCAM_HSYNC_ACTIVE_LOW | @@ -715,6 +654,7 @@ static int mt9v022_video_probe(struct soc_camera_device *icd) struct soc_camera_link *icl = mt9v022->client->dev.platform_data; s32 data; int ret; + unsigned long flags; if (!icd->dev.parent || to_soc_camera_host(icd->dev.parent)->nr != icd->iface) @@ -748,22 +688,36 @@ static int mt9v022_video_probe(struct soc_camera_device *icd) ret = reg_write(icd, MT9V022_PIXEL_OPERATION_MODE, 4 | 0x11); mt9v022->model = V4L2_IDENT_MT9V022IX7ATC; icd->formats = mt9v022_colour_formats; - if (gpio_is_valid(icl->gpio)) - icd->num_formats = ARRAY_SIZE(mt9v022_colour_formats); - else - icd->num_formats = 1; } else { ret = reg_write(icd, MT9V022_PIXEL_OPERATION_MODE, 0x11); mt9v022->model = V4L2_IDENT_MT9V022IX7ATM; icd->formats = mt9v022_monochrome_formats; - if (gpio_is_valid(icl->gpio)) - icd->num_formats = ARRAY_SIZE(mt9v022_monochrome_formats); - else - icd->num_formats = 1; } - if (!ret) - ret = soc_camera_video_start(icd); + if (ret < 0) + goto eisis; + + icd->num_formats = 0; + + /* + * This is a 10bit sensor, so by default we only allow 10bit. + * The platform may support different bus widths due to + * different routing of the data lines. + */ + if (icl->query_bus_param) + flags = icl->query_bus_param(icl); + else + flags = SOCAM_DATAWIDTH_10; + + if (flags & SOCAM_DATAWIDTH_10) + icd->num_formats++; + else + icd->formats++; + + if (flags & SOCAM_DATAWIDTH_8) + icd->num_formats++; + + ret = soc_camera_video_start(icd); if (ret < 0) goto eisis; @@ -828,14 +782,6 @@ static int mt9v022_probe(struct i2c_client *client, 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) @@ -844,8 +790,6 @@ static int mt9v022_probe(struct i2c_client *client, return 0; eisdr: - bus_switch_release(mt9v022); -eswinit: kfree(mt9v022); return ret; } @@ -855,7 +799,6 @@ 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; -- cgit v1.2.3 From c98afbfc20355dd04a7b817b232e06a4c3e73bac Mon Sep 17 00:00:00 2001 From: Philippe Rétornaz Date: Fri, 13 Mar 2009 09:42:32 -0300 Subject: V4L/DVB (11035): mt9t031 bugfix MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - The video device is not allocated when mt9t031_init() is called, don't use it in debug printk. - The clock polarity is inverted in mt9t031_set_bus_param(), use the correct one. Signed-off-by: Philippe Rétornaz Signed-off-by: Guennadi Liakhovetski Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/mt9t031.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/mt9t031.c b/drivers/media/video/mt9t031.c index 677be18df9b3..23f9ce9d67ef 100644 --- a/drivers/media/video/mt9t031.c +++ b/drivers/media/video/mt9t031.c @@ -144,8 +144,6 @@ static int mt9t031_init(struct soc_camera_device *icd) int ret; /* Disable chip output, synchronous option update */ - dev_dbg(icd->vdev->parent, "%s\n", __func__); - ret = reg_write(icd, MT9T031_RESET, 1); if (ret >= 0) ret = reg_write(icd, MT9T031_RESET, 0); @@ -186,9 +184,9 @@ static int mt9t031_set_bus_param(struct soc_camera_device *icd, return -EINVAL; if (flags & SOCAM_PCLK_SAMPLE_FALLING) - reg_set(icd, MT9T031_PIXEL_CLOCK_CONTROL, 0x8000); - else reg_clear(icd, MT9T031_PIXEL_CLOCK_CONTROL, 0x8000); + else + reg_set(icd, MT9T031_PIXEL_CLOCK_CONTROL, 0x8000); return 0; } -- cgit v1.2.3 From 71cb2764fcc51bd9e1b95be5b0f2da6f026634c7 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Tue, 3 Mar 2009 05:33:41 -0300 Subject: V4L/DVB (11039): gspca - most jpeg subdrivers: Change the JPEG header creation. Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab --- Documentation/video4linux/CARDLIST.bttv | 1 + drivers/media/video/gspca/conex.c | 21 ++- drivers/media/video/gspca/jpeg.h | 250 ++++++-------------------------- drivers/media/video/gspca/mars.c | 23 ++- drivers/media/video/gspca/sonixj.c | 94 ++++++++---- drivers/media/video/gspca/spca500.c | 22 ++- drivers/media/video/gspca/stk014.c | 25 +++- drivers/media/video/gspca/sunplus.c | 22 ++- drivers/media/video/gspca/zc3xx.c | 18 ++- 9 files changed, 226 insertions(+), 250 deletions(-) (limited to 'drivers/media/video') diff --git a/Documentation/video4linux/CARDLIST.bttv b/Documentation/video4linux/CARDLIST.bttv index e17750473e08..f11c583295e9 100644 --- a/Documentation/video4linux/CARDLIST.bttv +++ b/Documentation/video4linux/CARDLIST.bttv @@ -157,3 +157,4 @@ 156 -> IVCE-8784 [0000:f050,0001:f050,0002:f050,0003:f050] 157 -> Geovision GV-800(S) (master) [800a:763d] 158 -> Geovision GV-800(S) (slave) [800b:763d,800c:763d,800d:763d] +159 -> ProVideo PV183 [1830:1540,1831:1540,1832:1540,1833:1540,1834:1540,1835:1540,1836:1540,1837:1540] diff --git a/drivers/media/video/gspca/conex.c b/drivers/media/video/gspca/conex.c index de2e608bf5ba..fd4df402bc2f 100644 --- a/drivers/media/video/gspca/conex.c +++ b/drivers/media/video/gspca/conex.c @@ -23,7 +23,6 @@ #include "gspca.h" #define CONEX_CAM 1 /* special JPEG header */ -#define QUANT_VAL 0 /* quantization table */ #include "jpeg.h" MODULE_AUTHOR("Michel Xhaard "); @@ -37,6 +36,9 @@ struct sd { unsigned char brightness; unsigned char contrast; unsigned char colors; + u8 quality; + + u8 *jpeg_hdr; }; /* V4L2 controls supported by the driver */ @@ -820,6 +822,7 @@ static int sd_config(struct gspca_dev *gspca_dev, sd->brightness = BRIGHTNESS_DEF; sd->contrast = CONTRAST_DEF; sd->colors = COLOR_DEF; + sd->quality = 40; return 0; } @@ -836,6 +839,14 @@ static int sd_init(struct gspca_dev *gspca_dev) static int sd_start(struct gspca_dev *gspca_dev) { + struct sd *sd = (struct sd *) gspca_dev; + + /* create the JPEG header */ + sd->jpeg_hdr = kmalloc(JPEG_HDR_SZ, GFP_KERNEL); + jpeg_define(sd->jpeg_hdr, gspca_dev->height, gspca_dev->width, + 0x22); /* JPEG 411 */ + jpeg_set_qual(sd->jpeg_hdr, sd->quality); + cx11646_initsize(gspca_dev); cx11646_fw(gspca_dev); cx_sensor(gspca_dev); @@ -846,8 +857,11 @@ static int sd_start(struct gspca_dev *gspca_dev) /* called on streamoff with alt 0 and on disconnect */ static void sd_stop0(struct gspca_dev *gspca_dev) { + struct sd *sd = (struct sd *) gspca_dev; int retry = 50; + kfree(sd->jpeg_hdr); + if (!gspca_dev->present) return; reg_w_val(gspca_dev, 0x0000, 0x00); @@ -873,6 +887,8 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, __u8 *data, /* isoc packet */ int len) /* iso packet length */ { + struct sd *sd = (struct sd *) gspca_dev; + if (data[0] == 0xff && data[1] == 0xd8) { /* start of frame */ @@ -880,7 +896,8 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, data, 0); /* put the JPEG header in the new frame */ - jpeg_put_header(gspca_dev, frame, 0x22); + gspca_frame_add(gspca_dev, FIRST_PACKET, frame, + sd->jpeg_hdr, JPEG_HDR_SZ); data += 2; len -= 2; } diff --git a/drivers/media/video/gspca/jpeg.h b/drivers/media/video/gspca/jpeg.h index 7d2df9720025..de63c36806c0 100644 --- a/drivers/media/video/gspca/jpeg.h +++ b/drivers/media/video/gspca/jpeg.h @@ -27,42 +27,16 @@ /* * generation options * CONEX_CAM Conexant if present - * QUANT_VAL quantization table (0..8) */ -/* - * JPEG header: - * - start of jpeg frame - * - quantization table - * - huffman table - * - start of SOF0 - */ +/* JPEG header */ static const u8 jpeg_head[] = { 0xff, 0xd8, /* jpeg */ + +/* quantization table quality 50% */ 0xff, 0xdb, 0x00, 0x84, /* DQT */ -#if QUANT_VAL == 0 -/* index 0 - Q40*/ -0, /* quantization table part 1 */ - 0x14, 0x0e, 0x0f, 0x12, 0x0f, 0x0d, 0x14, 0x12, - 0x10, 0x12, 0x17, 0x15, 0x14, 0x18, 0x1e, 0x32, - 0x21, 0x1e, 0x1c, 0x1c, 0x1e, 0x3d, 0x2c, 0x2e, - 0x24, 0x32, 0x49, 0x40, 0x4c, 0x4b, 0x47, 0x40, - 0x46, 0x45, 0x50, 0x5a, 0x73, 0x62, 0x50, 0x55, - 0x6d, 0x56, 0x45, 0x46, 0x64, 0x88, 0x65, 0x6d, - 0x77, 0x7b, 0x81, 0x82, 0x81, 0x4e, 0x60, 0x8d, - 0x97, 0x8c, 0x7d, 0x96, 0x73, 0x7e, 0x81, 0x7c, -1, /* quantization table part 2 */ - 0x15, 0x17, 0x17, 0x1e, 0x1a, 0x1e, 0x3b, 0x21, - 0x21, 0x3b, 0x7c, 0x53, 0x46, 0x53, 0x7c, 0x0c, - 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, - 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, - 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, - 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, - 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, - 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, -#elif QUANT_VAL == 1 -/* index 1 - Q50 */ 0, +#define JPEG_QT0_OFFSET 7 0x10, 0x0b, 0x0c, 0x0e, 0x0c, 0x0a, 0x10, 0x0e, 0x0d, 0x0e, 0x12, 0x11, 0x10, 0x13, 0x18, 0x28, 0x1a, 0x18, 0x16, 0x16, 0x18, 0x31, 0x23, 0x25, @@ -72,6 +46,7 @@ static const u8 jpeg_head[] = { 0x5f, 0x62, 0x67, 0x68, 0x67, 0x3e, 0x4d, 0x71, 0x79, 0x70, 0x64, 0x78, 0x5c, 0x65, 0x67, 0x63, 1, +#define JPEG_QT1_OFFSET 72 0x11, 0x12, 0x12, 0x18, 0x15, 0x18, 0x2f, 0x1a, 0x1a, 0x2f, 0x63, 0x42, 0x38, 0x42, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, @@ -80,149 +55,6 @@ static const u8 jpeg_head[] = { 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, -#elif QUANT_VAL == 2 -/* index 2 Q60 */ -0, - 0x0d, 0x09, 0x0a, 0x0b, 0x0a, 0x08, 0x0d, 0x0b, - 0x0a, 0x0b, 0x0e, 0x0e, 0x0d, 0x0f, 0x13, 0x20, - 0x15, 0x13, 0x12, 0x12, 0x13, 0x27, 0x1c, 0x1e, - 0x17, 0x20, 0x2e, 0x29, 0x31, 0x30, 0x2e, 0x29, - 0x2d, 0x2c, 0x33, 0x3a, 0x4a, 0x3e, 0x33, 0x36, - 0x46, 0x37, 0x2c, 0x2d, 0x40, 0x57, 0x41, 0x46, - 0x4c, 0x4e, 0x52, 0x53, 0x52, 0x32, 0x3e, 0x5a, - 0x61, 0x5a, 0x50, 0x60, 0x4a, 0x51, 0x52, 0x4f, -1, - 0x0e, 0x0e, 0x0e, 0x13, 0x11, 0x13, 0x26, 0x15, - 0x15, 0x26, 0x4f, 0x35, 0x2d, 0x35, 0x4f, 0x4f, - 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, - 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, - 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, - 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, - 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, - 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, -#elif QUANT_VAL == 3 -/* index 3 - Q70 */ -0, - 0x0a, 0x07, 0x07, 0x08, 0x07, 0x06, 0x0a, 0x08, - 0x08, 0x08, 0x0b, 0x0a, 0x0a, 0x0b, 0x0e, 0x18, - 0x10, 0x0e, 0x0d, 0x0d, 0x0e, 0x1d, 0x15, 0x16, - 0x11, 0x18, 0x23, 0x1f, 0x25, 0x24, 0x22, 0x1f, - 0x22, 0x21, 0x26, 0x2b, 0x37, 0x2f, 0x26, 0x29, - 0x34, 0x29, 0x21, 0x22, 0x30, 0x41, 0x31, 0x34, - 0x39, 0x3b, 0x3e, 0x3e, 0x3e, 0x25, 0x2e, 0x44, - 0x49, 0x43, 0x3c, 0x48, 0x37, 0x3d, 0x3e, 0x3b, -1, - 0x0a, 0x0b, 0x0b, 0x0e, 0x0d, 0x0e, 0x1c, 0x10, - 0x10, 0x1c, 0x3b, 0x28, 0x22, 0x28, 0x3b, 0x3b, - 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, - 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, - 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, - 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, - 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, - 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, -#elif QUANT_VAL == 4 -/* index 4 - Q80 */ -0, - 0x06, 0x04, 0x05, 0x06, 0x05, 0x04, 0x06, 0x06, - 0x05, 0x06, 0x07, 0x07, 0x06, 0x08, 0x0a, 0x10, - 0x0a, 0x0a, 0x09, 0x09, 0x0a, 0x14, 0x0e, 0x0f, - 0x0c, 0x10, 0x17, 0x14, 0x18, 0x18, 0x17, 0x14, - 0x16, 0x16, 0x1a, 0x1d, 0x25, 0x1f, 0x1a, 0x1b, - 0x23, 0x1c, 0x16, 0x16, 0x20, 0x2c, 0x20, 0x23, - 0x26, 0x27, 0x29, 0x2a, 0x29, 0x19, 0x1f, 0x2d, - 0x30, 0x2d, 0x28, 0x30, 0x25, 0x28, 0x29, 0x28, -1, - 0x07, 0x07, 0x07, 0x0a, 0x08, 0x0a, 0x13, 0x0a, - 0x0a, 0x13, 0x28, 0x1a, 0x16, 0x1a, 0x28, 0x28, - 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, - 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, - 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, - 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, - 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, - 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, -#elif QUANT_VAL == 5 -/* index 5 - Q85 */ -0, - 0x05, 0x03, 0x04, 0x04, 0x04, 0x03, 0x05, 0x04, - 0x04, 0x04, 0x05, 0x05, 0x05, 0x06, 0x07, 0x0c, - 0x08, 0x07, 0x07, 0x07, 0x07, 0x0f, 0x0b, 0x0b, - 0x09, 0x0c, 0x11, 0x0f, 0x12, 0x12, 0x11, 0x0f, - 0x11, 0x11, 0x13, 0x16, 0x1c, 0x17, 0x13, 0x14, - 0x1a, 0x15, 0x11, 0x11, 0x18, 0x21, 0x18, 0x1a, - 0x1d, 0x1d, 0x1f, 0x1f, 0x1f, 0x13, 0x17, 0x22, - 0x24, 0x22, 0x1e, 0x24, 0x1c, 0x1e, 0x1f, 0x1e, -1, - 0x05, 0x05, 0x05, 0x07, 0x06, 0x07, 0x0e, 0x08, - 0x08, 0x0e, 0x1e, 0x14, 0x11, 0x14, 0x1e, 0x1e, - 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, - 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, - 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, - 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, - 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, - 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, -#elif QUANT_VAL == 6 -/* index 6 - 86 */ -0, - 0x04, 0x03, 0x03, 0x04, 0x03, 0x03, 0x04, 0x04, - 0x04, 0x04, 0x05, 0x05, 0x04, 0x05, 0x07, 0x0B, - 0x07, 0x07, 0x06, 0x06, 0x07, 0x0e, 0x0a, 0x0a, - 0x08, 0x0B, 0x10, 0x0e, 0x11, 0x11, 0x10, 0x0e, - 0x10, 0x0f, 0x12, 0x14, 0x1a, 0x16, 0x12, 0x13, - 0x18, 0x13, 0x0f, 0x10, 0x16, 0x1f, 0x17, 0x18, - 0x1b, 0x1b, 0x1d, 0x1d, 0x1d, 0x11, 0x16, 0x20, - 0x22, 0x1f, 0x1c, 0x22, 0x1a, 0x1c, 0x1d, 0x1c, -1, - 0x05, 0x05, 0x05, 0x07, 0x06, 0x07, 0x0D, 0x07, - 0x07, 0x0D, 0x1c, 0x12, 0x10, 0x12, 0x1c, 0x1c, - 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, - 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, - 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, - 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, - 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, - 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, -#elif QUANT_VAL == 7 -/* index 7 - 88 */ -0, - 0x04, 0x03, 0x03, 0x03, 0x03, 0x02, 0x04, 0x03, - 0x03, 0x03, 0x04, 0x04, 0x04, 0x05, 0x06, 0x0a, - 0x06, 0x06, 0x05, 0x05, 0x06, 0x0C, 0x08, 0x09, - 0x07, 0x0a, 0x0e, 0x0c, 0x0f, 0x0e, 0x0e, 0x0c, - 0x0d, 0x0d, 0x0f, 0x11, 0x16, 0x13, 0x0f, 0x10, - 0x15, 0x11, 0x0d, 0x0d, 0x13, 0x1a, 0x13, 0x15, - 0x17, 0x18, 0x19, 0x19, 0x19, 0x0f, 0x12, 0x1b, - 0x1d, 0x1b, 0x18, 0x1d, 0x16, 0x18, 0x19, 0x18, -1, - 0x04, 0x04, 0x04, 0x06, 0x05, 0x06, 0x0B, 0x06, - 0x06, 0x0B, 0x18, 0x10, 0x0d, 0x10, 0x18, 0x18, - 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, - 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, - 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, - 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, - 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, - 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, -#elif QUANT_VAL == 8 -/* index 8 - ?? */ -0, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x03, 0x05, - 0x03, 0x03, 0x03, 0x03, 0x03, 0x06, 0x04, 0x05, - 0x04, 0x05, 0x07, 0x06, 0x08, 0x08, 0x07, 0x06, - 0x07, 0x07, 0x08, 0x09, 0x0c, 0x0a, 0x08, 0x09, - 0x0B, 0x09, 0x07, 0x07, 0x0a, 0x0e, 0x0a, 0x0b, - 0x0c, 0x0c, 0x0d, 0x0d, 0x0d, 0x08, 0x0a, 0x0e, - 0x0f, 0x0e, 0x0d, 0x0f, 0x0c, 0x0d, 0x0d, 0x0c, -1, - 0x02, 0x02, 0x02, 0x03, 0x03, 0x03, 0x06, 0x03, - 0x03, 0x06, 0x0c, 0x08, 0x07, 0x08, 0x0c, 0x0c, - 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, - 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, - 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, - 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, - 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, - 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, -#else -#error "Invalid quantization table" -#endif /* huffman table */ 0xff, 0xc4, 0x01, 0xa2, @@ -280,55 +112,57 @@ static const u8 jpeg_head[] = { 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, #ifdef CONEX_CAM /* the Conexant frames start with SOF0 */ +#define JPEG_HDR_SZ 556 #else 0xff, 0xc0, 0x00, 0x11, /* SOF0 (start of frame 0 */ 0x08, /* data precision */ -#endif -}; - -#ifndef CONEX_CAM -/* variable part: - * 0x01, 0xe0, height - * 0x02, 0x80, width - * 0x03, component number - * 0x01, - * 0x21, samples Y - */ - -/* end of header */ -static u8 eoh[] = { +#define JPEG_HEIGHT_OFFSET 561 + 0x01, 0xe0, /* height */ + 0x02, 0x80, /* width */ + 0x03, /* component number */ + 0x01, + 0x21, /* samples Y */ 0x00, /* quant Y */ 0x02, 0x11, 0x01, /* samples CbCr - quant CbCr */ 0x03, 0x11, 0x01, 0xff, 0xda, 0x00, 0x0c, /* SOS (start of scan) */ 0x03, 0x01, 0x00, 0x02, 0x11, 0x03, 0x11, 0x00, 0x3f, 0x00 -}; +#define JPEG_HDR_SZ 589 #endif +}; -/* -- output the JPEG header -- */ -static void jpeg_put_header(struct gspca_dev *gspca_dev, - struct gspca_frame *frame, - int samplesY) +/* define the JPEG header */ +static void jpeg_define(u8 *jpeg_hdr, + int height, + int width, + int samplesY) { + memcpy(jpeg_hdr, jpeg_head, sizeof jpeg_head); #ifndef CONEX_CAM - u8 tmpbuf[8]; + jpeg_hdr[JPEG_HEIGHT_OFFSET + 0] = height >> 8; + jpeg_hdr[JPEG_HEIGHT_OFFSET + 1] = height & 0xff; + jpeg_hdr[JPEG_HEIGHT_OFFSET + 2] = width >> 8; + jpeg_hdr[JPEG_HEIGHT_OFFSET + 3] = width & 0xff; + jpeg_hdr[JPEG_HEIGHT_OFFSET + 6] = samplesY; #endif +} - gspca_frame_add(gspca_dev, FIRST_PACKET, frame, - jpeg_head, sizeof jpeg_head); -#ifndef CONEX_CAM - tmpbuf[0] = gspca_dev->height >> 8; - tmpbuf[1] = gspca_dev->height & 0xff; - tmpbuf[2] = gspca_dev->width >> 8; - tmpbuf[3] = gspca_dev->width & 0xff; - tmpbuf[4] = 0x03; /* component number */ - tmpbuf[5] = 0x01; /* first component */ - tmpbuf[6] = samplesY; - gspca_frame_add(gspca_dev, INTER_PACKET, frame, - tmpbuf, 7); - gspca_frame_add(gspca_dev, INTER_PACKET, frame, - eoh, sizeof eoh); -#endif +/* set the JPEG quality */ +static void jpeg_set_qual(u8 *jpeg_hdr, + int quality) +{ + int i, sc; + + if (quality < 50) + sc = 5000 / quality; + else + sc = 200 - quality * 2; + for (i = 0; i < 64; i++) { + jpeg_hdr[JPEG_QT0_OFFSET + i] = + (jpeg_head[JPEG_QT0_OFFSET + i] * sc + 50) / 100; + jpeg_hdr[JPEG_QT1_OFFSET + i] = + (jpeg_head[JPEG_QT1_OFFSET + i] * sc + 50) / 100; + } } #endif diff --git a/drivers/media/video/gspca/mars.c b/drivers/media/video/gspca/mars.c index ce065d363e8a..6eb813e7b714 100644 --- a/drivers/media/video/gspca/mars.c +++ b/drivers/media/video/gspca/mars.c @@ -22,7 +22,6 @@ #define MODULE_NAME "mars" #include "gspca.h" -#define QUANT_VAL 1 /* quantization table */ #include "jpeg.h" MODULE_AUTHOR("Michel Xhaard "); @@ -37,6 +36,9 @@ struct sd { u8 colors; u8 gamma; u8 sharpness; + u8 quality; + + u8 *jpeg_hdr; }; /* V4L2 controls supported by the driver */ @@ -176,6 +178,7 @@ static int sd_config(struct gspca_dev *gspca_dev, sd->colors = COLOR_DEF; sd->gamma = GAMMA_DEF; sd->sharpness = SHARPNESS_DEF; + sd->quality = 50; gspca_dev->nbalt = 9; /* use the altsetting 08 */ return 0; } @@ -193,6 +196,12 @@ static int sd_start(struct gspca_dev *gspca_dev) u8 *data; int i; + /* create the JPEG header */ + sd->jpeg_hdr = kmalloc(JPEG_HDR_SZ, GFP_KERNEL); + jpeg_define(sd->jpeg_hdr, gspca_dev->height, gspca_dev->width, + 0x21); /* JPEG 422 */ + jpeg_set_qual(sd->jpeg_hdr, sd->quality); + data = gspca_dev->usb_buf; data[0] = 0x01; /* address */ @@ -303,11 +312,19 @@ static void sd_stopN(struct gspca_dev *gspca_dev) PDEBUG(D_ERR, "Camera Stop failed"); } +static void sd_stop0(struct gspca_dev *gspca_dev) +{ + struct sd *sd = (struct sd *) gspca_dev; + + kfree(sd->jpeg_hdr); +} + static void sd_pkt_scan(struct gspca_dev *gspca_dev, struct gspca_frame *frame, /* target */ __u8 *data, /* isoc packet */ int len) /* iso packet length */ { + struct sd *sd = (struct sd *) gspca_dev; int p; if (len < 6) { @@ -330,7 +347,8 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, frame, data, p); /* put the JPEG header */ - jpeg_put_header(gspca_dev, frame, 0x21); + gspca_frame_add(gspca_dev, FIRST_PACKET, frame, + sd->jpeg_hdr, JPEG_HDR_SZ); data += p + 16; len -= p + 16; break; @@ -436,6 +454,7 @@ static const struct sd_desc sd_desc = { .init = sd_init, .start = sd_start, .stopN = sd_stopN, + .stop0 = sd_stop0, .pkt_scan = sd_pkt_scan, }; diff --git a/drivers/media/video/gspca/sonixj.c b/drivers/media/video/gspca/sonixj.c index edc26d8ad2ad..363c0fa39d9e 100644 --- a/drivers/media/video/gspca/sonixj.c +++ b/drivers/media/video/gspca/sonixj.c @@ -22,7 +22,6 @@ #define MODULE_NAME "sonixj" #include "gspca.h" -#define QUANT_VAL 4 /* quantization table */ #include "jpeg.h" #define V4L2_CID_INFRARED (V4L2_CID_PRIVATE_BASE + 0) @@ -47,6 +46,10 @@ struct sd { u8 gamma; u8 vflip; /* ov7630/ov7648 only */ u8 infrared; /* mt9v111 only */ + u8 quality; /* image quality */ + u8 jpegqual; /* webcam quality */ + + u8 reg18; s8 ag_cnt; #define AG_CNT_START 13 @@ -68,6 +71,8 @@ struct sd { #define SENSOR_OV7660 7 #define SENSOR_SP80708 8 u8 i2c_base; + + u8 *jpeg_hdr; }; /* V4L2 controls supported by the driver */ @@ -859,25 +864,6 @@ static const u8 sp80708_sensor_init[][8] = { {} }; -static const u8 qtable4[] = { - 0x06, 0x04, 0x04, 0x06, 0x04, 0x04, 0x06, 0x06, - 0x06, 0x06, 0x08, 0x06, 0x06, 0x08, 0x0a, 0x11, - 0x0a, 0x0a, 0x08, 0x08, 0x0a, 0x15, 0x0f, 0x0f, - 0x0c, 0x11, 0x19, 0x15, 0x19, 0x19, 0x17, 0x15, - 0x17, 0x17, 0x1b, 0x1d, 0x25, 0x21, 0x1b, 0x1d, - 0x23, 0x1d, 0x17, 0x17, 0x21, 0x2e, 0x21, 0x23, - 0x27, 0x29, 0x2c, 0x2c, 0x2c, 0x19, 0x1f, 0x30, - 0x32, 0x2e, 0x29, 0x32, 0x25, 0x29, 0x2c, 0x29, - 0x06, 0x08, 0x08, 0x0a, 0x08, 0x0a, 0x13, 0x0a, - 0x0a, 0x13, 0x29, 0x1b, 0x17, 0x1b, 0x29, 0x29, - 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, - 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, - 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, - 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, - 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, - 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29 -}; - /* read bytes to gspca_dev->usb_buf */ static void reg_r(struct gspca_dev *gspca_dev, u16 value, int len) @@ -1309,6 +1295,8 @@ static int sd_config(struct gspca_dev *gspca_dev, else sd->vflip = 1; sd->infrared = INFRARED_DEF; + sd->quality = 80; + sd->jpegqual = 80; gspca_dev->ctrl_dis = ctrl_dis[sd->sensor]; return 0; @@ -1610,12 +1598,49 @@ static void setinfrared(struct sd *sd) sd->infrared ? 0x66 : 0x64); } +static void setjpegqual(struct gspca_dev *gspca_dev) +{ + struct sd *sd = (struct sd *) gspca_dev; + int i, sc; + + if (sd->jpegqual < 50) + sc = 5000 / sd->jpegqual; + else + sc = 200 - sd->jpegqual * 2; +#if USB_BUF_SZ < 64 +#error "No room enough in usb_buf for quantization table" +#endif + for (i = 0; i < 64; i++) + gspca_dev->usb_buf[i] = + (jpeg_head[JPEG_QT0_OFFSET + i] * sc + 50) / 100; + usb_control_msg(gspca_dev->dev, + usb_sndctrlpipe(gspca_dev->dev, 0), + 0x08, + USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE, + 0x0100, 0, + gspca_dev->usb_buf, 64, + 500); + for (i = 0; i < 64; i++) + gspca_dev->usb_buf[i] = + (jpeg_head[JPEG_QT1_OFFSET + i] * sc + 50) / 100; + usb_control_msg(gspca_dev->dev, + usb_sndctrlpipe(gspca_dev->dev, 0), + 0x08, + USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE, + 0x0140, 0, + gspca_dev->usb_buf, 64, + 500); + + sd->reg18 ^= 0x40; + reg_w1(gspca_dev, 0x18, sd->reg18); +} + /* -- start the camera -- */ static int sd_start(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; int i; - u8 reg1, reg17, reg18; + u8 reg1, reg17; const u8 *sn9c1xx; int mode; static const u8 C0[] = { 0x2d, 0x2d, 0x3a, 0x05, 0x04, 0x3f }; @@ -1624,6 +1649,12 @@ static int sd_start(struct gspca_dev *gspca_dev) static const u8 CE_ov76xx[] = { 0x32, 0xdd, 0x32, 0xdd }; + /* create the JPEG header */ + sd->jpeg_hdr = kmalloc(JPEG_HDR_SZ, GFP_KERNEL); + jpeg_define(sd->jpeg_hdr, gspca_dev->height, gspca_dev->width, + 0x21); /* JPEG 422 */ + jpeg_set_qual(sd->jpeg_hdr, sd->quality); + sn9c1xx = sn_tb[(int) sd->sensor]; configure_gpio(gspca_dev, sn9c1xx); @@ -1782,13 +1813,9 @@ static int sd_start(struct gspca_dev *gspca_dev) } /* here change size mode 0 -> VGA; 1 -> CIF */ - reg18 = sn9c1xx[0x18] | (mode << 4); - reg_w1(gspca_dev, 0x18, reg18 | 0x40); - - reg_w(gspca_dev, 0x0100, qtable4, 0x40); - reg_w(gspca_dev, 0x0140, qtable4 + 0x40, 0x40); - - reg_w1(gspca_dev, 0x18, reg18); + sd->reg18 = sn9c1xx[0x18] | (mode << 4) | 0x40; + reg_w1(gspca_dev, 0x18, sd->reg18); + setjpegqual(gspca_dev); reg_w1(gspca_dev, 0x17, reg17); reg_w1(gspca_dev, 0x01, reg1); @@ -1845,6 +1872,13 @@ static void sd_stopN(struct gspca_dev *gspca_dev) reg_w1(gspca_dev, 0xf1, 0x00); } +static void sd_stop0(struct gspca_dev *gspca_dev) +{ + struct sd *sd = (struct sd *) gspca_dev; + + kfree(sd->jpeg_hdr); +} + static void do_autogain(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; @@ -1928,7 +1962,8 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, if (gspca_dev->last_packet_type == LAST_PACKET) { /* put the JPEG 422 header */ - jpeg_put_header(gspca_dev, frame, 0x21); + gspca_frame_add(gspca_dev, FIRST_PACKET, frame, + sd->jpeg_hdr, JPEG_HDR_SZ); } gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len); } @@ -2104,6 +2139,7 @@ static const struct sd_desc sd_desc = { .init = sd_init, .start = sd_start, .stopN = sd_stopN, + .stop0 = sd_stop0, .pkt_scan = sd_pkt_scan, .dq_callback = do_autogain, }; diff --git a/drivers/media/video/gspca/spca500.c b/drivers/media/video/gspca/spca500.c index f44613095d2e..2176ac6850e3 100644 --- a/drivers/media/video/gspca/spca500.c +++ b/drivers/media/video/gspca/spca500.c @@ -22,7 +22,6 @@ #define MODULE_NAME "spca500" #include "gspca.h" -#define QUANT_VAL 5 /* quantization table */ #include "jpeg.h" MODULE_AUTHOR("Michel Xhaard "); @@ -39,6 +38,7 @@ struct sd { unsigned char brightness; unsigned char contrast; unsigned char colors; + u8 quality; char subtype; #define AgfaCl20 0 @@ -56,6 +56,8 @@ struct sd { #define Optimedia 12 #define PalmPixDC85 13 #define ToptroIndus 14 + + u8 *jpeg_hdr; }; /* V4L2 controls supported by the driver */ @@ -640,6 +642,7 @@ static int sd_config(struct gspca_dev *gspca_dev, sd->brightness = BRIGHTNESS_DEF; sd->contrast = CONTRAST_DEF; sd->colors = COLOR_DEF; + sd->quality = 85; return 0; } @@ -665,6 +668,12 @@ static int sd_start(struct gspca_dev *gspca_dev) __u8 Data; __u8 xmult, ymult; + /* create the JPEG header */ + sd->jpeg_hdr = kmalloc(JPEG_HDR_SZ, GFP_KERNEL); + jpeg_define(sd->jpeg_hdr, gspca_dev->height, gspca_dev->width, + 0x22); /* JPEG 411 */ + jpeg_set_qual(sd->jpeg_hdr, sd->quality); + if (sd->subtype == LogitechClickSmart310) { xmult = 0x16; ymult = 0x12; @@ -880,6 +889,13 @@ static void sd_stopN(struct gspca_dev *gspca_dev) gspca_dev->usb_buf[0]); } +static void sd_stop0(struct gspca_dev *gspca_dev) +{ + struct sd *sd = (struct sd *) gspca_dev; + + kfree(sd->jpeg_hdr); +} + static void sd_pkt_scan(struct gspca_dev *gspca_dev, struct gspca_frame *frame, /* target */ __u8 *data, /* isoc packet */ @@ -900,7 +916,8 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, ffd9, 2); /* put the JPEG header in the new frame */ - jpeg_put_header(gspca_dev, frame, 0x22); + gspca_frame_add(gspca_dev, FIRST_PACKET, frame, + sd->jpeg_hdr, JPEG_HDR_SZ); data += SPCA500_OFFSET_DATA; len -= SPCA500_OFFSET_DATA; @@ -1013,6 +1030,7 @@ static struct sd_desc sd_desc = { .init = sd_init, .start = sd_start, .stopN = sd_stopN, + .stop0 = sd_stop0, .pkt_scan = sd_pkt_scan, }; diff --git a/drivers/media/video/gspca/stk014.c b/drivers/media/video/gspca/stk014.c index d1d54edd80bd..dd007cb52006 100644 --- a/drivers/media/video/gspca/stk014.c +++ b/drivers/media/video/gspca/stk014.c @@ -21,8 +21,6 @@ #define MODULE_NAME "stk014" #include "gspca.h" -#define QUANT_VAL 7 /* quantization table */ - /* <= 4 KO - 7: good (enough!) */ #include "jpeg.h" MODULE_AUTHOR("Jean-Francois Moine "); @@ -37,6 +35,9 @@ struct sd { unsigned char contrast; unsigned char colors; unsigned char lightfreq; + u8 quality; + + u8 *jpeg_hdr; }; /* V4L2 controls supported by the driver */ @@ -300,6 +301,7 @@ static int sd_config(struct gspca_dev *gspca_dev, sd->contrast = CONTRAST_DEF; sd->colors = COLOR_DEF; sd->lightfreq = FREQ_DEF; + sd->quality = 80; return 0; } @@ -323,8 +325,15 @@ static int sd_init(struct gspca_dev *gspca_dev) /* -- start the camera -- */ static int sd_start(struct gspca_dev *gspca_dev) { + struct sd *sd = (struct sd *) gspca_dev; int ret, value; + /* create the JPEG header */ + sd->jpeg_hdr = kmalloc(JPEG_HDR_SZ, GFP_KERNEL); + jpeg_define(sd->jpeg_hdr, gspca_dev->height, gspca_dev->width, + 0x22); /* JPEG 411 */ + jpeg_set_qual(sd->jpeg_hdr, sd->quality); + /* work on alternate 1 */ usb_set_interface(gspca_dev->dev, gspca_dev->iface, 1); @@ -396,11 +405,19 @@ static void sd_stopN(struct gspca_dev *gspca_dev) PDEBUG(D_STREAM, "camera stopped"); } +static void sd_stop0(struct gspca_dev *gspca_dev) +{ + struct sd *sd = (struct sd *) gspca_dev; + + kfree(sd->jpeg_hdr); +} + static void sd_pkt_scan(struct gspca_dev *gspca_dev, struct gspca_frame *frame, /* target */ __u8 *data, /* isoc packet */ int len) /* iso packet length */ { + struct sd *sd = (struct sd *) gspca_dev; static unsigned char ffd9[] = {0xff, 0xd9}; /* a frame starts with: @@ -417,7 +434,8 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, ffd9, 2); /* put the JPEG 411 header */ - jpeg_put_header(gspca_dev, frame, 0x22); + gspca_frame_add(gspca_dev, FIRST_PACKET, frame, + sd->jpeg_hdr, JPEG_HDR_SZ); /* beginning of the frame */ #define STKHDRSZ 12 @@ -526,6 +544,7 @@ static const struct sd_desc sd_desc = { .init = sd_init, .start = sd_start, .stopN = sd_stopN, + .stop0 = sd_stop0, .pkt_scan = sd_pkt_scan, .querymenu = sd_querymenu, }; diff --git a/drivers/media/video/gspca/sunplus.c b/drivers/media/video/gspca/sunplus.c index 9d08a66fe23d..eadfaa9f97d2 100644 --- a/drivers/media/video/gspca/sunplus.c +++ b/drivers/media/video/gspca/sunplus.c @@ -22,7 +22,6 @@ #define MODULE_NAME "sunplus" #include "gspca.h" -#define QUANT_VAL 5 /* quantization table */ #include "jpeg.h" MODULE_AUTHOR("Michel Xhaard "); @@ -40,6 +39,7 @@ struct sd { unsigned char contrast; unsigned char colors; unsigned char autogain; + u8 quality; char bridge; #define BRIDGE_SPCA504 0 @@ -52,6 +52,8 @@ struct sd { #define LogitechClickSmart420 2 #define LogitechClickSmart820 3 #define MegapixV4 4 + + u8 *jpeg_hdr; }; /* V4L2 controls supported by the driver */ @@ -852,6 +854,7 @@ static int sd_config(struct gspca_dev *gspca_dev, sd->brightness = sd_ctrls[SD_BRIGHTNESS].qctrl.default_value; sd->contrast = sd_ctrls[SD_CONTRAST].qctrl.default_value; sd->colors = sd_ctrls[SD_COLOR].qctrl.default_value; + sd->quality = 85; return 0; } @@ -968,6 +971,12 @@ static int sd_start(struct gspca_dev *gspca_dev) __u8 i; __u8 info[6]; + /* create the JPEG header */ + sd->jpeg_hdr = kmalloc(JPEG_HDR_SZ, GFP_KERNEL); + jpeg_define(sd->jpeg_hdr, gspca_dev->height, gspca_dev->width, + 0x22); /* JPEG 411 */ + jpeg_set_qual(sd->jpeg_hdr, sd->quality); + if (sd->bridge == BRIDGE_SPCA504B) spca504B_setQtable(gspca_dev); spca504B_SetSizeType(gspca_dev); @@ -1077,6 +1086,13 @@ static void sd_stopN(struct gspca_dev *gspca_dev) } } +static void sd_stop0(struct gspca_dev *gspca_dev) +{ + struct sd *sd = (struct sd *) gspca_dev; + + kfree(sd->jpeg_hdr); +} + static void sd_pkt_scan(struct gspca_dev *gspca_dev, struct gspca_frame *frame, /* target */ __u8 *data, /* isoc packet */ @@ -1153,7 +1169,8 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, ffd9, 2); /* put the JPEG header in the new frame */ - jpeg_put_header(gspca_dev, frame, 0x22); + gspca_frame_add(gspca_dev, FIRST_PACKET, frame, + sd->jpeg_hdr, JPEG_HDR_SZ); } /* add 0x00 after 0xff */ @@ -1311,6 +1328,7 @@ static const struct sd_desc sd_desc = { .init = sd_init, .start = sd_start, .stopN = sd_stopN, + .stop0 = sd_stop0, .pkt_scan = sd_pkt_scan, }; diff --git a/drivers/media/video/gspca/zc3xx.c b/drivers/media/video/gspca/zc3xx.c index 4f459a746037..a4c673ff8f02 100644 --- a/drivers/media/video/gspca/zc3xx.c +++ b/drivers/media/video/gspca/zc3xx.c @@ -23,6 +23,7 @@ #define MODULE_NAME "zc3xx" #include "gspca.h" +#include "jpeg.h" MODULE_AUTHOR("Michel Xhaard , " "Serge A. Suchkov "); @@ -32,7 +33,6 @@ MODULE_LICENSE("GPL"); static int force_sensor = -1; #define QUANT_VAL 1 /* quantization table */ -#include "jpeg.h" #include "zc3xx-reg.h" /* specific webcam descriptor */ @@ -45,6 +45,7 @@ struct sd { __u8 autogain; __u8 lightfreq; __u8 sharpness; + u8 quality; /* image quality */ signed char sensor; /* Type of image sensor chip */ /* !! values used in different tables */ @@ -69,6 +70,8 @@ struct sd { #define SENSOR_TAS5130C_VF0250 17 #define SENSOR_MAX 18 unsigned short chip_revision; + + u8 *jpeg_hdr; }; /* V4L2 controls supported by the driver */ @@ -7177,6 +7180,7 @@ static int sd_config(struct gspca_dev *gspca_dev, sd->gamma = gamma[(int) sd->sensor]; sd->autogain = sd_ctrls[SD_AUTOGAIN].qctrl.default_value; sd->lightfreq = sd_ctrls[SD_FREQ].qctrl.default_value; + sd->quality = 50; switch (sd->sensor) { case SENSOR_GC0305: @@ -7232,6 +7236,12 @@ static int sd_start(struct gspca_dev *gspca_dev) /* 17 */ }; + /* create the JPEG header */ + sd->jpeg_hdr = kmalloc(JPEG_HDR_SZ, GFP_KERNEL); + jpeg_define(sd->jpeg_hdr, gspca_dev->height, gspca_dev->width, + 0x21); /* JPEG 422 */ + jpeg_set_qual(sd->jpeg_hdr, sd->quality); + mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv; zc3_init = init_tb[(int) sd->sensor][mode]; switch (sd->sensor) { @@ -7365,6 +7375,7 @@ static void sd_stop0(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; + kfree(sd->jpeg_hdr); if (!gspca_dev->present) return; send_unknown(gspca_dev->dev, sd->sensor); @@ -7375,12 +7386,15 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, __u8 *data, int len) { + struct sd *sd = (struct sd *) gspca_dev; if (data[0] == 0xff && data[1] == 0xd8) { /* start of frame */ frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame, data, 0); /* put the JPEG header in the new frame */ - jpeg_put_header(gspca_dev, frame, 0x21); + gspca_frame_add(gspca_dev, FIRST_PACKET, frame, + sd->jpeg_hdr, JPEG_HDR_SZ); + /* remove the webcam's header: * ff d8 ff fe 00 0e 00 00 ss ss 00 01 ww ww hh hh pp pp * - 'ss ss' is the frame sequence number (BE) -- cgit v1.2.3 From 77ac0baf24d1a43498f7bdf6efa2ee6c4ed0ebaa Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Mon, 2 Mar 2009 06:40:52 -0300 Subject: V4L/DVB (11040): gspca - most jpeg subdrivers: Have the JPEG quality settable. The JPEG quality of the images (quantization tables) is now settable by the VIDIOC_S_JPEGCOMP ioctl. Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/conex.c | 35 ++++++++++++++++++++++++++++++++++- drivers/media/video/gspca/mars.c | 35 ++++++++++++++++++++++++++++++++++- drivers/media/video/gspca/sonixj.c | 35 ++++++++++++++++++++++++++++++++++- drivers/media/video/gspca/spca500.c | 35 ++++++++++++++++++++++++++++++++++- drivers/media/video/gspca/stk014.c | 35 ++++++++++++++++++++++++++++++++++- drivers/media/video/gspca/sunplus.c | 35 ++++++++++++++++++++++++++++++++++- drivers/media/video/gspca/zc3xx.c | 35 ++++++++++++++++++++++++++++++++++- 7 files changed, 238 insertions(+), 7 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/gspca/conex.c b/drivers/media/video/gspca/conex.c index fd4df402bc2f..219cfa6fb877 100644 --- a/drivers/media/video/gspca/conex.c +++ b/drivers/media/video/gspca/conex.c @@ -37,6 +37,9 @@ struct sd { unsigned char contrast; unsigned char colors; u8 quality; +#define QUALITY_MIN 30 +#define QUALITY_MAX 60 +#define QUALITY_DEF 40 u8 *jpeg_hdr; }; @@ -822,7 +825,7 @@ static int sd_config(struct gspca_dev *gspca_dev, sd->brightness = BRIGHTNESS_DEF; sd->contrast = CONTRAST_DEF; sd->colors = COLOR_DEF; - sd->quality = 40; + sd->quality = QUALITY_DEF; return 0; } @@ -1000,6 +1003,34 @@ static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val) return 0; } +static int sd_set_jcomp(struct gspca_dev *gspca_dev, + struct v4l2_jpegcompression *jcomp) +{ + struct sd *sd = (struct sd *) gspca_dev; + + if (jcomp->quality < QUALITY_MIN) + sd->quality = QUALITY_MIN; + else if (jcomp->quality > QUALITY_MAX) + sd->quality = QUALITY_MAX; + else + sd->quality = jcomp->quality; + if (gspca_dev->streaming) + jpeg_set_qual(sd->jpeg_hdr, sd->quality); + return 0; +} + +static int sd_get_jcomp(struct gspca_dev *gspca_dev, + struct v4l2_jpegcompression *jcomp) +{ + struct sd *sd = (struct sd *) gspca_dev; + + memset(jcomp, 0, sizeof *jcomp); + jcomp->quality = sd->quality; + jcomp->jpeg_markers = V4L2_JPEG_MARKER_DHT + | V4L2_JPEG_MARKER_DQT; + return 0; +} + /* sub-driver description */ static struct sd_desc sd_desc = { .name = MODULE_NAME, @@ -1010,6 +1041,8 @@ static struct sd_desc sd_desc = { .start = sd_start, .stop0 = sd_stop0, .pkt_scan = sd_pkt_scan, + .get_jcomp = sd_get_jcomp, + .set_jcomp = sd_set_jcomp, }; /* -- module initialisation -- */ diff --git a/drivers/media/video/gspca/mars.c b/drivers/media/video/gspca/mars.c index 6eb813e7b714..75e8d14e4ac7 100644 --- a/drivers/media/video/gspca/mars.c +++ b/drivers/media/video/gspca/mars.c @@ -37,6 +37,9 @@ struct sd { u8 gamma; u8 sharpness; u8 quality; +#define QUALITY_MIN 40 +#define QUALITY_MAX 70 +#define QUALITY_DEF 50 u8 *jpeg_hdr; }; @@ -178,7 +181,7 @@ static int sd_config(struct gspca_dev *gspca_dev, sd->colors = COLOR_DEF; sd->gamma = GAMMA_DEF; sd->sharpness = SHARPNESS_DEF; - sd->quality = 50; + sd->quality = QUALITY_DEF; gspca_dev->nbalt = 9; /* use the altsetting 08 */ return 0; } @@ -445,6 +448,34 @@ static int sd_getsharpness(struct gspca_dev *gspca_dev, __s32 *val) return 0; } +static int sd_set_jcomp(struct gspca_dev *gspca_dev, + struct v4l2_jpegcompression *jcomp) +{ + struct sd *sd = (struct sd *) gspca_dev; + + if (jcomp->quality < QUALITY_MIN) + sd->quality = QUALITY_MIN; + else if (jcomp->quality > QUALITY_MAX) + sd->quality = QUALITY_MAX; + else + sd->quality = jcomp->quality; + if (gspca_dev->streaming) + jpeg_set_qual(sd->jpeg_hdr, sd->quality); + return 0; +} + +static int sd_get_jcomp(struct gspca_dev *gspca_dev, + struct v4l2_jpegcompression *jcomp) +{ + struct sd *sd = (struct sd *) gspca_dev; + + memset(jcomp, 0, sizeof *jcomp); + jcomp->quality = sd->quality; + jcomp->jpeg_markers = V4L2_JPEG_MARKER_DHT + | V4L2_JPEG_MARKER_DQT; + return 0; +} + /* sub-driver description */ static const struct sd_desc sd_desc = { .name = MODULE_NAME, @@ -456,6 +487,8 @@ static const struct sd_desc sd_desc = { .stopN = sd_stopN, .stop0 = sd_stop0, .pkt_scan = sd_pkt_scan, + .get_jcomp = sd_get_jcomp, + .set_jcomp = sd_set_jcomp, }; /* -- module initialisation -- */ diff --git a/drivers/media/video/gspca/sonixj.c b/drivers/media/video/gspca/sonixj.c index 363c0fa39d9e..7d0d949b72ba 100644 --- a/drivers/media/video/gspca/sonixj.c +++ b/drivers/media/video/gspca/sonixj.c @@ -47,6 +47,9 @@ struct sd { u8 vflip; /* ov7630/ov7648 only */ u8 infrared; /* mt9v111 only */ u8 quality; /* image quality */ +#define QUALITY_MIN 60 +#define QUALITY_MAX 95 +#define QUALITY_DEF 80 u8 jpegqual; /* webcam quality */ u8 reg18; @@ -1295,7 +1298,7 @@ static int sd_config(struct gspca_dev *gspca_dev, else sd->vflip = 1; sd->infrared = INFRARED_DEF; - sd->quality = 80; + sd->quality = QUALITY_DEF; sd->jpegqual = 80; gspca_dev->ctrl_dis = ctrl_dis[sd->sensor]; @@ -2130,6 +2133,34 @@ static int sd_getinfrared(struct gspca_dev *gspca_dev, __s32 *val) return 0; } +static int sd_set_jcomp(struct gspca_dev *gspca_dev, + struct v4l2_jpegcompression *jcomp) +{ + struct sd *sd = (struct sd *) gspca_dev; + + if (jcomp->quality < QUALITY_MIN) + sd->quality = QUALITY_MIN; + else if (jcomp->quality > QUALITY_MAX) + sd->quality = QUALITY_MAX; + else + sd->quality = jcomp->quality; + if (gspca_dev->streaming) + jpeg_set_qual(sd->jpeg_hdr, sd->quality); + return 0; +} + +static int sd_get_jcomp(struct gspca_dev *gspca_dev, + struct v4l2_jpegcompression *jcomp) +{ + struct sd *sd = (struct sd *) gspca_dev; + + memset(jcomp, 0, sizeof *jcomp); + jcomp->quality = sd->quality; + jcomp->jpeg_markers = V4L2_JPEG_MARKER_DHT + | V4L2_JPEG_MARKER_DQT; + return 0; +} + /* sub-driver description */ static const struct sd_desc sd_desc = { .name = MODULE_NAME, @@ -2142,6 +2173,8 @@ static const struct sd_desc sd_desc = { .stop0 = sd_stop0, .pkt_scan = sd_pkt_scan, .dq_callback = do_autogain, + .get_jcomp = sd_get_jcomp, + .set_jcomp = sd_set_jcomp, }; /* -- module initialisation -- */ diff --git a/drivers/media/video/gspca/spca500.c b/drivers/media/video/gspca/spca500.c index 2176ac6850e3..6f38fa6d86b6 100644 --- a/drivers/media/video/gspca/spca500.c +++ b/drivers/media/video/gspca/spca500.c @@ -39,6 +39,9 @@ struct sd { unsigned char contrast; unsigned char colors; u8 quality; +#define QUALITY_MIN 70 +#define QUALITY_MAX 95 +#define QUALITY_DEF 85 char subtype; #define AgfaCl20 0 @@ -642,7 +645,7 @@ static int sd_config(struct gspca_dev *gspca_dev, sd->brightness = BRIGHTNESS_DEF; sd->contrast = CONTRAST_DEF; sd->colors = COLOR_DEF; - sd->quality = 85; + sd->quality = QUALITY_DEF; return 0; } @@ -1021,6 +1024,34 @@ static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val) return 0; } +static int sd_set_jcomp(struct gspca_dev *gspca_dev, + struct v4l2_jpegcompression *jcomp) +{ + struct sd *sd = (struct sd *) gspca_dev; + + if (jcomp->quality < QUALITY_MIN) + sd->quality = QUALITY_MIN; + else if (jcomp->quality > QUALITY_MAX) + sd->quality = QUALITY_MAX; + else + sd->quality = jcomp->quality; + if (gspca_dev->streaming) + jpeg_set_qual(sd->jpeg_hdr, sd->quality); + return 0; +} + +static int sd_get_jcomp(struct gspca_dev *gspca_dev, + struct v4l2_jpegcompression *jcomp) +{ + struct sd *sd = (struct sd *) gspca_dev; + + memset(jcomp, 0, sizeof *jcomp); + jcomp->quality = sd->quality; + jcomp->jpeg_markers = V4L2_JPEG_MARKER_DHT + | V4L2_JPEG_MARKER_DQT; + return 0; +} + /* sub-driver description */ static struct sd_desc sd_desc = { .name = MODULE_NAME, @@ -1032,6 +1063,8 @@ static struct sd_desc sd_desc = { .stopN = sd_stopN, .stop0 = sd_stop0, .pkt_scan = sd_pkt_scan, + .get_jcomp = sd_get_jcomp, + .set_jcomp = sd_set_jcomp, }; /* -- module initialisation -- */ diff --git a/drivers/media/video/gspca/stk014.c b/drivers/media/video/gspca/stk014.c index dd007cb52006..f25be20cf1a6 100644 --- a/drivers/media/video/gspca/stk014.c +++ b/drivers/media/video/gspca/stk014.c @@ -36,6 +36,9 @@ struct sd { unsigned char colors; unsigned char lightfreq; u8 quality; +#define QUALITY_MIN 60 +#define QUALITY_MAX 95 +#define QUALITY_DEF 80 u8 *jpeg_hdr; }; @@ -301,7 +304,7 @@ static int sd_config(struct gspca_dev *gspca_dev, sd->contrast = CONTRAST_DEF; sd->colors = COLOR_DEF; sd->lightfreq = FREQ_DEF; - sd->quality = 80; + sd->quality = QUALITY_DEF; return 0; } @@ -535,6 +538,34 @@ static int sd_querymenu(struct gspca_dev *gspca_dev, return -EINVAL; } +static int sd_set_jcomp(struct gspca_dev *gspca_dev, + struct v4l2_jpegcompression *jcomp) +{ + struct sd *sd = (struct sd *) gspca_dev; + + if (jcomp->quality < QUALITY_MIN) + sd->quality = QUALITY_MIN; + else if (jcomp->quality > QUALITY_MAX) + sd->quality = QUALITY_MAX; + else + sd->quality = jcomp->quality; + if (gspca_dev->streaming) + jpeg_set_qual(sd->jpeg_hdr, sd->quality); + return 0; +} + +static int sd_get_jcomp(struct gspca_dev *gspca_dev, + struct v4l2_jpegcompression *jcomp) +{ + struct sd *sd = (struct sd *) gspca_dev; + + memset(jcomp, 0, sizeof *jcomp); + jcomp->quality = sd->quality; + jcomp->jpeg_markers = V4L2_JPEG_MARKER_DHT + | V4L2_JPEG_MARKER_DQT; + return 0; +} + /* sub-driver description */ static const struct sd_desc sd_desc = { .name = MODULE_NAME, @@ -547,6 +578,8 @@ static const struct sd_desc sd_desc = { .stop0 = sd_stop0, .pkt_scan = sd_pkt_scan, .querymenu = sd_querymenu, + .get_jcomp = sd_get_jcomp, + .set_jcomp = sd_set_jcomp, }; /* -- module initialisation -- */ diff --git a/drivers/media/video/gspca/sunplus.c b/drivers/media/video/gspca/sunplus.c index eadfaa9f97d2..c2b8c10c075a 100644 --- a/drivers/media/video/gspca/sunplus.c +++ b/drivers/media/video/gspca/sunplus.c @@ -40,6 +40,9 @@ struct sd { unsigned char colors; unsigned char autogain; u8 quality; +#define QUALITY_MIN 70 +#define QUALITY_MAX 95 +#define QUALITY_DEF 85 char bridge; #define BRIDGE_SPCA504 0 @@ -854,7 +857,7 @@ static int sd_config(struct gspca_dev *gspca_dev, sd->brightness = sd_ctrls[SD_BRIGHTNESS].qctrl.default_value; sd->contrast = sd_ctrls[SD_CONTRAST].qctrl.default_value; sd->colors = sd_ctrls[SD_COLOR].qctrl.default_value; - sd->quality = 85; + sd->quality = QUALITY_DEF; return 0; } @@ -1319,6 +1322,34 @@ static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val) return 0; } +static int sd_set_jcomp(struct gspca_dev *gspca_dev, + struct v4l2_jpegcompression *jcomp) +{ + struct sd *sd = (struct sd *) gspca_dev; + + if (jcomp->quality < QUALITY_MIN) + sd->quality = QUALITY_MIN; + else if (jcomp->quality > QUALITY_MAX) + sd->quality = QUALITY_MAX; + else + sd->quality = jcomp->quality; + if (gspca_dev->streaming) + jpeg_set_qual(sd->jpeg_hdr, sd->quality); + return 0; +} + +static int sd_get_jcomp(struct gspca_dev *gspca_dev, + struct v4l2_jpegcompression *jcomp) +{ + struct sd *sd = (struct sd *) gspca_dev; + + memset(jcomp, 0, sizeof *jcomp); + jcomp->quality = sd->quality; + jcomp->jpeg_markers = V4L2_JPEG_MARKER_DHT + | V4L2_JPEG_MARKER_DQT; + return 0; +} + /* sub-driver description */ static const struct sd_desc sd_desc = { .name = MODULE_NAME, @@ -1330,6 +1361,8 @@ static const struct sd_desc sd_desc = { .stopN = sd_stopN, .stop0 = sd_stop0, .pkt_scan = sd_pkt_scan, + .get_jcomp = sd_get_jcomp, + .set_jcomp = sd_set_jcomp, }; /* -- module initialisation -- */ diff --git a/drivers/media/video/gspca/zc3xx.c b/drivers/media/video/gspca/zc3xx.c index a4c673ff8f02..e4c27a1e1e29 100644 --- a/drivers/media/video/gspca/zc3xx.c +++ b/drivers/media/video/gspca/zc3xx.c @@ -46,6 +46,9 @@ struct sd { __u8 lightfreq; __u8 sharpness; u8 quality; /* image quality */ +#define QUALITY_MIN 40 +#define QUALITY_MAX 60 +#define QUALITY_DEF 50 signed char sensor; /* Type of image sensor chip */ /* !! values used in different tables */ @@ -7180,7 +7183,7 @@ static int sd_config(struct gspca_dev *gspca_dev, sd->gamma = gamma[(int) sd->sensor]; sd->autogain = sd_ctrls[SD_AUTOGAIN].qctrl.default_value; sd->lightfreq = sd_ctrls[SD_FREQ].qctrl.default_value; - sd->quality = 50; + sd->quality = QUALITY_DEF; switch (sd->sensor) { case SENSOR_GC0305: @@ -7536,6 +7539,34 @@ static int sd_querymenu(struct gspca_dev *gspca_dev, return -EINVAL; } +static int sd_set_jcomp(struct gspca_dev *gspca_dev, + struct v4l2_jpegcompression *jcomp) +{ + struct sd *sd = (struct sd *) gspca_dev; + + if (jcomp->quality < QUALITY_MIN) + sd->quality = QUALITY_MIN; + else if (jcomp->quality > QUALITY_MAX) + sd->quality = QUALITY_MAX; + else + sd->quality = jcomp->quality; + if (gspca_dev->streaming) + jpeg_set_qual(sd->jpeg_hdr, sd->quality); + return 0; +} + +static int sd_get_jcomp(struct gspca_dev *gspca_dev, + struct v4l2_jpegcompression *jcomp) +{ + struct sd *sd = (struct sd *) gspca_dev; + + memset(jcomp, 0, sizeof *jcomp); + jcomp->quality = sd->quality; + jcomp->jpeg_markers = V4L2_JPEG_MARKER_DHT + | V4L2_JPEG_MARKER_DQT; + return 0; +} + static const struct sd_desc sd_desc = { .name = MODULE_NAME, .ctrls = sd_ctrls, @@ -7546,6 +7577,8 @@ static const struct sd_desc sd_desc = { .stop0 = sd_stop0, .pkt_scan = sd_pkt_scan, .querymenu = sd_querymenu, + .get_jcomp = sd_get_jcomp, + .set_jcomp = sd_set_jcomp, }; static const __devinitdata struct usb_device_id device_table[] = { -- cgit v1.2.3 From ae6cfaace120f4330715b56265ce0e4a710e1276 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sat, 14 Mar 2009 08:28:45 -0300 Subject: V4L/DVB (11044): v4l2-device: add v4l2_device_disconnect Call v4l2_device_disconnect when the parent of a hotpluggable device disconnects. This ensures that you do not have a pointer to a device that is no longer present. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- Documentation/video4linux/CARDLIST.bttv | 1 - Documentation/video4linux/v4l2-framework.txt | 11 +++++++++++ drivers/media/video/v4l2-device.c | 15 +++++++++++---- include/media/v4l2-device.h | 6 +++++- 4 files changed, 27 insertions(+), 6 deletions(-) (limited to 'drivers/media/video') diff --git a/Documentation/video4linux/CARDLIST.bttv b/Documentation/video4linux/CARDLIST.bttv index f11c583295e9..e17750473e08 100644 --- a/Documentation/video4linux/CARDLIST.bttv +++ b/Documentation/video4linux/CARDLIST.bttv @@ -157,4 +157,3 @@ 156 -> IVCE-8784 [0000:f050,0001:f050,0002:f050,0003:f050] 157 -> Geovision GV-800(S) (master) [800a:763d] 158 -> Geovision GV-800(S) (slave) [800b:763d,800c:763d,800d:763d] -159 -> ProVideo PV183 [1830:1540,1831:1540,1832:1540,1833:1540,1834:1540,1835:1540,1836:1540,1837:1540] diff --git a/Documentation/video4linux/v4l2-framework.txt b/Documentation/video4linux/v4l2-framework.txt index 4207590b2ac8..a31177390e55 100644 --- a/Documentation/video4linux/v4l2-framework.txt +++ b/Documentation/video4linux/v4l2-framework.txt @@ -105,6 +105,17 @@ You unregister with: Unregistering will also automatically unregister all subdevs from the device. +If you have a hotpluggable device (e.g. a USB device), then when a disconnect +happens the parent device becomes invalid. Since v4l2_device has a pointer to +that parent device it has to be cleared as well to mark that the parent is +gone. To do this call: + + v4l2_device_disconnect(struct v4l2_device *v4l2_dev); + +This does *not* unregister the subdevs, so you still need to call the +v4l2_device_unregister() function for that. If your driver is not hotpluggable, +then there is no need to call v4l2_device_disconnect(). + Sometimes you need to iterate over all devices registered by a specific driver. This is usually the case if multiple device drivers use the same hardware. E.g. the ivtvfb driver is a framebuffer driver that uses the ivtv diff --git a/drivers/media/video/v4l2-device.c b/drivers/media/video/v4l2-device.c index b3dcb8454379..94aa485ade52 100644 --- a/drivers/media/video/v4l2-device.c +++ b/drivers/media/video/v4l2-device.c @@ -49,19 +49,26 @@ int v4l2_device_register(struct device *dev, struct v4l2_device *v4l2_dev) } EXPORT_SYMBOL_GPL(v4l2_device_register); +void v4l2_device_disconnect(struct v4l2_device *v4l2_dev) +{ + if (v4l2_dev->dev) { + dev_set_drvdata(v4l2_dev->dev, NULL); + v4l2_dev->dev = NULL; + } +} +EXPORT_SYMBOL_GPL(v4l2_device_disconnect); + void v4l2_device_unregister(struct v4l2_device *v4l2_dev) { struct v4l2_subdev *sd, *next; if (v4l2_dev == NULL) return; - if (v4l2_dev->dev) - dev_set_drvdata(v4l2_dev->dev, NULL); + v4l2_device_disconnect(v4l2_dev); + /* Unregister subdevs */ list_for_each_entry_safe(sd, next, &v4l2_dev->subdevs, list) v4l2_device_unregister_subdev(sd); - - v4l2_dev->dev = NULL; } EXPORT_SYMBOL_GPL(v4l2_device_unregister); diff --git a/include/media/v4l2-device.h b/include/media/v4l2-device.h index 3d8e96f6ceb3..0dd3e8e8653e 100644 --- a/include/media/v4l2-device.h +++ b/include/media/v4l2-device.h @@ -53,7 +53,11 @@ struct v4l2_device { dev may be NULL in rare cases (ISA devices). In that case you must fill in the v4l2_dev->name field before calling this function. */ int __must_check v4l2_device_register(struct device *dev, struct v4l2_device *v4l2_dev); -/* Set v4l2_dev->dev->driver_data to NULL and unregister all sub-devices */ +/* Set v4l2_dev->dev to NULL. Call when the USB parent disconnects. + Since the parent disappears this ensures that v4l2_dev doesn't have an + invalid parent pointer. */ +void v4l2_device_disconnect(struct v4l2_device *v4l2_dev); +/* Unregister all sub-devices and any other resources related to v4l2_dev. */ void v4l2_device_unregister(struct v4l2_device *v4l2_dev); /* Register a subdev with a v4l2 device. While registered the subdev module -- cgit v1.2.3 From f1ba28c3a6e472742cbd73b05b807684e5d56b5a Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sat, 14 Mar 2009 12:27:01 -0300 Subject: V4L/DVB (11045): v4l2: call v4l2_device_disconnect in USB drivers. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/usbvision/usbvision-video.c | 2 ++ drivers/media/video/w9968cf.c | 4 +++- 2 files changed, 5 insertions(+), 1 deletion(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/usbvision/usbvision-video.c b/drivers/media/video/usbvision/usbvision-video.c index 3d400e4b7a27..74a7652dee43 100644 --- a/drivers/media/video/usbvision/usbvision-video.c +++ b/drivers/media/video/usbvision/usbvision-video.c @@ -1771,6 +1771,8 @@ static void __devexit usbvision_disconnect(struct usb_interface *intf) // At this time we ask to cancel outstanding URBs usbvision_stop_isoc(usbvision); + v4l2_device_disconnect(&usbvision->v4l2_dev); + if (usbvision->power) { usbvision_i2c_unregister(usbvision); usbvision_power_off(usbvision); diff --git a/drivers/media/video/w9968cf.c b/drivers/media/video/w9968cf.c index 2a25580a4b66..3b08bc4af909 100644 --- a/drivers/media/video/w9968cf.c +++ b/drivers/media/video/w9968cf.c @@ -3557,7 +3557,9 @@ static void w9968cf_usb_disconnect(struct usb_interface* intf) cam->disconnected = 1; - DBG(2, "Disconnecting %s...", symbolic(camlist, cam->id)) + DBG(2, "Disconnecting %s...", symbolic(camlist, cam->id)); + + v4l2_device_disconnect(&cam->v4l2_dev); wake_up_interruptible_all(&cam->open); -- cgit v1.2.3 From 74fc7bd9cec0ccdbea23659208492ec7ffc58297 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sat, 14 Mar 2009 12:36:54 -0300 Subject: V4L/DVB (11046): bttv: convert to v4l2_device. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/bt8xx/dvb-bt8xx.c | 2 +- drivers/media/video/bt8xx/bttv-driver.c | 47 ++++++++++++++++++++++----------- drivers/media/video/bt8xx/bttv-i2c.c | 10 ++++--- drivers/media/video/bt8xx/bttv.h | 3 ++- drivers/media/video/bt8xx/bttvp.h | 5 ++++ 5 files changed, 45 insertions(+), 22 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/dvb/bt8xx/dvb-bt8xx.c b/drivers/media/dvb/bt8xx/dvb-bt8xx.c index 48762a2b9e42..b1857c19bbd2 100644 --- a/drivers/media/dvb/bt8xx/dvb-bt8xx.c +++ b/drivers/media/dvb/bt8xx/dvb-bt8xx.c @@ -814,7 +814,7 @@ static int __devinit dvb_bt8xx_probe(struct bttv_sub_device *sub) mutex_init(&card->lock); card->bttv_nr = sub->core->nr; - strncpy(card->card_name, sub->core->name, sizeof(sub->core->name)); + strlcpy(card->card_name, sub->core->v4l2_dev.name, sizeof(card->card_name)); card->i2c_adapter = &sub->core->i2c_adap; switch(sub->core->type) { diff --git a/drivers/media/video/bt8xx/bttv-driver.c b/drivers/media/video/bt8xx/bttv-driver.c index b5fc3cc61888..3079d925e4cf 100644 --- a/drivers/media/video/bt8xx/bttv-driver.c +++ b/drivers/media/video/bt8xx/bttv-driver.c @@ -167,7 +167,7 @@ static ssize_t show_card(struct device *cd, struct device_attribute *attr, char *buf) { struct video_device *vfd = container_of(cd, struct video_device, dev); - struct bttv *btv = dev_get_drvdata(vfd->parent); + struct bttv *btv = video_get_drvdata(vfd); return sprintf(buf, "%d\n", btv ? btv->c.type : UNSET); } static DEVICE_ATTR(card, S_IRUGO, show_card, NULL); @@ -3692,14 +3692,14 @@ static void bttv_risc_disasm(struct bttv *btv, unsigned int i,j,n; printk("%s: risc disasm: %p [dma=0x%08lx]\n", - btv->c.name, risc->cpu, (unsigned long)risc->dma); + btv->c.v4l2_dev.name, risc->cpu, (unsigned long)risc->dma); for (i = 0; i < (risc->size >> 2); i += n) { - printk("%s: 0x%lx: ", btv->c.name, + printk("%s: 0x%lx: ", btv->c.v4l2_dev.name, (unsigned long)(risc->dma + (i<<2))); n = bttv_risc_decode(le32_to_cpu(risc->cpu[i])); for (j = 1; j < n; j++) printk("%s: 0x%lx: 0x%08x [ arg #%d ]\n", - btv->c.name, (unsigned long)(risc->dma + ((i+j)<<2)), + btv->c.v4l2_dev.name, (unsigned long)(risc->dma + ((i+j)<<2)), risc->cpu[i+j], j); if (0 == risc->cpu[i]) break; @@ -4175,7 +4175,7 @@ static struct video_device *vdev_init(struct bttv *btv, return NULL; *vfd = *template; vfd->minor = -1; - vfd->parent = &btv->c.pci->dev; + vfd->v4l2_dev = &btv->c.v4l2_dev; vfd->release = video_device_release; vfd->debug = bttv_debug; video_set_drvdata(vfd, btv); @@ -4289,8 +4289,13 @@ static int __devinit bttv_probe(struct pci_dev *dev, return -ENOMEM; printk(KERN_INFO "bttv: Bt8xx card found (%d).\n", bttv_num); bttvs[bttv_num] = btv = kzalloc(sizeof(*btv), GFP_KERNEL); + if (btv == NULL) { + printk(KERN_ERR "bttv: out of memory.\n"); + return -ENOMEM; + } btv->c.nr = bttv_num; - sprintf(btv->c.name,"bttv%d",btv->c.nr); + snprintf(btv->c.v4l2_dev.name, sizeof(btv->c.v4l2_dev.name), + "bttv%d", btv->c.nr); /* initialize structs / fill in defaults */ mutex_init(&btv->lock); @@ -4327,7 +4332,7 @@ static int __devinit bttv_probe(struct pci_dev *dev, } if (!request_mem_region(pci_resource_start(dev,0), pci_resource_len(dev,0), - btv->c.name)) { + btv->c.v4l2_dev.name)) { printk(KERN_WARNING "bttv%d: can't request iomem (0x%llx).\n", btv->c.nr, (unsigned long long)pci_resource_start(dev,0)); @@ -4335,7 +4340,12 @@ static int __devinit bttv_probe(struct pci_dev *dev, } pci_set_master(dev); pci_set_command(dev); - pci_set_drvdata(dev,btv); + + result = v4l2_device_register(&dev->dev, &btv->c.v4l2_dev); + if (result < 0) { + printk(KERN_WARNING "bttv%d: v4l2_device_register() failed\n", btv->c.nr); + goto fail0; + } pci_read_config_byte(dev, PCI_CLASS_REVISION, &btv->revision); pci_read_config_byte(dev, PCI_LATENCY_TIMER, &lat); @@ -4359,7 +4369,7 @@ static int __devinit bttv_probe(struct pci_dev *dev, /* disable irqs, register irq handler */ btwrite(0, BT848_INT_MASK); result = request_irq(btv->c.pci->irq, bttv_irq, - IRQF_SHARED | IRQF_DISABLED,btv->c.name,(void *)btv); + IRQF_SHARED | IRQF_DISABLED, btv->c.v4l2_dev.name, (void *)btv); if (result < 0) { printk(KERN_ERR "bttv%d: can't get IRQ %d\n", bttv_num,btv->c.pci->irq); @@ -4443,21 +4453,24 @@ static int __devinit bttv_probe(struct pci_dev *dev, bttv_num++; return 0; - fail2: +fail2: free_irq(btv->c.pci->irq,btv); - fail1: +fail1: + v4l2_device_unregister(&btv->c.v4l2_dev); + +fail0: if (btv->bt848_mmio) iounmap(btv->bt848_mmio); release_mem_region(pci_resource_start(btv->c.pci,0), pci_resource_len(btv->c.pci,0)); - pci_set_drvdata(dev,NULL); return result; } static void __devexit bttv_remove(struct pci_dev *pci_dev) { - struct bttv *btv = pci_get_drvdata(pci_dev); + struct v4l2_device *v4l2_dev = pci_get_drvdata(pci_dev); + struct bttv *btv = to_bttv(v4l2_dev); if (bttv_verbose) printk("bttv%d: unloading\n",btv->c.nr); @@ -4491,7 +4504,7 @@ static void __devexit bttv_remove(struct pci_dev *pci_dev) release_mem_region(pci_resource_start(btv->c.pci,0), pci_resource_len(btv->c.pci,0)); - pci_set_drvdata(pci_dev, NULL); + v4l2_device_unregister(&btv->c.v4l2_dev); bttvs[btv->c.nr] = NULL; kfree(btv); @@ -4501,7 +4514,8 @@ static void __devexit bttv_remove(struct pci_dev *pci_dev) #ifdef CONFIG_PM static int bttv_suspend(struct pci_dev *pci_dev, pm_message_t state) { - struct bttv *btv = pci_get_drvdata(pci_dev); + struct v4l2_device *v4l2_dev = pci_get_drvdata(pci_dev); + struct bttv *btv = to_bttv(v4l2_dev); struct bttv_buffer_set idle; unsigned long flags; @@ -4536,7 +4550,8 @@ static int bttv_suspend(struct pci_dev *pci_dev, pm_message_t state) static int bttv_resume(struct pci_dev *pci_dev) { - struct bttv *btv = pci_get_drvdata(pci_dev); + struct v4l2_device *v4l2_dev = pci_get_drvdata(pci_dev); + struct bttv *btv = to_bttv(v4l2_dev); unsigned long flags; int err; diff --git a/drivers/media/video/bt8xx/bttv-i2c.c b/drivers/media/video/bt8xx/bttv-i2c.c index 511d2bf176f1..9b66c5b09321 100644 --- a/drivers/media/video/bt8xx/bttv-i2c.c +++ b/drivers/media/video/bt8xx/bttv-i2c.c @@ -231,7 +231,8 @@ bttv_i2c_readbytes(struct bttv *btv, const struct i2c_msg *msg, int last) static int bttv_i2c_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg *msgs, int num) { - struct bttv *btv = i2c_get_adapdata(i2c_adap); + struct v4l2_device *v4l2_dev = i2c_get_adapdata(i2c_adap); + struct bttv *btv = to_bttv(v4l2_dev); int retval = 0; int i; @@ -267,7 +268,8 @@ static const struct i2c_algorithm bttv_algo = { static int attach_inform(struct i2c_client *client) { - struct bttv *btv = i2c_get_adapdata(client->adapter); + struct v4l2_device *v4l2_dev = i2c_get_adapdata(client->adapter); + struct bttv *btv = to_bttv(v4l2_dev); int addr=ADDR_UNSET; @@ -423,7 +425,7 @@ int __devinit init_bttv_i2c(struct bttv *btv) "bt%d #%d [%s]", btv->id, btv->c.nr, btv->use_i2c_hw ? "hw" : "sw"); - i2c_set_adapdata(&btv->c.i2c_adap, btv); + i2c_set_adapdata(&btv->c.i2c_adap, &btv->c.v4l2_dev); btv->i2c_client.adapter = &btv->c.i2c_adap; if (bttv_tvcards[btv->c.type].no_video) @@ -439,7 +441,7 @@ int __devinit init_bttv_i2c(struct bttv *btv) btv->i2c_rc = i2c_bit_add_bus(&btv->c.i2c_adap); } if (0 == btv->i2c_rc && i2c_scan) - do_i2c_scan(btv->c.name,&btv->i2c_client); + do_i2c_scan(btv->c.v4l2_dev.name, &btv->i2c_client); return btv->i2c_rc; } diff --git a/drivers/media/video/bt8xx/bttv.h b/drivers/media/video/bt8xx/bttv.h index e08719b378bd..85b0e3e9d382 100644 --- a/drivers/media/video/bt8xx/bttv.h +++ b/drivers/media/video/bt8xx/bttv.h @@ -16,6 +16,7 @@ #include #include +#include #include #include #include @@ -196,6 +197,7 @@ struct bttv_core { /* device structs */ + struct v4l2_device v4l2_dev; struct pci_dev *pci; struct i2c_adapter i2c_adap; struct list_head subs; /* struct bttv_sub_device */ @@ -203,7 +205,6 @@ struct bttv_core { /* device config */ unsigned int nr; /* dev nr (for printk("bttv%d: ..."); */ unsigned int type; /* card type (pointer into tvcards[]) */ - char name[8]; /* dev name */ }; struct bttv; diff --git a/drivers/media/video/bt8xx/bttvp.h b/drivers/media/video/bt8xx/bttvp.h index 2c0a2cc61d03..5755b407c0a2 100644 --- a/drivers/media/video/bt8xx/bttvp.h +++ b/drivers/media/video/bt8xx/bttvp.h @@ -458,6 +458,11 @@ struct bttv { __s32 crop_start; }; +static inline struct bttv *to_bttv(struct v4l2_device *v4l2_dev) +{ + return container_of(v4l2_dev, struct bttv, c.v4l2_dev); +} + /* our devices */ #define BTTV_MAX 32 extern unsigned int bttv_num; -- cgit v1.2.3 From 9467fe126451c7fc7878d21f3cd1938421ef972e Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sat, 14 Mar 2009 12:40:51 -0300 Subject: V4L/DVB (11047): cx88: convert to v4l2_device. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx88/cx88-cards.c | 8 ++++++++ drivers/media/video/cx88/cx88-core.c | 4 +++- drivers/media/video/cx88/cx88-i2c.c | 8 +++++--- drivers/media/video/cx88/cx88.h | 8 +++++++- 4 files changed, 23 insertions(+), 5 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/cx88/cx88-cards.c b/drivers/media/video/cx88/cx88-cards.c index 1d7e3a562995..b9def8cbcdab 100644 --- a/drivers/media/video/cx88/cx88-cards.c +++ b/drivers/media/video/cx88/cx88-cards.c @@ -3138,7 +3138,15 @@ struct cx88_core *cx88_core_create(struct pci_dev *pci, int nr) core->nr = nr; sprintf(core->name, "cx88[%d]", core->nr); + + strcpy(core->v4l2_dev.name, core->name); + if (v4l2_device_register(NULL, &core->v4l2_dev)) { + kfree(core); + return NULL; + } + if (0 != cx88_get_resources(core, pci)) { + v4l2_device_unregister(&core->v4l2_dev); kfree(core); return NULL; } diff --git a/drivers/media/video/cx88/cx88-core.c b/drivers/media/video/cx88/cx88-core.c index b045874ad04f..17c7dad42617 100644 --- a/drivers/media/video/cx88/cx88-core.c +++ b/drivers/media/video/cx88/cx88-core.c @@ -1011,7 +1011,8 @@ struct video_device *cx88_vdev_init(struct cx88_core *core, return NULL; *vfd = *template; vfd->minor = -1; - vfd->parent = &pci->dev; + vfd->v4l2_dev = &core->v4l2_dev; + vfd->parent = &pci->dev; vfd->release = video_device_release; snprintf(vfd->name, sizeof(vfd->name), "%s %s (%s)", core->name, type, core->board.name); @@ -1064,6 +1065,7 @@ void cx88_core_put(struct cx88_core *core, struct pci_dev *pci) iounmap(core->lmmio); cx88_devcount--; mutex_unlock(&devlist); + v4l2_device_unregister(&core->v4l2_dev); kfree(core); } diff --git a/drivers/media/video/cx88/cx88-i2c.c b/drivers/media/video/cx88/cx88-i2c.c index c0ff2305d804..4a17a7579323 100644 --- a/drivers/media/video/cx88/cx88-i2c.c +++ b/drivers/media/video/cx88/cx88-i2c.c @@ -99,7 +99,8 @@ static int cx8800_bit_getsda(void *data) static int attach_inform(struct i2c_client *client) { - struct cx88_core *core = i2c_get_adapdata(client->adapter); + struct v4l2_device *v4l2_dev = i2c_get_adapdata(client->adapter); + struct cx88_core *core = to_core(v4l2_dev); dprintk(1, "%s i2c attach [addr=0x%x,client=%s]\n", client->driver->driver.name, client->addr, client->name); @@ -108,7 +109,8 @@ static int attach_inform(struct i2c_client *client) static int detach_inform(struct i2c_client *client) { - struct cx88_core *core = i2c_get_adapdata(client->adapter); + struct v4l2_device *v4l2_dev = i2c_get_adapdata(client->adapter); + struct cx88_core *core = to_core(v4l2_dev); dprintk(1, "i2c detach [client=%s]\n", client->name); return 0; @@ -186,7 +188,7 @@ int cx88_i2c_init(struct cx88_core *core, struct pci_dev *pci) core->i2c_adap.client_unregister = detach_inform; core->i2c_algo.udelay = i2c_udelay; core->i2c_algo.data = core; - i2c_set_adapdata(&core->i2c_adap,core); + i2c_set_adapdata(&core->i2c_adap, &core->v4l2_dev); core->i2c_adap.algo_data = &core->i2c_algo; core->i2c_client.adapter = &core->i2c_adap; strlcpy(core->i2c_client.name, "cx88xx internal", I2C_NAME_SIZE); diff --git a/drivers/media/video/cx88/cx88.h b/drivers/media/video/cx88/cx88.h index 303d8d20fc91..890018c48cd8 100644 --- a/drivers/media/video/cx88/cx88.h +++ b/drivers/media/video/cx88/cx88.h @@ -25,7 +25,7 @@ #include #include -#include +#include #include #include #include @@ -327,6 +327,7 @@ struct cx88_core { u32 i2c_state, i2c_rc; /* config info -- analog */ + struct v4l2_device v4l2_dev; unsigned int boardnr; struct cx88_board board; @@ -365,6 +366,11 @@ struct cx88_core { int active_fe_id; }; +static inline struct cx88_core *to_core(struct v4l2_device *v4l2_dev) +{ + return container_of(v4l2_dev, struct cx88_core, v4l2_dev); +} + struct cx8800_dev; struct cx8802_dev; -- cgit v1.2.3 From 33470423aba5da982dc944658da232942824f2d5 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sat, 14 Mar 2009 12:53:37 -0300 Subject: V4L/DVB (11048): zoran: fix incorrect return type of notify function. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/zoran/zoran_card.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/zoran/zoran_card.c b/drivers/media/video/zoran/zoran_card.c index ec9b6ef56090..f91bba435ed5 100644 --- a/drivers/media/video/zoran/zoran_card.c +++ b/drivers/media/video/zoran/zoran_card.c @@ -1196,7 +1196,7 @@ zoran_setup_videocodec (struct zoran *zr, return m; } -static int zoran_subdev_notify(struct v4l2_subdev *sd, unsigned int cmd, void *arg) +static void zoran_subdev_notify(struct v4l2_subdev *sd, unsigned int cmd, void *arg) { struct zoran *zr = to_zoran(sd->v4l2_dev); @@ -1206,7 +1206,6 @@ static int zoran_subdev_notify(struct v4l2_subdev *sd, unsigned int cmd, void *a GPIO(zr, 7, 0); else if (cmd == BT819_FIFO_RESET_HIGH) GPIO(zr, 7, 1); - return 0; } /* -- cgit v1.2.3 From 15965f063d6d42bd451415923c4cccbdb4a61bdd Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sat, 14 Mar 2009 15:06:08 -0300 Subject: V4L/DVB (11051): v4l-dvb: replace remaining references to the old mailinglist. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- Documentation/video4linux/bttv/README | 4 ++-- drivers/media/radio/radio-si470x.c | 2 +- drivers/media/video/bt8xx/bttv-cards.c | 2 +- drivers/media/video/usbvision/usbvision.h | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers/media/video') diff --git a/Documentation/video4linux/bttv/README b/Documentation/video4linux/bttv/README index 7ca2154c2bf5..3a367cdb664e 100644 --- a/Documentation/video4linux/bttv/README +++ b/Documentation/video4linux/bttv/README @@ -63,8 +63,8 @@ If you have some knowledge and spare time, please try to fix this yourself (patches very welcome of course...) You know: The linux slogan is "Do it yourself". -There is a mailing list: video4linux-list@redhat.com. -https://listman.redhat.com/mailman/listinfo/video4linux-list +There is a mailing list: linux-media@vger.kernel.org +http://vger.kernel.org/vger-lists.html#linux-media If you have trouble with some specific TV card, try to ask there instead of mailing me directly. The chance that someone with the diff --git a/drivers/media/radio/radio-si470x.c b/drivers/media/radio/radio-si470x.c index 9827445086aa..713e242ba8b2 100644 --- a/drivers/media/radio/radio-si470x.c +++ b/drivers/media/radio/radio-si470x.c @@ -1713,7 +1713,7 @@ static int si470x_usb_driver_probe(struct usb_interface *intf, ": If you have some trouble using this driver,\n"); printk(KERN_WARNING DRIVER_NAME ": please report to V4L ML at " - "video4linux-list@redhat.com\n"); + "linux-media@vger.kernel.org\n"); } /* set initial frequency */ diff --git a/drivers/media/video/bt8xx/bttv-cards.c b/drivers/media/video/bt8xx/bttv-cards.c index 187ed4ef3993..7725d9487abf 100644 --- a/drivers/media/video/bt8xx/bttv-cards.c +++ b/drivers/media/video/bt8xx/bttv-cards.c @@ -2924,7 +2924,7 @@ void __devinit bttv_idcard(struct bttv *btv) btv->c.nr, btv->cardid & 0xffff, (btv->cardid >> 16) & 0xffff); printk(KERN_DEBUG "please mail id, board name and " - "the correct card= insmod option to video4linux-list@redhat.com\n"); + "the correct card= insmod option to linux-media@vger.kernel.org\n"); } } diff --git a/drivers/media/video/usbvision/usbvision.h b/drivers/media/video/usbvision/usbvision.h index 06fe43655957..f8d7458daf3e 100644 --- a/drivers/media/video/usbvision/usbvision.h +++ b/drivers/media/video/usbvision/usbvision.h @@ -6,7 +6,7 @@ * Dwaine Garden * * - * Report problems to v4l MailingList : http://www.redhat.com/mailman/listinfo/video4linux-list + * Report problems to v4l MailingList: linux-media@vger.kernel.org * * This module is part of usbvision driver project. * Updates to driver completed by Dwaine P. Garden -- cgit v1.2.3 From 1efd5261ff0b615c482c734e3fb11a75f671d8da Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sat, 14 Mar 2009 16:34:07 -0300 Subject: V4L/DVB (11052): bt819: remove an unused header Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/bt819.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/bt819.c b/drivers/media/video/bt819.c index 217294d56414..df4516d8dcab 100644 --- a/drivers/media/video/bt819.c +++ b/drivers/media/video/bt819.c @@ -32,7 +32,6 @@ #include #include #include -#include #include #include #include -- cgit v1.2.3 From b8ced13462cdb0e407831683b8e2c989b13db3ac Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sun, 15 Mar 2009 06:53:32 -0300 Subject: V4L/DVB (11053): saa7134: set v4l2_dev field of video_device The v4l2_dev field of video_device wasn't initialized. The parent field is derived from v4l2_dev, so that doesn't need to be set anymore. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/saa7134/saa7134-core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/saa7134/saa7134-core.c b/drivers/media/video/saa7134/saa7134-core.c index ac574452d01e..321f0d724485 100644 --- a/drivers/media/video/saa7134/saa7134-core.c +++ b/drivers/media/video/saa7134/saa7134-core.c @@ -776,7 +776,7 @@ static struct video_device *vdev_init(struct saa7134_dev *dev, return NULL; *vfd = *template; vfd->minor = -1; - vfd->parent = &dev->pci->dev; + vfd->v4l2_dev = &dev->v4l2_dev; vfd->release = video_device_release; vfd->debug = video_debug; snprintf(vfd->name, sizeof(vfd->name), "%s %s (%s)", -- cgit v1.2.3 From f1bee6994426c3a1435ee8d214b1c426a009784f Mon Sep 17 00:00:00 2001 From: Abylay Ospan Date: Tue, 17 Mar 2009 18:13:52 -0300 Subject: V4L/DVB (11056): Bug fix in NetUP: restore high address lines in CI CI high address lines disappears due to wrong data type used. Patch to fix it. Signed-off-by: Abylay Ospan Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx23885/cimax2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/cx23885/cimax2.c b/drivers/media/video/cx23885/cimax2.c index 2105c2e4cf46..9a6536998d90 100644 --- a/drivers/media/video/cx23885/cimax2.c +++ b/drivers/media/video/cx23885/cimax2.c @@ -157,7 +157,7 @@ int netup_ci_get_mem(struct cx23885_dev *dev) } int netup_ci_op_cam(struct dvb_ca_en50221 *en50221, int slot, - u8 flag, u8 read, u8 addr, u8 data) + u8 flag, u8 read, int addr, u8 data) { struct netup_ci_state *state = en50221->data; struct cx23885_tsport *port = state->priv; -- cgit v1.2.3 From ea2278633ab4728c41b4043f47df4d3e39131992 Mon Sep 17 00:00:00 2001 From: Devin Heitmueller Date: Wed, 11 Mar 2009 02:58:53 -0300 Subject: V4L/DVB (11059): xc5000: fix bug for hybrid xc5000 devices with IF other than 5380 The xc5000 driver has a bug where the IF is always set to whatever the first caller to dvb_attach() provides. This fails when the device requires an IF other than 5380 and the analog driver is loaded first through tuner-core (which always supplies the hard-coded value of 5380). Thanks to Michael Krufky and Steven Toth for providing sample hardware, engineering level support, and testing. Signed-off-by: Devin Heitmueller Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/common/tuners/xc5000.c | 9 +++++++-- drivers/media/video/tuner-core.c | 3 ++- 2 files changed, 9 insertions(+), 3 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/common/tuners/xc5000.c b/drivers/media/common/tuners/xc5000.c index ef4bdf2315f1..b54598550dc4 100644 --- a/drivers/media/common/tuners/xc5000.c +++ b/drivers/media/common/tuners/xc5000.c @@ -973,8 +973,6 @@ struct dvb_frontend *xc5000_attach(struct dvb_frontend *fe, case 1: /* new tuner instance */ priv->bandwidth = BANDWIDTH_6_MHZ; - priv->if_khz = cfg->if_khz; - fe->tuner_priv = priv; break; default: @@ -983,6 +981,13 @@ struct dvb_frontend *xc5000_attach(struct dvb_frontend *fe, break; } + if (priv->if_khz == 0) { + /* If the IF hasn't been set yet, use the value provided by + the caller (occurs in hybrid devices where the analog + call to xc5000_attach occurs before the digital side) */ + priv->if_khz = cfg->if_khz; + } + /* Check if firmware has been loaded. It is possible that another instance of the driver has loaded the firmware. */ diff --git a/drivers/media/video/tuner-core.c b/drivers/media/video/tuner-core.c index 30640fbfd0f9..2a957e2beabf 100644 --- a/drivers/media/video/tuner-core.c +++ b/drivers/media/video/tuner-core.c @@ -452,7 +452,8 @@ static void set_type(struct i2c_client *c, unsigned int type, struct dvb_tuner_ops *xc_tuner_ops; xc5000_cfg.i2c_address = t->i2c->addr; - xc5000_cfg.if_khz = 5380; + /* if_khz will be set when the digital dvb_attach() occurs */ + xc5000_cfg.if_khz = 0; if (!dvb_attach(xc5000_attach, &t->fe, t->i2c->adapter, &xc5000_cfg)) goto attach_failed; -- cgit v1.2.3 From 8b2f079523450fa2d65cbb3f8453820bf1e17533 Mon Sep 17 00:00:00 2001 From: Devin Heitmueller Date: Wed, 11 Mar 2009 03:00:40 -0300 Subject: V4L/DVB (11066): au0828: add support for analog functionality in bridge Add support for the analog functionality found in the au0828 bridge Thanks to Michael Krufky and Steven Toth for providing sample hardware, engineering level support, and testing. Signed-off-by: Devin Heitmueller Signed-off-by: Michael Krufky [mchehab@redhat.com: fix compilation by adding linux/version.h] Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/au0828/Makefile | 2 +- drivers/media/video/au0828/au0828-cards.c | 41 +- drivers/media/video/au0828/au0828-core.c | 33 +- drivers/media/video/au0828/au0828-reg.h | 6 + drivers/media/video/au0828/au0828-video.c | 1677 +++++++++++++++++++++++++++++ drivers/media/video/au0828/au0828.h | 174 ++- 6 files changed, 1920 insertions(+), 13 deletions(-) create mode 100644 drivers/media/video/au0828/au0828-video.c (limited to 'drivers/media/video') diff --git a/drivers/media/video/au0828/Makefile b/drivers/media/video/au0828/Makefile index cd2c58281b4e..4d2623158188 100644 --- a/drivers/media/video/au0828/Makefile +++ b/drivers/media/video/au0828/Makefile @@ -1,4 +1,4 @@ -au0828-objs := au0828-core.o au0828-i2c.o au0828-cards.o au0828-dvb.o +au0828-objs := au0828-core.o au0828-i2c.o au0828-cards.o au0828-dvb.o au0828-video.o obj-$(CONFIG_VIDEO_AU0828) += au0828.o diff --git a/drivers/media/video/au0828/au0828-cards.c b/drivers/media/video/au0828/au0828-cards.c index d60123b413f5..aa79e6b7ecab 100644 --- a/drivers/media/video/au0828/au0828-cards.c +++ b/drivers/media/video/au0828/au0828-cards.c @@ -21,6 +21,18 @@ #include "au0828.h" #include "au0828-cards.h" +#include "au8522.h" + +void hvr950q_cs5340_audio(void *priv, int enable) +{ + /* Because the HVR-950q shares an i2s bus between the cs5340 and the + au8522, we need to hold cs5340 in reset when using the au8522 */ + struct au0828_dev *dev = priv; + if (enable == 1) + au0828_set(dev, REG_000, 0x10); + else + au0828_clear(dev, REG_000, 0x10); +} struct au0828_board au0828_boards[] = { [AU0828_BOARD_UNKNOWN] = { @@ -31,6 +43,25 @@ struct au0828_board au0828_boards[] = { }, [AU0828_BOARD_HAUPPAUGE_HVR950Q] = { .name = "Hauppauge HVR950Q", + .input = { + { + .type = AU0828_VMUX_TELEVISION, + .vmux = AU8522_COMPOSITE_CH4_SIF, + .amux = AU8522_AUDIO_SIF, + }, + { + .type = AU0828_VMUX_COMPOSITE, + .vmux = AU8522_COMPOSITE_CH1, + .amux = AU8522_AUDIO_NONE, + .audio_setup = hvr950q_cs5340_audio, + }, + { + .type = AU0828_VMUX_SVIDEO, + .vmux = AU8522_SVIDEO_CH13, + .amux = AU8522_AUDIO_NONE, + .audio_setup = hvr950q_cs5340_audio, + }, + }, }, [AU0828_BOARD_HAUPPAUGE_HVR950Q_MXL] = { .name = "Hauppauge HVR950Q rev xxF8", @@ -144,21 +175,23 @@ void au0828_gpio_setup(struct au0828_dev *dev) * 4 - CS5340 * 5 - AU8522 Demodulator * 6 - eeprom W/P + * 7 - power supply * 9 - XC5000 Tuner */ /* Into reset */ au0828_write(dev, REG_003, 0x02); - au0828_write(dev, REG_002, 0x88 | 0x20); + au0828_write(dev, REG_002, 0x80 | 0x20 | 0x10); au0828_write(dev, REG_001, 0x0); au0828_write(dev, REG_000, 0x0); msleep(100); - /* Out of reset */ + /* Out of reset (leave the cs5340 in reset until needed) */ au0828_write(dev, REG_003, 0x02); au0828_write(dev, REG_001, 0x02); - au0828_write(dev, REG_002, 0x88 | 0x20); - au0828_write(dev, REG_000, 0x88 | 0x20 | 0x40); + au0828_write(dev, REG_002, 0x80 | 0x20 | 0x10); + au0828_write(dev, REG_000, 0x80 | 0x40 | 0x20); + msleep(250); break; case AU0828_BOARD_DVICO_FUSIONHDTV7: diff --git a/drivers/media/video/au0828/au0828-core.c b/drivers/media/video/au0828/au0828-core.c index 5765e8656376..680e88f61397 100644 --- a/drivers/media/video/au0828/au0828-core.c +++ b/drivers/media/video/au0828/au0828-core.c @@ -146,6 +146,8 @@ static void au0828_usb_disconnect(struct usb_interface *interface) /* Digital TV */ au0828_dvb_unregister(dev); + au0828_analog_unregister(dev); + /* I2C */ au0828_i2c_unregister(dev); @@ -162,9 +164,11 @@ static void au0828_usb_disconnect(struct usb_interface *interface) static int au0828_usb_probe(struct usb_interface *interface, const struct usb_device_id *id) { - int ifnum; + int ifnum, i; struct au0828_dev *dev; struct usb_device *usbdev = interface_to_usbdev(interface); + struct usb_host_interface *iface_desc; + struct usb_endpoint_descriptor *endpoint; ifnum = interface->altsetting->desc.bInterfaceNumber; @@ -189,6 +193,30 @@ static int au0828_usb_probe(struct usb_interface *interface, usb_set_intfdata(interface, dev); + /* set au0828 usb interface0 to as5 */ + usb_set_interface(usbdev, + interface->cur_altsetting->desc.bInterfaceNumber, 5); + + /* Figure out which endpoint has the isoc interface */ + iface_desc = interface->cur_altsetting; + for(i = 0; i < iface_desc->desc.bNumEndpoints; i++){ + endpoint = &iface_desc->endpoint[i].desc; + if(((endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_IN) && + ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_ISOC)){ + + /* we find our isoc in endpoint */ + u16 tmp = le16_to_cpu(endpoint->wMaxPacketSize); + dev->max_pkt_size = (tmp & 0x07ff) * (((tmp & 0x1800) >> 11) + 1); + dev->isoc_in_endpointaddr = endpoint->bEndpointAddress; + } + } + if(!(dev->isoc_in_endpointaddr)) { + printk("Could not locate isoc endpoint\n"); + kfree(dev); + return -ENODEV; + } + + /* Power Up the bridge */ au0828_write(dev, REG_600, 1 << 4); @@ -201,6 +229,9 @@ static int au0828_usb_probe(struct usb_interface *interface, /* Setup */ au0828_card_setup(dev); + /* Analog TV */ + au0828_analog_register(dev); + /* Digital TV */ au0828_dvb_register(dev); diff --git a/drivers/media/video/au0828/au0828-reg.h b/drivers/media/video/au0828/au0828-reg.h index 1e87fa0c6842..b15e4a3b6fc0 100644 --- a/drivers/media/video/au0828/au0828-reg.h +++ b/drivers/media/video/au0828/au0828-reg.h @@ -27,6 +27,9 @@ #define REG_002 0x002 #define REG_003 0x003 +#define AU0828_SENSORCTRL_100 0x100 +#define AU0828_SENSORCTRL_VBI_103 0x103 + #define REG_200 0x200 #define REG_201 0x201 #define REG_202 0x202 @@ -35,4 +38,7 @@ #define REG_209 0x209 #define REG_2FF 0x2ff +/* Audio registers */ +#define AU0828_AUDIOCTRL_50C 0x50C + #define REG_600 0x600 diff --git a/drivers/media/video/au0828/au0828-video.c b/drivers/media/video/au0828/au0828-video.c new file mode 100644 index 000000000000..e34464f81f36 --- /dev/null +++ b/drivers/media/video/au0828/au0828-video.c @@ -0,0 +1,1677 @@ +/* + * Auvitek AU0828 USB Bridge (Analog video support) + * + * Copyright (C) 2009 Devin Heitmueller + * Copyright (C) 2005-2008 Auvitek International, Ltd. + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +/* Developer Notes: + * + * VBI support is not yet working + * The hardware scaler supported is unimplemented + * AC97 audio support is unimplemented (only i2s audio mode) + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "au0828.h" +#include "au0828-reg.h" + +static LIST_HEAD(au0828_devlist); +static DEFINE_MUTEX(au0828_sysfs_lock); + +#define AU0828_VERSION_CODE KERNEL_VERSION(0, 0, 1) + +/* Forward declarations */ +void au0828_analog_stream_reset(struct au0828_dev *dev); + +/* ------------------------------------------------------------------ + Videobuf operations + ------------------------------------------------------------------*/ + +static unsigned int isoc_debug; +module_param(isoc_debug, int, 0644); +MODULE_PARM_DESC(isoc_debug, "enable debug messages [isoc transfers]"); + +#define au0828_isocdbg(fmt, arg...) \ +do {\ + if (isoc_debug) { \ + printk(KERN_INFO "au0828 %s :"fmt, \ + __func__ , ##arg); \ + } \ + } while (0) + +static inline void print_err_status(struct au0828_dev *dev, + int packet, int status) +{ + char *errmsg = "Unknown"; + + switch (status) { + case -ENOENT: + errmsg = "unlinked synchronuously"; + break; + case -ECONNRESET: + errmsg = "unlinked asynchronuously"; + break; + case -ENOSR: + errmsg = "Buffer error (overrun)"; + break; + case -EPIPE: + errmsg = "Stalled (device not responding)"; + break; + case -EOVERFLOW: + errmsg = "Babble (bad cable?)"; + break; + case -EPROTO: + errmsg = "Bit-stuff error (bad cable?)"; + break; + case -EILSEQ: + errmsg = "CRC/Timeout (could be anything)"; + break; + case -ETIME: + errmsg = "Device does not respond"; + break; + } + if (packet < 0) { + au0828_isocdbg("URB status %d [%s].\n", status, errmsg); + } else { + au0828_isocdbg("URB packet %d, status %d [%s].\n", + packet, status, errmsg); + } +} + +static int check_dev(struct au0828_dev *dev) +{ + if (dev->dev_state & DEV_DISCONNECTED) { + printk("v4l2 ioctl: device not present\n"); + return -ENODEV; + } + + if (dev->dev_state & DEV_MISCONFIGURED) { + printk("v4l2 ioctl: device is misconfigured; " + "close and open it again\n"); + return -EIO; + } + return 0; +} + +/* + * IRQ callback, called by URB callback + */ +static void au0828_irq_callback(struct urb *urb) +{ + struct au0828_dmaqueue *dma_q = urb->context; + struct au0828_dev *dev = container_of(dma_q, struct au0828_dev, vidq); + int rc, i; + + switch (urb->status) { + case 0: /* success */ + case -ETIMEDOUT: /* NAK */ + break; + case -ECONNRESET: /* kill */ + case -ENOENT: + case -ESHUTDOWN: + au0828_isocdbg("au0828_irq_callback called: status kill\n"); + return; + default: /* unknown error */ + au0828_isocdbg("urb completition error %d.\n", urb->status); + break; + } + + /* Copy data from URB */ + spin_lock(&dev->slock); + rc = dev->isoc_ctl.isoc_copy(dev, urb); + spin_unlock(&dev->slock); + + /* Reset urb buffers */ + for (i = 0; i < urb->number_of_packets; i++) { + urb->iso_frame_desc[i].status = 0; + urb->iso_frame_desc[i].actual_length = 0; + } + urb->status = 0; + + urb->status = usb_submit_urb(urb, GFP_ATOMIC); + if (urb->status) { + au0828_isocdbg("urb resubmit failed (error=%i)\n", + urb->status); + } +} + +/* + * Stop and Deallocate URBs + */ +void au0828_uninit_isoc(struct au0828_dev *dev) +{ + struct urb *urb; + int i; + + au0828_isocdbg("au0828: called au0828_uninit_isoc\n"); + + dev->isoc_ctl.nfields = -1; + for (i = 0; i < dev->isoc_ctl.num_bufs; i++) { + urb = dev->isoc_ctl.urb[i]; + if (urb) { + if (!irqs_disabled()) + usb_kill_urb(urb); + else + usb_unlink_urb(urb); + + if (dev->isoc_ctl.transfer_buffer[i]) { + usb_buffer_free(dev->usbdev, + urb->transfer_buffer_length, + dev->isoc_ctl.transfer_buffer[i], + urb->transfer_dma); + } + usb_free_urb(urb); + dev->isoc_ctl.urb[i] = NULL; + } + dev->isoc_ctl.transfer_buffer[i] = NULL; + } + + kfree(dev->isoc_ctl.urb); + kfree(dev->isoc_ctl.transfer_buffer); + + dev->isoc_ctl.urb = NULL; + dev->isoc_ctl.transfer_buffer = NULL; + dev->isoc_ctl.num_bufs = 0; +} + +/* + * Allocate URBs and start IRQ + */ +int au0828_init_isoc(struct au0828_dev *dev, int max_packets, + int num_bufs, int max_pkt_size, + int (*isoc_copy) (struct au0828_dev *dev, struct urb *urb)) +{ + struct au0828_dmaqueue *dma_q = &dev->vidq; + int i; + int sb_size, pipe; + struct urb *urb; + int j, k; + int rc; + + au0828_isocdbg("au0828: called au0828_prepare_isoc\n"); + + /* De-allocates all pending stuff */ + au0828_uninit_isoc(dev); + + dev->isoc_ctl.isoc_copy = isoc_copy; + dev->isoc_ctl.num_bufs = num_bufs; + + dev->isoc_ctl.urb = kzalloc(sizeof(void *)*num_bufs, GFP_KERNEL); + if (!dev->isoc_ctl.urb) { + au0828_isocdbg("cannot alloc memory for usb buffers\n"); + return -ENOMEM; + } + + dev->isoc_ctl.transfer_buffer = kzalloc(sizeof(void *)*num_bufs, + GFP_KERNEL); + if (!dev->isoc_ctl.transfer_buffer) { + au0828_isocdbg("cannot allocate memory for usb transfer\n"); + kfree(dev->isoc_ctl.urb); + return -ENOMEM; + } + + dev->isoc_ctl.max_pkt_size = max_pkt_size; + dev->isoc_ctl.buf = NULL; + + sb_size = max_packets * dev->isoc_ctl.max_pkt_size; + + /* allocate urbs and transfer buffers */ + for (i = 0; i < dev->isoc_ctl.num_bufs; i++) { + urb = usb_alloc_urb(max_packets, GFP_KERNEL); + if (!urb) { + au0828_isocdbg("cannot alloc isoc_ctl.urb %i\n", i); + au0828_uninit_isoc(dev); + return -ENOMEM; + } + dev->isoc_ctl.urb[i] = urb; + + dev->isoc_ctl.transfer_buffer[i] = usb_buffer_alloc(dev->usbdev, + sb_size, GFP_KERNEL, &urb->transfer_dma); + if (!dev->isoc_ctl.transfer_buffer[i]) { + printk("unable to allocate %i bytes for transfer" + " buffer %i%s\n", + sb_size, i, + in_interrupt() ? " while in int" : ""); + au0828_uninit_isoc(dev); + return -ENOMEM; + } + memset(dev->isoc_ctl.transfer_buffer[i], 0, sb_size); + + pipe = usb_rcvisocpipe(dev->usbdev, + dev->isoc_in_endpointaddr), + + usb_fill_int_urb(urb, dev->usbdev, pipe, + dev->isoc_ctl.transfer_buffer[i], sb_size, + au0828_irq_callback, dma_q, 1); + + urb->number_of_packets = max_packets; + urb->transfer_flags = URB_ISO_ASAP; + + k = 0; + for (j = 0; j < max_packets; j++) { + urb->iso_frame_desc[j].offset = k; + urb->iso_frame_desc[j].length = + dev->isoc_ctl.max_pkt_size; + k += dev->isoc_ctl.max_pkt_size; + } + } + + init_waitqueue_head(&dma_q->wq); + + /* submit urbs and enables IRQ */ + for (i = 0; i < dev->isoc_ctl.num_bufs; i++) { + rc = usb_submit_urb(dev->isoc_ctl.urb[i], GFP_ATOMIC); + if (rc) { + au0828_isocdbg("submit of urb %i failed (error=%i)\n", + i, rc); + au0828_uninit_isoc(dev); + return rc; + } + } + + return 0; +} + +/* + * Announces that a buffer were filled and request the next + */ +static inline void buffer_filled(struct au0828_dev *dev, + struct au0828_dmaqueue *dma_q, + struct au0828_buffer *buf) +{ + /* Advice that buffer was filled */ + au0828_isocdbg("[%p/%d] wakeup\n", buf, buf->vb.i); + + buf->vb.state = VIDEOBUF_DONE; + buf->vb.field_count++; + do_gettimeofday(&buf->vb.ts); + + dev->isoc_ctl.buf = NULL; + + list_del(&buf->vb.queue); + wake_up(&buf->vb.done); +} + +/* + * Identify the buffer header type and properly handles + */ +static void au0828_copy_video(struct au0828_dev *dev, + struct au0828_dmaqueue *dma_q, + struct au0828_buffer *buf, + unsigned char *p, + unsigned char *outp, unsigned long len) +{ + void *fieldstart, *startwrite, *startread; + int linesdone, currlinedone, offset, lencopy, remain; + int bytesperline = dev->width << 1; /* Assumes 16-bit depth @@@@ */ + + if (dma_q->pos + len > buf->vb.size) + len = buf->vb.size - dma_q->pos; + + startread = p; + remain = len; + + /* Interlaces frame */ + if (buf->top_field) + fieldstart = outp; + else + fieldstart = outp + bytesperline; + + linesdone = dma_q->pos / bytesperline; + currlinedone = dma_q->pos % bytesperline; + offset = linesdone * bytesperline * 2 + currlinedone; + startwrite = fieldstart + offset; + lencopy = bytesperline - currlinedone; + lencopy = lencopy > remain ? remain : lencopy; + + if ((char *)startwrite + lencopy > (char *)outp + buf->vb.size) { + au0828_isocdbg("Overflow of %zi bytes past buffer end (1)\n", + ((char *)startwrite + lencopy) - + ((char *)outp + buf->vb.size)); + remain = (char *)outp + buf->vb.size - (char *)startwrite; + lencopy = remain; + } + if (lencopy <= 0) + return; + memcpy(startwrite, startread, lencopy); + + remain -= lencopy; + + while (remain > 0) { + startwrite += lencopy + bytesperline; + startread += lencopy; + if (bytesperline > remain) + lencopy = remain; + else + lencopy = bytesperline; + + if ((char *)startwrite + lencopy > (char *)outp + + buf->vb.size) { + au0828_isocdbg("Overflow of %zi bytes past buffer end (2)\n", + ((char *)startwrite + lencopy) - + ((char *)outp + buf->vb.size)); + lencopy = remain = (char *)outp + buf->vb.size - + (char *)startwrite; + } + if (lencopy <= 0) + break; + + memcpy(startwrite, startread, lencopy); + + remain -= lencopy; + } + + if (offset > 1440) { + /* We have enough data to check for greenscreen */ + if (outp[0] < 0x60 && outp[1440] < 0x60) { + dev->greenscreen_detected = 1; + } + } + + dma_q->pos += len; +} + +/* + * video-buf generic routine to get the next available buffer + */ +static inline void get_next_buf(struct au0828_dmaqueue *dma_q, + struct au0828_buffer **buf) +{ + struct au0828_dev *dev = container_of(dma_q, struct au0828_dev, vidq); + + if (list_empty(&dma_q->active)) { + au0828_isocdbg("No active queue to serve\n"); + dev->isoc_ctl.buf = NULL; + *buf = NULL; + return; + } + + /* Get the next buffer */ + *buf = list_entry(dma_q->active.next, struct au0828_buffer, vb.queue); + dev->isoc_ctl.buf = *buf; + + return; +} + +/* + * Controls the isoc copy of each urb packet + */ +static inline int au0828_isoc_copy(struct au0828_dev *dev, struct urb *urb) +{ + struct au0828_buffer *buf; + struct au0828_dmaqueue *dma_q = urb->context; + unsigned char *outp = NULL; + int i, len = 0, rc = 1; + unsigned char *p; + unsigned char fbyte; + + if (!dev) + return 0; + + if ((dev->dev_state & DEV_DISCONNECTED) || + (dev->dev_state & DEV_MISCONFIGURED)) + return 0; + + if (urb->status < 0) { + print_err_status(dev, -1, urb->status); + if (urb->status == -ENOENT) + return 0; + } + + buf = dev->isoc_ctl.buf; + if (buf != NULL) + outp = videobuf_to_vmalloc(&buf->vb); + + for (i = 0; i < urb->number_of_packets; i++) { + int status = urb->iso_frame_desc[i].status; + + if (status < 0) { + print_err_status(dev, i, status); + if (urb->iso_frame_desc[i].status != -EPROTO) + continue; + } + + if (urb->iso_frame_desc[i].actual_length <= 0) { + continue; + } + if (urb->iso_frame_desc[i].actual_length > + dev->max_pkt_size) { + au0828_isocdbg("packet bigger than packet size"); + continue; + } + + p = urb->transfer_buffer + urb->iso_frame_desc[i].offset; + fbyte = p[0]; + len = urb->iso_frame_desc[i].actual_length - 4; + p += 4; + + if (fbyte & 0x80) { + len -= 4; + p += 4; + au0828_isocdbg("Video frame %s\n", + (fbyte & 0x40) ? "odd" : "even"); + if (!(fbyte & 0x40)) { + if (buf != NULL) + buffer_filled(dev, dma_q, buf); + get_next_buf(dma_q, &buf); + if (buf == NULL) { + outp = NULL; + } else + outp = videobuf_to_vmalloc(&buf->vb); + } + + if (buf != NULL) { + if (fbyte & 0x40) { + buf->top_field = 1; + } else { + buf->top_field = 0; + } + } + + dma_q->pos = 0; + } + if (buf != NULL) { + au0828_copy_video(dev, dma_q, buf, p, outp, len); + } + } + return rc; +} + +static int +buffer_setup(struct videobuf_queue *vq, unsigned int *count, + unsigned int *size) +{ + struct au0828_fh *fh = vq->priv_data; + *size = (fh->dev->width * fh->dev->height * 16 + 7) >> 3; + + if (0 == *count) + *count = AU0828_DEF_BUF; + + if (*count < AU0828_MIN_BUF) + *count = AU0828_MIN_BUF; + return 0; +} + +/* This is called *without* dev->slock held; please keep it that way */ +static void free_buffer(struct videobuf_queue *vq, struct au0828_buffer *buf) +{ + struct au0828_fh *fh = vq->priv_data; + struct au0828_dev *dev = fh->dev; + unsigned long flags = 0; + if (in_interrupt()) + BUG(); + + /* We used to wait for the buffer to finish here, but this didn't work + because, as we were keeping the state as VIDEOBUF_QUEUED, + videobuf_queue_cancel marked it as finished for us. + (Also, it could wedge forever if the hardware was misconfigured.) + + This should be safe; by the time we get here, the buffer isn't + queued anymore. If we ever start marking the buffers as + VIDEOBUF_ACTIVE, it won't be, though. + */ + spin_lock_irqsave(&dev->slock, flags); + if (dev->isoc_ctl.buf == buf) + dev->isoc_ctl.buf = NULL; + spin_unlock_irqrestore(&dev->slock, flags); + + videobuf_vmalloc_free(&buf->vb); + buf->vb.state = VIDEOBUF_NEEDS_INIT; +} + +static int +buffer_prepare(struct videobuf_queue *vq, struct videobuf_buffer *vb, + enum v4l2_field field) +{ + struct au0828_fh *fh = vq->priv_data; + struct au0828_buffer *buf = container_of(vb, struct au0828_buffer, vb); + struct au0828_dev *dev = fh->dev; + int rc = 0, urb_init = 0; + + buf->vb.size = (fh->dev->width * fh->dev->height * 16 + 7) >> 3; + + if (0 != buf->vb.baddr && buf->vb.bsize < buf->vb.size) + return -EINVAL; + + buf->vb.width = dev->width; + buf->vb.height = dev->height; + buf->vb.field = field; + + if (VIDEOBUF_NEEDS_INIT == buf->vb.state) { + rc = videobuf_iolock(vq, &buf->vb, NULL); + if (rc < 0) { + printk("videobuf_iolock failed\n"); + goto fail; + } + } + + if (!dev->isoc_ctl.num_bufs) + urb_init = 1; + + if (urb_init) { + rc = au0828_init_isoc(dev, AU0828_ISO_PACKETS_PER_URB, + AU0828_MAX_ISO_BUFS, dev->max_pkt_size, + au0828_isoc_copy); + if (rc < 0) { + printk("au0828_init_isoc failed\n"); + goto fail; + } + } + + buf->vb.state = VIDEOBUF_PREPARED; + return 0; + +fail: + free_buffer(vq, buf); + return rc; +} + +static void +buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb) +{ + struct au0828_buffer *buf = container_of(vb, + struct au0828_buffer, + vb); + struct au0828_fh *fh = vq->priv_data; + struct au0828_dev *dev = fh->dev; + struct au0828_dmaqueue *vidq = &dev->vidq; + + buf->vb.state = VIDEOBUF_QUEUED; + list_add_tail(&buf->vb.queue, &vidq->active); +} + +static void buffer_release(struct videobuf_queue *vq, + struct videobuf_buffer *vb) +{ + struct au0828_buffer *buf = container_of(vb, + struct au0828_buffer, + vb); + + free_buffer(vq, buf); +} + +static struct videobuf_queue_ops au0828_video_qops = { + .buf_setup = buffer_setup, + .buf_prepare = buffer_prepare, + .buf_queue = buffer_queue, + .buf_release = buffer_release, +}; + +/* ------------------------------------------------------------------ + V4L2 interface + ------------------------------------------------------------------*/ + +static int au0828_i2s_init(struct au0828_dev *dev) +{ + /* Enable i2s mode */ + au0828_writereg(dev, AU0828_AUDIOCTRL_50C, 0x01); + return 0; +} + +/* + * Auvitek au0828 analog stream enable + * Please set interface0 to AS5 before enable the stream + */ +int au0828_analog_stream_enable(struct au0828_dev *d) +{ + dprintk(1, "au0828_analog_stream_enable called\n"); + au0828_writereg(d, AU0828_SENSORCTRL_VBI_103, 0x00); + au0828_writereg(d, 0x106, 0x00); + /* set x position */ + au0828_writereg(d, 0x110, 0x00); + au0828_writereg(d, 0x111, 0x00); + au0828_writereg(d, 0x114, 0xa0); + au0828_writereg(d, 0x115, 0x05); + /* set y position */ + au0828_writereg(d, 0x112, 0x02); + au0828_writereg(d, 0x113, 0x00); + au0828_writereg(d, 0x116, 0xf2); + au0828_writereg(d, 0x117, 0x00); + au0828_writereg(d, AU0828_SENSORCTRL_100, 0xb3); + + return 0; +} + +int au0828_analog_stream_disable(struct au0828_dev *d) +{ + dprintk(1, "au0828_analog_stream_disable called\n"); + au0828_writereg(d, AU0828_SENSORCTRL_100, 0x0); + return 0; +} + +void au0828_analog_stream_reset(struct au0828_dev *dev) +{ + dprintk(1, "au0828_analog_stream_reset called\n"); + au0828_writereg(dev, AU0828_SENSORCTRL_100, 0x0); + mdelay(30); + au0828_writereg(dev, AU0828_SENSORCTRL_100, 0xb3); +} + +/* + * Some operations needs to stop current streaming + */ +static int au0828_stream_interrupt(struct au0828_dev *dev) +{ + int ret = 0; + + dev->stream_state = STREAM_INTERRUPT; + if(dev->dev_state == DEV_DISCONNECTED) + return -ENODEV; + else if(ret) { + dev->dev_state = DEV_MISCONFIGURED; + dprintk(1, "%s device is misconfigured!\n", __FUNCTION__); + return ret; + } + return 0; +} + +/* + * au0828_release_resources + * unregister v4l2 devices + */ +void au0828_analog_unregister(struct au0828_dev *dev) +{ + dprintk(1, "au0828_release_resources called\n"); + mutex_lock(&au0828_sysfs_lock); + + list_del(&dev->au0828list); + video_unregister_device(dev->vdev); + video_unregister_device(dev->vbi_dev); + + mutex_unlock(&au0828_sysfs_lock); +} + + +/* Usage lock check functions */ +static int res_get(struct au0828_fh *fh) +{ + struct au0828_dev *dev = fh->dev; + int rc = 0; + + /* This instance already has stream_on */ + if (fh->stream_on) + return rc; + + if (dev->stream_on) + return -EBUSY; + + dev->stream_on = 1; + fh->stream_on = 1; + return rc; +} + +static int res_check(struct au0828_fh *fh) +{ + return fh->stream_on; +} + +static void res_free(struct au0828_fh *fh) +{ + struct au0828_dev *dev = fh->dev; + + fh->stream_on = 0; + dev->stream_on = 0; +} + +static int au0828_v4l2_open(struct file *filp) +{ + int minor = video_devdata(filp)->minor; + int ret = 0; + struct au0828_dev *h, *dev = NULL; + struct au0828_fh *fh; + int type = 0; + struct list_head *list; + + list_for_each(list, &au0828_devlist) { + h = list_entry(list, struct au0828_dev, au0828list); + if(h->vdev->minor == minor) { + dev = h; + type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + } + if(h->vbi_dev->minor == minor) { + dev = h; + type = V4L2_BUF_TYPE_VBI_CAPTURE; + } + } + + if(NULL == dev) + return -ENODEV; + + fh = kzalloc(sizeof(struct au0828_fh), GFP_KERNEL); + if(NULL == fh) { + dprintk(1, "Failed allocate au0828_fh struct!\n"); + return -ENOMEM; + } + + fh->type = type; + fh->dev = dev; + filp->private_data = fh; + + if(fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE && dev->users == 0) { + /* set au0828 interface0 to AS5 here again */ + ret = usb_set_interface(dev->usbdev, 0, 5); + if(ret < 0) { + printk("Au0828 can't set alt setting to 5!\n"); + return -EBUSY; + } + dev->width = NTSC_STD_W; + dev->height = NTSC_STD_H; + dev->frame_size = dev->width * dev->height * 2; + dev->field_size = dev->width * dev->height; + dev->bytesperline = dev->width * 2; + + au0828_analog_stream_enable(dev); + au0828_analog_stream_reset(dev); + + /* If we were doing ac97 instead of i2s, it would go here...*/ + au0828_i2s_init(dev); + + dev->stream_state = STREAM_OFF; + dev->dev_state |= DEV_INITIALIZED; + } + + dev->users++; + + videobuf_queue_vmalloc_init(&fh->vb_vidq, &au0828_video_qops, + NULL, &dev->slock, fh->type, + V4L2_FIELD_INTERLACED, + sizeof(struct au0828_buffer), fh); + + return ret; +} + +static int au0828_v4l2_close(struct file *filp) +{ + int ret; + struct au0828_fh *fh = filp->private_data; + struct au0828_dev *dev = fh->dev; + + mutex_lock(&dev->lock); + if (res_check(fh)) + res_free(fh); + + if(dev->users == 1) { + videobuf_stop(&fh->vb_vidq); + videobuf_mmap_free(&fh->vb_vidq); + + if(dev->dev_state & DEV_DISCONNECTED) { + au0828_analog_unregister(dev); + mutex_unlock(&dev->lock); + kfree(dev); + return 0; + } + + au0828_analog_stream_disable(dev); + + au0828_uninit_isoc(dev); + + /* When close the device, set the usb intf0 into alt0 to free + USB bandwidth */ + ret = usb_set_interface(dev->usbdev, 0, 0); + if(ret < 0) + printk("Au0828 can't set alt setting to 0!\n"); + } + + kfree(fh); + dev->users--; + wake_up_interruptible_nr(&dev->open, 1); + mutex_unlock(&dev->lock); + return 0; +} + +static ssize_t au0828_v4l2_read(struct file *filp, char __user *buf, + size_t count, loff_t *pos) +{ + struct au0828_fh *fh = filp->private_data; + struct au0828_dev *dev = fh->dev; + int rc; + + rc = check_dev(dev); + if (rc < 0) + return rc; + + if(fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) { + mutex_lock(&dev->lock); + rc = res_get(fh); + mutex_unlock(&dev->lock); + + if (unlikely(rc < 0)) + return rc; + + return videobuf_read_stream(&fh->vb_vidq, buf, count, pos, 0, + filp->f_flags & O_NONBLOCK); + } + return 0; +} + +static unsigned int au0828_v4l2_poll(struct file *filp, poll_table *wait) +{ + struct au0828_fh *fh = filp->private_data; + struct au0828_dev *dev = fh->dev; + int rc; + + rc = check_dev(dev); + if (rc < 0) + return rc; + + mutex_lock(&dev->lock); + rc = res_get(fh); + mutex_unlock(&dev->lock); + + if (unlikely(rc < 0)) + return POLLERR; + + if (V4L2_BUF_TYPE_VIDEO_CAPTURE != fh->type) + return POLLERR; + + return videobuf_poll_stream(filp, &fh->vb_vidq, wait); +} + +static int au0828_v4l2_mmap(struct file *filp, struct vm_area_struct *vma) +{ + struct au0828_fh *fh = filp->private_data; + struct au0828_dev *dev = fh->dev; + int rc; + + rc = check_dev(dev); + if (rc < 0) + return rc; + + mutex_lock(&dev->lock); + rc = res_get(fh); + mutex_unlock(&dev->lock); + + if (unlikely(rc < 0)) + return rc; + + rc = videobuf_mmap_mapper(&fh->vb_vidq, vma); + + dprintk(2, "vma start=0x%08lx, size=%ld, ret=%d\n", + (unsigned long)vma->vm_start, + (unsigned long)vma->vm_end-(unsigned long)vma->vm_start, + rc); + + return rc; +} + +static int au0828_set_format(struct au0828_dev *dev, unsigned int cmd, + struct v4l2_format *format) +{ + int ret; + int width = format->fmt.pix.width; + int height = format->fmt.pix.height; + unsigned int maxwidth, maxheight; + + maxwidth = 720; + maxheight = 480; + + if(format->type == V4L2_BUF_TYPE_SLICED_VBI_CAPTURE) { + dprintk(1, "VBI format set: to be supported!\n"); + return 0; + } + if(format->type == V4L2_BUF_TYPE_VBI_CAPTURE) { + return 0; + } + if(format->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) { + return -EINVAL; + } + + /* If they are demanding a format other than the one we support, + bail out (tvtime asks for UYVY and then retries with YUYV) */ + if (format->fmt.pix.pixelformat != V4L2_PIX_FMT_UYVY) { + return -EINVAL; + } + + /* format->fmt.pix.width only support 720 and height 480 */ + if(width != 720) + width = 720; + if(height != 480) + height = 480; + + format->fmt.pix.width = width; + format->fmt.pix.height = height; + format->fmt.pix.pixelformat = V4L2_PIX_FMT_UYVY; + format->fmt.pix.bytesperline = width * 2; + format->fmt.pix.sizeimage = width * height * 2; + format->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; + format->fmt.pix.field = V4L2_FIELD_INTERLACED; + + if(cmd == VIDIOC_TRY_FMT) + return 0; + + /* maybe set new image format, driver current only support 720*480 */ + dev->width = width; + dev->height = height; + dev->frame_size = width * height * 2; + dev->field_size = width * height; + dev->bytesperline = width * 2; + + if(dev->stream_state == STREAM_ON) { + dprintk(1, "VIDIOC_SET_FMT: interrupting stream!\n"); + if((ret = au0828_stream_interrupt(dev))) { + dprintk(1, "error interrupting video stream!\n"); + return ret; + } + } + + /* set au0828 interface0 to AS5 here again */ + ret = usb_set_interface(dev->usbdev, 0, 5); + if(ret < 0) { + printk("Au0828 can't set alt setting to 5!\n"); + return -EBUSY; + } + + au0828_analog_stream_enable(dev); + + return 0; +} + + +static int vidioc_queryctrl(struct file *file, void *priv, + struct v4l2_queryctrl *qc) +{ + struct au0828_fh *fh = priv; + struct au0828_dev *dev = fh->dev; + au0828_call_i2c_clients(dev, VIDIOC_QUERYCTRL, qc); + if (qc->type) + return 0; + else + return -EINVAL; +} + +static int vidioc_querycap(struct file *file, void *priv, + struct v4l2_capability *cap) +{ + struct au0828_fh *fh = priv; + struct au0828_dev *dev = fh->dev; + + memset(cap, 0, sizeof(*cap)); + strlcpy(cap->driver, "au0828", sizeof(cap->driver)); + strlcpy(cap->card, au0828_boards[dev->board].name, sizeof(cap->card)); + strlcpy(cap->bus_info, dev->usbdev->dev.bus_id, sizeof(cap->bus_info)); + + cap->version = AU0828_VERSION_CODE; + + /*set the device capabilities */ + cap->capabilities = V4L2_CAP_VBI_CAPTURE | + V4L2_CAP_VIDEO_CAPTURE | + V4L2_CAP_AUDIO | + V4L2_CAP_READWRITE | + V4L2_CAP_STREAMING | + V4L2_CAP_TUNER; + return 0; +} + +static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv, + struct v4l2_fmtdesc *f) +{ + if(f->index) + return -EINVAL; + + memset(f, 0, sizeof(*f)); + f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + strcpy(f->description, "Packed YUV2"); + + f->flags = 0; + f->pixelformat = V4L2_PIX_FMT_UYVY; + + memset(f->reserved, 0, sizeof(f->reserved)); + return 0; +} + +static int vidioc_g_fmt_vid_cap(struct file *file, void *priv, + struct v4l2_format *f) +{ + struct au0828_fh *fh = priv; + struct au0828_dev *dev = fh->dev; + + f->fmt.pix.width = dev->width; + f->fmt.pix.height = dev->height; + f->fmt.pix.pixelformat = V4L2_PIX_FMT_UYVY; + f->fmt.pix.bytesperline = dev->bytesperline; + f->fmt.pix.sizeimage = dev->frame_size; + f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; /* NTSC/PAL */ + f->fmt.pix.field = V4L2_FIELD_INTERLACED; + return 0; +} + +static int vidioc_try_fmt_vid_cap(struct file *file, void *priv, + struct v4l2_format *f) +{ + struct au0828_fh *fh = priv; + struct au0828_dev *dev = fh->dev; + + return au0828_set_format(dev, VIDIOC_TRY_FMT, f); +} + +static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, + struct v4l2_format *f) +{ + struct au0828_fh *fh = priv; + struct au0828_dev *dev = fh->dev; + int rc; + + if (videobuf_queue_is_busy(&fh->vb_vidq)) { + printk("%s queue busy\n", __func__); + rc = -EBUSY; + goto out; + } + + if (dev->stream_on && !fh->stream_on) { + printk("%s device in use by another fh\n", __func__); + rc = -EBUSY; + goto out; + } + + return au0828_set_format(dev, VIDIOC_S_FMT, f); +out: + return rc; +} + +static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id * norm) +{ + struct au0828_fh *fh = priv; + struct au0828_dev *dev = fh->dev; + + /* FIXME: when we support something other than NTSC, we are going to + have to make the au0828 bridge adjust the size of its capture + buffer, which is currently hardcoded at 720x480 */ + + au0828_call_i2c_clients(dev, VIDIOC_S_STD, norm); + return 0; +} + +static int vidioc_enum_input(struct file *file, void *priv, + struct v4l2_input *input) +{ + struct au0828_fh *fh = priv; + struct au0828_dev *dev = fh->dev; + unsigned int tmp; + + static const char *inames[] = { + [AU0828_VMUX_COMPOSITE] = "Composite", + [AU0828_VMUX_SVIDEO] = "S-Video", + [AU0828_VMUX_CABLE] = "Cable TV", + [AU0828_VMUX_TELEVISION] = "Television", + [AU0828_VMUX_DVB] = "DVB", + [AU0828_VMUX_DEBUG] = "tv debug" + }; + + tmp = input->index; + + if(tmp > AU0828_MAX_INPUT) + return -EINVAL; + if(AUVI_INPUT(tmp)->type == 0) + return -EINVAL; + + memset(input, 0, sizeof(*input)); + input->index = tmp; + strcpy(input->name, inames[AUVI_INPUT(tmp)->type]); + if((AUVI_INPUT(tmp)->type == AU0828_VMUX_TELEVISION) || + (AUVI_INPUT(tmp)->type == AU0828_VMUX_CABLE)) + input->type |= V4L2_INPUT_TYPE_TUNER; + else + input->type |= V4L2_INPUT_TYPE_CAMERA; + + input->std = dev->vdev->tvnorms; + + return 0; +} + +static int vidioc_g_input(struct file *file, void *priv, unsigned int *i) +{ + struct au0828_fh *fh = priv; + struct au0828_dev *dev = fh->dev; + *i = dev->ctrl_input; + return 0; +} + +static int vidioc_s_input(struct file *file, void *priv, unsigned int index) +{ + struct au0828_fh *fh = priv; + struct au0828_dev *dev = fh->dev; + int i; + struct v4l2_routing route; + + dprintk(1, "VIDIOC_S_INPUT in function %s, input=%d\n", __FUNCTION__, + index); + if(index >= AU0828_MAX_INPUT) + return -EINVAL; + if(AUVI_INPUT(index)->type == 0) + return -EINVAL; + dev->ctrl_input = index; + + switch(AUVI_INPUT(index)->type) { + case AU0828_VMUX_SVIDEO: + { + dev->input_type = AU0828_VMUX_SVIDEO; + break; + } + case AU0828_VMUX_COMPOSITE: + { + dev->input_type = AU0828_VMUX_COMPOSITE; + break; + } + case AU0828_VMUX_TELEVISION: + { + dev->input_type = AU0828_VMUX_TELEVISION; + break; + } + default: + ; + } + + route.input = AUVI_INPUT(index)->vmux; + route.output = 0; + au0828_call_i2c_clients(dev, VIDIOC_INT_S_VIDEO_ROUTING, &route); + + for (i = 0; i < AU0828_MAX_INPUT; i++) { + int enable = 0; + if (AUVI_INPUT(i)->audio_setup == NULL) { + continue; + } + + if (i == index) + enable = 1; + else + enable = 0; + if (enable) { + (AUVI_INPUT(i)->audio_setup)(dev, enable); + } else { + /* Make sure we leave it turned on if some + other input is routed to this callback */ + if ((AUVI_INPUT(i)->audio_setup) != + ((AUVI_INPUT(index)->audio_setup))) { + (AUVI_INPUT(i)->audio_setup)(dev, enable); + } + } + } + + route.input = AUVI_INPUT(index)->amux; + au0828_call_i2c_clients(dev, VIDIOC_INT_S_AUDIO_ROUTING, + &route); + return 0; +} + +static int vidioc_g_audio(struct file *file, void *priv, struct v4l2_audio *a) +{ + struct au0828_fh *fh = priv; + struct au0828_dev *dev = fh->dev; + unsigned int index = a->index; + + if(a->index > 1) + return -EINVAL; + + memset(a, 0, sizeof(*a)); + index = dev->ctrl_ainput; + if(index == 0) + strcpy(a->name, "Television"); + else + strcpy(a->name, "Line in"); + + a->capability = V4L2_AUDCAP_STEREO; + a->index = index; + return 0; +} + +static int vidioc_s_audio(struct file *file, void *priv, struct v4l2_audio *a) +{ + struct au0828_fh *fh = priv; + struct au0828_dev *dev = fh->dev; + if(a->index != dev->ctrl_ainput) + return -EINVAL; + return 0; +} + +static int vidioc_g_ctrl(struct file *file, void *priv, + struct v4l2_control *ctrl) +{ + struct au0828_fh *fh = priv; + struct au0828_dev *dev = fh->dev; + + au0828_call_i2c_clients(dev, VIDIOC_G_CTRL, ctrl); + return 0; + +} + +static int vidioc_s_ctrl(struct file *file, void *priv, + struct v4l2_control *ctrl) +{ + struct au0828_fh *fh = priv; + struct au0828_dev *dev = fh->dev; + au0828_call_i2c_clients(dev, VIDIOC_S_CTRL, ctrl); + return 0; +} + +static int vidioc_g_tuner(struct file *file, void *priv, struct v4l2_tuner *t) +{ + struct au0828_fh *fh = priv; + struct au0828_dev *dev = fh->dev; + + if(t->index != 0) + return -EINVAL; + + memset(t, 0, sizeof(*t)); + strcpy(t->name, "Auvitek tuner"); + + au0828_call_i2c_clients(dev, VIDIOC_G_TUNER, t); + return 0; +} + +static int vidioc_s_tuner(struct file *file, void *priv, + struct v4l2_tuner *t) +{ + struct au0828_fh *fh = priv; + struct au0828_dev *dev = fh->dev; + + if(t->index != 0) + return -EINVAL; + + t->type = V4L2_TUNER_ANALOG_TV; + au0828_call_i2c_clients(dev, VIDIOC_S_TUNER, t); + dprintk(1, "VIDIOC_S_TUNER: signal = %x, afc = %x\n", t->signal, + t->afc); + return 0; + +} + +static int vidioc_g_frequency(struct file *file, void *priv, + struct v4l2_frequency *freq) +{ + struct au0828_fh *fh = priv; + struct au0828_dev *dev = fh->dev; + memset(freq, 0, sizeof(*freq)); + freq->type = V4L2_TUNER_ANALOG_TV; + freq->frequency = dev->ctrl_freq; + return 0; +} + +static int vidioc_s_frequency(struct file *file, void *priv, + struct v4l2_frequency *freq) +{ + struct au0828_fh *fh = priv; + struct au0828_dev *dev = fh->dev; + + if(freq->tuner != 0) + return -EINVAL; + if(freq->type != V4L2_TUNER_ANALOG_TV) + return -EINVAL; + + dev->ctrl_freq = freq->frequency; + + au0828_call_i2c_clients(dev, VIDIOC_S_FREQUENCY, freq); + + au0828_analog_stream_reset(dev); + + return 0; +} + +static int vidioc_g_chip_ident(struct file *file, void *priv, + struct v4l2_dbg_chip_ident *chip) +{ + struct au0828_fh *fh = priv; + struct au0828_dev *dev = fh->dev; + chip->ident = V4L2_IDENT_NONE; + chip->revision = 0; + + au0828_call_i2c_clients(dev, VIDIOC_DBG_G_CHIP_IDENT, chip); + return 0; +} + +static int vidioc_cropcap(struct file *file, void *priv, + struct v4l2_cropcap *cc) +{ + struct au0828_fh *fh = priv; + struct au0828_dev *dev = fh->dev; + + if(cc->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + return -EINVAL; + + cc->bounds.left = 0; + cc->bounds.top = 0; + cc->bounds.width = dev->width; + cc->bounds.height = dev->height; + + cc->defrect = cc->bounds; + + cc->pixelaspect.numerator = 54; + cc->pixelaspect.denominator = 59; + + return 0; +} + +static int vidioc_streamon(struct file *file, void *priv, + enum v4l2_buf_type type) +{ + struct au0828_fh *fh = priv; + struct au0828_dev *dev = fh->dev; + int b = V4L2_BUF_TYPE_VIDEO_CAPTURE; + int rc; + + rc = check_dev(dev); + if (rc < 0) + return rc; + + if (type == V4L2_BUF_TYPE_VIDEO_CAPTURE) { + au0828_analog_stream_enable(dev); + au0828_call_i2c_clients(dev, VIDIOC_STREAMON, &b); + } + + mutex_lock(&dev->lock); + rc = res_get(fh); + + if (likely(rc >= 0)) + rc = videobuf_streamon(&fh->vb_vidq); + mutex_unlock(&dev->lock); + + return rc; +} + +static int vidioc_streamoff(struct file *file, void *priv, + enum v4l2_buf_type type) +{ + struct au0828_fh *fh = priv; + struct au0828_dev *dev = fh->dev; + int b = V4L2_BUF_TYPE_VIDEO_CAPTURE; + int i; + int ret; + int rc; + + rc = check_dev(dev); + if (rc < 0) + return rc; + + if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + return -EINVAL; + if (type != fh->type) + return -EINVAL; + + if (type == V4L2_BUF_TYPE_VIDEO_CAPTURE) { + au0828_call_i2c_clients(dev, VIDIOC_STREAMOFF, &b); + if((ret = au0828_stream_interrupt(dev)) != 0) + return ret; + } + + for (i = 0; i < AU0828_MAX_INPUT; i++) { + if (AUVI_INPUT(i)->audio_setup == NULL) { + continue; + } + (AUVI_INPUT(i)->audio_setup)(dev, 0); + } + + mutex_lock(&dev->lock); + videobuf_streamoff(&fh->vb_vidq); + res_free(fh); + mutex_unlock(&dev->lock); + + return 0; +} + +static int vidioc_g_register(struct file *file, void *priv, + struct v4l2_dbg_register *reg) +{ + struct au0828_fh *fh = priv; + struct au0828_dev *dev = fh->dev; + + switch (reg->match.type) { + case V4L2_CHIP_MATCH_I2C_DRIVER: + au0828_call_i2c_clients(dev, VIDIOC_DBG_G_REGISTER, reg); + return 0; + default: + return -EINVAL; + } +} + +static int vidioc_s_register(struct file *file, void *priv, + struct v4l2_dbg_register *reg) +{ + struct au0828_fh *fh = priv; + struct au0828_dev *dev = fh->dev; + + switch (reg->match.type) { + case V4L2_CHIP_MATCH_I2C_DRIVER: + au0828_call_i2c_clients(dev, VIDIOC_DBG_S_REGISTER, reg); + return 0; + default: + return -EINVAL; + } + return 0; +} + +static int vidioc_reqbufs(struct file *file, void *priv, + struct v4l2_requestbuffers *rb) +{ + struct au0828_fh *fh = priv; + struct au0828_dev *dev = fh->dev; + int rc; + + rc = check_dev(dev); + if (rc < 0) + return rc; + + return videobuf_reqbufs(&fh->vb_vidq, rb); +} + +static int vidioc_querybuf(struct file *file, void *priv, + struct v4l2_buffer *b) +{ + struct au0828_fh *fh = priv; + struct au0828_dev *dev = fh->dev; + int rc; + + rc = check_dev(dev); + if (rc < 0) + return rc; + + return videobuf_querybuf(&fh->vb_vidq, b); +} + +static int vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *b) +{ + struct au0828_fh *fh = priv; + struct au0828_dev *dev = fh->dev; + int rc; + + rc = check_dev(dev); + if (rc < 0) + return rc; + + return videobuf_qbuf(&fh->vb_vidq, b); +} + +static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *b) +{ + struct au0828_fh *fh = priv; + struct au0828_dev *dev = fh->dev; + int rc; + + rc = check_dev(dev); + if (rc < 0) + return rc; + + /* Workaround for a bug in the au0828 hardware design that sometimes + results in the colorspace being inverted */ + if (dev->greenscreen_detected == 1) { + dprintk(1, "Detected green frame. Resetting stream...\n"); + au0828_analog_stream_reset(dev); + dev->greenscreen_detected = 0; + } + + return videobuf_dqbuf(&fh->vb_vidq, b, file->f_flags & O_NONBLOCK); +} + +#ifdef CONFIG_VIDEO_V4L1_COMPAT +static int vidiocgmbuf(struct file *file, void *priv, struct video_mbuf *mbuf) +{ + struct au0828_fh *fh = priv; + + return videobuf_cgmbuf(&fh->vb_vidq, mbuf, 8); +} +#endif + +static struct v4l2_file_operations au0828_v4l_fops = { + .owner = THIS_MODULE, + .open = au0828_v4l2_open, + .release = au0828_v4l2_close, + .read = au0828_v4l2_read, + .poll = au0828_v4l2_poll, + .mmap = au0828_v4l2_mmap, + .ioctl = video_ioctl2, +}; + +static const struct v4l2_ioctl_ops video_ioctl_ops = { + .vidioc_querycap = vidioc_querycap, + .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap, + .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap, + .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap, + .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap, + .vidioc_g_audio = vidioc_g_audio, + .vidioc_s_audio = vidioc_s_audio, + .vidioc_cropcap = vidioc_cropcap, +#ifdef AAA + .vidioc_g_fmt_sliced_vbi_cap = vidioc_g_fmt_sliced_vbi_cap, + .vidioc_try_fmt_sliced_vbi_cap = vidioc_try_set_sliced_vbi_cap, + .vidioc_s_fmt_sliced_vbi_cap = vidioc_try_set_sliced_vbi_cap, +#endif + .vidioc_reqbufs = vidioc_reqbufs, + .vidioc_querybuf = vidioc_querybuf, + .vidioc_qbuf = vidioc_qbuf, + .vidioc_dqbuf = vidioc_dqbuf, + .vidioc_s_std = vidioc_s_std, + .vidioc_enum_input = vidioc_enum_input, + .vidioc_g_input = vidioc_g_input, + .vidioc_s_input = vidioc_s_input, + .vidioc_queryctrl = vidioc_queryctrl, + .vidioc_g_ctrl = vidioc_g_ctrl, + .vidioc_s_ctrl = vidioc_s_ctrl, + .vidioc_streamon = vidioc_streamon, + .vidioc_streamoff = vidioc_streamoff, + .vidioc_g_tuner = vidioc_g_tuner, + .vidioc_s_tuner = vidioc_s_tuner, + .vidioc_g_frequency = vidioc_g_frequency, + .vidioc_s_frequency = vidioc_s_frequency, +#ifdef CONFIG_VIDEO_ADV_DEBUG + .vidioc_g_register = vidioc_g_register, + .vidioc_s_register = vidioc_s_register, + .vidioc_g_chip_ident = vidioc_g_chip_ident, +#endif +#ifdef CONFIG_VIDEO_V4L1_COMPAT + .vidiocgmbuf = vidiocgmbuf, +#endif +}; + +static const struct video_device au0828_video_template = { + .fops = &au0828_v4l_fops, + .release = video_device_release, + .ioctl_ops = &video_ioctl_ops, + .minor = -1, + .tvnorms = V4L2_STD_NTSC, + .current_norm = V4L2_STD_NTSC, +}; + +/**************************************************************************/ + +int au0828_analog_register(struct au0828_dev *dev) +{ + int retval = -ENOMEM; + + dprintk(1, "au0828_analog_register called!\n"); + + /* Load the analog demodulator driver (note this would need to be + abstracted out if we ever need to support a different demod) */ + request_module("au8522"); + + /* Load the tuner module, which results in i2c enumeration and + attachment of whatever tuner is on the bus */ + request_module("tuner"); + + init_waitqueue_head(&dev->open); + spin_lock_init(&dev->slock); + mutex_init(&dev->lock); + + INIT_LIST_HEAD(&dev->vidq.active); + INIT_LIST_HEAD(&dev->vidq.queued); + + dev->width = NTSC_STD_W; + dev->height = NTSC_STD_H; + dev->field_size = dev->width * dev->height; + dev->frame_size = dev->field_size << 1; + dev->bytesperline = dev->width << 1; + dev->ctrl_ainput = 0; + + /* allocate and fill v4l2 video struct */ + dev->vdev = video_device_alloc(); + if(NULL == dev->vdev) { + dprintk(1, "Can't allocate video_device.\n"); + return -ENOMEM; + } + + dev->vbi_dev = video_device_alloc(); + if(NULL == dev->vbi_dev) { + dprintk(1, "Can't allocate vbi_device.\n"); + kfree(dev->vdev); + return -ENOMEM; + } + + /* Fill the video capture device struct */ + *dev->vdev = au0828_video_template; + dev->vdev->vfl_type = VID_TYPE_CAPTURE | VID_TYPE_TUNER; + dev->vdev->parent = &dev->usbdev->dev; + strcpy(dev->vdev->name, "au0828a video"); + + /* Setup the VBI device */ + *dev->vbi_dev = au0828_video_template; + dev->vbi_dev->vfl_type = VFL_TYPE_VBI; + dev->vbi_dev->parent = &dev->usbdev->dev; + strcpy(dev->vbi_dev->name, "au0828a vbi"); + + list_add_tail(&dev->au0828list, &au0828_devlist); + + /* Register the v4l2 device */ + if((retval = video_register_device(dev->vdev, VFL_TYPE_GRABBER, -1)) != 0) { + dprintk(1, "unable to register video device (error = %d).\n", retval); + list_del(&dev->au0828list); + video_device_release(dev->vdev); + return -ENODEV; + } + + /* Register the vbi device */ + if((retval = video_register_device(dev->vbi_dev, VFL_TYPE_VBI, -1)) != 0) { + dprintk(1, "unable to register vbi device (error = %d).\n", retval); + list_del(&dev->au0828list); + video_device_release(dev->vbi_dev); + video_device_release(dev->vdev); + return -ENODEV; + } + + dprintk(1, "%s completed!\n", __FUNCTION__); + + return 0; +} + diff --git a/drivers/media/video/au0828/au0828.h b/drivers/media/video/au0828/au0828.h index 9d6a1161dc98..3b8e3e913475 100644 --- a/drivers/media/video/au0828/au0828.h +++ b/drivers/media/video/au0828/au0828.h @@ -24,6 +24,10 @@ #include #include +/* Analog */ +#include +#include + /* DVB */ #include "demux.h" #include "dmxdev.h" @@ -39,8 +43,48 @@ #define URB_COUNT 16 #define URB_BUFSIZE (0xe522) +/* Analog constants */ +#define NTSC_STD_W 720 +#define NTSC_STD_H 480 + +#define AU0828_INTERLACED_DEFAULT 1 +#define V4L2_CID_PRIVATE_SHARPNESS (V4L2_CID_PRIVATE_BASE + 0) + +/* Defination for AU0828 USB transfer */ +#define AU0828_MAX_ISO_BUFS 12 /* maybe resize this value in the future */ +#define AU0828_ISO_PACKETS_PER_URB 10 +#define AU0828_ISO_MAX_FRAME_SIZE (3 * 1024) +#define AU0828_ISO_BUFFER_SIZE (AU0828_ISO_PACKETS_PER_URB * AU0828_ISO_MAX_FRAME_SIZE) + +#define AU0828_MIN_BUF 4 +#define AU0828_DEF_BUF 8 + +#define AU0828_MAX_IMAGES 10 +#define AU0828_FRAME_SIZE (1028 * 1024 * 4) +#define AU0828_URB_TIMEOUT msecs_to_jiffies(AU0828_MAX_ISO_BUFS * AU0828_ISO_PACKETS_PER_URB) + +#define AU0828_MAX_INPUT 4 + +enum au0828_itype { + AU0828_VMUX_COMPOSITE = 1, + AU0828_VMUX_SVIDEO, + AU0828_VMUX_CABLE, + AU0828_VMUX_TELEVISION, + AU0828_VMUX_DVB, + AU0828_VMUX_DEBUG +}; + +struct au0828_input { + enum au0828_itype type; + unsigned int vmux; + unsigned int amux; + void (*audio_setup) (void *priv, int enable); +}; + struct au0828_board { char *name; + struct au0828_input input[AU0828_MAX_INPUT]; + }; struct au0828_dvb { @@ -55,6 +99,83 @@ struct au0828_dvb { int feeding; }; +enum au0828_stream_state { + STREAM_OFF, + STREAM_INTERRUPT, + STREAM_ON +}; + +#define AUVI_INPUT(nr) (&au0828_boards[dev->board].input[nr]) + +/* device state */ +enum au0828_dev_state { + DEV_INITIALIZED = 0x01, + DEV_DISCONNECTED = 0x02, + DEV_MISCONFIGURED = 0x04 +}; + +struct au0828_fh { + struct au0828_dev *dev; + unsigned int stream_on:1; /* Locks streams */ + struct videobuf_queue vb_vidq; + enum v4l2_buf_type type; +}; + +struct au0828_usb_isoc_ctl { + /* max packet size of isoc transaction */ + int max_pkt_size; + + /* number of allocated urbs */ + int num_bufs; + + /* urb for isoc transfers */ + struct urb **urb; + + /* transfer buffers for isoc transfer */ + char **transfer_buffer; + + /* Last buffer command and region */ + u8 cmd; + int pos, size, pktsize; + + /* Last field: ODD or EVEN? */ + int field; + + /* Stores incomplete commands */ + u32 tmp_buf; + int tmp_buf_len; + + /* Stores already requested buffers */ + struct au0828_buffer *buf; + + /* Stores the number of received fields */ + int nfields; + + /* isoc urb callback */ + int (*isoc_copy) (struct au0828_dev *dev, struct urb *urb); + +}; + +/* buffer for one video frame */ +struct au0828_buffer { + /* common v4l buffer stuff -- must be first */ + struct videobuf_buffer vb; + + struct list_head frame; + int top_field; + int receiving; +}; + +struct au0828_dmaqueue { + struct list_head active; + struct list_head queued; + + wait_queue_head_t wq; + + /* Counters to control buffer fill */ + int pos; +}; + struct au0828_dev { struct mutex mutex; struct usb_device *usbdev; @@ -70,16 +191,49 @@ struct au0828_dev { /* Digital */ struct au0828_dvb dvb; + /* Analog */ + struct list_head au0828list; + int users; + unsigned int stream_on:1; /* Locks streams */ + struct video_device *vdev; + struct video_device *vbi_dev; + int width; + int height; + u32 field_size; + u32 frame_size; + u32 bytesperline; + int type; + u8 ctrl_ainput; + __u8 isoc_in_endpointaddr; + u8 isoc_init_ok; + int greenscreen_detected; + unsigned int frame_count; + int ctrl_freq; + int input_type; + unsigned int ctrl_input; + enum au0828_dev_state dev_state; + enum au0828_stream_state stream_state; + wait_queue_head_t open; + + struct mutex lock; + + /* Isoc control struct */ + struct au0828_dmaqueue vidq; + struct au0828_usb_isoc_ctl isoc_ctl; + spinlock_t slock; + + /* usb transfer */ + int alt; /* alternate */ + int max_pkt_size; /* max packet size of isoc transaction */ + int num_alt; /* Number of alternative settings */ + unsigned int *alt_max_pkt_size; /* array of wMaxPacketSize */ + struct urb *urb[AU0828_MAX_ISO_BUFS]; /* urb for isoc transfers */ + char *transfer_buffer[AU0828_MAX_ISO_BUFS];/* transfer buffers for isoc + transfer */ + /* USB / URB Related */ int urb_streaming; struct urb *urbs[URB_COUNT]; - -}; - -struct au0828_buff { - struct au0828_dev *dev; - struct urb *purb; - struct list_head buff_list; }; /* ----------------------------------------------------------- */ @@ -114,6 +268,12 @@ extern int au0828_i2c_unregister(struct au0828_dev *dev); extern void au0828_call_i2c_clients(struct au0828_dev *dev, unsigned int cmd, void *arg); +/* ----------------------------------------------------------- */ +/* au0828-video.c */ +int au0828_analog_register(struct au0828_dev *dev); +int au0828_analog_stream_disable(struct au0828_dev *d); +void au0828_analog_unregister(struct au0828_dev *dev); + /* ----------------------------------------------------------- */ /* au0828-dvb.c */ extern int au0828_dvb_register(struct au0828_dev *dev); -- cgit v1.2.3 From 32c000ad93fe8c447342632024ddef1ca516a0e9 Mon Sep 17 00:00:00 2001 From: Devin Heitmueller Date: Wed, 11 Mar 2009 03:00:41 -0300 Subject: V4L/DVB (11067): au0828: workaround a bug in the au0828 i2c handling There is an issue related to the i2c clock for addressing the xc5000. The au0828 chip does not support clock stretching, which the xc5000 makes use of. This results in cases where we silently get back garbage in i2c read operations. To work around this issue until we slow down the i2c clock when talking with that specific device. This was not an issue before we had analog support because we never needed to enumerate the i2c bus, and digital tuning never actually needed to perform read operations against the xc5000. Thanks to Michael Krufky and Steven Toth for providing sample hardware, engineering level support, and testing. Signed-off-by: Devin Heitmueller Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/au0828/au0828-i2c.c | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/au0828/au0828-i2c.c b/drivers/media/video/au0828/au0828-i2c.c index d618fbaade1b..ee3e3040d54c 100644 --- a/drivers/media/video/au0828/au0828-i2c.c +++ b/drivers/media/video/au0828/au0828-i2c.c @@ -140,7 +140,16 @@ static int i2c_sendbytes(struct i2c_adapter *i2c_adap, dprintk(4, "%s()\n", __func__); au0828_write(dev, REG_2FF, 0x01); - au0828_write(dev, REG_202, 0x07); + + /* FIXME: There is a problem with i2c communications with xc5000 that + requires us to slow down the i2c clock until we have a better + strategy (such as using the secondary i2c bus to do firmware + loading */ + if ((msg->addr << 1) == 0xc2) { + au0828_write(dev, REG_202, 0x40); + } else { + au0828_write(dev, REG_202, 0x07); + } /* Hardware needs 8 bit addresses */ au0828_write(dev, REG_203, msg->addr << 1); @@ -191,7 +200,16 @@ static int i2c_readbytes(struct i2c_adapter *i2c_adap, dprintk(4, "%s()\n", __func__); au0828_write(dev, REG_2FF, 0x01); - au0828_write(dev, REG_202, 0x07); + + /* FIXME: There is a problem with i2c communications with xc5000 that + requires us to slow down the i2c clock until we have a better + strategy (such as using the secondary i2c bus to do firmware + loading */ + if ((msg->addr << 1) == 0xc2) { + au0828_write(dev, REG_202, 0x40); + } else { + au0828_write(dev, REG_202, 0x07); + } /* Hardware needs 8 bit addresses */ au0828_write(dev, REG_203, msg->addr << 1); -- cgit v1.2.3 From 7fdd7c72ad65ef98d1071cf4cd8a39490f423bae Mon Sep 17 00:00:00 2001 From: Devin Heitmueller Date: Wed, 11 Mar 2009 03:00:43 -0300 Subject: V4L/DVB (11068): au0828: add analog profile for the HVR-850 Add the analog parameters to the device profile for the HVR-850 Thanks to Michael Krufky and Steven Toth for providing sample hardware, engineering level support, and testing. Signed-off-by: Devin Heitmueller Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/au0828/au0828-cards.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) (limited to 'drivers/media/video') diff --git a/drivers/media/video/au0828/au0828-cards.c b/drivers/media/video/au0828/au0828-cards.c index aa79e6b7ecab..8b7ad43ed57c 100644 --- a/drivers/media/video/au0828/au0828-cards.c +++ b/drivers/media/video/au0828/au0828-cards.c @@ -40,6 +40,25 @@ struct au0828_board au0828_boards[] = { }, [AU0828_BOARD_HAUPPAUGE_HVR850] = { .name = "Hauppauge HVR850", + .input = { + { + .type = AU0828_VMUX_TELEVISION, + .vmux = AU8522_COMPOSITE_CH4_SIF, + .amux = AU8522_AUDIO_SIF, + }, + { + .type = AU0828_VMUX_COMPOSITE, + .vmux = AU8522_COMPOSITE_CH1, + .amux = AU8522_AUDIO_NONE, + .audio_setup = hvr950q_cs5340_audio, + }, + { + .type = AU0828_VMUX_SVIDEO, + .vmux = AU8522_SVIDEO_CH13, + .amux = AU8522_AUDIO_NONE, + .audio_setup = hvr950q_cs5340_audio, + }, + }, }, [AU0828_BOARD_HAUPPAUGE_HVR950Q] = { .name = "Hauppauge HVR950Q", -- cgit v1.2.3 From f1add5b5ec2a6efaa0f5648d0dc2c56d83a3ecf8 Mon Sep 17 00:00:00 2001 From: Devin Heitmueller Date: Wed, 11 Mar 2009 03:00:47 -0300 Subject: V4L/DVB (11070): au0828: Rework the way the analog video binding occurs Rework the way boards are managed so that we can change the board description based on the Hauppauge eeprom (modeled after cx88-cards.c). Also, make sure that we don't load the analog stack if there are no analog inputs defined in the board profile. Thanks to Michael Krufky for providing information on the various ways different Hauppauge boards can be configured. Signed-off-by: Devin Heitmueller Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/au0828/au0828-cards.c | 45 ++++++++++++++++++++++++++++--- drivers/media/video/au0828/au0828-core.c | 11 ++++---- drivers/media/video/au0828/au0828-dvb.c | 2 +- drivers/media/video/au0828/au0828-video.c | 40 +++++++++++---------------- drivers/media/video/au0828/au0828.h | 7 +++-- 5 files changed, 70 insertions(+), 35 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/au0828/au0828-cards.c b/drivers/media/video/au0828/au0828-cards.c index 8b7ad43ed57c..e10b1b9221e0 100644 --- a/drivers/media/video/au0828/au0828-cards.c +++ b/drivers/media/video/au0828/au0828-cards.c @@ -22,6 +22,8 @@ #include "au0828.h" #include "au0828-cards.h" #include "au8522.h" +#include "media/tuner.h" +#include "media/v4l2-common.h" void hvr950q_cs5340_audio(void *priv, int enable) { @@ -37,9 +39,13 @@ void hvr950q_cs5340_audio(void *priv, int enable) struct au0828_board au0828_boards[] = { [AU0828_BOARD_UNKNOWN] = { .name = "Unknown board", + .tuner_type = UNSET, + .tuner_addr = ADDR_UNSET, }, [AU0828_BOARD_HAUPPAUGE_HVR850] = { .name = "Hauppauge HVR850", + .tuner_type = TUNER_XC5000, + .tuner_addr = 0x61, .input = { { .type = AU0828_VMUX_TELEVISION, @@ -62,6 +68,8 @@ struct au0828_board au0828_boards[] = { }, [AU0828_BOARD_HAUPPAUGE_HVR950Q] = { .name = "Hauppauge HVR950Q", + .tuner_type = TUNER_XC5000, + .tuner_addr = 0x61, .input = { { .type = AU0828_VMUX_TELEVISION, @@ -84,12 +92,18 @@ struct au0828_board au0828_boards[] = { }, [AU0828_BOARD_HAUPPAUGE_HVR950Q_MXL] = { .name = "Hauppauge HVR950Q rev xxF8", + .tuner_type = UNSET, + .tuner_addr = ADDR_UNSET, }, [AU0828_BOARD_DVICO_FUSIONHDTV7] = { .name = "DViCO FusionHDTV USB", + .tuner_type = UNSET, + .tuner_addr = ADDR_UNSET, }, [AU0828_BOARD_HAUPPAUGE_WOODBURY] = { .name = "Hauppauge Woodbury", + .tuner_type = UNSET, + .tuner_addr = ADDR_UNSET, }, }; @@ -102,7 +116,7 @@ int au0828_tuner_callback(void *priv, int component, int command, int arg) dprintk(1, "%s()\n", __func__); - switch (dev->board) { + switch (dev->boardnr) { case AU0828_BOARD_HAUPPAUGE_HVR850: case AU0828_BOARD_HAUPPAUGE_HVR950Q: case AU0828_BOARD_HAUPPAUGE_HVR950Q_MXL: @@ -131,6 +145,7 @@ static void hauppauge_eeprom(struct au0828_dev *dev, u8 *eeprom_data) struct tveeprom tv; tveeprom_hauppauge_analog(&dev->i2c_client, &tv, eeprom_data); + dev->board.tuner_type = tv.tuner_type; /* Make sure we support the board model */ switch (tv.model) { @@ -157,15 +172,20 @@ static void hauppauge_eeprom(struct au0828_dev *dev, u8 *eeprom_data) void au0828_card_setup(struct au0828_dev *dev) { static u8 eeprom[256]; + struct tuner_setup tun_setup; + unsigned int mode_mask = T_ANALOG_TV | + T_DIGITAL_TV; dprintk(1, "%s()\n", __func__); + memcpy(&dev->board, &au0828_boards[dev->boardnr], sizeof(dev->board)); + if (dev->i2c_rc == 0) { dev->i2c_client.addr = 0xa0 >> 1; tveeprom_read(&dev->i2c_client, eeprom, sizeof(eeprom)); } - switch (dev->board) { + switch (dev->boardnr) { case AU0828_BOARD_HAUPPAUGE_HVR850: case AU0828_BOARD_HAUPPAUGE_HVR950Q: case AU0828_BOARD_HAUPPAUGE_HVR950Q_MXL: @@ -174,6 +194,25 @@ void au0828_card_setup(struct au0828_dev *dev) hauppauge_eeprom(dev, eeprom+0xa0); break; } + + if (dev->board.input != NULL) { + /* Load the analog demodulator driver (note this would need to + be abstracted out if we ever need to support a different + demod) */ + request_module("au8522"); + } + + /* Setup tuners */ + if (dev->board.tuner_type != TUNER_ABSENT) { + /* Load the tuner module, which does the attach */ + request_module("tuner"); + + tun_setup.mode_mask = mode_mask; + tun_setup.type = dev->board.tuner_type; + tun_setup.addr = dev->board.tuner_addr; + tun_setup.tuner_callback = au0828_tuner_callback; + au0828_call_i2c_clients(dev, TUNER_SET_TYPE_ADDR, &tun_setup); + } } /* @@ -185,7 +224,7 @@ void au0828_gpio_setup(struct au0828_dev *dev) { dprintk(1, "%s()\n", __func__); - switch (dev->board) { + switch (dev->boardnr) { case AU0828_BOARD_HAUPPAUGE_HVR850: case AU0828_BOARD_HAUPPAUGE_HVR950Q: case AU0828_BOARD_HAUPPAUGE_HVR950Q_MXL: diff --git a/drivers/media/video/au0828/au0828-core.c b/drivers/media/video/au0828/au0828-core.c index 680e88f61397..0bc85b7d67d4 100644 --- a/drivers/media/video/au0828/au0828-core.c +++ b/drivers/media/video/au0828/au0828-core.c @@ -146,7 +146,8 @@ static void au0828_usb_disconnect(struct usb_interface *interface) /* Digital TV */ au0828_dvb_unregister(dev); - au0828_analog_unregister(dev); + if (dev->board.input != NULL) + au0828_analog_unregister(dev); /* I2C */ au0828_i2c_unregister(dev); @@ -189,7 +190,7 @@ static int au0828_usb_probe(struct usb_interface *interface, mutex_init(&dev->mutex); mutex_init(&dev->dvb.lock); dev->usbdev = usbdev; - dev->board = id->driver_info; + dev->boardnr = id->driver_info; usb_set_intfdata(interface, dev); @@ -230,14 +231,14 @@ static int au0828_usb_probe(struct usb_interface *interface, au0828_card_setup(dev); /* Analog TV */ - au0828_analog_register(dev); + if (dev->board.input != NULL) + au0828_analog_register(dev); /* Digital TV */ au0828_dvb_register(dev); printk(KERN_INFO "Registered device AU0828 [%s]\n", - au0828_boards[dev->board].name == NULL ? "Unset" : - au0828_boards[dev->board].name); + dev->board.name == NULL ? "Unset" : dev->board.name); return 0; } diff --git a/drivers/media/video/au0828/au0828-dvb.c b/drivers/media/video/au0828/au0828-dvb.c index a882cf546d0a..14baffc22192 100644 --- a/drivers/media/video/au0828/au0828-dvb.c +++ b/drivers/media/video/au0828/au0828-dvb.c @@ -378,7 +378,7 @@ int au0828_dvb_register(struct au0828_dev *dev) dprintk(1, "%s()\n", __func__); /* init frontend */ - switch (dev->board) { + switch (dev->boardnr) { case AU0828_BOARD_HAUPPAUGE_HVR850: case AU0828_BOARD_HAUPPAUGE_HVR950Q: dvb->frontend = dvb_attach(au8522_attach, diff --git a/drivers/media/video/au0828/au0828-video.c b/drivers/media/video/au0828/au0828-video.c index e34464f81f36..064de23a3ce1 100644 --- a/drivers/media/video/au0828/au0828-video.c +++ b/drivers/media/video/au0828/au0828-video.c @@ -1013,7 +1013,7 @@ static int vidioc_querycap(struct file *file, void *priv, memset(cap, 0, sizeof(*cap)); strlcpy(cap->driver, "au0828", sizeof(cap->driver)); - strlcpy(cap->card, au0828_boards[dev->board].name, sizeof(cap->card)); + strlcpy(cap->card, dev->board.name, sizeof(cap->card)); strlcpy(cap->bus_info, dev->usbdev->dev.bus_id, sizeof(cap->bus_info)); cap->version = AU0828_VERSION_CODE; @@ -1127,14 +1127,14 @@ static int vidioc_enum_input(struct file *file, void *priv, if(tmp > AU0828_MAX_INPUT) return -EINVAL; - if(AUVI_INPUT(tmp)->type == 0) + if(AUVI_INPUT(tmp).type == 0) return -EINVAL; memset(input, 0, sizeof(*input)); input->index = tmp; - strcpy(input->name, inames[AUVI_INPUT(tmp)->type]); - if((AUVI_INPUT(tmp)->type == AU0828_VMUX_TELEVISION) || - (AUVI_INPUT(tmp)->type == AU0828_VMUX_CABLE)) + strcpy(input->name, inames[AUVI_INPUT(tmp).type]); + if((AUVI_INPUT(tmp).type == AU0828_VMUX_TELEVISION) || + (AUVI_INPUT(tmp).type == AU0828_VMUX_CABLE)) input->type |= V4L2_INPUT_TYPE_TUNER; else input->type |= V4L2_INPUT_TYPE_CAMERA; @@ -1163,11 +1163,11 @@ static int vidioc_s_input(struct file *file, void *priv, unsigned int index) index); if(index >= AU0828_MAX_INPUT) return -EINVAL; - if(AUVI_INPUT(index)->type == 0) + if(AUVI_INPUT(index).type == 0) return -EINVAL; dev->ctrl_input = index; - switch(AUVI_INPUT(index)->type) { + switch(AUVI_INPUT(index).type) { case AU0828_VMUX_SVIDEO: { dev->input_type = AU0828_VMUX_SVIDEO; @@ -1187,13 +1187,13 @@ static int vidioc_s_input(struct file *file, void *priv, unsigned int index) ; } - route.input = AUVI_INPUT(index)->vmux; + route.input = AUVI_INPUT(index).vmux; route.output = 0; au0828_call_i2c_clients(dev, VIDIOC_INT_S_VIDEO_ROUTING, &route); for (i = 0; i < AU0828_MAX_INPUT; i++) { int enable = 0; - if (AUVI_INPUT(i)->audio_setup == NULL) { + if (AUVI_INPUT(i).audio_setup == NULL) { continue; } @@ -1202,18 +1202,18 @@ static int vidioc_s_input(struct file *file, void *priv, unsigned int index) else enable = 0; if (enable) { - (AUVI_INPUT(i)->audio_setup)(dev, enable); + (AUVI_INPUT(i).audio_setup)(dev, enable); } else { /* Make sure we leave it turned on if some other input is routed to this callback */ - if ((AUVI_INPUT(i)->audio_setup) != - ((AUVI_INPUT(index)->audio_setup))) { - (AUVI_INPUT(i)->audio_setup)(dev, enable); + if ((AUVI_INPUT(i).audio_setup) != + ((AUVI_INPUT(index).audio_setup))) { + (AUVI_INPUT(i).audio_setup)(dev, enable); } } } - route.input = AUVI_INPUT(index)->amux; + route.input = AUVI_INPUT(index).amux; au0828_call_i2c_clients(dev, VIDIOC_INT_S_AUDIO_ROUTING, &route); return 0; @@ -1419,10 +1419,10 @@ static int vidioc_streamoff(struct file *file, void *priv, } for (i = 0; i < AU0828_MAX_INPUT; i++) { - if (AUVI_INPUT(i)->audio_setup == NULL) { + if (AUVI_INPUT(i).audio_setup == NULL) { continue; } - (AUVI_INPUT(i)->audio_setup)(dev, 0); + (AUVI_INPUT(i).audio_setup)(dev, 0); } mutex_lock(&dev->lock); @@ -1603,14 +1603,6 @@ int au0828_analog_register(struct au0828_dev *dev) dprintk(1, "au0828_analog_register called!\n"); - /* Load the analog demodulator driver (note this would need to be - abstracted out if we ever need to support a different demod) */ - request_module("au8522"); - - /* Load the tuner module, which results in i2c enumeration and - attachment of whatever tuner is on the bus */ - request_module("tuner"); - init_waitqueue_head(&dev->open); spin_lock_init(&dev->slock); mutex_init(&dev->lock); diff --git a/drivers/media/video/au0828/au0828.h b/drivers/media/video/au0828/au0828.h index 3b8e3e913475..2f48ec2136bf 100644 --- a/drivers/media/video/au0828/au0828.h +++ b/drivers/media/video/au0828/au0828.h @@ -83,6 +83,8 @@ struct au0828_input { struct au0828_board { char *name; + unsigned int tuner_type; + unsigned char tuner_addr; struct au0828_input input[AU0828_MAX_INPUT]; }; @@ -105,7 +107,7 @@ enum au0828_stream_state { STREAM_ON }; -#define AUVI_INPUT(nr) (&au0828_boards[dev->board].input[nr]) +#define AUVI_INPUT(nr) (dev->board.input[nr]) /* device state */ enum au0828_dev_state { @@ -179,7 +181,8 @@ struct au0828_dmaqueue { struct au0828_dev { struct mutex mutex; struct usb_device *usbdev; - int board; + int boardnr; + struct au0828_board board; u8 ctrlmsg[64]; /* I2C */ -- cgit v1.2.3 From e2bff45cd6151b4deb6adfd94eab87374f43ea34 Mon Sep 17 00:00:00 2001 From: Devin Heitmueller Date: Wed, 11 Mar 2009 03:00:49 -0300 Subject: V4L/DVB (11071): tveeprom: add the xc5000 tuner to the tveeprom definition Prior to now, we never relied on the Hauppauge tveeprom to identify which tuner is associated with the board. Now that the HVR-950q determines what the tuner is based on the eeprom, set the tuner ID appropriately. Thanks to Michael Krufky for providing information on the tveeprom organization. Signed-off-by: Devin Heitmueller Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/tveeprom.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/tveeprom.c b/drivers/media/video/tveeprom.c index 63705b8cd1ed..e24a38c7fa46 100644 --- a/drivers/media/video/tveeprom.c +++ b/drivers/media/video/tveeprom.c @@ -261,7 +261,7 @@ hauppauge_tuner[] = { TUNER_ABSENT, "MaxLinear MXL5005_v2"}, { TUNER_PHILIPS_TDA8290, "Philips 18271_8295"}, /* 150-159 */ - { TUNER_ABSENT, "Xceive XC5000"}, + { TUNER_XC5000, "Xceive XC5000"}, { TUNER_ABSENT, "Xceive XC3028L"}, { TUNER_ABSENT, "NXP 18271C2_716x"}, { TUNER_ABSENT, "Xceive XC4000"}, -- cgit v1.2.3 From 0ef21071d985cb9e33238210760810c71e100b20 Mon Sep 17 00:00:00 2001 From: Devin Heitmueller Date: Wed, 11 Mar 2009 03:00:53 -0300 Subject: V4L/DVB (11072): au0828: advertise only NTSC-M (as opposed to all NTSC standards) We don't now how to make any variant of NTSC work other than NTSC-M, so don't advertise that we support the other variants. Signed-off-by: Devin Heitmueller Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/au0828/au0828-video.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/au0828/au0828-video.c b/drivers/media/video/au0828/au0828-video.c index 064de23a3ce1..7f6f9d998aa9 100644 --- a/drivers/media/video/au0828/au0828-video.c +++ b/drivers/media/video/au0828/au0828-video.c @@ -1591,8 +1591,8 @@ static const struct video_device au0828_video_template = { .release = video_device_release, .ioctl_ops = &video_ioctl_ops, .minor = -1, - .tvnorms = V4L2_STD_NTSC, - .current_norm = V4L2_STD_NTSC, + .tvnorms = V4L2_STD_NTSC_M, + .current_norm = V4L2_STD_NTSC_M, }; /**************************************************************************/ -- cgit v1.2.3 From 5a5a4e16fa19fa3789398e8c707168b7da718b64 Mon Sep 17 00:00:00 2001 From: Devin Heitmueller Date: Wed, 11 Mar 2009 03:00:55 -0300 Subject: V4L/DVB (11073): au0828: disable VBI code since it doesn't yet work Since the VBI support is not yet working for the au0828, don't advertise the capability or create the /dev/vbi device. Signed-off-by: Devin Heitmueller Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/au0828/au0828-video.c | 29 ++++++++++++++++++++++++----- 1 file changed, 24 insertions(+), 5 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/au0828/au0828-video.c b/drivers/media/video/au0828/au0828-video.c index 7f6f9d998aa9..0dd138370b62 100644 --- a/drivers/media/video/au0828/au0828-video.c +++ b/drivers/media/video/au0828/au0828-video.c @@ -701,8 +701,10 @@ void au0828_analog_unregister(struct au0828_dev *dev) mutex_lock(&au0828_sysfs_lock); list_del(&dev->au0828list); - video_unregister_device(dev->vdev); - video_unregister_device(dev->vbi_dev); + if (dev->vdev) + video_unregister_device(dev->vdev); + if (dev->vbi_dev) + video_unregister_device(dev->vbi_dev); mutex_unlock(&au0828_sysfs_lock); } @@ -754,10 +756,12 @@ static int au0828_v4l2_open(struct file *filp) dev = h; type = V4L2_BUF_TYPE_VIDEO_CAPTURE; } +#ifdef VBI_NOT_YET_WORKING if(h->vbi_dev->minor == minor) { dev = h; type = V4L2_BUF_TYPE_VBI_CAPTURE; } +#endif } if(NULL == dev) @@ -931,6 +935,7 @@ static int au0828_set_format(struct au0828_dev *dev, unsigned int cmd, maxwidth = 720; maxheight = 480; +#ifdef VBI_NOT_YET_WORKING if(format->type == V4L2_BUF_TYPE_SLICED_VBI_CAPTURE) { dprintk(1, "VBI format set: to be supported!\n"); return 0; @@ -938,6 +943,7 @@ static int au0828_set_format(struct au0828_dev *dev, unsigned int cmd, if(format->type == V4L2_BUF_TYPE_VBI_CAPTURE) { return 0; } +#endif if(format->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) { return -EINVAL; } @@ -1019,8 +1025,10 @@ static int vidioc_querycap(struct file *file, void *priv, cap->version = AU0828_VERSION_CODE; /*set the device capabilities */ - cap->capabilities = V4L2_CAP_VBI_CAPTURE | - V4L2_CAP_VIDEO_CAPTURE | + cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | +#ifdef VBI_NOT_YET_WORKING + V4L2_CAP_VBI_CAPTURE | +#endif V4L2_CAP_AUDIO | V4L2_CAP_READWRITE | V4L2_CAP_STREAMING | @@ -1551,10 +1559,15 @@ static const struct v4l2_ioctl_ops video_ioctl_ops = { .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap, .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap, .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap, +#ifdef VBI_NOT_YET_WORKING + .vidioc_g_fmt_vbi_cap = vidioc_g_fmt_vbi_cap, + .vidioc_try_fmt_vbi_cap = vidioc_s_fmt_vbi_cap, + .vidioc_s_fmt_vbi_cap = vidioc_s_fmt_vbi_cap, +#endif .vidioc_g_audio = vidioc_g_audio, .vidioc_s_audio = vidioc_s_audio, .vidioc_cropcap = vidioc_cropcap, -#ifdef AAA +#ifdef VBI_NOT_YET_WORKING .vidioc_g_fmt_sliced_vbi_cap = vidioc_g_fmt_sliced_vbi_cap, .vidioc_try_fmt_sliced_vbi_cap = vidioc_try_set_sliced_vbi_cap, .vidioc_s_fmt_sliced_vbi_cap = vidioc_try_set_sliced_vbi_cap, @@ -1624,12 +1637,14 @@ int au0828_analog_register(struct au0828_dev *dev) return -ENOMEM; } +#ifdef VBI_NOT_YET_WORKING dev->vbi_dev = video_device_alloc(); if(NULL == dev->vbi_dev) { dprintk(1, "Can't allocate vbi_device.\n"); kfree(dev->vdev); return -ENOMEM; } +#endif /* Fill the video capture device struct */ *dev->vdev = au0828_video_template; @@ -1637,11 +1652,13 @@ int au0828_analog_register(struct au0828_dev *dev) dev->vdev->parent = &dev->usbdev->dev; strcpy(dev->vdev->name, "au0828a video"); +#ifdef VBI_NOT_YET_WORKING /* Setup the VBI device */ *dev->vbi_dev = au0828_video_template; dev->vbi_dev->vfl_type = VFL_TYPE_VBI; dev->vbi_dev->parent = &dev->usbdev->dev; strcpy(dev->vbi_dev->name, "au0828a vbi"); +#endif list_add_tail(&dev->au0828list, &au0828_devlist); @@ -1653,6 +1670,7 @@ int au0828_analog_register(struct au0828_dev *dev) return -ENODEV; } +#ifdef VBI_NOT_YET_WORKING /* Register the vbi device */ if((retval = video_register_device(dev->vbi_dev, VFL_TYPE_VBI, -1)) != 0) { dprintk(1, "unable to register vbi device (error = %d).\n", retval); @@ -1661,6 +1679,7 @@ int au0828_analog_register(struct au0828_dev *dev) video_device_release(dev->vdev); return -ENODEV; } +#endif dprintk(1, "%s completed!\n", __FUNCTION__); -- cgit v1.2.3 From dc8685b565d6526aca6aaefb80059d115c124821 Mon Sep 17 00:00:00 2001 From: Devin Heitmueller Date: Wed, 11 Mar 2009 03:00:56 -0300 Subject: V4L/DVB (11074): au0828: fix i2c enumeration bug There was a bug where enumerating the i2c for devices would result in false positives. The root of the issue was the scanning was using SMBUS_QUICK messages, which are zero length write requests (which our i2c adapter implementation didn't handle). Because we never strobed any bytes onto the bus, the status register would still contain the value from the previous request. Thanks to Michael Krufky and Steven Toth for providing sample hardware, engineering level support, and testing. Signed-off-by: Devin Heitmueller Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/au0828/au0828-i2c.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) (limited to 'drivers/media/video') diff --git a/drivers/media/video/au0828/au0828-i2c.c b/drivers/media/video/au0828/au0828-i2c.c index ee3e3040d54c..d57a38f5c738 100644 --- a/drivers/media/video/au0828/au0828-i2c.c +++ b/drivers/media/video/au0828/au0828-i2c.c @@ -156,6 +156,24 @@ static int i2c_sendbytes(struct i2c_adapter *i2c_adap, dprintk(4, "SEND: %02x\n", msg->addr); + /* Deal with i2c_scan */ + if (msg->len == 0) { + /* The analog tuner detection code makes use of the SMBUS_QUICK + message (which involves a zero length i2c write). To avoid + checking the status register when we didn't strobe out any + actual bytes to the bus, just do a read check. This is + consistent with how I saw i2c device checking done in the + USB trace of the Windows driver */ + au0828_write(dev, REG_200, 0x20); + if (!i2c_wait_done(i2c_adap)) + return -EIO; + + if (i2c_wait_read_ack(i2c_adap)) + return -EIO; + + return 0; + } + for (i = 0; i < msg->len;) { dprintk(4, " %02x\n", msg->buf[i]); -- cgit v1.2.3 From b80f770a981db1d1f5a41626792c701f8c5bf973 Mon Sep 17 00:00:00 2001 From: Devin Heitmueller Date: Wed, 11 Mar 2009 03:00:57 -0300 Subject: V4L/DVB (11075): au0828: make register debug lines easier to read Make it a little easier to read the debug messages for register read/write operations Signed-off-by: Devin Heitmueller Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/au0828/au0828-core.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/au0828/au0828-core.c b/drivers/media/video/au0828/au0828-core.c index 0bc85b7d67d4..f47fd9d78fa0 100644 --- a/drivers/media/video/au0828/au0828-core.c +++ b/drivers/media/video/au0828/au0828-core.c @@ -51,13 +51,13 @@ static int recv_control_msg(struct au0828_dev *dev, u16 request, u32 value, u32 au0828_readreg(struct au0828_dev *dev, u16 reg) { recv_control_msg(dev, CMD_REQUEST_IN, 0, reg, dev->ctrlmsg, 1); - dprintk(8, "%s(0x%x) = 0x%x\n", __func__, reg, dev->ctrlmsg[0]); + dprintk(8, "%s(0x%04x) = 0x%02x\n", __func__, reg, dev->ctrlmsg[0]); return dev->ctrlmsg[0]; } u32 au0828_writereg(struct au0828_dev *dev, u16 reg, u32 val) { - dprintk(8, "%s(0x%x, 0x%x)\n", __func__, reg, val); + dprintk(8, "%s(0x%04x, 0x%02x)\n", __func__, reg, val); return send_control_msg(dev, CMD_REQUEST_OUT, val, reg, dev->ctrlmsg, 0); } -- cgit v1.2.3 From d9109bef4b4f501eee94ae68bf876f765d5c6941 Mon Sep 17 00:00:00 2001 From: Devin Heitmueller Date: Wed, 11 Mar 2009 03:00:58 -0300 Subject: V4L/DVB (11076): au0828: make g_chip_ident call work properly Make the g_chip_ident call work for the au0828/au8522. Discovered when testing with the v4l2_compliance tool Signed-off-by: Devin Heitmueller Signed-off-by: Michael Krufky [mchehab@redhat.com: fix merge conflict, due to a path change for analog demod] Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/au8522_decoder.c | 1 + drivers/media/video/au0828/au0828-video.c | 8 ++++++++ include/media/v4l2-chip-ident.h | 3 +++ 3 files changed, 12 insertions(+) (limited to 'drivers/media/video') diff --git a/drivers/media/dvb/frontends/au8522_decoder.c b/drivers/media/dvb/frontends/au8522_decoder.c index e2927c145cd8..564636389bae 100644 --- a/drivers/media/dvb/frontends/au8522_decoder.c +++ b/drivers/media/dvb/frontends/au8522_decoder.c @@ -636,6 +636,7 @@ static int au8522_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qc) break; } + qc->type = 0; return -EINVAL; } diff --git a/drivers/media/video/au0828/au0828-video.c b/drivers/media/video/au0828/au0828-video.c index 0dd138370b62..ce80882d45e2 100644 --- a/drivers/media/video/au0828/au0828-video.c +++ b/drivers/media/video/au0828/au0828-video.c @@ -1348,7 +1348,15 @@ static int vidioc_g_chip_ident(struct file *file, void *priv, chip->ident = V4L2_IDENT_NONE; chip->revision = 0; + if (v4l2_chip_match_host(&chip->match)) { + chip->ident = V4L2_IDENT_AU0828; + return 0; + } + au0828_call_i2c_clients(dev, VIDIOC_DBG_G_CHIP_IDENT, chip); + if (chip->ident == V4L2_IDENT_NONE) + return -EINVAL; + return 0; } diff --git a/include/media/v4l2-chip-ident.h b/include/media/v4l2-chip-ident.h index 43684f105fd8..ca2aa6d7e386 100644 --- a/include/media/v4l2-chip-ident.h +++ b/include/media/v4l2-chip-ident.h @@ -70,6 +70,9 @@ enum { V4L2_IDENT_CX23416 = 416, V4L2_IDENT_CX23418 = 418, + /* module au0828 */ + V4L2_IDENT_AU0828 = 828, + /* module indycam: just ident 2000 */ V4L2_IDENT_INDYCAM = 2000, -- cgit v1.2.3 From fc4ce6cd9855dcd1151a9afc067ea354179089f9 Mon Sep 17 00:00:00 2001 From: Devin Heitmueller Date: Wed, 11 Mar 2009 03:01:00 -0300 Subject: V4L/DVB (11077): au0828: properly handle missing analog USB endpoint Move the setup of the analog isoc handler into au0828-video.c, so it does not occur if there is not an .input section defined for the board. Also fixes a case where if there is an input section but the board does not actually have analog support, the digital support will continue to work as expected. Thanks to Michael Krufky for providing sample hardware of various configurations to test with. Signed-off-by: Devin Heitmueller Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/au0828/au0828-core.c | 30 ++-------------------------- drivers/media/video/au0828/au0828-video.c | 33 ++++++++++++++++++++++++++++++- drivers/media/video/au0828/au0828.h | 3 ++- 3 files changed, 36 insertions(+), 30 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/au0828/au0828-core.c b/drivers/media/video/au0828/au0828-core.c index f47fd9d78fa0..2b5ade626e57 100644 --- a/drivers/media/video/au0828/au0828-core.c +++ b/drivers/media/video/au0828/au0828-core.c @@ -165,11 +165,9 @@ static void au0828_usb_disconnect(struct usb_interface *interface) static int au0828_usb_probe(struct usb_interface *interface, const struct usb_device_id *id) { - int ifnum, i; + int ifnum; struct au0828_dev *dev; struct usb_device *usbdev = interface_to_usbdev(interface); - struct usb_host_interface *iface_desc; - struct usb_endpoint_descriptor *endpoint; ifnum = interface->altsetting->desc.bInterfaceNumber; @@ -194,30 +192,6 @@ static int au0828_usb_probe(struct usb_interface *interface, usb_set_intfdata(interface, dev); - /* set au0828 usb interface0 to as5 */ - usb_set_interface(usbdev, - interface->cur_altsetting->desc.bInterfaceNumber, 5); - - /* Figure out which endpoint has the isoc interface */ - iface_desc = interface->cur_altsetting; - for(i = 0; i < iface_desc->desc.bNumEndpoints; i++){ - endpoint = &iface_desc->endpoint[i].desc; - if(((endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_IN) && - ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_ISOC)){ - - /* we find our isoc in endpoint */ - u16 tmp = le16_to_cpu(endpoint->wMaxPacketSize); - dev->max_pkt_size = (tmp & 0x07ff) * (((tmp & 0x1800) >> 11) + 1); - dev->isoc_in_endpointaddr = endpoint->bEndpointAddress; - } - } - if(!(dev->isoc_in_endpointaddr)) { - printk("Could not locate isoc endpoint\n"); - kfree(dev); - return -ENODEV; - } - - /* Power Up the bridge */ au0828_write(dev, REG_600, 1 << 4); @@ -232,7 +206,7 @@ static int au0828_usb_probe(struct usb_interface *interface, /* Analog TV */ if (dev->board.input != NULL) - au0828_analog_register(dev); + au0828_analog_register(dev, interface); /* Digital TV */ au0828_dvb_register(dev); diff --git a/drivers/media/video/au0828/au0828-video.c b/drivers/media/video/au0828/au0828-video.c index ce80882d45e2..4c77aebfe6ee 100644 --- a/drivers/media/video/au0828/au0828-video.c +++ b/drivers/media/video/au0828/au0828-video.c @@ -1618,12 +1618,43 @@ static const struct video_device au0828_video_template = { /**************************************************************************/ -int au0828_analog_register(struct au0828_dev *dev) +int au0828_analog_register(struct au0828_dev *dev, + struct usb_interface *interface) { int retval = -ENOMEM; + struct usb_host_interface *iface_desc; + struct usb_endpoint_descriptor *endpoint; + int i; dprintk(1, "au0828_analog_register called!\n"); + /* set au0828 usb interface0 to as5 */ + retval = usb_set_interface(dev->usbdev, + interface->cur_altsetting->desc.bInterfaceNumber, 5); + if (retval != 0) { + printk("Failure setting usb interface0 to as5\n"); + return retval; + } + + /* Figure out which endpoint has the isoc interface */ + iface_desc = interface->cur_altsetting; + for(i = 0; i < iface_desc->desc.bNumEndpoints; i++){ + endpoint = &iface_desc->endpoint[i].desc; + if(((endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_IN) && + ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_ISOC)){ + + /* we find our isoc in endpoint */ + u16 tmp = le16_to_cpu(endpoint->wMaxPacketSize); + dev->max_pkt_size = (tmp & 0x07ff) * (((tmp & 0x1800) >> 11) + 1); + dev->isoc_in_endpointaddr = endpoint->bEndpointAddress; + } + } + if(!(dev->isoc_in_endpointaddr)) { + printk("Could not locate isoc endpoint\n"); + kfree(dev); + return -ENODEV; + } + init_waitqueue_head(&dev->open); spin_lock_init(&dev->slock); mutex_init(&dev->lock); diff --git a/drivers/media/video/au0828/au0828.h b/drivers/media/video/au0828/au0828.h index 2f48ec2136bf..d2e54c8e18c4 100644 --- a/drivers/media/video/au0828/au0828.h +++ b/drivers/media/video/au0828/au0828.h @@ -273,7 +273,8 @@ extern void au0828_call_i2c_clients(struct au0828_dev *dev, /* ----------------------------------------------------------- */ /* au0828-video.c */ -int au0828_analog_register(struct au0828_dev *dev); +int au0828_analog_register(struct au0828_dev *dev, + struct usb_interface *interface); int au0828_analog_stream_disable(struct au0828_dev *d); void au0828_analog_unregister(struct au0828_dev *dev); -- cgit v1.2.3 From 220be77c6e4302207c34afc78a98b4994f92f6e5 Mon Sep 17 00:00:00 2001 From: Devin Heitmueller Date: Wed, 11 Mar 2009 03:01:01 -0300 Subject: V4L/DVB (11078): au0828: properly handle non-existent analog inputs It is not valid to look for dev->board.input == NULL to detect an undefined analog configuration section, since it is a member of the struct and not a pointer (hence it will *always* be non-NULL). Do the check based on whether the first input is actually a valid input type instead. Thanks to Michael Krufky for providing sample hardware of various configurations to test with. Signed-off-by: Devin Heitmueller Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/au0828/au0828-cards.c | 2 +- drivers/media/video/au0828/au0828-core.c | 4 ++-- drivers/media/video/au0828/au0828.h | 3 ++- 3 files changed, 5 insertions(+), 4 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/au0828/au0828-cards.c b/drivers/media/video/au0828/au0828-cards.c index e10b1b9221e0..0516c060810e 100644 --- a/drivers/media/video/au0828/au0828-cards.c +++ b/drivers/media/video/au0828/au0828-cards.c @@ -195,7 +195,7 @@ void au0828_card_setup(struct au0828_dev *dev) break; } - if (dev->board.input != NULL) { + if (AUVI_INPUT(0).type != AU0828_VMUX_UNDEFINED) { /* Load the analog demodulator driver (note this would need to be abstracted out if we ever need to support a different demod) */ diff --git a/drivers/media/video/au0828/au0828-core.c b/drivers/media/video/au0828/au0828-core.c index 2b5ade626e57..5199c8aa5888 100644 --- a/drivers/media/video/au0828/au0828-core.c +++ b/drivers/media/video/au0828/au0828-core.c @@ -146,7 +146,7 @@ static void au0828_usb_disconnect(struct usb_interface *interface) /* Digital TV */ au0828_dvb_unregister(dev); - if (dev->board.input != NULL) + if (AUVI_INPUT(0).type != AU0828_VMUX_UNDEFINED) au0828_analog_unregister(dev); /* I2C */ @@ -205,7 +205,7 @@ static int au0828_usb_probe(struct usb_interface *interface, au0828_card_setup(dev); /* Analog TV */ - if (dev->board.input != NULL) + if (AUVI_INPUT(0).type != AU0828_VMUX_UNDEFINED) au0828_analog_register(dev, interface); /* Digital TV */ diff --git a/drivers/media/video/au0828/au0828.h b/drivers/media/video/au0828/au0828.h index d2e54c8e18c4..590d15e461dc 100644 --- a/drivers/media/video/au0828/au0828.h +++ b/drivers/media/video/au0828/au0828.h @@ -66,7 +66,8 @@ #define AU0828_MAX_INPUT 4 enum au0828_itype { - AU0828_VMUX_COMPOSITE = 1, + AU0828_VMUX_UNDEFINED = 0, + AU0828_VMUX_COMPOSITE, AU0828_VMUX_SVIDEO, AU0828_VMUX_CABLE, AU0828_VMUX_TELEVISION, -- cgit v1.2.3 From 2eaf396020555973cad7aa5b517c2418eccbca50 Mon Sep 17 00:00:00 2001 From: Devin Heitmueller Date: Wed, 11 Mar 2009 03:01:02 -0300 Subject: V4L/DVB (11079): au0828: fix panic on disconnect if analog initialization failed If the analog initialization failed to create the video device, we never actually add the entry to the au0828_devlist. Therefore a panic occurs when unregistering the analog subsystem. Make it so we only remove the entry from the list if we added it to the list in the first place. Signed-off-by: Devin Heitmueller Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/au0828/au0828-video.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/au0828/au0828-video.c b/drivers/media/video/au0828/au0828-video.c index 4c77aebfe6ee..6abdd8bf4494 100644 --- a/drivers/media/video/au0828/au0828-video.c +++ b/drivers/media/video/au0828/au0828-video.c @@ -700,9 +700,10 @@ void au0828_analog_unregister(struct au0828_dev *dev) dprintk(1, "au0828_release_resources called\n"); mutex_lock(&au0828_sysfs_lock); - list_del(&dev->au0828list); - if (dev->vdev) + if (dev->vdev) { + list_del(&dev->au0828list); video_unregister_device(dev->vdev); + } if (dev->vbi_dev) video_unregister_device(dev->vbi_dev); -- cgit v1.2.3 From b14667f32ad0f85f986847ef65f9f3d12a44b71a Mon Sep 17 00:00:00 2001 From: Devin Heitmueller Date: Wed, 11 Mar 2009 03:01:04 -0300 Subject: V4L/DVB (11080): au0828: Convert to use v4l2_device/subdev framework Convert over to using the new subdev framework for the au0828 bridge. This includes using the new i2c probing mechanism. Signed-off-by: Devin Heitmueller Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/au0828/au0828-cards.c | 13 +++++++++++-- drivers/media/video/au0828/au0828-core.c | 15 ++++++++++++++- drivers/media/video/au0828/au0828-i2c.c | 5 ++--- drivers/media/video/au0828/au0828-video.c | 2 +- drivers/media/video/au0828/au0828.h | 4 +++- 5 files changed, 31 insertions(+), 8 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/au0828/au0828-cards.c b/drivers/media/video/au0828/au0828-cards.c index 0516c060810e..a12c92c03746 100644 --- a/drivers/media/video/au0828/au0828-cards.c +++ b/drivers/media/video/au0828/au0828-cards.c @@ -173,6 +173,7 @@ void au0828_card_setup(struct au0828_dev *dev) { static u8 eeprom[256]; struct tuner_setup tun_setup; + struct v4l2_subdev *sd; unsigned int mode_mask = T_ANALOG_TV | T_DIGITAL_TV; @@ -199,13 +200,21 @@ void au0828_card_setup(struct au0828_dev *dev) /* Load the analog demodulator driver (note this would need to be abstracted out if we ever need to support a different demod) */ - request_module("au8522"); + sd = v4l2_i2c_new_subdev(&dev->i2c_adap, "au8522", "au8522", + 0x8e >> 1); + if (sd == NULL) { + printk("analog subdev registration failure\n"); + } } /* Setup tuners */ if (dev->board.tuner_type != TUNER_ABSENT) { /* Load the tuner module, which does the attach */ - request_module("tuner"); + sd = v4l2_i2c_new_subdev(&dev->i2c_adap, "tuner", "tuner", + dev->board.tuner_addr); + if (sd == NULL) { + printk("analog tuner subdev registration failure\n"); + } tun_setup.mode_mask = mode_mask; tun_setup.type = dev->board.tuner_type; diff --git a/drivers/media/video/au0828/au0828-core.c b/drivers/media/video/au0828/au0828-core.c index 5199c8aa5888..3281a17fa2cd 100644 --- a/drivers/media/video/au0828/au0828-core.c +++ b/drivers/media/video/au0828/au0828-core.c @@ -152,6 +152,8 @@ static void au0828_usb_disconnect(struct usb_interface *interface) /* I2C */ au0828_i2c_unregister(dev); + v4l2_device_unregister(&dev->v4l2_dev); + usb_set_intfdata(interface, NULL); mutex_lock(&dev->mutex); @@ -165,7 +167,7 @@ static void au0828_usb_disconnect(struct usb_interface *interface) static int au0828_usb_probe(struct usb_interface *interface, const struct usb_device_id *id) { - int ifnum; + int ifnum, retval; struct au0828_dev *dev; struct usb_device *usbdev = interface_to_usbdev(interface); @@ -192,6 +194,17 @@ static int au0828_usb_probe(struct usb_interface *interface, usb_set_intfdata(interface, dev); + /* Create the v4l2_device */ + snprintf(dev->v4l2_dev.name, sizeof(dev->v4l2_dev.name), "%s-%03d", + "au0828", 0); + retval = v4l2_device_register(&dev->usbdev->dev, &dev->v4l2_dev); + if (retval) { + printk(KERN_ERR "%s() v4l2_device_register failed\n", + __func__); + kfree(dev); + return -EIO; + } + /* Power Up the bridge */ au0828_write(dev, REG_600, 1 << 4); diff --git a/drivers/media/video/au0828/au0828-i2c.c b/drivers/media/video/au0828/au0828-i2c.c index d57a38f5c738..e841ba5a6424 100644 --- a/drivers/media/video/au0828/au0828-i2c.c +++ b/drivers/media/video/au0828/au0828-i2c.c @@ -345,7 +345,6 @@ static struct i2c_adapter au0828_i2c_adap_template = { .owner = THIS_MODULE, .id = I2C_HW_B_AU0828, .algo = &au0828_i2c_algo_template, - .class = I2C_CLASS_TV_ANALOG, .client_register = attach_inform, .client_unregister = detach_inform, }; @@ -392,9 +391,9 @@ int au0828_i2c_register(struct au0828_dev *dev) strlcpy(dev->i2c_adap.name, DRIVER_NAME, sizeof(dev->i2c_adap.name)); - dev->i2c_algo.data = dev; + dev->i2c_adap.algo = &dev->i2c_algo; dev->i2c_adap.algo_data = dev; - i2c_set_adapdata(&dev->i2c_adap, dev); + i2c_set_adapdata(&dev->i2c_adap, &dev->v4l2_dev); i2c_add_adapter(&dev->i2c_adap); dev->i2c_client.adapter = &dev->i2c_adap; diff --git a/drivers/media/video/au0828/au0828-video.c b/drivers/media/video/au0828/au0828-video.c index 6abdd8bf4494..f6e8cb17445b 100644 --- a/drivers/media/video/au0828/au0828-video.c +++ b/drivers/media/video/au0828/au0828-video.c @@ -1021,7 +1021,7 @@ static int vidioc_querycap(struct file *file, void *priv, memset(cap, 0, sizeof(*cap)); strlcpy(cap->driver, "au0828", sizeof(cap->driver)); strlcpy(cap->card, dev->board.name, sizeof(cap->card)); - strlcpy(cap->bus_info, dev->usbdev->dev.bus_id, sizeof(cap->bus_info)); + strlcpy(cap->bus_info, dev->v4l2_dev.name, sizeof(cap->bus_info)); cap->version = AU0828_VERSION_CODE; diff --git a/drivers/media/video/au0828/au0828.h b/drivers/media/video/au0828/au0828.h index 590d15e461dc..876b18cfbf55 100644 --- a/drivers/media/video/au0828/au0828.h +++ b/drivers/media/video/au0828/au0828.h @@ -27,6 +27,7 @@ /* Analog */ #include #include +#include /* DVB */ #include "demux.h" @@ -188,7 +189,7 @@ struct au0828_dev { /* I2C */ struct i2c_adapter i2c_adap; - struct i2c_algo_bit_data i2c_algo; + struct i2c_algorithm i2c_algo; struct i2c_client i2c_client; u32 i2c_rc; @@ -197,6 +198,7 @@ struct au0828_dev { /* Analog */ struct list_head au0828list; + struct v4l2_device v4l2_dev; int users; unsigned int stream_on:1; /* Locks streams */ struct video_device *vdev; -- cgit v1.2.3 From e13ce79734348610a2b782cb818db65659b0dc83 Mon Sep 17 00:00:00 2001 From: Devin Heitmueller Date: Wed, 11 Mar 2009 21:58:04 -0300 Subject: V4L/DVB (11081): au0828: make sure v4l2_device name is unique Make sure newly created v4l2 devices have a unique name, modeling the logic after the cx18 driver. Thanks to Andy Walls for pointing out the issue. Signed-off-by: Devin Heitmueller Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/au0828/au0828-core.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/au0828/au0828-core.c b/drivers/media/video/au0828/au0828-core.c index 3281a17fa2cd..8c761d164442 100644 --- a/drivers/media/video/au0828/au0828-core.c +++ b/drivers/media/video/au0828/au0828-core.c @@ -36,6 +36,8 @@ int au0828_debug; module_param_named(debug, au0828_debug, int, 0644); MODULE_PARM_DESC(debug, "enable debug messages"); +static atomic_t au0828_instance = ATOMIC_INIT(0); + #define _AU0828_BULKPIPE 0x03 #define _BULKPIPESIZE 0xffff @@ -167,7 +169,7 @@ static void au0828_usb_disconnect(struct usb_interface *interface) static int au0828_usb_probe(struct usb_interface *interface, const struct usb_device_id *id) { - int ifnum, retval; + int ifnum, retval, i; struct au0828_dev *dev; struct usb_device *usbdev = interface_to_usbdev(interface); @@ -195,8 +197,9 @@ static int au0828_usb_probe(struct usb_interface *interface, usb_set_intfdata(interface, dev); /* Create the v4l2_device */ + i = atomic_inc_return(&au0828_instance) - 1; snprintf(dev->v4l2_dev.name, sizeof(dev->v4l2_dev.name), "%s-%03d", - "au0828", 0); + "au0828", i); retval = v4l2_device_register(&dev->usbdev->dev, &dev->v4l2_dev); if (retval) { printk(KERN_ERR "%s() v4l2_device_register failed\n", -- cgit v1.2.3 From c888923debf8c8a799629f77d07aeb0f8350c87b Mon Sep 17 00:00:00 2001 From: Devin Heitmueller Date: Sun, 15 Mar 2009 17:38:47 -0300 Subject: V4L/DVB (11082): au0828: remove memset calls in v4l2 routines. The userland callers are responsible for clearing the output buffers, so remove the unneeded memset calls. Thanks to Mauro Carvalho Chehab for pointing this out. Signed-off-by: Devin Heitmueller Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/au0828/au0828-video.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/au0828/au0828-video.c b/drivers/media/video/au0828/au0828-video.c index f6e8cb17445b..96895117a0ce 100644 --- a/drivers/media/video/au0828/au0828-video.c +++ b/drivers/media/video/au0828/au0828-video.c @@ -1018,7 +1018,6 @@ static int vidioc_querycap(struct file *file, void *priv, struct au0828_fh *fh = priv; struct au0828_dev *dev = fh->dev; - memset(cap, 0, sizeof(*cap)); strlcpy(cap->driver, "au0828", sizeof(cap->driver)); strlcpy(cap->card, dev->board.name, sizeof(cap->card)); strlcpy(cap->bus_info, dev->v4l2_dev.name, sizeof(cap->bus_info)); @@ -1043,14 +1042,12 @@ static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv, if(f->index) return -EINVAL; - memset(f, 0, sizeof(*f)); f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; strcpy(f->description, "Packed YUV2"); f->flags = 0; f->pixelformat = V4L2_PIX_FMT_UYVY; - memset(f->reserved, 0, sizeof(f->reserved)); return 0; } @@ -1139,7 +1136,6 @@ static int vidioc_enum_input(struct file *file, void *priv, if(AUVI_INPUT(tmp).type == 0) return -EINVAL; - memset(input, 0, sizeof(*input)); input->index = tmp; strcpy(input->name, inames[AUVI_INPUT(tmp).type]); if((AUVI_INPUT(tmp).type == AU0828_VMUX_TELEVISION) || @@ -1237,7 +1233,6 @@ static int vidioc_g_audio(struct file *file, void *priv, struct v4l2_audio *a) if(a->index > 1) return -EINVAL; - memset(a, 0, sizeof(*a)); index = dev->ctrl_ainput; if(index == 0) strcpy(a->name, "Television"); @@ -1286,7 +1281,6 @@ static int vidioc_g_tuner(struct file *file, void *priv, struct v4l2_tuner *t) if(t->index != 0) return -EINVAL; - memset(t, 0, sizeof(*t)); strcpy(t->name, "Auvitek tuner"); au0828_call_i2c_clients(dev, VIDIOC_G_TUNER, t); @@ -1315,7 +1309,7 @@ static int vidioc_g_frequency(struct file *file, void *priv, { struct au0828_fh *fh = priv; struct au0828_dev *dev = fh->dev; - memset(freq, 0, sizeof(*freq)); + freq->type = V4L2_TUNER_ANALOG_TV; freq->frequency = dev->ctrl_freq; return 0; -- cgit v1.2.3 From a1094c4cd10a7075598b73cd0bbf07f6b1acbb6a Mon Sep 17 00:00:00 2001 From: Devin Heitmueller Date: Sun, 15 Mar 2009 17:43:13 -0300 Subject: V4L/DVB (11083): au0828: remove some unneeded braces There were some braces left behind from when there was more code in the block. Remove it. Thanks to Mauro Carvalho Chehab for pointing this out. Signed-off-by: Devin Heitmueller Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/au0828/au0828-video.c | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/au0828/au0828-video.c b/drivers/media/video/au0828/au0828-video.c index 96895117a0ce..e7b2733ba86e 100644 --- a/drivers/media/video/au0828/au0828-video.c +++ b/drivers/media/video/au0828/au0828-video.c @@ -1174,22 +1174,18 @@ static int vidioc_s_input(struct file *file, void *priv, unsigned int index) switch(AUVI_INPUT(index).type) { case AU0828_VMUX_SVIDEO: - { dev->input_type = AU0828_VMUX_SVIDEO; break; - } case AU0828_VMUX_COMPOSITE: - { dev->input_type = AU0828_VMUX_COMPOSITE; break; - } case AU0828_VMUX_TELEVISION: - { dev->input_type = AU0828_VMUX_TELEVISION; break; - } default: - ; + dprintk(1, "VIDIOC_S_INPUT unknown input type set [%d]\n", + AUVI_INPUT(index).type); + break; } route.input = AUVI_INPUT(index).vmux; -- cgit v1.2.3 From 3d62287e2c6c5b3351e04dd2c2209b2536995fdb Mon Sep 17 00:00:00 2001 From: Devin Heitmueller Date: Sun, 15 Mar 2009 17:48:26 -0300 Subject: V4L/DVB (11084): au0828: add entry for undefined input type For the sake of completeness, include the "undefined" input type enumeration, even though there is no path that can actually call it. Thanks to Mauro Carvalho Chehab for pointing this out. Signed-off-by: Devin Heitmueller Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/au0828/au0828-video.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/media/video') diff --git a/drivers/media/video/au0828/au0828-video.c b/drivers/media/video/au0828/au0828-video.c index e7b2733ba86e..800345cbe0ef 100644 --- a/drivers/media/video/au0828/au0828-video.c +++ b/drivers/media/video/au0828/au0828-video.c @@ -1121,6 +1121,7 @@ static int vidioc_enum_input(struct file *file, void *priv, unsigned int tmp; static const char *inames[] = { + [AU0828_VMUX_UNDEFINED] = "Undefined", [AU0828_VMUX_COMPOSITE] = "Composite", [AU0828_VMUX_SVIDEO] = "S-Video", [AU0828_VMUX_CABLE] = "Cable TV", -- cgit v1.2.3 From 62899a28008d635f25c3408b4cc46021f0cb34d3 Mon Sep 17 00:00:00 2001 From: Devin Heitmueller Date: Sun, 15 Mar 2009 18:48:52 -0300 Subject: V4L/DVB (11085): au0828/au8522: Codingstyle fixes Take a pass over all of the au0828/au8522 files and cleanup all the codingstyle issues. This patch does not make *any* functional change to the code. Signed-off-by: Devin Heitmueller Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/au8522_decoder.c | 233 ++++++++++++++------------- drivers/media/dvb/frontends/au8522_dig.c | 14 +- drivers/media/video/au0828/au0828-cards.c | 24 ++- drivers/media/video/au0828/au0828-i2c.c | 10 +- drivers/media/video/au0828/au0828-video.c | 175 ++++++++++---------- drivers/media/video/au0828/au0828.h | 6 - 6 files changed, 226 insertions(+), 236 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/dvb/frontends/au8522_decoder.c b/drivers/media/dvb/frontends/au8522_decoder.c index 564636389bae..2ad84c236ec7 100644 --- a/drivers/media/dvb/frontends/au8522_decoder.c +++ b/drivers/media/dvb/frontends/au8522_decoder.c @@ -67,39 +67,40 @@ struct au8522_register_config { 0="ATV RF" 1="ATV RF13" 2="CVBS" 3="S-Video" 4="PAL" 5=CVBS13" 6="SVideo13" */ struct au8522_register_config filter_coef[] = { - {AU8522_FILTER_COEF_R410, {0x25, 0x00, 0x25, 0x25, 0x00, 0x00, 0x00}}, - {AU8522_FILTER_COEF_R411, {0x20, 0x00, 0x20, 0x20, 0x00, 0x00, 0x00}}, - {AU8522_FILTER_COEF_R412, {0x03, 0x00, 0x03, 0x03, 0x00, 0x00, 0x00}}, - {AU8522_FILTER_COEF_R413, {0xe6, 0x00, 0xe6, 0xe6, 0x00, 0x00, 0x00}}, - {AU8522_FILTER_COEF_R414, {0x40, 0x00, 0x40, 0x40, 0x00, 0x00, 0x00}}, - {AU8522_FILTER_COEF_R415, {0x1b, 0x00, 0x1b, 0x1b, 0x00, 0x00, 0x00}}, - {AU8522_FILTER_COEF_R416, {0xc0, 0x00, 0xc0, 0x04, 0x00, 0x00, 0x00}}, - {AU8522_FILTER_COEF_R417, {0x04, 0x00, 0x04, 0x04, 0x00, 0x00, 0x00}}, - {AU8522_FILTER_COEF_R418, {0x8c, 0x00, 0x8c, 0x8c, 0x00, 0x00, 0x00}}, - {AU8522_FILTER_COEF_R419, {0xa0, 0x40, 0xa0, 0xa0, 0x40, 0x40, 0x40}}, - {AU8522_FILTER_COEF_R41A, {0x21, 0x09, 0x21, 0x21, 0x09, 0x09, 0x09}}, - {AU8522_FILTER_COEF_R41B, {0x6c, 0x38, 0x6c, 0x6c, 0x38, 0x38, 0x38}}, - {AU8522_FILTER_COEF_R41C, {0x03, 0xff, 0x03, 0x03, 0xff, 0xff, 0xff}}, - {AU8522_FILTER_COEF_R41D, {0xbf, 0xc7, 0xbf, 0xbf, 0xc7, 0xc7, 0xc7}}, - {AU8522_FILTER_COEF_R41E, {0xa0, 0xdf, 0xa0, 0xa0, 0xdf, 0xdf, 0xdf}}, - {AU8522_FILTER_COEF_R41F, {0x10, 0x06, 0x10, 0x10, 0x06, 0x06, 0x06}}, - {AU8522_FILTER_COEF_R420, {0xae, 0x30, 0xae, 0xae, 0x30, 0x30, 0x30}}, - {AU8522_FILTER_COEF_R421, {0xc4, 0x01, 0xc4, 0xc4, 0x01, 0x01, 0x01}}, - {AU8522_FILTER_COEF_R422, {0x54, 0xdd, 0x54, 0x54, 0xdd, 0xdd, 0xdd}}, - {AU8522_FILTER_COEF_R423, {0xd0, 0xaf, 0xd0, 0xd0, 0xaf, 0xaf, 0xaf}}, - {AU8522_FILTER_COEF_R424, {0x1c, 0xf7, 0x1c, 0x1c, 0xf7, 0xf7, 0xf7}}, - {AU8522_FILTER_COEF_R425, {0x76, 0xdb, 0x76, 0x76, 0xdb, 0xdb, 0xdb}}, - {AU8522_FILTER_COEF_R426, {0x61, 0xc0, 0x61, 0x61, 0xc0, 0xc0, 0xc0}}, - {AU8522_FILTER_COEF_R427, {0xd1, 0x2f, 0xd1, 0xd1, 0x2f, 0x2f, 0x2f}}, - {AU8522_FILTER_COEF_R428, {0x84, 0xd8, 0x84, 0x84, 0xd8, 0xd8, 0xd8}}, - {AU8522_FILTER_COEF_R429, {0x06, 0xfb, 0x06, 0x06, 0xfb, 0xfb, 0xfb}}, - {AU8522_FILTER_COEF_R42A, {0x21, 0xd5, 0x21, 0x21, 0xd5, 0xd5, 0xd5}}, - {AU8522_FILTER_COEF_R42B, {0x0a, 0x3e, 0x0a, 0x0a, 0x3e, 0x3e, 0x3e}}, - {AU8522_FILTER_COEF_R42C, {0xe6, 0x15, 0xe6, 0xe6, 0x15, 0x15, 0x15}}, - {AU8522_FILTER_COEF_R42D, {0x01, 0x34, 0x01, 0x01, 0x34, 0x34, 0x34}}, + {AU8522_FILTER_COEF_R410, {0x25, 0x00, 0x25, 0x25, 0x00, 0x00, 0x00} }, + {AU8522_FILTER_COEF_R411, {0x20, 0x00, 0x20, 0x20, 0x00, 0x00, 0x00} }, + {AU8522_FILTER_COEF_R412, {0x03, 0x00, 0x03, 0x03, 0x00, 0x00, 0x00} }, + {AU8522_FILTER_COEF_R413, {0xe6, 0x00, 0xe6, 0xe6, 0x00, 0x00, 0x00} }, + {AU8522_FILTER_COEF_R414, {0x40, 0x00, 0x40, 0x40, 0x00, 0x00, 0x00} }, + {AU8522_FILTER_COEF_R415, {0x1b, 0x00, 0x1b, 0x1b, 0x00, 0x00, 0x00} }, + {AU8522_FILTER_COEF_R416, {0xc0, 0x00, 0xc0, 0x04, 0x00, 0x00, 0x00} }, + {AU8522_FILTER_COEF_R417, {0x04, 0x00, 0x04, 0x04, 0x00, 0x00, 0x00} }, + {AU8522_FILTER_COEF_R418, {0x8c, 0x00, 0x8c, 0x8c, 0x00, 0x00, 0x00} }, + {AU8522_FILTER_COEF_R419, {0xa0, 0x40, 0xa0, 0xa0, 0x40, 0x40, 0x40} }, + {AU8522_FILTER_COEF_R41A, {0x21, 0x09, 0x21, 0x21, 0x09, 0x09, 0x09} }, + {AU8522_FILTER_COEF_R41B, {0x6c, 0x38, 0x6c, 0x6c, 0x38, 0x38, 0x38} }, + {AU8522_FILTER_COEF_R41C, {0x03, 0xff, 0x03, 0x03, 0xff, 0xff, 0xff} }, + {AU8522_FILTER_COEF_R41D, {0xbf, 0xc7, 0xbf, 0xbf, 0xc7, 0xc7, 0xc7} }, + {AU8522_FILTER_COEF_R41E, {0xa0, 0xdf, 0xa0, 0xa0, 0xdf, 0xdf, 0xdf} }, + {AU8522_FILTER_COEF_R41F, {0x10, 0x06, 0x10, 0x10, 0x06, 0x06, 0x06} }, + {AU8522_FILTER_COEF_R420, {0xae, 0x30, 0xae, 0xae, 0x30, 0x30, 0x30} }, + {AU8522_FILTER_COEF_R421, {0xc4, 0x01, 0xc4, 0xc4, 0x01, 0x01, 0x01} }, + {AU8522_FILTER_COEF_R422, {0x54, 0xdd, 0x54, 0x54, 0xdd, 0xdd, 0xdd} }, + {AU8522_FILTER_COEF_R423, {0xd0, 0xaf, 0xd0, 0xd0, 0xaf, 0xaf, 0xaf} }, + {AU8522_FILTER_COEF_R424, {0x1c, 0xf7, 0x1c, 0x1c, 0xf7, 0xf7, 0xf7} }, + {AU8522_FILTER_COEF_R425, {0x76, 0xdb, 0x76, 0x76, 0xdb, 0xdb, 0xdb} }, + {AU8522_FILTER_COEF_R426, {0x61, 0xc0, 0x61, 0x61, 0xc0, 0xc0, 0xc0} }, + {AU8522_FILTER_COEF_R427, {0xd1, 0x2f, 0xd1, 0xd1, 0x2f, 0x2f, 0x2f} }, + {AU8522_FILTER_COEF_R428, {0x84, 0xd8, 0x84, 0x84, 0xd8, 0xd8, 0xd8} }, + {AU8522_FILTER_COEF_R429, {0x06, 0xfb, 0x06, 0x06, 0xfb, 0xfb, 0xfb} }, + {AU8522_FILTER_COEF_R42A, {0x21, 0xd5, 0x21, 0x21, 0xd5, 0xd5, 0xd5} }, + {AU8522_FILTER_COEF_R42B, {0x0a, 0x3e, 0x0a, 0x0a, 0x3e, 0x3e, 0x3e} }, + {AU8522_FILTER_COEF_R42C, {0xe6, 0x15, 0xe6, 0xe6, 0x15, 0x15, 0x15} }, + {AU8522_FILTER_COEF_R42D, {0x01, 0x34, 0x01, 0x01, 0x34, 0x34, 0x34} }, }; -#define NUM_FILTER_COEF (sizeof (filter_coef) / sizeof(struct au8522_register_config)) +#define NUM_FILTER_COEF (sizeof(filter_coef)\ + / sizeof(struct au8522_register_config)) /* Registers 0x060b through 0x0652 are the LP Filter coefficients @@ -108,80 +109,81 @@ struct au8522_register_config filter_coef[] = { Note: the "ATVRF/ATVRF13" mode has never been tested */ struct au8522_register_config lpfilter_coef[] = { - {0x060b, {0x21, 0x0b}}, - {0x060c, {0xad, 0xad}}, - {0x060d, {0x70, 0xf0}}, - {0x060e, {0xea, 0xe9}}, - {0x060f, {0xdd, 0xdd}}, - {0x0610, {0x08, 0x64}}, - {0x0611, {0x60, 0x60}}, - {0x0612, {0xf8, 0xb2}}, - {0x0613, {0x01, 0x02}}, - {0x0614, {0xe4, 0xb4}}, - {0x0615, {0x19, 0x02}}, - {0x0616, {0xae, 0x2e}}, - {0x0617, {0xee, 0xc5}}, - {0x0618, {0x56, 0x56}}, - {0x0619, {0x30, 0x58}}, - {0x061a, {0xf9, 0xf8}}, - {0x061b, {0x24, 0x64}}, - {0x061c, {0x07, 0x07}}, - {0x061d, {0x30, 0x30}}, - {0x061e, {0xa9, 0xed}}, - {0x061f, {0x09, 0x0b}}, - {0x0620, {0x42, 0xc2}}, - {0x0621, {0x1d, 0x2a}}, - {0x0622, {0xd6, 0x56}}, - {0x0623, {0x95, 0x8b}}, - {0x0624, {0x2b, 0x2b}}, - {0x0625, {0x30, 0x24}}, - {0x0626, {0x3e, 0x3e}}, - {0x0627, {0x62, 0xe2}}, - {0x0628, {0xe9, 0xf5}}, - {0x0629, {0x99, 0x19}}, - {0x062a, {0xd4, 0x11}}, - {0x062b, {0x03, 0x04}}, - {0x062c, {0xb5, 0x85}}, - {0x062d, {0x1e, 0x20}}, - {0x062e, {0x2a, 0xea}}, - {0x062f, {0xd7, 0xd2}}, - {0x0630, {0x15, 0x15}}, - {0x0631, {0xa3, 0xa9}}, - {0x0632, {0x1f, 0x1f}}, - {0x0633, {0xf9, 0xd1}}, - {0x0634, {0xc0, 0xc3}}, - {0x0635, {0x4d, 0x8d}}, - {0x0636, {0x21, 0x31}}, - {0x0637, {0x83, 0x83}}, - {0x0638, {0x08, 0x8c}}, - {0x0639, {0x19, 0x19}}, - {0x063a, {0x45, 0xa5}}, - {0x063b, {0xef, 0xec}}, - {0x063c, {0x8a, 0x8a}}, - {0x063d, {0xf4, 0xf6}}, - {0x063e, {0x8f, 0x8f}}, - {0x063f, {0x44, 0x0c}}, - {0x0640, {0xef, 0xf0}}, - {0x0641, {0x66, 0x66}}, - {0x0642, {0xcc, 0xd2}}, - {0x0643, {0x41, 0x41}}, - {0x0644, {0x63, 0x93}}, - {0x0645, {0x8e, 0x8e}}, - {0x0646, {0xa2, 0x42}}, - {0x0647, {0x7b, 0x7b}}, - {0x0648, {0x04, 0x04}}, - {0x0649, {0x00, 0x00}}, - {0x064a, {0x40, 0x40}}, - {0x064b, {0x8c, 0x98}}, - {0x064c, {0x00, 0x00}}, - {0x064d, {0x63, 0xc3}}, - {0x064e, {0x04, 0x04}}, - {0x064f, {0x20, 0x20}}, - {0x0650, {0x00, 0x00}}, - {0x0651, {0x40 ,0x40}}, - {0x0652, {0x01, 0x01}}, + {0x060b, {0x21, 0x0b} }, + {0x060c, {0xad, 0xad} }, + {0x060d, {0x70, 0xf0} }, + {0x060e, {0xea, 0xe9} }, + {0x060f, {0xdd, 0xdd} }, + {0x0610, {0x08, 0x64} }, + {0x0611, {0x60, 0x60} }, + {0x0612, {0xf8, 0xb2} }, + {0x0613, {0x01, 0x02} }, + {0x0614, {0xe4, 0xb4} }, + {0x0615, {0x19, 0x02} }, + {0x0616, {0xae, 0x2e} }, + {0x0617, {0xee, 0xc5} }, + {0x0618, {0x56, 0x56} }, + {0x0619, {0x30, 0x58} }, + {0x061a, {0xf9, 0xf8} }, + {0x061b, {0x24, 0x64} }, + {0x061c, {0x07, 0x07} }, + {0x061d, {0x30, 0x30} }, + {0x061e, {0xa9, 0xed} }, + {0x061f, {0x09, 0x0b} }, + {0x0620, {0x42, 0xc2} }, + {0x0621, {0x1d, 0x2a} }, + {0x0622, {0xd6, 0x56} }, + {0x0623, {0x95, 0x8b} }, + {0x0624, {0x2b, 0x2b} }, + {0x0625, {0x30, 0x24} }, + {0x0626, {0x3e, 0x3e} }, + {0x0627, {0x62, 0xe2} }, + {0x0628, {0xe9, 0xf5} }, + {0x0629, {0x99, 0x19} }, + {0x062a, {0xd4, 0x11} }, + {0x062b, {0x03, 0x04} }, + {0x062c, {0xb5, 0x85} }, + {0x062d, {0x1e, 0x20} }, + {0x062e, {0x2a, 0xea} }, + {0x062f, {0xd7, 0xd2} }, + {0x0630, {0x15, 0x15} }, + {0x0631, {0xa3, 0xa9} }, + {0x0632, {0x1f, 0x1f} }, + {0x0633, {0xf9, 0xd1} }, + {0x0634, {0xc0, 0xc3} }, + {0x0635, {0x4d, 0x8d} }, + {0x0636, {0x21, 0x31} }, + {0x0637, {0x83, 0x83} }, + {0x0638, {0x08, 0x8c} }, + {0x0639, {0x19, 0x19} }, + {0x063a, {0x45, 0xa5} }, + {0x063b, {0xef, 0xec} }, + {0x063c, {0x8a, 0x8a} }, + {0x063d, {0xf4, 0xf6} }, + {0x063e, {0x8f, 0x8f} }, + {0x063f, {0x44, 0x0c} }, + {0x0640, {0xef, 0xf0} }, + {0x0641, {0x66, 0x66} }, + {0x0642, {0xcc, 0xd2} }, + {0x0643, {0x41, 0x41} }, + {0x0644, {0x63, 0x93} }, + {0x0645, {0x8e, 0x8e} }, + {0x0646, {0xa2, 0x42} }, + {0x0647, {0x7b, 0x7b} }, + {0x0648, {0x04, 0x04} }, + {0x0649, {0x00, 0x00} }, + {0x064a, {0x40, 0x40} }, + {0x064b, {0x8c, 0x98} }, + {0x064c, {0x00, 0x00} }, + {0x064d, {0x63, 0xc3} }, + {0x064e, {0x04, 0x04} }, + {0x064f, {0x20, 0x20} }, + {0x0650, {0x00, 0x00} }, + {0x0651, {0x40, 0x40} }, + {0x0652, {0x01, 0x01} }, }; -#define NUM_LPFILTER_COEF (sizeof (lpfilter_coef) / sizeof(struct au8522_register_config)) +#define NUM_LPFILTER_COEF (sizeof(lpfilter_coef)\ + / sizeof(struct au8522_register_config)) static inline struct au8522_state *to_state(struct v4l2_subdev *sd) { @@ -202,14 +204,17 @@ static void setup_vbi(struct au8522_state *state, int aud_input) au8522_writereg(state, AU8522_TVDEC_VBI_USER_FRAME_PAT2_REG01EH, 0x00); au8522_writereg(state, AU8522_TVDEC_VBI_USER_FRAME_PAT1_REG01FH, 0x00); au8522_writereg(state, AU8522_TVDEC_VBI_USER_FRAME_PAT0_REG020H, 0x00); - au8522_writereg(state, AU8522_TVDEC_VBI_USER_FRAME_MASK2_REG021H,0x00); - au8522_writereg(state, AU8522_TVDEC_VBI_USER_FRAME_MASK1_REG022H,0x00); - au8522_writereg(state, AU8522_TVDEC_VBI_USER_FRAME_MASK0_REG023H,0x00); + au8522_writereg(state, AU8522_TVDEC_VBI_USER_FRAME_MASK2_REG021H, + 0x00); + au8522_writereg(state, AU8522_TVDEC_VBI_USER_FRAME_MASK1_REG022H, + 0x00); + au8522_writereg(state, AU8522_TVDEC_VBI_USER_FRAME_MASK0_REG023H, + 0x00); /* Setup the VBI registers */ - for (i = 0x30; i < 0x60; i++) { + for (i = 0x30; i < 0x60; i++) au8522_writereg(state, i, 0x40); - } + /* For some reason, every register is 0x40 except register 0x44 (confirmed via the HVR-950q USB capture) */ au8522_writereg(state, 0x44, 0x60); @@ -448,7 +453,7 @@ static void set_audio_input(struct au8522_state *state, int aud_input) if (aud_input != AU8522_AUDIO_SIF) { /* The caller asked for a mode we don't currently support */ - printk("Unsupported audio mode requested! mode=%d\n", + printk(KERN_ERR "Unsupported audio mode requested! mode=%d\n", aud_input); return; } @@ -668,7 +673,7 @@ static int au8522_s_video_routing(struct v4l2_subdev *sd, } else if (route->input == AU8522_COMPOSITE_CH4_SIF) { au8522_setup_cvbs_tuner_mode(state); } else { - printk("au8522 mode not currently supported\n"); + printk(KERN_ERR "au8522 mode not currently supported\n"); return -EINVAL; } return 0; @@ -782,15 +787,15 @@ static int au8522_probe(struct i2c_client *client, instance = au8522_get_state(&state, client->adapter, client->addr); switch (instance) { case 0: - printk("au8522_decoder allocation failed\n"); + printk(KERN_ERR "au8522_decoder allocation failed\n"); return -EIO; case 1: /* new demod instance */ - printk("au8522_decoder creating new instance...\n"); + printk(KERN_INFO "au8522_decoder creating new instance...\n"); break; default: /* existing demod instance */ - printk("au8522_decoder attaching to existing instance...\n"); + printk(KERN_INFO "au8522_decoder attach existing instance.\n"); break; } diff --git a/drivers/media/dvb/frontends/au8522_dig.c b/drivers/media/dvb/frontends/au8522_dig.c index 7e24b914dbe5..35731258bb0a 100644 --- a/drivers/media/dvb/frontends/au8522_dig.c +++ b/drivers/media/dvb/frontends/au8522_dig.c @@ -36,16 +36,16 @@ static int debug; static LIST_HEAD(hybrid_tuner_instance_list); static DEFINE_MUTEX(au8522_list_mutex); -#define dprintk(arg...) do { \ - if (debug) \ - printk(arg); \ +#define dprintk(arg...)\ + do { if (debug)\ + printk(arg);\ } while (0) /* 16 bit registers, 8 bit values */ int au8522_writereg(struct au8522_state *state, u16 reg, u8 data) { int ret; - u8 buf [] = { (reg >> 8) | 0x80, reg & 0xff, data }; + u8 buf[] = { (reg >> 8) | 0x80, reg & 0xff, data }; struct i2c_msg msg = { .addr = state->config->demod_address, .flags = 0, .buf = buf, .len = 3 }; @@ -62,10 +62,10 @@ int au8522_writereg(struct au8522_state *state, u16 reg, u8 data) u8 au8522_readreg(struct au8522_state *state, u16 reg) { int ret; - u8 b0 [] = { (reg >> 8) | 0x40, reg & 0xff }; - u8 b1 [] = { 0 }; + u8 b0[] = { (reg >> 8) | 0x40, reg & 0xff }; + u8 b1[] = { 0 }; - struct i2c_msg msg [] = { + struct i2c_msg msg[] = { { .addr = state->config->demod_address, .flags = 0, .buf = b0, .len = 2 }, { .addr = state->config->demod_address, .flags = I2C_M_RD, diff --git a/drivers/media/video/au0828/au0828-cards.c b/drivers/media/video/au0828/au0828-cards.c index a12c92c03746..1b48eb58a161 100644 --- a/drivers/media/video/au0828/au0828-cards.c +++ b/drivers/media/video/au0828/au0828-cards.c @@ -150,13 +150,13 @@ static void hauppauge_eeprom(struct au0828_dev *dev, u8 *eeprom_data) /* Make sure we support the board model */ switch (tv.model) { case 72000: /* WinTV-HVR950q (Retail, IR, ATSC/QAM */ - case 72001: /* WinTV-HVR950q (Retail, IR, ATSC/QAM and basic analog video */ - case 72211: /* WinTV-HVR950q (OEM, IR, ATSC/QAM and basic analog video */ - case 72221: /* WinTV-HVR950q (OEM, IR, ATSC/QAM and basic analog video */ - case 72231: /* WinTV-HVR950q (OEM, IR, ATSC/QAM and basic analog video */ - case 72241: /* WinTV-HVR950q (OEM, No IR, ATSC/QAM and basic analog video */ - case 72251: /* WinTV-HVR950q (Retail, IR, ATSC/QAM and basic analog video */ - case 72301: /* WinTV-HVR850 (Retail, IR, ATSC and basic analog video */ + case 72001: /* WinTV-HVR950q (Retail, IR, ATSC/QAM and analog video */ + case 72211: /* WinTV-HVR950q (OEM, IR, ATSC/QAM and analog video */ + case 72221: /* WinTV-HVR950q (OEM, IR, ATSC/QAM and analog video */ + case 72231: /* WinTV-HVR950q (OEM, IR, ATSC/QAM and analog video */ + case 72241: /* WinTV-HVR950q (OEM, No IR, ATSC/QAM and analog video */ + case 72251: /* WinTV-HVR950q (Retail, IR, ATSC/QAM and analog video */ + case 72301: /* WinTV-HVR850 (Retail, IR, ATSC and analog video */ case 72500: /* WinTV-HVR950q (OEM, No IR, ATSC/QAM */ break; default: @@ -202,9 +202,8 @@ void au0828_card_setup(struct au0828_dev *dev) demod) */ sd = v4l2_i2c_new_subdev(&dev->i2c_adap, "au8522", "au8522", 0x8e >> 1); - if (sd == NULL) { - printk("analog subdev registration failure\n"); - } + if (sd == NULL) + printk(KERN_ERR "analog subdev registration failed\n"); } /* Setup tuners */ @@ -212,9 +211,8 @@ void au0828_card_setup(struct au0828_dev *dev) /* Load the tuner module, which does the attach */ sd = v4l2_i2c_new_subdev(&dev->i2c_adap, "tuner", "tuner", dev->board.tuner_addr); - if (sd == NULL) { - printk("analog tuner subdev registration failure\n"); - } + if (sd == NULL) + printk(KERN_ERR "tuner subdev registration fail\n"); tun_setup.mode_mask = mode_mask; tun_setup.type = dev->board.tuner_type; diff --git a/drivers/media/video/au0828/au0828-i2c.c b/drivers/media/video/au0828/au0828-i2c.c index e841ba5a6424..1b110f37b895 100644 --- a/drivers/media/video/au0828/au0828-i2c.c +++ b/drivers/media/video/au0828/au0828-i2c.c @@ -145,11 +145,10 @@ static int i2c_sendbytes(struct i2c_adapter *i2c_adap, requires us to slow down the i2c clock until we have a better strategy (such as using the secondary i2c bus to do firmware loading */ - if ((msg->addr << 1) == 0xc2) { + if ((msg->addr << 1) == 0xc2) au0828_write(dev, REG_202, 0x40); - } else { + else au0828_write(dev, REG_202, 0x07); - } /* Hardware needs 8 bit addresses */ au0828_write(dev, REG_203, msg->addr << 1); @@ -223,11 +222,10 @@ static int i2c_readbytes(struct i2c_adapter *i2c_adap, requires us to slow down the i2c clock until we have a better strategy (such as using the secondary i2c bus to do firmware loading */ - if ((msg->addr << 1) == 0xc2) { + if ((msg->addr << 1) == 0xc2) au0828_write(dev, REG_202, 0x40); - } else { + else au0828_write(dev, REG_202, 0x07); - } /* Hardware needs 8 bit addresses */ au0828_write(dev, REG_203, msg->addr << 1); diff --git a/drivers/media/video/au0828/au0828-video.c b/drivers/media/video/au0828/au0828-video.c index 800345cbe0ef..057496414ea2 100644 --- a/drivers/media/video/au0828/au0828-video.c +++ b/drivers/media/video/au0828/au0828-video.c @@ -33,7 +33,6 @@ #include #include #include -#include #include #include #include @@ -46,9 +45,6 @@ static DEFINE_MUTEX(au0828_sysfs_lock); #define AU0828_VERSION_CODE KERNEL_VERSION(0, 0, 1) -/* Forward declarations */ -void au0828_analog_stream_reset(struct au0828_dev *dev); - /* ------------------------------------------------------------------ Videobuf operations ------------------------------------------------------------------*/ @@ -107,12 +103,12 @@ static inline void print_err_status(struct au0828_dev *dev, static int check_dev(struct au0828_dev *dev) { if (dev->dev_state & DEV_DISCONNECTED) { - printk("v4l2 ioctl: device not present\n"); + printk(KERN_INFO "v4l2 ioctl: device not present\n"); return -ENODEV; } if (dev->dev_state & DEV_MISCONFIGURED) { - printk("v4l2 ioctl: device is misconfigured; " + printk(KERN_INFO "v4l2 ioctl: device is misconfigured; " "close and open it again\n"); return -EIO; } @@ -373,7 +369,7 @@ static void au0828_copy_video(struct au0828_dev *dev, if ((char *)startwrite + lencopy > (char *)outp + buf->vb.size) { - au0828_isocdbg("Overflow of %zi bytes past buffer end (2)\n", + au0828_isocdbg("Overflow %zi bytes past buf end (2)\n", ((char *)startwrite + lencopy) - ((char *)outp + buf->vb.size)); lencopy = remain = (char *)outp + buf->vb.size - @@ -389,9 +385,8 @@ static void au0828_copy_video(struct au0828_dev *dev, if (offset > 1440) { /* We have enough data to check for greenscreen */ - if (outp[0] < 0x60 && outp[1440] < 0x60) { + if (outp[0] < 0x60 && outp[1440] < 0x60) dev->greenscreen_detected = 1; - } } dma_q->pos += len; @@ -457,9 +452,9 @@ static inline int au0828_isoc_copy(struct au0828_dev *dev, struct urb *urb) continue; } - if (urb->iso_frame_desc[i].actual_length <= 0) { + if (urb->iso_frame_desc[i].actual_length <= 0) continue; - } + if (urb->iso_frame_desc[i].actual_length > dev->max_pkt_size) { au0828_isocdbg("packet bigger than packet size"); @@ -480,25 +475,23 @@ static inline int au0828_isoc_copy(struct au0828_dev *dev, struct urb *urb) if (buf != NULL) buffer_filled(dev, dma_q, buf); get_next_buf(dma_q, &buf); - if (buf == NULL) { + if (buf == NULL) outp = NULL; - } else + else outp = videobuf_to_vmalloc(&buf->vb); } if (buf != NULL) { - if (fbyte & 0x40) { + if (fbyte & 0x40) buf->top_field = 1; - } else { + else buf->top_field = 0; - } } dma_q->pos = 0; } - if (buf != NULL) { + if (buf != NULL) au0828_copy_video(dev, dma_q, buf, p, outp, len); - } } return rc; } @@ -566,7 +559,7 @@ buffer_prepare(struct videobuf_queue *vq, struct videobuf_buffer *vb, if (VIDEOBUF_NEEDS_INIT == buf->vb.state) { rc = videobuf_iolock(vq, &buf->vb, NULL); if (rc < 0) { - printk("videobuf_iolock failed\n"); + printk(KERN_INFO "videobuf_iolock failed\n"); goto fail; } } @@ -579,7 +572,7 @@ buffer_prepare(struct videobuf_queue *vq, struct videobuf_buffer *vb, AU0828_MAX_ISO_BUFS, dev->max_pkt_size, au0828_isoc_copy); if (rc < 0) { - printk("au0828_init_isoc failed\n"); + printk(KERN_INFO "au0828_init_isoc failed\n"); goto fail; } } @@ -681,11 +674,11 @@ static int au0828_stream_interrupt(struct au0828_dev *dev) int ret = 0; dev->stream_state = STREAM_INTERRUPT; - if(dev->dev_state == DEV_DISCONNECTED) + if (dev->dev_state == DEV_DISCONNECTED) return -ENODEV; - else if(ret) { + else if (ret) { dev->dev_state = DEV_MISCONFIGURED; - dprintk(1, "%s device is misconfigured!\n", __FUNCTION__); + dprintk(1, "%s device is misconfigured!\n", __func__); return ret; } return 0; @@ -753,23 +746,23 @@ static int au0828_v4l2_open(struct file *filp) list_for_each(list, &au0828_devlist) { h = list_entry(list, struct au0828_dev, au0828list); - if(h->vdev->minor == minor) { + if (h->vdev->minor == minor) { dev = h; type = V4L2_BUF_TYPE_VIDEO_CAPTURE; } #ifdef VBI_NOT_YET_WORKING - if(h->vbi_dev->minor == minor) { + if (h->vbi_dev->minor == minor) { dev = h; type = V4L2_BUF_TYPE_VBI_CAPTURE; } #endif } - if(NULL == dev) + if (NULL == dev) return -ENODEV; fh = kzalloc(sizeof(struct au0828_fh), GFP_KERNEL); - if(NULL == fh) { + if (NULL == fh) { dprintk(1, "Failed allocate au0828_fh struct!\n"); return -ENOMEM; } @@ -778,11 +771,11 @@ static int au0828_v4l2_open(struct file *filp) fh->dev = dev; filp->private_data = fh; - if(fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE && dev->users == 0) { + if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE && dev->users == 0) { /* set au0828 interface0 to AS5 here again */ ret = usb_set_interface(dev->usbdev, 0, 5); - if(ret < 0) { - printk("Au0828 can't set alt setting to 5!\n"); + if (ret < 0) { + printk(KERN_INFO "Au0828 can't set alternate to 5!\n"); return -EBUSY; } dev->width = NTSC_STD_W; @@ -821,11 +814,11 @@ static int au0828_v4l2_close(struct file *filp) if (res_check(fh)) res_free(fh); - if(dev->users == 1) { + if (dev->users == 1) { videobuf_stop(&fh->vb_vidq); videobuf_mmap_free(&fh->vb_vidq); - if(dev->dev_state & DEV_DISCONNECTED) { + if (dev->dev_state & DEV_DISCONNECTED) { au0828_analog_unregister(dev); mutex_unlock(&dev->lock); kfree(dev); @@ -839,8 +832,8 @@ static int au0828_v4l2_close(struct file *filp) /* When close the device, set the usb intf0 into alt0 to free USB bandwidth */ ret = usb_set_interface(dev->usbdev, 0, 0); - if(ret < 0) - printk("Au0828 can't set alt setting to 0!\n"); + if (ret < 0) + printk(KERN_INFO "Au0828 can't set alternate to 0!\n"); } kfree(fh); @@ -861,7 +854,7 @@ static ssize_t au0828_v4l2_read(struct file *filp, char __user *buf, if (rc < 0) return rc; - if(fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) { + if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) { mutex_lock(&dev->lock); rc = res_get(fh); mutex_unlock(&dev->lock); @@ -937,28 +930,25 @@ static int au0828_set_format(struct au0828_dev *dev, unsigned int cmd, maxheight = 480; #ifdef VBI_NOT_YET_WORKING - if(format->type == V4L2_BUF_TYPE_SLICED_VBI_CAPTURE) { + if (format->type == V4L2_BUF_TYPE_SLICED_VBI_CAPTURE) { dprintk(1, "VBI format set: to be supported!\n"); return 0; } - if(format->type == V4L2_BUF_TYPE_VBI_CAPTURE) { + if (format->type == V4L2_BUF_TYPE_VBI_CAPTURE) return 0; - } #endif - if(format->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) { + if (format->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) return -EINVAL; - } /* If they are demanding a format other than the one we support, bail out (tvtime asks for UYVY and then retries with YUYV) */ - if (format->fmt.pix.pixelformat != V4L2_PIX_FMT_UYVY) { + if (format->fmt.pix.pixelformat != V4L2_PIX_FMT_UYVY) return -EINVAL; - } /* format->fmt.pix.width only support 720 and height 480 */ - if(width != 720) + if (width != 720) width = 720; - if(height != 480) + if (height != 480) height = 480; format->fmt.pix.width = width; @@ -969,7 +959,7 @@ static int au0828_set_format(struct au0828_dev *dev, unsigned int cmd, format->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; format->fmt.pix.field = V4L2_FIELD_INTERLACED; - if(cmd == VIDIOC_TRY_FMT) + if (cmd == VIDIOC_TRY_FMT) return 0; /* maybe set new image format, driver current only support 720*480 */ @@ -979,9 +969,10 @@ static int au0828_set_format(struct au0828_dev *dev, unsigned int cmd, dev->field_size = width * height; dev->bytesperline = width * 2; - if(dev->stream_state == STREAM_ON) { + if (dev->stream_state == STREAM_ON) { dprintk(1, "VIDIOC_SET_FMT: interrupting stream!\n"); - if((ret = au0828_stream_interrupt(dev))) { + ret = au0828_stream_interrupt(dev); + if (ret != 0) { dprintk(1, "error interrupting video stream!\n"); return ret; } @@ -989,8 +980,8 @@ static int au0828_set_format(struct au0828_dev *dev, unsigned int cmd, /* set au0828 interface0 to AS5 here again */ ret = usb_set_interface(dev->usbdev, 0, 5); - if(ret < 0) { - printk("Au0828 can't set alt setting to 5!\n"); + if (ret < 0) { + printk(KERN_INFO "Au0828 can't set alt setting to 5!\n"); return -EBUSY; } @@ -1039,7 +1030,7 @@ static int vidioc_querycap(struct file *file, void *priv, static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv, struct v4l2_fmtdesc *f) { - if(f->index) + if (f->index) return -EINVAL; f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; @@ -1084,13 +1075,13 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, int rc; if (videobuf_queue_is_busy(&fh->vb_vidq)) { - printk("%s queue busy\n", __func__); + printk(KERN_INFO "%s queue busy\n", __func__); rc = -EBUSY; goto out; } if (dev->stream_on && !fh->stream_on) { - printk("%s device in use by another fh\n", __func__); + printk(KERN_INFO "%s device in use by another fh\n", __func__); rc = -EBUSY; goto out; } @@ -1132,15 +1123,15 @@ static int vidioc_enum_input(struct file *file, void *priv, tmp = input->index; - if(tmp > AU0828_MAX_INPUT) + if (tmp > AU0828_MAX_INPUT) return -EINVAL; - if(AUVI_INPUT(tmp).type == 0) + if (AUVI_INPUT(tmp).type == 0) return -EINVAL; input->index = tmp; strcpy(input->name, inames[AUVI_INPUT(tmp).type]); - if((AUVI_INPUT(tmp).type == AU0828_VMUX_TELEVISION) || - (AUVI_INPUT(tmp).type == AU0828_VMUX_CABLE)) + if ((AUVI_INPUT(tmp).type == AU0828_VMUX_TELEVISION) || + (AUVI_INPUT(tmp).type == AU0828_VMUX_CABLE)) input->type |= V4L2_INPUT_TYPE_TUNER; else input->type |= V4L2_INPUT_TYPE_CAMERA; @@ -1165,15 +1156,15 @@ static int vidioc_s_input(struct file *file, void *priv, unsigned int index) int i; struct v4l2_routing route; - dprintk(1, "VIDIOC_S_INPUT in function %s, input=%d\n", __FUNCTION__, + dprintk(1, "VIDIOC_S_INPUT in function %s, input=%d\n", __func__, index); - if(index >= AU0828_MAX_INPUT) + if (index >= AU0828_MAX_INPUT) return -EINVAL; - if(AUVI_INPUT(index).type == 0) + if (AUVI_INPUT(index).type == 0) return -EINVAL; dev->ctrl_input = index; - switch(AUVI_INPUT(index).type) { + switch (AUVI_INPUT(index).type) { case AU0828_VMUX_SVIDEO: dev->input_type = AU0828_VMUX_SVIDEO; break; @@ -1195,9 +1186,8 @@ static int vidioc_s_input(struct file *file, void *priv, unsigned int index) for (i = 0; i < AU0828_MAX_INPUT; i++) { int enable = 0; - if (AUVI_INPUT(i).audio_setup == NULL) { + if (AUVI_INPUT(i).audio_setup == NULL) continue; - } if (i == index) enable = 1; @@ -1227,11 +1217,11 @@ static int vidioc_g_audio(struct file *file, void *priv, struct v4l2_audio *a) struct au0828_dev *dev = fh->dev; unsigned int index = a->index; - if(a->index > 1) + if (a->index > 1) return -EINVAL; index = dev->ctrl_ainput; - if(index == 0) + if (index == 0) strcpy(a->name, "Television"); else strcpy(a->name, "Line in"); @@ -1245,7 +1235,7 @@ static int vidioc_s_audio(struct file *file, void *priv, struct v4l2_audio *a) { struct au0828_fh *fh = priv; struct au0828_dev *dev = fh->dev; - if(a->index != dev->ctrl_ainput) + if (a->index != dev->ctrl_ainput) return -EINVAL; return 0; } @@ -1275,7 +1265,7 @@ static int vidioc_g_tuner(struct file *file, void *priv, struct v4l2_tuner *t) struct au0828_fh *fh = priv; struct au0828_dev *dev = fh->dev; - if(t->index != 0) + if (t->index != 0) return -EINVAL; strcpy(t->name, "Auvitek tuner"); @@ -1290,7 +1280,7 @@ static int vidioc_s_tuner(struct file *file, void *priv, struct au0828_fh *fh = priv; struct au0828_dev *dev = fh->dev; - if(t->index != 0) + if (t->index != 0) return -EINVAL; t->type = V4L2_TUNER_ANALOG_TV; @@ -1318,9 +1308,9 @@ static int vidioc_s_frequency(struct file *file, void *priv, struct au0828_fh *fh = priv; struct au0828_dev *dev = fh->dev; - if(freq->tuner != 0) + if (freq->tuner != 0) return -EINVAL; - if(freq->type != V4L2_TUNER_ANALOG_TV) + if (freq->type != V4L2_TUNER_ANALOG_TV) return -EINVAL; dev->ctrl_freq = freq->frequency; @@ -1358,7 +1348,7 @@ static int vidioc_cropcap(struct file *file, void *priv, struct au0828_fh *fh = priv; struct au0828_dev *dev = fh->dev; - if(cc->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + if (cc->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) return -EINVAL; cc->bounds.left = 0; @@ -1422,14 +1412,14 @@ static int vidioc_streamoff(struct file *file, void *priv, if (type == V4L2_BUF_TYPE_VIDEO_CAPTURE) { au0828_call_i2c_clients(dev, VIDIOC_STREAMOFF, &b); - if((ret = au0828_stream_interrupt(dev)) != 0) + ret = au0828_stream_interrupt(dev); + if (ret != 0) return ret; } for (i = 0; i < AU0828_MAX_INPUT; i++) { - if (AUVI_INPUT(i).audio_setup == NULL) { + if (AUVI_INPUT(i).audio_setup == NULL) continue; - } (AUVI_INPUT(i).audio_setup)(dev, 0); } @@ -1622,27 +1612,30 @@ int au0828_analog_register(struct au0828_dev *dev, /* set au0828 usb interface0 to as5 */ retval = usb_set_interface(dev->usbdev, - interface->cur_altsetting->desc.bInterfaceNumber, 5); + interface->cur_altsetting->desc.bInterfaceNumber, 5); if (retval != 0) { - printk("Failure setting usb interface0 to as5\n"); + printk(KERN_INFO "Failure setting usb interface0 to as5\n"); return retval; } /* Figure out which endpoint has the isoc interface */ iface_desc = interface->cur_altsetting; - for(i = 0; i < iface_desc->desc.bNumEndpoints; i++){ + for (i = 0; i < iface_desc->desc.bNumEndpoints; i++) { endpoint = &iface_desc->endpoint[i].desc; - if(((endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_IN) && - ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_ISOC)){ + if (((endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK) + == USB_DIR_IN) && + ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) + == USB_ENDPOINT_XFER_ISOC)) { /* we find our isoc in endpoint */ u16 tmp = le16_to_cpu(endpoint->wMaxPacketSize); - dev->max_pkt_size = (tmp & 0x07ff) * (((tmp & 0x1800) >> 11) + 1); + dev->max_pkt_size = (tmp & 0x07ff) * + (((tmp & 0x1800) >> 11) + 1); dev->isoc_in_endpointaddr = endpoint->bEndpointAddress; } } - if(!(dev->isoc_in_endpointaddr)) { - printk("Could not locate isoc endpoint\n"); + if (!(dev->isoc_in_endpointaddr)) { + printk(KERN_INFO "Could not locate isoc endpoint\n"); kfree(dev); return -ENODEV; } @@ -1663,14 +1656,14 @@ int au0828_analog_register(struct au0828_dev *dev, /* allocate and fill v4l2 video struct */ dev->vdev = video_device_alloc(); - if(NULL == dev->vdev) { + if (NULL == dev->vdev) { dprintk(1, "Can't allocate video_device.\n"); return -ENOMEM; } #ifdef VBI_NOT_YET_WORKING dev->vbi_dev = video_device_alloc(); - if(NULL == dev->vbi_dev) { + if (NULL == dev->vbi_dev) { dprintk(1, "Can't allocate vbi_device.\n"); kfree(dev->vdev); return -ENOMEM; @@ -1679,14 +1672,12 @@ int au0828_analog_register(struct au0828_dev *dev, /* Fill the video capture device struct */ *dev->vdev = au0828_video_template; - dev->vdev->vfl_type = VID_TYPE_CAPTURE | VID_TYPE_TUNER; dev->vdev->parent = &dev->usbdev->dev; strcpy(dev->vdev->name, "au0828a video"); #ifdef VBI_NOT_YET_WORKING /* Setup the VBI device */ *dev->vbi_dev = au0828_video_template; - dev->vbi_dev->vfl_type = VFL_TYPE_VBI; dev->vbi_dev->parent = &dev->usbdev->dev; strcpy(dev->vbi_dev->name, "au0828a vbi"); #endif @@ -1694,8 +1685,10 @@ int au0828_analog_register(struct au0828_dev *dev, list_add_tail(&dev->au0828list, &au0828_devlist); /* Register the v4l2 device */ - if((retval = video_register_device(dev->vdev, VFL_TYPE_GRABBER, -1)) != 0) { - dprintk(1, "unable to register video device (error = %d).\n", retval); + retval = video_register_device(dev->vdev, VFL_TYPE_GRABBER, -1); + if (retval != 0) { + dprintk(1, "unable to register video device (error = %d).\n", + retval); list_del(&dev->au0828list); video_device_release(dev->vdev); return -ENODEV; @@ -1703,8 +1696,10 @@ int au0828_analog_register(struct au0828_dev *dev, #ifdef VBI_NOT_YET_WORKING /* Register the vbi device */ - if((retval = video_register_device(dev->vbi_dev, VFL_TYPE_VBI, -1)) != 0) { - dprintk(1, "unable to register vbi device (error = %d).\n", retval); + retval = video_register_device(dev->vbi_dev, VFL_TYPE_VBI, -1); + if (retval != 0) { + dprintk(1, "unable to register vbi device (error = %d).\n", + retval); list_del(&dev->au0828list); video_device_release(dev->vbi_dev); video_device_release(dev->vdev); @@ -1712,7 +1707,7 @@ int au0828_analog_register(struct au0828_dev *dev, } #endif - dprintk(1, "%s completed!\n", __FUNCTION__); + dprintk(1, "%s completed!\n", __func__); return 0; } diff --git a/drivers/media/video/au0828/au0828.h b/drivers/media/video/au0828/au0828.h index 876b18cfbf55..6d9bd454ea53 100644 --- a/drivers/media/video/au0828/au0828.h +++ b/drivers/media/video/au0828/au0828.h @@ -54,16 +54,10 @@ /* Defination for AU0828 USB transfer */ #define AU0828_MAX_ISO_BUFS 12 /* maybe resize this value in the future */ #define AU0828_ISO_PACKETS_PER_URB 10 -#define AU0828_ISO_MAX_FRAME_SIZE (3 * 1024) -#define AU0828_ISO_BUFFER_SIZE (AU0828_ISO_PACKETS_PER_URB * AU0828_ISO_MAX_FRAME_SIZE) #define AU0828_MIN_BUF 4 #define AU0828_DEF_BUF 8 -#define AU0828_MAX_IMAGES 10 -#define AU0828_FRAME_SIZE (1028 * 1024 * 4) -#define AU0828_URB_TIMEOUT msecs_to_jiffies(AU0828_MAX_ISO_BUFS * AU0828_ISO_PACKETS_PER_URB) - #define AU0828_MAX_INPUT 4 enum au0828_itype { -- cgit v1.2.3 From dd27ade7a9195cb3b1f56df4d0ec39763830390b Mon Sep 17 00:00:00 2001 From: Devin Heitmueller Date: Sun, 15 Mar 2009 18:52:10 -0300 Subject: V4L/DVB (11086): au0828: rename macro for currently non-function VBI support The VBI support or the au0828 has the framework written but it does not yet work. Rename the macro per Mauro's request. Signed-off-by: Devin Heitmueller Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/au0828/au0828-video.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/au0828/au0828-video.c b/drivers/media/video/au0828/au0828-video.c index 057496414ea2..e1940467b472 100644 --- a/drivers/media/video/au0828/au0828-video.c +++ b/drivers/media/video/au0828/au0828-video.c @@ -750,7 +750,7 @@ static int au0828_v4l2_open(struct file *filp) dev = h; type = V4L2_BUF_TYPE_VIDEO_CAPTURE; } -#ifdef VBI_NOT_YET_WORKING +#ifdef VBI_IS_WORKING if (h->vbi_dev->minor == minor) { dev = h; type = V4L2_BUF_TYPE_VBI_CAPTURE; @@ -929,7 +929,7 @@ static int au0828_set_format(struct au0828_dev *dev, unsigned int cmd, maxwidth = 720; maxheight = 480; -#ifdef VBI_NOT_YET_WORKING +#ifdef VBI_IS_WORKING if (format->type == V4L2_BUF_TYPE_SLICED_VBI_CAPTURE) { dprintk(1, "VBI format set: to be supported!\n"); return 0; @@ -1017,7 +1017,7 @@ static int vidioc_querycap(struct file *file, void *priv, /*set the device capabilities */ cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | -#ifdef VBI_NOT_YET_WORKING +#ifdef VBI_IS_WORKING V4L2_CAP_VBI_CAPTURE | #endif V4L2_CAP_AUDIO | @@ -1549,7 +1549,7 @@ static const struct v4l2_ioctl_ops video_ioctl_ops = { .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap, .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap, .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap, -#ifdef VBI_NOT_YET_WORKING +#ifdef VBI_IS_WORKING .vidioc_g_fmt_vbi_cap = vidioc_g_fmt_vbi_cap, .vidioc_try_fmt_vbi_cap = vidioc_s_fmt_vbi_cap, .vidioc_s_fmt_vbi_cap = vidioc_s_fmt_vbi_cap, @@ -1557,7 +1557,7 @@ static const struct v4l2_ioctl_ops video_ioctl_ops = { .vidioc_g_audio = vidioc_g_audio, .vidioc_s_audio = vidioc_s_audio, .vidioc_cropcap = vidioc_cropcap, -#ifdef VBI_NOT_YET_WORKING +#ifdef VBI_IS_WORKING .vidioc_g_fmt_sliced_vbi_cap = vidioc_g_fmt_sliced_vbi_cap, .vidioc_try_fmt_sliced_vbi_cap = vidioc_try_set_sliced_vbi_cap, .vidioc_s_fmt_sliced_vbi_cap = vidioc_try_set_sliced_vbi_cap, @@ -1661,7 +1661,7 @@ int au0828_analog_register(struct au0828_dev *dev, return -ENOMEM; } -#ifdef VBI_NOT_YET_WORKING +#ifdef VBI_IS_WORKING dev->vbi_dev = video_device_alloc(); if (NULL == dev->vbi_dev) { dprintk(1, "Can't allocate vbi_device.\n"); @@ -1675,7 +1675,7 @@ int au0828_analog_register(struct au0828_dev *dev, dev->vdev->parent = &dev->usbdev->dev; strcpy(dev->vdev->name, "au0828a video"); -#ifdef VBI_NOT_YET_WORKING +#ifdef VBI_IS_WORKING /* Setup the VBI device */ *dev->vbi_dev = au0828_video_template; dev->vbi_dev->parent = &dev->usbdev->dev; @@ -1694,7 +1694,7 @@ int au0828_analog_register(struct au0828_dev *dev, return -ENODEV; } -#ifdef VBI_NOT_YET_WORKING +#ifdef VBI_IS_WORKING /* Register the vbi device */ retval = video_register_device(dev->vbi_dev, VFL_TYPE_VBI, -1); if (retval != 0) { -- cgit v1.2.3 From 2689d3dcc6c75c0b4a05b66330db85df2c036d3e Mon Sep 17 00:00:00 2001 From: Devin Heitmueller Date: Sun, 15 Mar 2009 20:01:53 -0300 Subject: V4L/DVB (11088): au0828: finish videodev/subdev conversion Per Hans Verkuil instruction, remove the deprecated attach_inform/detach_inform routines, and convert over the i2c calls to subdev calls. Thanks to Hans Verkuil for providing feedback on the au0828 analog support. Signed-off-by: Devin Heitmueller Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/au0828/au0828-cards.c | 3 ++- drivers/media/video/au0828/au0828-i2c.c | 29 ---------------------------- drivers/media/video/au0828/au0828-video.c | 32 ++++++++++++++----------------- drivers/media/video/au0828/au0828.h | 2 -- 4 files changed, 16 insertions(+), 50 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/au0828/au0828-cards.c b/drivers/media/video/au0828/au0828-cards.c index 1b48eb58a161..1aabaa7e55bb 100644 --- a/drivers/media/video/au0828/au0828-cards.c +++ b/drivers/media/video/au0828/au0828-cards.c @@ -218,7 +218,8 @@ void au0828_card_setup(struct au0828_dev *dev) tun_setup.type = dev->board.tuner_type; tun_setup.addr = dev->board.tuner_addr; tun_setup.tuner_callback = au0828_tuner_callback; - au0828_call_i2c_clients(dev, TUNER_SET_TYPE_ADDR, &tun_setup); + v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_type_addr, + &tun_setup); } } diff --git a/drivers/media/video/au0828/au0828-i2c.c b/drivers/media/video/au0828/au0828-i2c.c index 1b110f37b895..f9a958d0aef1 100644 --- a/drivers/media/video/au0828/au0828-i2c.c +++ b/drivers/media/video/au0828/au0828-i2c.c @@ -299,33 +299,6 @@ err: return retval; } -static int attach_inform(struct i2c_client *client) -{ - dprintk(1, "%s i2c attach [addr=0x%x,client=%s]\n", - client->driver->driver.name, client->addr, client->name); - - if (!client->driver->command) - return 0; - - return 0; -} - -static int detach_inform(struct i2c_client *client) -{ - dprintk(1, "i2c detach [client=%s]\n", client->name); - - return 0; -} - -void au0828_call_i2c_clients(struct au0828_dev *dev, - unsigned int cmd, void *arg) -{ - if (dev->i2c_rc != 0) - return; - - i2c_clients_command(&dev->i2c_adap, cmd, arg); -} - static u32 au0828_functionality(struct i2c_adapter *adap) { return I2C_FUNC_SMBUS_EMUL | I2C_FUNC_I2C; @@ -343,8 +316,6 @@ static struct i2c_adapter au0828_i2c_adap_template = { .owner = THIS_MODULE, .id = I2C_HW_B_AU0828, .algo = &au0828_i2c_algo_template, - .client_register = attach_inform, - .client_unregister = detach_inform, }; static struct i2c_client au0828_i2c_client_template = { diff --git a/drivers/media/video/au0828/au0828-video.c b/drivers/media/video/au0828/au0828-video.c index e1940467b472..5de968e128f6 100644 --- a/drivers/media/video/au0828/au0828-video.c +++ b/drivers/media/video/au0828/au0828-video.c @@ -996,7 +996,7 @@ static int vidioc_queryctrl(struct file *file, void *priv, { struct au0828_fh *fh = priv; struct au0828_dev *dev = fh->dev; - au0828_call_i2c_clients(dev, VIDIOC_QUERYCTRL, qc); + v4l2_device_call_all(&dev->v4l2_dev, 0, core, queryctrl, qc); if (qc->type) return 0; else @@ -1100,7 +1100,7 @@ static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id * norm) have to make the au0828 bridge adjust the size of its capture buffer, which is currently hardcoded at 720x480 */ - au0828_call_i2c_clients(dev, VIDIOC_S_STD, norm); + v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_std, *norm); return 0; } @@ -1182,7 +1182,7 @@ static int vidioc_s_input(struct file *file, void *priv, unsigned int index) route.input = AUVI_INPUT(index).vmux; route.output = 0; - au0828_call_i2c_clients(dev, VIDIOC_INT_S_VIDEO_ROUTING, &route); + v4l2_device_call_all(&dev->v4l2_dev, 0, video, s_routing, &route); for (i = 0; i < AU0828_MAX_INPUT; i++) { int enable = 0; @@ -1206,8 +1206,7 @@ static int vidioc_s_input(struct file *file, void *priv, unsigned int index) } route.input = AUVI_INPUT(index).amux; - au0828_call_i2c_clients(dev, VIDIOC_INT_S_AUDIO_ROUTING, - &route); + v4l2_device_call_all(&dev->v4l2_dev, 0, audio, s_routing, &route); return 0; } @@ -1246,7 +1245,7 @@ static int vidioc_g_ctrl(struct file *file, void *priv, struct au0828_fh *fh = priv; struct au0828_dev *dev = fh->dev; - au0828_call_i2c_clients(dev, VIDIOC_G_CTRL, ctrl); + v4l2_device_call_all(&dev->v4l2_dev, 0, core, g_ctrl, ctrl); return 0; } @@ -1256,7 +1255,7 @@ static int vidioc_s_ctrl(struct file *file, void *priv, { struct au0828_fh *fh = priv; struct au0828_dev *dev = fh->dev; - au0828_call_i2c_clients(dev, VIDIOC_S_CTRL, ctrl); + v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_ctrl, ctrl); return 0; } @@ -1269,8 +1268,7 @@ static int vidioc_g_tuner(struct file *file, void *priv, struct v4l2_tuner *t) return -EINVAL; strcpy(t->name, "Auvitek tuner"); - - au0828_call_i2c_clients(dev, VIDIOC_G_TUNER, t); + v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, g_tuner, t); return 0; } @@ -1284,7 +1282,7 @@ static int vidioc_s_tuner(struct file *file, void *priv, return -EINVAL; t->type = V4L2_TUNER_ANALOG_TV; - au0828_call_i2c_clients(dev, VIDIOC_S_TUNER, t); + v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_tuner, t); dprintk(1, "VIDIOC_S_TUNER: signal = %x, afc = %x\n", t->signal, t->afc); return 0; @@ -1315,7 +1313,7 @@ static int vidioc_s_frequency(struct file *file, void *priv, dev->ctrl_freq = freq->frequency; - au0828_call_i2c_clients(dev, VIDIOC_S_FREQUENCY, freq); + v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_frequency, freq); au0828_analog_stream_reset(dev); @@ -1335,7 +1333,7 @@ static int vidioc_g_chip_ident(struct file *file, void *priv, return 0; } - au0828_call_i2c_clients(dev, VIDIOC_DBG_G_CHIP_IDENT, chip); + v4l2_device_call_all(&dev->v4l2_dev, 0, core, g_chip_ident, chip); if (chip->ident == V4L2_IDENT_NONE) return -EINVAL; @@ -1369,7 +1367,6 @@ static int vidioc_streamon(struct file *file, void *priv, { struct au0828_fh *fh = priv; struct au0828_dev *dev = fh->dev; - int b = V4L2_BUF_TYPE_VIDEO_CAPTURE; int rc; rc = check_dev(dev); @@ -1378,7 +1375,7 @@ static int vidioc_streamon(struct file *file, void *priv, if (type == V4L2_BUF_TYPE_VIDEO_CAPTURE) { au0828_analog_stream_enable(dev); - au0828_call_i2c_clients(dev, VIDIOC_STREAMON, &b); + v4l2_device_call_all(&dev->v4l2_dev, 0, video, s_stream, 1); } mutex_lock(&dev->lock); @@ -1396,7 +1393,6 @@ static int vidioc_streamoff(struct file *file, void *priv, { struct au0828_fh *fh = priv; struct au0828_dev *dev = fh->dev; - int b = V4L2_BUF_TYPE_VIDEO_CAPTURE; int i; int ret; int rc; @@ -1411,7 +1407,7 @@ static int vidioc_streamoff(struct file *file, void *priv, return -EINVAL; if (type == V4L2_BUF_TYPE_VIDEO_CAPTURE) { - au0828_call_i2c_clients(dev, VIDIOC_STREAMOFF, &b); + v4l2_device_call_all(&dev->v4l2_dev, 0, video, s_stream, 0); ret = au0828_stream_interrupt(dev); if (ret != 0) return ret; @@ -1439,7 +1435,7 @@ static int vidioc_g_register(struct file *file, void *priv, switch (reg->match.type) { case V4L2_CHIP_MATCH_I2C_DRIVER: - au0828_call_i2c_clients(dev, VIDIOC_DBG_G_REGISTER, reg); + v4l2_device_call_all(&dev->v4l2_dev, 0, core, g_register, reg); return 0; default: return -EINVAL; @@ -1454,7 +1450,7 @@ static int vidioc_s_register(struct file *file, void *priv, switch (reg->match.type) { case V4L2_CHIP_MATCH_I2C_DRIVER: - au0828_call_i2c_clients(dev, VIDIOC_DBG_S_REGISTER, reg); + v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_register, reg); return 0; default: return -EINVAL; diff --git a/drivers/media/video/au0828/au0828.h b/drivers/media/video/au0828/au0828.h index 6d9bd454ea53..6ed1a6129731 100644 --- a/drivers/media/video/au0828/au0828.h +++ b/drivers/media/video/au0828/au0828.h @@ -265,8 +265,6 @@ extern void au0828_card_setup(struct au0828_dev *dev); /* au0828-i2c.c */ extern int au0828_i2c_register(struct au0828_dev *dev); extern int au0828_i2c_unregister(struct au0828_dev *dev); -extern void au0828_call_i2c_clients(struct au0828_dev *dev, - unsigned int cmd, void *arg); /* ----------------------------------------------------------- */ /* au0828-video.c */ -- cgit v1.2.3 From 6e1a63720228ef7fc3bd00b04dfb608064fbab4e Mon Sep 17 00:00:00 2001 From: Andy Walls Date: Sat, 14 Mar 2009 20:03:26 -0300 Subject: V4L/DVB (11091): cx18, ivtv: Ensure endianess for linemasks in VBI embedded in MPEG stream The sliced VBI payloads that cx18 and ivtv would insert in the MPEG stream did not have consistent endianess for the linemasks in the payload (a big endian platform would write them out big endian). This change ensures the linemasks are always stored as little-endian in the MPEG stream to ensure cross platform consistency in parsing the generated MPEG stream. Signed-off-by: Andy Walls Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx18/cx18-vbi.c | 2 ++ drivers/media/video/ivtv/ivtv-vbi.c | 2 ++ 2 files changed, 4 insertions(+) (limited to 'drivers/media/video') diff --git a/drivers/media/video/cx18/cx18-vbi.c b/drivers/media/video/cx18/cx18-vbi.c index 355737bff13e..99f9b2c86b0c 100644 --- a/drivers/media/video/cx18/cx18-vbi.c +++ b/drivers/media/video/cx18/cx18-vbi.c @@ -88,6 +88,8 @@ static void copy_vbi_data(struct cx18 *cx, int lines, u32 pts_stamp) size = 4 + ((43 * line + 3) & ~3); } else { memcpy(dst + sd, "itv0", 4); + cpu_to_le32s(&linemask[0]); + cpu_to_le32s(&linemask[1]); memcpy(dst + sd + 4, &linemask[0], 8); size = 12 + ((43 * line + 3) & ~3); } diff --git a/drivers/media/video/ivtv/ivtv-vbi.c b/drivers/media/video/ivtv/ivtv-vbi.c index 5c5d1c462fef..f420d31b937d 100644 --- a/drivers/media/video/ivtv/ivtv-vbi.c +++ b/drivers/media/video/ivtv/ivtv-vbi.c @@ -185,6 +185,8 @@ static void copy_vbi_data(struct ivtv *itv, int lines, u32 pts_stamp) size = 4 + ((43 * line + 3) & ~3); } else { memcpy(dst + sd, "itv0", 4); + cpu_to_le32s(&linemask[0]); + cpu_to_le32s(&linemask[1]); memcpy(dst + sd + 4, &linemask[0], 8); size = 12 + ((43 * line + 3) & ~3); } -- cgit v1.2.3 From 4ab9b256b5908afbdc030a8c3184ce243f5aca39 Mon Sep 17 00:00:00 2001 From: Andy Walls Date: Sat, 14 Mar 2009 23:20:49 -0300 Subject: V4L/DVB (11092): cx18: Optimize processing of VBI buffers from the capture unit Removed some unnecessary memcpy()'s by reworking the compress_*_vbi_buf() functions. Signed-off-by: Andy Walls Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx18/cx18-vbi.c | 103 +++++++++++++++++------------------- 1 file changed, 49 insertions(+), 54 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/cx18/cx18-vbi.c b/drivers/media/video/cx18/cx18-vbi.c index 99f9b2c86b0c..c2aef4add31d 100644 --- a/drivers/media/video/cx18/cx18-vbi.c +++ b/drivers/media/video/cx18/cx18-vbi.c @@ -105,54 +105,72 @@ static void copy_vbi_data(struct cx18 *cx, int lines, u32 pts_stamp) /* Compress raw VBI format, removes leading SAV codes and surplus space after the frame. Returns new compressed size. */ -static u32 compress_raw_buf(struct cx18 *cx, u8 *buf, u32 size) +static u32 compress_raw_buf(struct cx18 *cx, u8 *buf, u32 size, u32 hdr_size) { u32 line_size = vbi_active_samples; u32 lines = cx->vbi.count * 2; - u8 sav1 = raw_vbi_sav_rp[0]; - u8 sav2 = raw_vbi_sav_rp[1]; u8 *q = buf; u8 *p; int i; + /* Skip the header */ + buf += hdr_size; + for (i = 0; i < lines; i++) { p = buf + i * line_size; /* Look for SAV code */ if (p[0] != 0xff || p[1] || p[2] || - (p[3] != sav1 && p[3] != sav2)) + (p[3] != raw_vbi_sav_rp[0] && + p[3] != raw_vbi_sav_rp[1])) break; - memcpy(q, p + 4, line_size - 4); - q += line_size - 4; + if (i == lines - 1) { + /* last line is hdr_size bytes short - extrapolate it */ + memcpy(q, p + 4, line_size - 4 - hdr_size); + q += line_size - 4 - hdr_size; + p += line_size - hdr_size - 1; + memset(q, (int) *p, hdr_size); + } else { + memcpy(q, p + 4, line_size - 4); + q += line_size - 4; + } } return lines * (line_size - 4); } - -/* Compressed VBI format, all found sliced blocks put next to one another - Returns new compressed size */ -static u32 compress_sliced_buf(struct cx18 *cx, u32 line, u8 *buf, - u32 size, u8 eav) +static u32 compress_sliced_buf(struct cx18 *cx, u8 *buf, u32 size, + const u32 hdr_size) { struct v4l2_decode_vbi_line vbi; int i; + u32 line = 0; u32 line_size = cx->is_60hz ? vbi_hblank_samples_60Hz : vbi_hblank_samples_50Hz; /* find the first valid line */ - for (i = 0; i < size; i++, buf++) { - if (buf[0] == 0xff && !buf[1] && !buf[2] && buf[3] == eav) + for (i = hdr_size, buf += hdr_size; i < size; i++, buf++) { + if (buf[0] == 0xff && !buf[1] && !buf[2] && + (buf[3] == sliced_vbi_eav_rp[0] || + buf[3] == sliced_vbi_eav_rp[1])) break; } - size -= i; + /* + * The last line is short by hdr_size bytes, but for the remaining + * checks against size, we pretend that it is not, by counting the + * header bytes we knowingly skipped + */ + size -= (i - hdr_size); if (size < line_size) return line; + for (i = 0; i < size / line_size; i++) { u8 *p = buf + i * line_size; /* Look for EAV code */ - if (p[0] != 0xff || p[1] || p[2] || p[3] != eav) + if (p[0] != 0xff || p[1] || p[2] || + (p[3] != sliced_vbi_eav_rp[0] && + p[3] != sliced_vbi_eav_rp[1])) continue; vbi.p = p + 4; v4l2_subdev_call(cx->sd_av, video, decode_vbi_line, &vbi); @@ -170,8 +188,17 @@ static u32 compress_sliced_buf(struct cx18 *cx, u32 line, u8 *buf, void cx18_process_vbi_data(struct cx18 *cx, struct cx18_buffer *buf, int streamtype) { + /* + * The CX23418 provides a 12 byte header in its raw VBI buffers to us: + * 0x3fffffff [4 bytes of something] [4 byte presentation time stamp] + */ + struct vbi_data_hdr { + __be32 magic; + __be32 unknown; + __be32 pts; + } *hdr = (struct vbi_data_hdr *) buf->buf; + u8 *p = (u8 *) buf->buf; - __be32 *q = (__be32 *) buf->buf; u32 size = buf->bytesused; u32 pts; int lines; @@ -182,32 +209,15 @@ void cx18_process_vbi_data(struct cx18 *cx, struct cx18_buffer *buf, /* * The CX23418 sends us data that is 32 bit little-endian swapped, * but we want the raw VBI bytes in the order they were in the raster - * line. This has a side effect of making the 12 byte header big endian + * line. This has a side effect of making the header big endian */ cx18_buf_swap(buf); - /* - * The CX23418 provides a 12 byte header in it's raw VBI buffers to us: - * 0x3fffffff [4 bytes of something] [4 byte presentation time stamp?] - */ - /* Raw VBI data */ if (cx18_raw_vbi(cx)) { - u8 type; - - /* - * We've set up to get a frame's worth of VBI data at a time. - * Skip 12 bytes of header prefixing the first field. - */ - size -= 12; - memcpy(p, &buf->buf[12], size); - type = p[3]; - /* Extrapolate the last 12 bytes of the frame's last line */ - memset(&p[size], (int) p[size - 1], 12); - size += 12; - - size = buf->bytesused = compress_raw_buf(cx, p, size); + size = buf->bytesused = + compress_raw_buf(cx, p, size, sizeof(struct vbi_data_hdr)); /* * Hack needed for compatibility with old VBI software. @@ -221,26 +231,11 @@ void cx18_process_vbi_data(struct cx18 *cx, struct cx18_buffer *buf, /* Sliced VBI data with data insertion */ - pts = (be32_to_cpu(q[0]) == 0x3fffffff) ? be32_to_cpu(q[2]) : 0; + pts = (be32_to_cpu(hdr->magic) == 0x3fffffff) ? be32_to_cpu(hdr->pts) + : 0; - /* - * For calls to compress_sliced_buf(), ensure there are an integral - * number of lines by shifting the real data up over the 12 bytes header - * that got stuffed in. - * FIXME - there's a smarter way to do this with pointers, but for some - * reason I can't get it to work correctly right now. - */ - memcpy(p, &buf->buf[12], size-12); + lines = compress_sliced_buf(cx, p, size, sizeof(struct vbi_data_hdr)); - /* first field */ - lines = compress_sliced_buf(cx, 0, p, size / 2, sliced_vbi_eav_rp[0]); - /* - * second field - * In case the second half does not always begin at the exact address, - * start a bit earlier (hence 32). - */ - lines = compress_sliced_buf(cx, lines, p + size / 2 - 32, - size / 2 + 32, sliced_vbi_eav_rp[1]); /* always return at least one empty line */ if (lines == 0) { cx->vbi.sliced_data[0].id = 0; -- cgit v1.2.3 From 8c84cfda3e37540abc38f42383b03dd69829faee Mon Sep 17 00:00:00 2001 From: Janne Grunau Date: Wed, 18 Mar 2009 17:00:39 -0300 Subject: V4L/DVB (11095): adds V4L2_CID_SHARPNESS to v4l2_ctrl_query_fill() Signed-off-by: Janne Grunau Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/v4l2-common.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/media/video') diff --git a/drivers/media/video/v4l2-common.c b/drivers/media/video/v4l2-common.c index 49aad1ed0b26..b09782563c29 100644 --- a/drivers/media/video/v4l2-common.c +++ b/drivers/media/video/v4l2-common.c @@ -569,6 +569,7 @@ int v4l2_ctrl_query_fill(struct v4l2_queryctrl *qctrl, s32 min, s32 max, s32 ste case V4L2_CID_RED_BALANCE: case V4L2_CID_BLUE_BALANCE: case V4L2_CID_GAMMA: + case V4L2_CID_SHARPNESS: qctrl->flags |= V4L2_CTRL_FLAG_SLIDER; break; case V4L2_CID_PAN_RELATIVE: -- cgit v1.2.3 From 9aba42efe85bc7a55e3fed0747ce14abc9ee96e7 Mon Sep 17 00:00:00 2001 From: Janne Grunau Date: Wed, 18 Mar 2009 18:10:04 -0300 Subject: V4L/DVB (11096): V4L2 Driver for the Hauppauge HD PVR usb capture device The device encodes component video up to 1080i to a MPEG-TS stream with H.264 video and stereo AAC audio. Newer firmwares accept also AC3 (up to 5.1) audio over optical SPDIF without reencoding. Firmware upgrade is unimplemeted but rather unimportant since the firmware sits on a flash chip. The I2C adapter to drive the integrated infrared receiver/sender is currently disabled due to a conflict with cx18-based devices. Tested-by: Jarod Wilson Signed-off-by: Janne Grunau Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/Kconfig | 2 + drivers/media/video/Makefile | 2 + drivers/media/video/hdpvr/Kconfig | 10 + drivers/media/video/hdpvr/Makefile | 7 + drivers/media/video/hdpvr/hdpvr-control.c | 201 +++++ drivers/media/video/hdpvr/hdpvr-core.c | 439 +++++++++++ drivers/media/video/hdpvr/hdpvr-i2c.c | 145 ++++ drivers/media/video/hdpvr/hdpvr-video.c | 1228 +++++++++++++++++++++++++++++ drivers/media/video/hdpvr/hdpvr.h | 298 +++++++ include/linux/i2c-id.h | 1 + 10 files changed, 2333 insertions(+) create mode 100644 drivers/media/video/hdpvr/Kconfig create mode 100644 drivers/media/video/hdpvr/Makefile create mode 100644 drivers/media/video/hdpvr/hdpvr-control.c create mode 100644 drivers/media/video/hdpvr/hdpvr-core.c create mode 100644 drivers/media/video/hdpvr/hdpvr-i2c.c create mode 100644 drivers/media/video/hdpvr/hdpvr-video.c create mode 100644 drivers/media/video/hdpvr/hdpvr.h (limited to 'drivers/media/video') diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig index d5ddb819a961..3f85b9e63754 100644 --- a/drivers/media/video/Kconfig +++ b/drivers/media/video/Kconfig @@ -789,6 +789,8 @@ source "drivers/media/video/gspca/Kconfig" source "drivers/media/video/pvrusb2/Kconfig" +source "drivers/media/video/hdpvr/Kconfig" + source "drivers/media/video/em28xx/Kconfig" source "drivers/media/video/usbvision/Kconfig" diff --git a/drivers/media/video/Makefile b/drivers/media/video/Makefile index 08a0675fea34..b9046744463b 100644 --- a/drivers/media/video/Makefile +++ b/drivers/media/video/Makefile @@ -119,6 +119,8 @@ obj-$(CONFIG_USB_PWC) += pwc/ obj-$(CONFIG_USB_ZC0301) += zc0301/ obj-$(CONFIG_USB_GSPCA) += gspca/ +obj-$(CONFIG_VIDEO_HDPVR) += hdpvr/ + obj-$(CONFIG_USB_IBMCAM) += usbvideo/ obj-$(CONFIG_USB_KONICAWC) += usbvideo/ obj-$(CONFIG_USB_VICAM) += usbvideo/ diff --git a/drivers/media/video/hdpvr/Kconfig b/drivers/media/video/hdpvr/Kconfig new file mode 100644 index 000000000000..de247f3c7d05 --- /dev/null +++ b/drivers/media/video/hdpvr/Kconfig @@ -0,0 +1,10 @@ + +config VIDEO_HDPVR + tristate "Hauppauge HD PVR support" + depends on VIDEO_DEV + ---help--- + This is a video4linux driver for Hauppauge's HD PVR USB device. + + To compile this driver as a module, choose M here: the + module will be called hdpvr + diff --git a/drivers/media/video/hdpvr/Makefile b/drivers/media/video/hdpvr/Makefile new file mode 100644 index 000000000000..79ad2e16cb8f --- /dev/null +++ b/drivers/media/video/hdpvr/Makefile @@ -0,0 +1,7 @@ +hdpvr-objs := hdpvr-control.o hdpvr-core.o hdpvr-i2c.o hdpvr-video.o + +obj-$(CONFIG_VIDEO_HDPVR) += hdpvr.o + +EXTRA_CFLAGS += -Idrivers/media/video + +EXTRA_CFLAGS += $(extra-cflags-y) $(extra-cflags-m) diff --git a/drivers/media/video/hdpvr/hdpvr-control.c b/drivers/media/video/hdpvr/hdpvr-control.c new file mode 100644 index 000000000000..ecf02c621f13 --- /dev/null +++ b/drivers/media/video/hdpvr/hdpvr-control.c @@ -0,0 +1,201 @@ +/* + * Hauppage HD PVR USB driver - video 4 linux 2 interface + * + * Copyright (C) 2008 Janne Grunau (j@jannau.net) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation, version 2. + * + */ + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +#include "hdpvr.h" + + +int hdpvr_config_call(struct hdpvr_device *dev, uint value, u8 valbuf) +{ + int ret; + char request_type = 0x38, snd_request = 0x01; + + msleep(10); + + mutex_lock(&dev->usbc_mutex); + dev->usbc_buf[0] = valbuf; + ret = usb_control_msg(dev->udev, + usb_sndctrlpipe(dev->udev, 0), + snd_request, 0x00 | request_type, + value, CTRL_DEFAULT_INDEX, + dev->usbc_buf, 1, 10000); + + mutex_unlock(&dev->usbc_mutex); + dev_dbg(&dev->udev->dev, + "config call request for value 0x%x returned %d\n", value, + ret); + + return ret < 0 ? ret : 0; +} + +struct hdpvr_video_info *get_video_info(struct hdpvr_device *dev) +{ + struct hdpvr_video_info *vidinf = NULL; +#ifdef HDPVR_DEBUG + char print_buf[15]; +#endif + int ret; + + vidinf = kzalloc(sizeof(struct hdpvr_video_info), GFP_KERNEL); + if (!vidinf) { + dev_err(&dev->udev->dev, "out of memory"); + goto err; + } + + mutex_lock(&dev->usbc_mutex); + ret = usb_control_msg(dev->udev, + usb_rcvctrlpipe(dev->udev, 0), + 0x81, 0x80 | 0x38, + 0x1400, 0x0003, + dev->usbc_buf, 5, + 1000); + if (ret == 5) { + vidinf->width = dev->usbc_buf[1] << 8 | dev->usbc_buf[0]; + vidinf->height = dev->usbc_buf[3] << 8 | dev->usbc_buf[2]; + vidinf->fps = dev->usbc_buf[4]; + } + +#ifdef HDPVR_DEBUG + if (hdpvr_debug & MSG_INFO) { + hex_dump_to_buffer(dev->usbc_buf, 5, 16, 1, print_buf, + sizeof(print_buf), 0); + dev_dbg(&dev->udev->dev, "get video info returned: %d, %s\n", + ret, print_buf); + } +#endif + mutex_unlock(&dev->usbc_mutex); + + if (!vidinf->width || !vidinf->height || !vidinf->fps) { + kfree(vidinf); + vidinf = NULL; + } +err: + return vidinf; +} + +int get_input_lines_info(struct hdpvr_device *dev) +{ +#ifdef HDPVR_DEBUG + char print_buf[9]; +#endif + int ret, lines; + + mutex_lock(&dev->usbc_mutex); + ret = usb_control_msg(dev->udev, + usb_rcvctrlpipe(dev->udev, 0), + 0x81, 0x80 | 0x38, + 0x1800, 0x0003, + dev->usbc_buf, 3, + 1000); + +#ifdef HDPVR_DEBUG + if (hdpvr_debug & MSG_INFO) { + hex_dump_to_buffer(dev->usbc_buf, 3, 16, 1, print_buf, + sizeof(print_buf), 0); + dev_dbg(&dev->udev->dev, + "get input lines info returned: %d, %s\n", ret, + print_buf); + } +#endif + lines = dev->usbc_buf[1] << 8 | dev->usbc_buf[0]; + mutex_unlock(&dev->usbc_mutex); + return lines; +} + + +int hdpvr_set_bitrate(struct hdpvr_device *dev) +{ + int ret; + + mutex_lock(&dev->usbc_mutex); + memset(dev->usbc_buf, 0, 4); + dev->usbc_buf[0] = dev->options.bitrate; + dev->usbc_buf[2] = dev->options.peak_bitrate; + + ret = usb_control_msg(dev->udev, + usb_sndctrlpipe(dev->udev, 0), + 0x01, 0x38, CTRL_BITRATE_VALUE, + CTRL_DEFAULT_INDEX, dev->usbc_buf, 4, 1000); + mutex_unlock(&dev->usbc_mutex); + + return ret; +} + +int hdpvr_set_audio(struct hdpvr_device *dev, u8 input, + enum v4l2_mpeg_audio_encoding codec) +{ + int ret = 0; + + if (dev->flags & HDPVR_FLAG_AC3_CAP) { + mutex_lock(&dev->usbc_mutex); + memset(dev->usbc_buf, 0, 2); + dev->usbc_buf[0] = input; + if (codec == V4L2_MPEG_AUDIO_ENCODING_AAC) + dev->usbc_buf[1] = 0; + else if (codec == V4L2_MPEG_AUDIO_ENCODING_AC3) + dev->usbc_buf[1] = 1; + else { + mutex_unlock(&dev->usbc_mutex); + dev_err(&dev->udev->dev, "invalid audio codec %d\n", + codec); + ret = -EINVAL; + goto error; + } + + ret = usb_control_msg(dev->udev, + usb_sndctrlpipe(dev->udev, 0), + 0x01, 0x38, CTRL_AUDIO_INPUT_VALUE, + CTRL_DEFAULT_INDEX, dev->usbc_buf, 2, + 1000); + mutex_unlock(&dev->usbc_mutex); + if (ret == 2) + ret = 0; + } else + ret = hdpvr_config_call(dev, CTRL_AUDIO_INPUT_VALUE, + dev->options.audio_input+1); +error: + return ret; +} + +int hdpvr_set_options(struct hdpvr_device *dev) +{ + hdpvr_config_call(dev, CTRL_VIDEO_STD_TYPE, dev->options.video_std); + + hdpvr_config_call(dev, CTRL_VIDEO_INPUT_VALUE, + dev->options.video_input+1); + + hdpvr_set_audio(dev, dev->options.audio_input+1, + dev->options.audio_codec); + + hdpvr_set_bitrate(dev); + hdpvr_config_call(dev, CTRL_BITRATE_MODE_VALUE, + dev->options.bitrate_mode); + hdpvr_config_call(dev, CTRL_GOP_MODE_VALUE, dev->options.gop_mode); + + hdpvr_config_call(dev, CTRL_BRIGHTNESS, dev->options.brightness); + hdpvr_config_call(dev, CTRL_CONTRAST, dev->options.contrast); + hdpvr_config_call(dev, CTRL_HUE, dev->options.hue); + hdpvr_config_call(dev, CTRL_SATURATION, dev->options.saturation); + hdpvr_config_call(dev, CTRL_SHARPNESS, dev->options.sharpness); + + return 0; +} diff --git a/drivers/media/video/hdpvr/hdpvr-core.c b/drivers/media/video/hdpvr/hdpvr-core.c new file mode 100644 index 000000000000..e7300b570bb7 --- /dev/null +++ b/drivers/media/video/hdpvr/hdpvr-core.c @@ -0,0 +1,439 @@ +/* + * Hauppage HD PVR USB driver + * + * Copyright (C) 2001-2004 Greg Kroah-Hartman (greg@kroah.com) + * Copyright (C) 2008 Janne Grunau (j@jannau.net) + * Copyright (C) 2008 John Poet + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation, version 2. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "hdpvr.h" + +static int video_nr[HDPVR_MAX] = {[0 ... (HDPVR_MAX - 1)] = UNSET}; +module_param_array(video_nr, int, NULL, 0); +MODULE_PARM_DESC(video_nr, "video device number (-1=Auto)"); + +/* holds the number of currently registered devices */ +static atomic_t dev_nr = ATOMIC_INIT(-1); + +int hdpvr_debug; +module_param(hdpvr_debug, int, S_IRUGO|S_IWUSR); +MODULE_PARM_DESC(hdpvr_debug, "enable debugging output"); + +uint default_video_input = HDPVR_VIDEO_INPUTS; +module_param(default_video_input, uint, S_IRUGO|S_IWUSR); +MODULE_PARM_DESC(default_video_input, "default video input: 0=Component / " + "1=S-Video / 2=Composite"); + +uint default_audio_input = HDPVR_AUDIO_INPUTS; +module_param(default_audio_input, uint, S_IRUGO|S_IWUSR); +MODULE_PARM_DESC(default_audio_input, "default audio input: 0=RCA back / " + "1=RCA front / 2=S/PDIF"); + +static int boost_audio; +module_param(boost_audio, bool, S_IRUGO|S_IWUSR); +MODULE_PARM_DESC(boost_audio, "boost the audio signal"); + + +/* table of devices that work with this driver */ +static struct usb_device_id hdpvr_table[] = { + { USB_DEVICE(HD_PVR_VENDOR_ID, HD_PVR_PRODUCT_ID) }, + { USB_DEVICE(HD_PVR_VENDOR_ID, HD_PVR_PRODUCT_ID1) }, + { USB_DEVICE(HD_PVR_VENDOR_ID, HD_PVR_PRODUCT_ID2) }, + { } /* Terminating entry */ +}; +MODULE_DEVICE_TABLE(usb, hdpvr_table); + + +void hdpvr_delete(struct hdpvr_device *dev) +{ + hdpvr_free_buffers(dev); + + if (dev->video_dev) + video_device_release(dev->video_dev); + + usb_put_dev(dev->udev); +} + +static void challenge(u8 *bytes) +{ + u64 *i64P, tmp64; + uint i, idx; + + for (idx = 0; idx < 32; ++idx) { + + if (idx & 0x3) + bytes[(idx >> 3) + 3] = bytes[(idx >> 2) & 0x3]; + + switch (idx & 0x3) { + case 0x3: + bytes[2] += bytes[3] * 4 + bytes[4] + bytes[5]; + bytes[4] += bytes[(idx & 0x1) * 2] * 9 + 9; + break; + case 0x1: + bytes[0] *= 8; + bytes[0] += 7*idx + 4; + bytes[6] += bytes[3] * 3; + break; + case 0x0: + bytes[3 - (idx >> 3)] = bytes[idx >> 2]; + bytes[5] += bytes[6] * 3; + for (i = 0; i < 3; i++) + bytes[3] *= bytes[3] + 1; + break; + case 0x2: + for (i = 0; i < 3; i++) + bytes[1] *= bytes[6] + 1; + for (i = 0; i < 3; i++) { + i64P = (u64 *)bytes; + tmp64 = le64_to_cpup(i64P); + tmp64 <<= bytes[7] & 0x0f; + *i64P += cpu_to_le64(tmp64); + } + break; + } + } +} + +/* try to init the device like the windows driver */ +static int device_authorization(struct hdpvr_device *dev) +{ + + int ret, retval = -ENOMEM; + char request_type = 0x38, rcv_request = 0x81; + char *response; +#ifdef HDPVR_DEBUG + size_t buf_size = 46; + char *print_buf = kzalloc(5*buf_size+1, GFP_KERNEL); + if (!print_buf) { + dev_err(&dev->udev->dev, "Out of memory"); + goto error; + } +#endif + + mutex_lock(&dev->usbc_mutex); + ret = usb_control_msg(dev->udev, + usb_rcvctrlpipe(dev->udev, 0), + rcv_request, 0x80 | request_type, + 0x0400, 0x0003, + dev->usbc_buf, 46, + 10000); + if (ret != 46) { + dev_err(&dev->udev->dev, + "unexpected answer of status request, len %d", ret); + goto error; + } +#ifdef HDPVR_DEBUG + else { + hex_dump_to_buffer(dev->usbc_buf, 46, 16, 1, print_buf, + sizeof(print_buf), 0); + dev_dbg(&dev->udev->dev, + "Status request returned, len %d: %s\n", + ret, print_buf); + } +#endif + if (dev->usbc_buf[1] == HDPVR_FIRMWARE_VERSION) { + dev->flags &= ~HDPVR_FLAG_AC3_CAP; + } else if (dev->usbc_buf[1] == HDPVR_FIRMWARE_VERSION_AC3) { + dev->flags |= HDPVR_FLAG_AC3_CAP; + } else if (dev->usbc_buf[1] > HDPVR_FIRMWARE_VERSION_AC3) { + dev_notice(&dev->udev->dev, "untested firmware version 0x%x, " + "the driver might not work\n", dev->usbc_buf[1]); + dev->flags |= HDPVR_FLAG_AC3_CAP; + } else { + dev_err(&dev->udev->dev, "unknown firmware version 0x%x\n", + dev->usbc_buf[1]); + ret = -EINVAL; + goto error; + } + + response = dev->usbc_buf+38; +#ifdef HDPVR_DEBUG + hex_dump_to_buffer(response, 8, 16, 1, print_buf, sizeof(print_buf), 0); + dev_dbg(&dev->udev->dev, "challenge: %s\n", print_buf); +#endif + challenge(response); +#ifdef HDPVR_DEBUG + hex_dump_to_buffer(response, 8, 16, 1, print_buf, sizeof(print_buf), 0); + dev_dbg(&dev->udev->dev, " response: %s\n", print_buf); +#endif + + msleep(100); + ret = usb_control_msg(dev->udev, + usb_sndctrlpipe(dev->udev, 0), + 0xd1, 0x00 | request_type, + 0x0000, 0x0000, + response, 8, + 10000); + dev_dbg(&dev->udev->dev, "magic request returned %d\n", ret); + mutex_unlock(&dev->usbc_mutex); + + retval = ret != 8; +error: + return retval; +} + +static int hdpvr_device_init(struct hdpvr_device *dev) +{ + int ret; + u8 *buf; + struct hdpvr_video_info *vidinf; + + if (device_authorization(dev)) + return -EACCES; + + /* default options for init */ + hdpvr_set_options(dev); + + /* set filter options */ + mutex_lock(&dev->usbc_mutex); + buf = dev->usbc_buf; + buf[0] = 0x03; buf[1] = 0x03; buf[2] = 0x00; buf[3] = 0x00; + ret = usb_control_msg(dev->udev, + usb_sndctrlpipe(dev->udev, 0), + 0x01, 0x38, + CTRL_LOW_PASS_FILTER_VALUE, CTRL_DEFAULT_INDEX, + buf, 4, + 1000); + dev_dbg(&dev->udev->dev, "control request returned %d\n", ret); + mutex_unlock(&dev->usbc_mutex); + + vidinf = get_video_info(dev); + if (!vidinf) + dev_dbg(&dev->udev->dev, + "no valid video signal or device init failed\n"); + else + kfree(vidinf); + + /* enable fan and bling leds */ + mutex_lock(&dev->usbc_mutex); + buf[0] = 0x1; + ret = usb_control_msg(dev->udev, + usb_sndctrlpipe(dev->udev, 0), + 0xd4, 0x38, 0, 0, buf, 1, + 1000); + dev_dbg(&dev->udev->dev, "control request returned %d\n", ret); + + /* boost analog audio */ + buf[0] = boost_audio; + ret = usb_control_msg(dev->udev, + usb_sndctrlpipe(dev->udev, 0), + 0xd5, 0x38, 0, 0, buf, 1, + 1000); + dev_dbg(&dev->udev->dev, "control request returned %d\n", ret); + mutex_unlock(&dev->usbc_mutex); + + dev->status = STATUS_IDLE; + return 0; +} + +static const struct hdpvr_options hdpvr_default_options = { + .video_std = HDPVR_60HZ, + .video_input = HDPVR_COMPONENT, + .audio_input = HDPVR_RCA_BACK, + .bitrate = 65, /* 6 mbps */ + .peak_bitrate = 90, /* 9 mbps */ + .bitrate_mode = HDPVR_CONSTANT, + .gop_mode = HDPVR_SIMPLE_IDR_GOP, + .audio_codec = V4L2_MPEG_AUDIO_ENCODING_AAC, + .brightness = 0x86, + .contrast = 0x80, + .hue = 0x80, + .saturation = 0x80, + .sharpness = 0x80, +}; + +static int hdpvr_probe(struct usb_interface *interface, + const struct usb_device_id *id) +{ + struct hdpvr_device *dev; + struct usb_host_interface *iface_desc; + struct usb_endpoint_descriptor *endpoint; + size_t buffer_size; + int i; + int retval = -ENOMEM; + + /* allocate memory for our device state and initialize it */ + dev = kzalloc(sizeof(*dev), GFP_KERNEL); + if (!dev) { + err("Out of memory"); + goto error; + } + mutex_init(&dev->io_mutex); + mutex_init(&dev->i2c_mutex); + mutex_init(&dev->usbc_mutex); + dev->usbc_buf = kmalloc(64, GFP_KERNEL); + if (!dev->usbc_buf) { + dev_err(&dev->udev->dev, "Out of memory"); + goto error; + } + + init_waitqueue_head(&dev->wait_buffer); + init_waitqueue_head(&dev->wait_data); + + dev->workqueue = create_singlethread_workqueue("hdpvr_buffer"); + if (!dev->workqueue) + goto error; + + /* init video transfer queues */ + INIT_LIST_HEAD(&dev->free_buff_list); + INIT_LIST_HEAD(&dev->rec_buff_list); + + dev->options = hdpvr_default_options; + + if (default_video_input < HDPVR_VIDEO_INPUTS) + dev->options.video_input = default_video_input; + + if (default_audio_input < HDPVR_AUDIO_INPUTS) + dev->options.audio_input = default_audio_input; + + dev->udev = usb_get_dev(interface_to_usbdev(interface)); + + /* set up the endpoint information */ + /* use only the first bulk-in and bulk-out endpoints */ + iface_desc = interface->cur_altsetting; + for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) { + endpoint = &iface_desc->endpoint[i].desc; + + if (!dev->bulk_in_endpointAddr && + usb_endpoint_is_bulk_in(endpoint)) { + /* USB interface description is buggy, reported max + * packet size is 512 bytes, windows driver uses 8192 */ + buffer_size = 8192; + dev->bulk_in_size = buffer_size; + dev->bulk_in_endpointAddr = endpoint->bEndpointAddress; + } + + } + if (!dev->bulk_in_endpointAddr) { + err("Could not find bulk-in endpoint"); + goto error; + } + + /* init the device */ + if (hdpvr_device_init(dev)) { + err("device init failed"); + goto error; + } + + mutex_lock(&dev->io_mutex); + if (hdpvr_alloc_buffers(dev, NUM_BUFFERS)) { + err("allocating transfer buffers failed"); + goto error; + } + mutex_unlock(&dev->io_mutex); + + if (hdpvr_register_videodev(dev, + video_nr[atomic_inc_return(&dev_nr)])) { + err("registering videodev failed"); + goto error; + } + + + /* save our data pointer in this interface device */ + usb_set_intfdata(interface, dev); + + /* let the user know what node this device is now attached to */ + v4l2_info(dev->video_dev, "device now attached to /dev/video%d\n", + dev->video_dev->minor); + return 0; + +error: + if (dev) { + mutex_unlock(&dev->io_mutex); + /* this frees allocated memory */ + hdpvr_delete(dev); + } + return retval; +} + +static void hdpvr_disconnect(struct usb_interface *interface) +{ + struct hdpvr_device *dev; + int minor; + + dev = usb_get_intfdata(interface); + usb_set_intfdata(interface, NULL); + + minor = dev->video_dev->minor; + + /* prevent more I/O from starting and stop any ongoing */ + mutex_lock(&dev->io_mutex); + dev->status = STATUS_DISCONNECTED; + video_unregister_device(dev->video_dev); + wake_up_interruptible(&dev->wait_data); + wake_up_interruptible(&dev->wait_buffer); + msleep(100); + flush_workqueue(dev->workqueue); + hdpvr_cancel_queue(dev); + destroy_workqueue(dev->workqueue); + mutex_unlock(&dev->io_mutex); + + /* deregister I2C adapter */ + mutex_lock(&dev->i2c_mutex); + if (dev->i2c_adapter) + i2c_del_adapter(dev->i2c_adapter); + kfree(dev->i2c_adapter); + dev->i2c_adapter = NULL; + mutex_unlock(&dev->i2c_mutex); + + atomic_dec(&dev_nr); + + printk(KERN_INFO "Hauppauge HD PVR: device /dev/video%d disconnected\n", + minor); + + kfree(dev->usbc_buf); + kfree(dev); +} + + +static struct usb_driver hdpvr_usb_driver = { + .name = "hdpvr", + .probe = hdpvr_probe, + .disconnect = hdpvr_disconnect, + .id_table = hdpvr_table, +}; + +static int __init hdpvr_init(void) +{ + int result; + + /* register this driver with the USB subsystem */ + result = usb_register(&hdpvr_usb_driver); + if (result) + err("usb_register failed. Error number %d", result); + + return result; +} + +static void __exit hdpvr_exit(void) +{ + /* deregister this driver with the USB subsystem */ + usb_deregister(&hdpvr_usb_driver); +} + +module_init(hdpvr_init); +module_exit(hdpvr_exit); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Janne Grunau"); +MODULE_DESCRIPTION("Hauppauge HD PVR driver"); diff --git a/drivers/media/video/hdpvr/hdpvr-i2c.c b/drivers/media/video/hdpvr/hdpvr-i2c.c new file mode 100644 index 000000000000..35096dec2411 --- /dev/null +++ b/drivers/media/video/hdpvr/hdpvr-i2c.c @@ -0,0 +1,145 @@ + +/* + * Hauppage HD PVR USB driver + * + * Copyright (C) 2008 Janne Grunau (j@jannau.net) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation, version 2. + * + */ + +#include + +#include "hdpvr.h" + +#define CTRL_READ_REQUEST 0xb8 +#define CTRL_WRITE_REQUEST 0x38 + +#define REQTYPE_I2C_READ 0xb1 +#define REQTYPE_I2C_WRITE 0xb0 +#define REQTYPE_I2C_WRITE_STATT 0xd0 + +static int hdpvr_i2c_read(struct hdpvr_device *dev, unsigned char addr, + char *data, int len) +{ + int ret; + char *buf = kmalloc(len, GFP_KERNEL); + if (!buf) + return -ENOMEM; + + ret = usb_control_msg(dev->udev, + usb_rcvctrlpipe(dev->udev, 0), + REQTYPE_I2C_READ, CTRL_READ_REQUEST, + 0x100|addr, 0, buf, len, 1000); + + if (ret == len) { + memcpy(data, buf, len); + ret = 0; + } else if (ret >= 0) + ret = -EIO; + + kfree(buf); + + return ret; +} + +static int hdpvr_i2c_write(struct hdpvr_device *dev, unsigned char addr, + char *data, int len) +{ + int ret; + char *buf = kmalloc(len, GFP_KERNEL); + if (!buf) + return -ENOMEM; + + memcpy(buf, data, len); + ret = usb_control_msg(dev->udev, + usb_sndctrlpipe(dev->udev, 0), + REQTYPE_I2C_WRITE, CTRL_WRITE_REQUEST, + 0x100|addr, 0, buf, len, 1000); + + if (ret < 0) + goto error; + + ret = usb_control_msg(dev->udev, + usb_rcvctrlpipe(dev->udev, 0), + REQTYPE_I2C_WRITE_STATT, CTRL_READ_REQUEST, + 0, 0, buf, 2, 1000); + + if (ret == 2) + ret = 0; + else if (ret >= 0) + ret = -EIO; + +error: + kfree(buf); + return ret; +} + +static int hdpvr_transfer(struct i2c_adapter *i2c_adapter, struct i2c_msg *msgs, + int num) +{ + struct hdpvr_device *dev = i2c_get_adapdata(i2c_adapter); + int retval = 0, i, addr; + + if (num <= 0) + return 0; + + mutex_lock(&dev->i2c_mutex); + + for (i = 0; i < num && !retval; i++) { + addr = msgs[i].addr << 1; + + if (msgs[i].flags & I2C_M_RD) + retval = hdpvr_i2c_read(dev, addr, msgs[i].buf, + msgs[i].len); + else + retval = hdpvr_i2c_write(dev, addr, msgs[i].buf, + msgs[i].len); + } + + mutex_unlock(&dev->i2c_mutex); + + return retval ? retval : num; +} + +static u32 hdpvr_functionality(struct i2c_adapter *adapter) +{ + return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; +} + +static struct i2c_algorithm hdpvr_algo = { + .master_xfer = hdpvr_transfer, + .functionality = hdpvr_functionality, +}; + +int hdpvr_register_i2c_adapter(struct hdpvr_device *dev) +{ + struct i2c_adapter *i2c_adap; + int retval = -ENOMEM; + + i2c_adap = kzalloc(sizeof(struct i2c_adapter), GFP_KERNEL); + if (i2c_adap == NULL) + goto error; + + strlcpy(i2c_adap->name, "Hauppauge HD PVR I2C", + sizeof(i2c_adap->name)); + i2c_adap->algo = &hdpvr_algo; + i2c_adap->class = I2C_CLASS_TV_ANALOG; + i2c_adap->id = I2C_HW_B_HDPVR; + i2c_adap->owner = THIS_MODULE; + i2c_adap->dev.parent = &dev->udev->dev; + + i2c_set_adapdata(i2c_adap, dev); + + retval = i2c_add_adapter(i2c_adap); + + if (!retval) + dev->i2c_adapter = i2c_adap; + else + kfree(i2c_adap); + +error: + return retval; +} diff --git a/drivers/media/video/hdpvr/hdpvr-video.c b/drivers/media/video/hdpvr/hdpvr-video.c new file mode 100644 index 000000000000..ee481495e4fc --- /dev/null +++ b/drivers/media/video/hdpvr/hdpvr-video.c @@ -0,0 +1,1228 @@ +/* + * Hauppage HD PVR USB driver - video 4 linux 2 interface + * + * Copyright (C) 2008 Janne Grunau (j@jannau.net) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation, version 2. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include "hdpvr.h" + +#define BULK_URB_TIMEOUT 1250 /* 1.25 seconds */ + +struct hdpvr_fh { + struct hdpvr_device *dev; +}; + +static uint list_size(struct list_head *list) +{ + struct list_head *tmp; + uint count = 0; + + list_for_each(tmp, list) { + count++; + } + + return count; +} + +/*=========================================================================*/ +/* urb callback */ +static void hdpvr_read_bulk_callback(struct urb *urb) +{ + struct hdpvr_buffer *buf = (struct hdpvr_buffer *)urb->context; + struct hdpvr_device *dev = buf->dev; + + /* marking buffer as received and wake waiting */ + buf->status = BUFSTAT_READY; + wake_up_interruptible(&dev->wait_data); +} + +/*=========================================================================*/ +/* bufffer bits */ + +/* function expects dev->io_mutex to be hold by caller */ +int hdpvr_cancel_queue(struct hdpvr_device *dev) +{ + struct hdpvr_buffer *buf; + + list_for_each_entry(buf, &dev->rec_buff_list, buff_list) { + usb_kill_urb(buf->urb); + buf->status = BUFSTAT_AVAILABLE; + } + + list_splice_init(&dev->rec_buff_list, dev->free_buff_list.prev); + + return 0; +} + +static int hdpvr_free_queue(struct list_head *q) +{ + struct list_head *tmp; + struct list_head *p; + struct hdpvr_buffer *buf; + struct urb *urb; + + for (p = q->next; p != q;) { + buf = list_entry(p, struct hdpvr_buffer, buff_list); + + urb = buf->urb; + usb_buffer_free(urb->dev, urb->transfer_buffer_length, + urb->transfer_buffer, urb->transfer_dma); + usb_free_urb(urb); + tmp = p->next; + list_del(p); + kfree(buf); + p = tmp; + } + + return 0; +} + +/* function expects dev->io_mutex to be hold by caller */ +int hdpvr_free_buffers(struct hdpvr_device *dev) +{ + hdpvr_cancel_queue(dev); + + hdpvr_free_queue(&dev->free_buff_list); + hdpvr_free_queue(&dev->rec_buff_list); + + return 0; +} + +/* function expects dev->io_mutex to be hold by caller */ +int hdpvr_alloc_buffers(struct hdpvr_device *dev, uint count) +{ + uint i; + int retval = -ENOMEM; + u8 *mem; + struct hdpvr_buffer *buf; + struct urb *urb; + + v4l2_dbg(MSG_INFO, hdpvr_debug, dev->video_dev, + "allocating %u buffers\n", count); + + for (i = 0; i < count; i++) { + + buf = kzalloc(sizeof(struct hdpvr_buffer), GFP_KERNEL); + if (!buf) { + err("cannot allocate buffer"); + goto exit; + } + buf->dev = dev; + + urb = usb_alloc_urb(0, GFP_KERNEL); + if (!urb) { + err("cannot allocate urb"); + goto exit; + } + buf->urb = urb; + + mem = usb_buffer_alloc(dev->udev, dev->bulk_in_size, GFP_KERNEL, + &urb->transfer_dma); + if (!mem) { + err("cannot allocate usb transfer buffer"); + goto exit; + } + + usb_fill_bulk_urb(buf->urb, dev->udev, + usb_rcvbulkpipe(dev->udev, + dev->bulk_in_endpointAddr), + mem, dev->bulk_in_size, + hdpvr_read_bulk_callback, buf); + + buf->status = BUFSTAT_AVAILABLE; + list_add_tail(&buf->buff_list, &dev->free_buff_list); + } + return 0; +exit: + hdpvr_free_buffers(dev); + return retval; +} + +static int hdpvr_submit_buffers(struct hdpvr_device *dev) +{ + struct hdpvr_buffer *buf; + struct urb *urb; + int ret = 0, err_count = 0; + + mutex_lock(&dev->io_mutex); + + while (dev->status == STATUS_STREAMING && + !list_empty(&dev->free_buff_list)) { + + buf = list_entry(dev->free_buff_list.next, struct hdpvr_buffer, + buff_list); + if (buf->status != BUFSTAT_AVAILABLE) { + err("buffer not marked as availbale"); + ret = -EFAULT; + goto err; + } + + urb = buf->urb; + urb->status = 0; + urb->actual_length = 0; + ret = usb_submit_urb(urb, GFP_KERNEL); + if (ret) { + err("usb_submit_urb in %s returned %d", __func__, ret); + if (++err_count > 2) + break; + continue; + } + buf->status = BUFSTAT_INPROGRESS; + list_move_tail(&buf->buff_list, &dev->rec_buff_list); + } +err: + v4l2_dbg(MSG_BUFFER, hdpvr_debug, dev->video_dev, + "buffer queue stat: %d free, %d proc\n", + list_size(&dev->free_buff_list), + list_size(&dev->rec_buff_list)); + mutex_unlock(&dev->io_mutex); + return ret; +} + +static struct hdpvr_buffer *hdpvr_get_next_buffer(struct hdpvr_device *dev) +{ + struct hdpvr_buffer *buf; + + mutex_lock(&dev->io_mutex); + + if (list_empty(&dev->rec_buff_list)) { + mutex_unlock(&dev->io_mutex); + return NULL; + } + + buf = list_entry(dev->rec_buff_list.next, struct hdpvr_buffer, + buff_list); + mutex_unlock(&dev->io_mutex); + + return buf; +} + +static void hdpvr_transmit_buffers(struct work_struct *work) +{ + struct hdpvr_device *dev = container_of(work, struct hdpvr_device, + worker); + + while (dev->status == STATUS_STREAMING) { + + if (hdpvr_submit_buffers(dev)) { + v4l2_err(dev->video_dev, "couldn't submit buffers\n"); + goto error; + } + if (wait_event_interruptible(dev->wait_buffer, + !list_empty(&dev->free_buff_list) || + dev->status != STATUS_STREAMING)) + goto error; + } + + v4l2_dbg(MSG_INFO, hdpvr_debug, dev->video_dev, + "transmit worker exited\n"); + return; +error: + v4l2_dbg(MSG_INFO, hdpvr_debug, dev->video_dev, + "transmit buffers errored\n"); + dev->status = STATUS_ERROR; +} + +/* function expects dev->io_mutex to be hold by caller */ +static int hdpvr_start_streaming(struct hdpvr_device *dev) +{ + int ret; + struct hdpvr_video_info *vidinf; + + if (dev->status == STATUS_STREAMING) + return 0; + else if (dev->status != STATUS_IDLE) + return -EAGAIN; + + vidinf = get_video_info(dev); + + if (vidinf) { + v4l2_dbg(MSG_BUFFER, hdpvr_debug, dev->video_dev, + "video signal: %dx%d@%dhz\n", vidinf->width, + vidinf->height, vidinf->fps); + kfree(vidinf); + + /* start streaming 2 request */ + ret = usb_control_msg(dev->udev, + usb_sndctrlpipe(dev->udev, 0), + 0xb8, 0x38, 0x1, 0, NULL, 0, 8000); + v4l2_dbg(MSG_BUFFER, hdpvr_debug, dev->video_dev, + "encoder start control request returned %d\n", ret); + + hdpvr_config_call(dev, CTRL_START_STREAMING_VALUE, 0x00); + + INIT_WORK(&dev->worker, hdpvr_transmit_buffers); + queue_work(dev->workqueue, &dev->worker); + + v4l2_dbg(MSG_BUFFER, hdpvr_debug, dev->video_dev, + "streaming started\n"); + dev->status = STATUS_STREAMING; + + return 0; + } + msleep(250); + v4l2_dbg(MSG_INFO, hdpvr_debug, dev->video_dev, + "no video signal at input %d\n", dev->options.video_input); + return -EAGAIN; +} + + +/* function expects dev->io_mutex to be hold by caller */ +static int hdpvr_stop_streaming(struct hdpvr_device *dev) +{ + if (dev->status == STATUS_IDLE) + return 0; + else if (dev->status != STATUS_STREAMING) + return -EAGAIN; + + dev->status = STATUS_SHUTTING_DOWN; + hdpvr_config_call(dev, CTRL_STOP_STREAMING_VALUE, 0x00); + + wake_up_interruptible(&dev->wait_buffer); + msleep(50); + + flush_workqueue(dev->workqueue); + + /* kill the still outstanding urbs */ + hdpvr_cancel_queue(dev); + + dev->status = STATUS_IDLE; + + return 0; +} + + +/*=======================================================================*/ +/* + * video 4 linux 2 file operations + */ + +static int hdpvr_open(struct file *file) +{ + struct hdpvr_device *dev; + struct hdpvr_fh *fh; + int retval = -ENOMEM; + + dev = (struct hdpvr_device *)video_get_drvdata(video_devdata(file)); + if (!dev) { + err("open failing with with ENODEV"); + retval = -ENODEV; + goto err; + } + + fh = kzalloc(sizeof(struct hdpvr_fh), GFP_KERNEL); + if (!fh) { + err("Out of memory?"); + goto err; + } + /* lock the device to allow correctly handling errors + * in resumption */ + mutex_lock(&dev->io_mutex); + dev->open_count++; + + fh->dev = dev; + + /* save our object in the file's private structure */ + file->private_data = fh; + + retval = 0; +err: + mutex_unlock(&dev->io_mutex); + return retval; +} + +static int hdpvr_release(struct file *file) +{ + struct hdpvr_fh *fh = (struct hdpvr_fh *)file->private_data; + struct hdpvr_device *dev = fh->dev; + + if (!dev) + return -ENODEV; + + mutex_lock(&dev->io_mutex); + if (!(--dev->open_count) && dev->status == STATUS_STREAMING) + hdpvr_stop_streaming(dev); + + mutex_unlock(&dev->io_mutex); + + return 0; +} + +/* + * hdpvr_v4l2_read() + * will allocate buffers when called for the first time + */ +static ssize_t hdpvr_read(struct file *file, char __user *buffer, size_t count, + loff_t *pos) +{ + struct hdpvr_fh *fh = file->private_data; + struct hdpvr_device *dev = fh->dev; + struct hdpvr_buffer *buf = NULL; + struct urb *urb; + unsigned int ret = 0; + int rem, cnt; + + if (*pos) + return -ESPIPE; + + if (!dev) + return -ENODEV; + + mutex_lock(&dev->io_mutex); + if (dev->status == STATUS_IDLE) { + if (hdpvr_start_streaming(dev)) { + v4l2_dbg(MSG_INFO, hdpvr_debug, dev->video_dev, + "start_streaming failed"); + ret = -EIO; + msleep(200); + dev->status = STATUS_IDLE; + mutex_unlock(&dev->io_mutex); + goto err; + } + + v4l2_dbg(MSG_BUFFER, hdpvr_debug, dev->video_dev, + "buffer queue stat: %d free, %d proc\n", + list_size(&dev->free_buff_list), + list_size(&dev->rec_buff_list)); + } + mutex_unlock(&dev->io_mutex); + + /* wait for the first buffer */ + if (!(file->f_flags & O_NONBLOCK)) { + if (wait_event_interruptible(dev->wait_data, + hdpvr_get_next_buffer(dev))) + return -ERESTARTSYS; + } + + buf = hdpvr_get_next_buffer(dev); + + while (count > 0 && buf) { + + if (buf->status != BUFSTAT_READY && + dev->status != STATUS_DISCONNECTED) { + /* return nonblocking */ + if (file->f_flags & O_NONBLOCK) { + if (!ret) + ret = -EAGAIN; + goto err; + } + + if (wait_event_interruptible(dev->wait_data, + buf->status == BUFSTAT_READY)) { + ret = -ERESTARTSYS; + goto err; + } + } + + if (buf->status != BUFSTAT_READY) + break; + + /* set remaining bytes to copy */ + urb = buf->urb; + rem = urb->actual_length - buf->pos; + cnt = rem > count ? count : rem; + + if (copy_to_user(buffer, urb->transfer_buffer + buf->pos, + cnt)) { + err("read: copy_to_user failed"); + if (!ret) + ret = -EFAULT; + goto err; + } + + buf->pos += cnt; + count -= cnt; + buffer += cnt; + ret += cnt; + + /* finished, take next buffer */ + if (buf->pos == urb->actual_length) { + mutex_lock(&dev->io_mutex); + buf->pos = 0; + buf->status = BUFSTAT_AVAILABLE; + + list_move_tail(&buf->buff_list, &dev->free_buff_list); + + v4l2_dbg(MSG_BUFFER, hdpvr_debug, dev->video_dev, + "buffer queue stat: %d free, %d proc\n", + list_size(&dev->free_buff_list), + list_size(&dev->rec_buff_list)); + + mutex_unlock(&dev->io_mutex); + + wake_up_interruptible(&dev->wait_buffer); + + buf = hdpvr_get_next_buffer(dev); + } + } +err: + if (!ret && !buf) + ret = -EAGAIN; + return ret; +} + +static unsigned int hdpvr_poll(struct file *filp, poll_table *wait) +{ + struct hdpvr_fh *fh = (struct hdpvr_fh *)filp->private_data; + struct hdpvr_device *dev = fh->dev; + unsigned int mask = 0; + + mutex_lock(&dev->io_mutex); + + if (video_is_unregistered(dev->video_dev)) + return -EIO; + + if (dev->status == STATUS_IDLE) { + if (hdpvr_start_streaming(dev)) { + v4l2_dbg(MSG_BUFFER, hdpvr_debug, dev->video_dev, + "start_streaming failed"); + dev->status = STATUS_IDLE; + } + + v4l2_dbg(MSG_BUFFER, hdpvr_debug, dev->video_dev, + "buffer queue stat: %d free, %d proc\n", + list_size(&dev->free_buff_list), + list_size(&dev->rec_buff_list)); + } + mutex_unlock(&dev->io_mutex); + + poll_wait(filp, &dev->wait_data, wait); + + mutex_lock(&dev->io_mutex); + if (!list_empty(&dev->rec_buff_list)) { + + struct hdpvr_buffer *buf = list_entry(dev->rec_buff_list.next, + struct hdpvr_buffer, + buff_list); + + if (buf->status == BUFSTAT_READY) + mask |= POLLIN | POLLRDNORM; + } + mutex_unlock(&dev->io_mutex); + + return mask; +} + + +static long hdpvr_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) +{ + struct hdpvr_fh *fh = (struct hdpvr_fh *)filp->private_data; + struct hdpvr_device *dev = fh->dev; + int res; + + if (video_is_unregistered(dev->video_dev)) + return -EIO; + + mutex_lock(&dev->io_mutex); + switch (cmd) { + case VIDIOC_TRY_ENCODER_CMD: + case VIDIOC_ENCODER_CMD: { + struct v4l2_encoder_cmd *enc = (struct v4l2_encoder_cmd *)arg; + int try = cmd == VIDIOC_TRY_ENCODER_CMD; + + memset(&enc->raw, 0, sizeof(enc->raw)); + switch (enc->cmd) { + case V4L2_ENC_CMD_START: + enc->flags = 0; + if (try) + return 0; + res = hdpvr_start_streaming(dev); + break; + case V4L2_ENC_CMD_STOP: + if (try) + return 0; + res = hdpvr_stop_streaming(dev); + break; + default: + v4l2_dbg(MSG_INFO, hdpvr_debug, dev->video_dev, + "Unsupported encoder cmd %d\n", enc->cmd); + return -EINVAL; + } + break; + } + default: + res = video_ioctl2(filp, cmd, arg); + } + mutex_unlock(&dev->io_mutex); + return res; +} + +static const struct v4l2_file_operations hdpvr_fops = { + .owner = THIS_MODULE, + .open = hdpvr_open, + .release = hdpvr_release, + .read = hdpvr_read, + .poll = hdpvr_poll, + .unlocked_ioctl = hdpvr_ioctl, +}; + +/*=======================================================================*/ +/* + * V4L2 ioctl handling + */ + +static int vidioc_querycap(struct file *file, void *priv, + struct v4l2_capability *cap) +{ + struct hdpvr_device *dev = video_drvdata(file); + + strcpy(cap->driver, "hdpvr"); + strcpy(cap->card, "Haupauge HD PVR"); + usb_make_path(dev->udev, cap->bus_info, sizeof(cap->bus_info)); + cap->version = HDPVR_VERSION; + cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | + V4L2_CAP_AUDIO | + V4L2_CAP_READWRITE; + return 0; +} + +static int vidioc_s_std(struct file *file, void *private_data, + v4l2_std_id *std) +{ + struct hdpvr_fh *fh = file->private_data; + struct hdpvr_device *dev = fh->dev; + u8 std_type = 1; + + if (*std & (V4L2_STD_NTSC | V4L2_STD_PAL_60)) + std_type = 0; + + return hdpvr_config_call(dev, CTRL_VIDEO_STD_TYPE, std_type); +} + +static const char *iname[] = { + [HDPVR_COMPONENT] = "Component", + [HDPVR_SVIDEO] = "S-Video", + [HDPVR_COMPOSITE] = "Composite", +}; + +static int vidioc_enum_input(struct file *file, void *priv, + struct v4l2_input *i) +{ + struct hdpvr_fh *fh = file->private_data; + struct hdpvr_device *dev = fh->dev; + unsigned int n; + + n = i->index; + if (n >= HDPVR_VIDEO_INPUTS) + return -EINVAL; + + i->type = V4L2_INPUT_TYPE_CAMERA; + + strncpy(i->name, iname[n], sizeof(i->name) - 1); + i->name[sizeof(i->name) - 1] = '\0'; + + i->audioset = 1<std = dev->video_dev->tvnorms; + + return 0; +} + +static int vidioc_s_input(struct file *file, void *private_data, + unsigned int index) +{ + struct hdpvr_fh *fh = file->private_data; + struct hdpvr_device *dev = fh->dev; + int retval; + + if (index >= HDPVR_VIDEO_INPUTS) + return -EINVAL; + + if (dev->status != STATUS_IDLE) + return -EAGAIN; + + retval = hdpvr_config_call(dev, CTRL_VIDEO_INPUT_VALUE, index+1); + if (!retval) + dev->options.video_input = index; + + return retval; +} + +static int vidioc_g_input(struct file *file, void *private_data, + unsigned int *index) +{ + struct hdpvr_fh *fh = file->private_data; + struct hdpvr_device *dev = fh->dev; + + *index = dev->options.video_input; + return 0; +} + + +static const char *audio_iname[] = { + [HDPVR_RCA_FRONT] = "RCA front", + [HDPVR_RCA_BACK] = "RCA back", + [HDPVR_SPDIF] = "SPDIF", +}; + +static int vidioc_enumaudio(struct file *file, void *priv, + struct v4l2_audio *audio) +{ + unsigned int n; + + n = audio->index; + if (n >= HDPVR_AUDIO_INPUTS) + return -EINVAL; + + audio->capability = V4L2_AUDCAP_STEREO; + + strncpy(audio->name, audio_iname[n], sizeof(audio->name) - 1); + audio->name[sizeof(audio->name) - 1] = '\0'; + + return 0; +} + +static int vidioc_s_audio(struct file *file, void *private_data, + struct v4l2_audio *audio) +{ + struct hdpvr_fh *fh = file->private_data; + struct hdpvr_device *dev = fh->dev; + int retval; + + if (audio->index >= HDPVR_AUDIO_INPUTS) + return -EINVAL; + + if (dev->status != STATUS_IDLE) + return -EAGAIN; + + retval = hdpvr_set_audio(dev, audio->index+1, dev->options.audio_codec); + if (!retval) + dev->options.audio_input = audio->index; + + return retval; +} + +static int vidioc_g_audio(struct file *file, void *private_data, + struct v4l2_audio *audio) +{ + struct hdpvr_fh *fh = file->private_data; + struct hdpvr_device *dev = fh->dev; + + audio->index = dev->options.audio_input; + audio->capability = V4L2_AUDCAP_STEREO; + strncpy(audio->name, audio_iname[audio->index], sizeof(audio->name)); + audio->name[sizeof(audio->name) - 1] = '\0'; + return 0; +} + +static const s32 supported_v4l2_ctrls[] = { + V4L2_CID_BRIGHTNESS, + V4L2_CID_CONTRAST, + V4L2_CID_SATURATION, + V4L2_CID_HUE, + V4L2_CID_SHARPNESS, + V4L2_CID_MPEG_AUDIO_ENCODING, + V4L2_CID_MPEG_VIDEO_ENCODING, + V4L2_CID_MPEG_VIDEO_BITRATE_MODE, + V4L2_CID_MPEG_VIDEO_BITRATE, + V4L2_CID_MPEG_VIDEO_BITRATE_PEAK, +}; + +static int fill_queryctrl(struct hdpvr_options *opt, struct v4l2_queryctrl *qc, + int ac3) +{ + int err; + + switch (qc->id) { + case V4L2_CID_BRIGHTNESS: + return v4l2_ctrl_query_fill(qc, 0x0, 0xff, 1, 0x86); + case V4L2_CID_CONTRAST: + return v4l2_ctrl_query_fill(qc, 0x0, 0xff, 1, 0x80); + case V4L2_CID_SATURATION: + return v4l2_ctrl_query_fill(qc, 0x0, 0xff, 1, 0x80); + case V4L2_CID_HUE: + return v4l2_ctrl_query_fill(qc, 0x0, 0xff, 1, 0x80); + case V4L2_CID_SHARPNESS: + return v4l2_ctrl_query_fill(qc, 0x0, 0xff, 1, 0x80); + case V4L2_CID_MPEG_AUDIO_ENCODING: + return v4l2_ctrl_query_fill( + qc, V4L2_MPEG_AUDIO_ENCODING_AAC, + ac3 ? V4L2_MPEG_AUDIO_ENCODING_AC3 + : V4L2_MPEG_AUDIO_ENCODING_AAC, + 1, V4L2_MPEG_AUDIO_ENCODING_AAC); + case V4L2_CID_MPEG_VIDEO_ENCODING: + return v4l2_ctrl_query_fill( + qc, V4L2_MPEG_VIDEO_ENCODING_MPEG_4_AVC, + V4L2_MPEG_VIDEO_ENCODING_MPEG_4_AVC, 1, + V4L2_MPEG_VIDEO_ENCODING_MPEG_4_AVC); + +/* case V4L2_CID_MPEG_VIDEO_? maybe keyframe interval: */ +/* return v4l2_ctrl_query_fill(qc, 0, 128, 128, 0); */ + case V4L2_CID_MPEG_VIDEO_BITRATE_MODE: + return v4l2_ctrl_query_fill( + qc, V4L2_MPEG_VIDEO_BITRATE_MODE_VBR, + V4L2_MPEG_VIDEO_BITRATE_MODE_CBR, 1, + V4L2_MPEG_VIDEO_BITRATE_MODE_CBR); + + case V4L2_CID_MPEG_VIDEO_BITRATE: + return v4l2_ctrl_query_fill(qc, 1000000, 13500000, 100000, + 6500000); + case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK: + err = v4l2_ctrl_query_fill(qc, 1100000, 20200000, 100000, + 9000000); + if (!err && opt->bitrate_mode == HDPVR_CONSTANT) + qc->flags |= V4L2_CTRL_FLAG_INACTIVE; + return err; + default: + return -EINVAL; + } +} + +static int vidioc_queryctrl(struct file *file, void *private_data, + struct v4l2_queryctrl *qc) +{ + struct hdpvr_fh *fh = file->private_data; + struct hdpvr_device *dev = fh->dev; + int i, next; + u32 id = qc->id; + + memset(qc, 0, sizeof(*qc)); + + next = !!(id & V4L2_CTRL_FLAG_NEXT_CTRL); + qc->id = id & ~V4L2_CTRL_FLAG_NEXT_CTRL; + + for (i = 0; i < ARRAY_SIZE(supported_v4l2_ctrls); i++) { + if (next) { + if (qc->id < supported_v4l2_ctrls[i]) + qc->id = supported_v4l2_ctrls[i]; + else + continue; + } + + if (qc->id == supported_v4l2_ctrls[i]) + return fill_queryctrl(&dev->options, qc, + dev->flags & HDPVR_FLAG_AC3_CAP); + + if (qc->id < supported_v4l2_ctrls[i]) + break; + } + + return -EINVAL; +} + +static int vidioc_g_ctrl(struct file *file, void *private_data, + struct v4l2_control *ctrl) +{ + struct hdpvr_fh *fh = file->private_data; + struct hdpvr_device *dev = fh->dev; + + switch (ctrl->id) { + case V4L2_CID_BRIGHTNESS: + ctrl->value = dev->options.brightness; + break; + case V4L2_CID_CONTRAST: + ctrl->value = dev->options.contrast; + break; + case V4L2_CID_SATURATION: + ctrl->value = dev->options.saturation; + break; + case V4L2_CID_HUE: + ctrl->value = dev->options.hue; + break; + case V4L2_CID_SHARPNESS: + ctrl->value = dev->options.sharpness; + break; + default: + return -EINVAL; + } + return 0; +} + +static int vidioc_s_ctrl(struct file *file, void *private_data, + struct v4l2_control *ctrl) +{ + struct hdpvr_fh *fh = file->private_data; + struct hdpvr_device *dev = fh->dev; + int retval; + + switch (ctrl->id) { + case V4L2_CID_BRIGHTNESS: + retval = hdpvr_config_call(dev, CTRL_BRIGHTNESS, ctrl->value); + if (!retval) + dev->options.brightness = ctrl->value; + break; + case V4L2_CID_CONTRAST: + retval = hdpvr_config_call(dev, CTRL_CONTRAST, ctrl->value); + if (!retval) + dev->options.contrast = ctrl->value; + break; + case V4L2_CID_SATURATION: + retval = hdpvr_config_call(dev, CTRL_SATURATION, ctrl->value); + if (!retval) + dev->options.saturation = ctrl->value; + break; + case V4L2_CID_HUE: + retval = hdpvr_config_call(dev, CTRL_HUE, ctrl->value); + if (!retval) + dev->options.hue = ctrl->value; + break; + case V4L2_CID_SHARPNESS: + retval = hdpvr_config_call(dev, CTRL_SHARPNESS, ctrl->value); + if (!retval) + dev->options.sharpness = ctrl->value; + break; + default: + return -EINVAL; + } + + return retval; +} + + +static int hdpvr_get_ctrl(struct hdpvr_options *opt, + struct v4l2_ext_control *ctrl) +{ + switch (ctrl->id) { + case V4L2_CID_MPEG_AUDIO_ENCODING: + ctrl->value = opt->audio_codec; + break; + case V4L2_CID_MPEG_VIDEO_ENCODING: + ctrl->value = V4L2_MPEG_VIDEO_ENCODING_MPEG_4_AVC; + break; +/* case V4L2_CID_MPEG_VIDEO_B_FRAMES: */ +/* ctrl->value = (opt->gop_mode & 0x2) ? 0 : 128; */ +/* break; */ + case V4L2_CID_MPEG_VIDEO_BITRATE_MODE: + ctrl->value = opt->bitrate_mode == HDPVR_CONSTANT + ? V4L2_MPEG_VIDEO_BITRATE_MODE_CBR + : V4L2_MPEG_VIDEO_BITRATE_MODE_VBR; + break; + case V4L2_CID_MPEG_VIDEO_BITRATE: + ctrl->value = opt->bitrate * 100000; + break; + case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK: + ctrl->value = opt->peak_bitrate * 100000; + break; + case V4L2_CID_MPEG_STREAM_TYPE: + ctrl->value = V4L2_MPEG_STREAM_TYPE_MPEG2_TS; + break; + default: + return -EINVAL; + } + return 0; +} + +static int vidioc_g_ext_ctrls(struct file *file, void *priv, + struct v4l2_ext_controls *ctrls) +{ + struct hdpvr_fh *fh = file->private_data; + struct hdpvr_device *dev = fh->dev; + int i, err = 0; + + if (ctrls->ctrl_class == V4L2_CTRL_CLASS_MPEG) { + for (i = 0; i < ctrls->count; i++) { + struct v4l2_ext_control *ctrl = ctrls->controls + i; + + err = hdpvr_get_ctrl(&dev->options, ctrl); + if (err) { + ctrls->error_idx = i; + break; + } + } + return err; + + } + + return -EINVAL; +} + + +static int hdpvr_try_ctrl(struct v4l2_ext_control *ctrl, int ac3) +{ + int ret = -EINVAL; + + switch (ctrl->id) { + case V4L2_CID_MPEG_AUDIO_ENCODING: + if (ctrl->value == V4L2_MPEG_AUDIO_ENCODING_AAC || + (ac3 && ctrl->value == V4L2_MPEG_AUDIO_ENCODING_AC3)) + ret = 0; + break; + case V4L2_CID_MPEG_VIDEO_ENCODING: + if (ctrl->value == V4L2_MPEG_VIDEO_ENCODING_MPEG_4_AVC) + ret = 0; + break; +/* case V4L2_CID_MPEG_VIDEO_B_FRAMES: */ +/* if (ctrl->value == 0 || ctrl->value == 128) */ +/* ret = 0; */ +/* break; */ + case V4L2_CID_MPEG_VIDEO_BITRATE_MODE: + if (ctrl->value == V4L2_MPEG_VIDEO_BITRATE_MODE_CBR || + ctrl->value == V4L2_MPEG_VIDEO_BITRATE_MODE_VBR) + ret = 0; + break; + case V4L2_CID_MPEG_VIDEO_BITRATE: + { + uint bitrate = ctrl->value / 100000; + if (bitrate >= 10 && bitrate <= 135) + ret = 0; + break; + } + case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK: + { + uint peak_bitrate = ctrl->value / 100000; + if (peak_bitrate >= 10 && peak_bitrate <= 202) + ret = 0; + break; + } + case V4L2_CID_MPEG_STREAM_TYPE: + if (ctrl->value == V4L2_MPEG_STREAM_TYPE_MPEG2_TS) + ret = 0; + break; + default: + return -EINVAL; + } + return 0; +} + +static int vidioc_try_ext_ctrls(struct file *file, void *priv, + struct v4l2_ext_controls *ctrls) +{ + struct hdpvr_fh *fh = file->private_data; + struct hdpvr_device *dev = fh->dev; + int i, err = 0; + + if (ctrls->ctrl_class == V4L2_CTRL_CLASS_MPEG) { + for (i = 0; i < ctrls->count; i++) { + struct v4l2_ext_control *ctrl = ctrls->controls + i; + + err = hdpvr_try_ctrl(ctrl, + dev->flags & HDPVR_FLAG_AC3_CAP); + if (err) { + ctrls->error_idx = i; + break; + } + } + return err; + } + + return -EINVAL; +} + + +static int hdpvr_set_ctrl(struct hdpvr_device *dev, + struct v4l2_ext_control *ctrl) +{ + struct hdpvr_options *opt = &dev->options; + int ret = 0; + + switch (ctrl->id) { + case V4L2_CID_MPEG_AUDIO_ENCODING: + if (dev->flags & HDPVR_FLAG_AC3_CAP) { + opt->audio_codec = ctrl->value; + ret = hdpvr_set_audio(dev, opt->audio_input, + opt->audio_codec); + } + break; + case V4L2_CID_MPEG_VIDEO_ENCODING: + break; +/* case V4L2_CID_MPEG_VIDEO_B_FRAMES: */ +/* if (ctrl->value == 0 && !(opt->gop_mode & 0x2)) { */ +/* opt->gop_mode |= 0x2; */ +/* hdpvr_config_call(dev, CTRL_GOP_MODE_VALUE, */ +/* opt->gop_mode); */ +/* } */ +/* if (ctrl->value == 128 && opt->gop_mode & 0x2) { */ +/* opt->gop_mode &= ~0x2; */ +/* hdpvr_config_call(dev, CTRL_GOP_MODE_VALUE, */ +/* opt->gop_mode); */ +/* } */ +/* break; */ + case V4L2_CID_MPEG_VIDEO_BITRATE_MODE: + if (ctrl->value == V4L2_MPEG_VIDEO_BITRATE_MODE_CBR && + opt->bitrate_mode != HDPVR_CONSTANT) { + opt->bitrate_mode = HDPVR_CONSTANT; + hdpvr_config_call(dev, CTRL_BITRATE_MODE_VALUE, + opt->bitrate_mode); + } + if (ctrl->value == V4L2_MPEG_VIDEO_BITRATE_MODE_VBR && + opt->bitrate_mode == HDPVR_CONSTANT) { + opt->bitrate_mode = HDPVR_VARIABLE_AVERAGE; + hdpvr_config_call(dev, CTRL_BITRATE_MODE_VALUE, + opt->bitrate_mode); + } + break; + case V4L2_CID_MPEG_VIDEO_BITRATE: { + uint bitrate = ctrl->value / 100000; + + opt->bitrate = bitrate; + if (bitrate >= opt->peak_bitrate) + opt->peak_bitrate = bitrate+1; + + hdpvr_set_bitrate(dev); + break; + } + case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK: { + uint peak_bitrate = ctrl->value / 100000; + + if (opt->bitrate_mode == HDPVR_CONSTANT) + break; + + if (opt->bitrate < peak_bitrate) { + opt->peak_bitrate = peak_bitrate; + hdpvr_set_bitrate(dev); + } else + ret = -EINVAL; + break; + } + case V4L2_CID_MPEG_STREAM_TYPE: + break; + default: + return -EINVAL; + } + return ret; +} + +static int vidioc_s_ext_ctrls(struct file *file, void *priv, + struct v4l2_ext_controls *ctrls) +{ + struct hdpvr_fh *fh = file->private_data; + struct hdpvr_device *dev = fh->dev; + int i, err = 0; + + if (ctrls->ctrl_class == V4L2_CTRL_CLASS_MPEG) { + for (i = 0; i < ctrls->count; i++) { + struct v4l2_ext_control *ctrl = ctrls->controls + i; + + err = hdpvr_try_ctrl(ctrl, + dev->flags & HDPVR_FLAG_AC3_CAP); + if (err) { + ctrls->error_idx = i; + break; + } + err = hdpvr_set_ctrl(dev, ctrl); + if (err) { + ctrls->error_idx = i; + break; + } + } + return err; + + } + + return -EINVAL; +} + +static int vidioc_enum_fmt_vid_cap(struct file *file, void *private_data, + struct v4l2_fmtdesc *f) +{ + + if (f->index != 0 || f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + return -EINVAL; + + f->flags = V4L2_FMT_FLAG_COMPRESSED; + strncpy(f->description, "MPEG2-TS with AVC/AAC streams", 32); + f->pixelformat = V4L2_PIX_FMT_MPEG; + + return 0; +} + +static int vidioc_g_fmt_vid_cap(struct file *file, void *private_data, + struct v4l2_format *f) +{ + struct hdpvr_fh *fh = file->private_data; + struct hdpvr_device *dev = fh->dev; + struct hdpvr_video_info *vid_info; + + if (!dev) + return -ENODEV; + + vid_info = get_video_info(dev); + if (!vid_info) + return -EFAULT; + + f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG; + f->fmt.pix.width = vid_info->width; + f->fmt.pix.height = vid_info->height; + f->fmt.pix.sizeimage = dev->bulk_in_size; + f->fmt.pix.colorspace = 0; + f->fmt.pix.bytesperline = 0; + f->fmt.pix.field = V4L2_FIELD_ANY; + + kfree(vid_info); + return 0; +} + + +static const struct v4l2_ioctl_ops hdpvr_ioctl_ops = { + .vidioc_querycap = vidioc_querycap, + .vidioc_s_std = vidioc_s_std, + .vidioc_enum_input = vidioc_enum_input, + .vidioc_g_input = vidioc_g_input, + .vidioc_s_input = vidioc_s_input, + .vidioc_enumaudio = vidioc_enumaudio, + .vidioc_g_audio = vidioc_g_audio, + .vidioc_s_audio = vidioc_s_audio, + .vidioc_queryctrl = vidioc_queryctrl, + .vidioc_g_ctrl = vidioc_g_ctrl, + .vidioc_s_ctrl = vidioc_s_ctrl, + .vidioc_g_ext_ctrls = vidioc_g_ext_ctrls, + .vidioc_s_ext_ctrls = vidioc_s_ext_ctrls, + .vidioc_try_ext_ctrls = vidioc_try_ext_ctrls, + .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap, + .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap, +}; + +static void hdpvr_device_release(struct video_device *vdev) +{ + struct hdpvr_device *dev = video_get_drvdata(vdev); + + hdpvr_delete(dev); +} + +static const struct video_device hdpvr_video_template = { +/* .type = VFL_TYPE_GRABBER, */ +/* .type2 = VID_TYPE_CAPTURE | VID_TYPE_MPEG_ENCODER, */ + .fops = &hdpvr_fops, + .release = hdpvr_device_release, + .ioctl_ops = &hdpvr_ioctl_ops, + .tvnorms = + V4L2_STD_NTSC | V4L2_STD_SECAM | V4L2_STD_PAL_B | + V4L2_STD_PAL_G | V4L2_STD_PAL_H | V4L2_STD_PAL_I | + V4L2_STD_PAL_D | V4L2_STD_PAL_M | V4L2_STD_PAL_N | + V4L2_STD_PAL_60, +}; + +int hdpvr_register_videodev(struct hdpvr_device *dev, int devnum) +{ + /* setup and register video device */ + dev->video_dev = video_device_alloc(); + if (!dev->video_dev) { + err("video_device_alloc() failed"); + goto error; + } + + *(dev->video_dev) = hdpvr_video_template; + strcpy(dev->video_dev->name, "Hauppauge HD PVR"); + dev->video_dev->parent = &dev->udev->dev; + video_set_drvdata(dev->video_dev, dev); + + if (video_register_device(dev->video_dev, VFL_TYPE_GRABBER, devnum)) { + err("V4L2 device registration failed"); + goto error; + } + + return 0; +error: + return -ENOMEM; +} diff --git a/drivers/media/video/hdpvr/hdpvr.h b/drivers/media/video/hdpvr/hdpvr.h new file mode 100644 index 000000000000..17db74feb884 --- /dev/null +++ b/drivers/media/video/hdpvr/hdpvr.h @@ -0,0 +1,298 @@ +/* + * Hauppage HD PVR USB driver + * + * Copyright (C) 2008 Janne Grunau (j@jannau.net) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation, version 2. + * + */ + +#include +#include +#include +#include +#include + +#define HDPVR_MAJOR_VERSION 0 +#define HDPVR_MINOR_VERSION 2 +#define HDPVR_RELEASE 0 +#define HDPVR_VERSION \ + KERNEL_VERSION(HDPVR_MAJOR_VERSION, HDPVR_MINOR_VERSION, HDPVR_RELEASE) + +#define HDPVR_MAX 8 + +/* Define these values to match your devices */ +#define HD_PVR_VENDOR_ID 0x2040 +#define HD_PVR_PRODUCT_ID 0x4900 +#define HD_PVR_PRODUCT_ID1 0x4901 +#define HD_PVR_PRODUCT_ID2 0x4902 + +#define UNSET (-1U) + +#define NUM_BUFFERS 64 + +#define HDPVR_FIRMWARE_VERSION 0x8 +#define HDPVR_FIRMWARE_VERSION_AC3 0xd + +/* #define HDPVR_DEBUG */ + +extern int hdpvr_debug; + +#define MSG_INFO 1 +#define MSG_BUFFER 2 + +struct hdpvr_options { + u8 video_std; + u8 video_input; + u8 audio_input; + u8 bitrate; /* in 100kbps */ + u8 peak_bitrate; /* in 100kbps */ + u8 bitrate_mode; + u8 gop_mode; + enum v4l2_mpeg_audio_encoding audio_codec; + u8 brightness; + u8 contrast; + u8 hue; + u8 saturation; + u8 sharpness; +}; + +/* Structure to hold all of our device specific stuff */ +struct hdpvr_device { + /* the v4l device for this device */ + struct video_device *video_dev; + /* the usb device for this device */ + struct usb_device *udev; + + /* the max packet size of the bulk endpoint */ + size_t bulk_in_size; + /* the address of the bulk in endpoint */ + __u8 bulk_in_endpointAddr; + + /* holds the current device status */ + __u8 status; + /* count the number of openers */ + uint open_count; + + /* holds the cureent set options */ + struct hdpvr_options options; + + uint flags; + + /* synchronize I/O */ + struct mutex io_mutex; + /* available buffers */ + struct list_head free_buff_list; + /* in progress buffers */ + struct list_head rec_buff_list; + /* waitqueue for buffers */ + wait_queue_head_t wait_buffer; + /* waitqueue for data */ + wait_queue_head_t wait_data; + /**/ + struct workqueue_struct *workqueue; + /**/ + struct work_struct worker; + + /* I2C adapter */ + struct i2c_adapter *i2c_adapter; + /* I2C lock */ + struct mutex i2c_mutex; + + /* usb control transfer buffer and lock */ + struct mutex usbc_mutex; + u8 *usbc_buf; +}; + + +/* buffer one bulk urb of data */ +struct hdpvr_buffer { + struct list_head buff_list; + + struct urb *urb; + + struct hdpvr_device *dev; + + uint pos; + + __u8 status; +}; + +/* */ + +struct hdpvr_video_info { + u16 width; + u16 height; + u8 fps; +}; + +enum { + STATUS_UNINITIALIZED = 0, + STATUS_IDLE, + STATUS_STARTING, + STATUS_SHUTTING_DOWN, + STATUS_STREAMING, + STATUS_ERROR, + STATUS_DISCONNECTED, +}; + +enum { + HDPVR_FLAG_AC3_CAP = 1, +}; + +enum { + BUFSTAT_UNINITIALIZED = 0, + BUFSTAT_AVAILABLE, + BUFSTAT_INPROGRESS, + BUFSTAT_READY, +}; + +#define CTRL_START_STREAMING_VALUE 0x0700 +#define CTRL_STOP_STREAMING_VALUE 0x0800 +#define CTRL_BITRATE_VALUE 0x1000 +#define CTRL_BITRATE_MODE_VALUE 0x1200 +#define CTRL_GOP_MODE_VALUE 0x1300 +#define CTRL_VIDEO_INPUT_VALUE 0x1500 +#define CTRL_VIDEO_STD_TYPE 0x1700 +#define CTRL_AUDIO_INPUT_VALUE 0x2500 +#define CTRL_BRIGHTNESS 0x2900 +#define CTRL_CONTRAST 0x2a00 +#define CTRL_HUE 0x2b00 +#define CTRL_SATURATION 0x2c00 +#define CTRL_SHARPNESS 0x2d00 +#define CTRL_LOW_PASS_FILTER_VALUE 0x3100 + +#define CTRL_DEFAULT_INDEX 0x0003 + + + /* :0 s 38 01 1000 0003 0004 4 = 0a00ca00 + * BITRATE SETTING + * 1st and 2nd byte (little endian): average bitrate in 100 000 bit/s + * min: 1 mbit/s, max: 13.5 mbit/s + * 3rd and 4th byte (little endian): peak bitrate in 100 000 bit/s + * min: average + 100kbit/s, + * max: 20.2 mbit/s + */ + + /* :0 s 38 01 1200 0003 0001 1 = 02 + * BIT RATE MODE + * constant = 1, variable (peak) = 2, variable (average) = 3 + */ + + /* :0 s 38 01 1300 0003 0001 1 = 03 + * GOP MODE (2 bit) + * low bit 0/1: advanced/simple GOP + * high bit 0/1: IDR(4/32/128) / no IDR (4/32/0) + */ + + /* :0 s 38 01 1700 0003 0001 1 = 00 + * VIDEO STANDARD or FREQUNCY 0 = 60hz, 1 = 50hz + */ + + /* :0 s 38 01 3100 0003 0004 4 = 03030000 + * FILTER CONTROL + * 1st byte luma low pass filter strength, + * 2nd byte chroma low pass filter strength, + * 3rd byte MF enable chroma, min=0, max=1 + * 4th byte n + */ + + + /* :0 s 38 b9 0001 0000 0000 0 */ + + + +/* :0 s 38 d3 0000 0000 0001 1 = 00 */ +/* ret = usb_control_msg(dev->udev, */ +/* usb_sndctrlpipe(dev->udev, 0), */ +/* 0xd3, 0x38, */ +/* 0, 0, */ +/* "\0", 1, */ +/* 1000); */ + +/* info("control request returned %d", ret); */ +/* msleep(5000); */ + + + /* :0 s b8 81 1400 0003 0005 5 < + * :0 0 5 = d0024002 19 + * QUERY FRAME SIZE AND RATE + * 1st and 2nd byte (little endian): horizontal resolution + * 3rd and 4th byte (little endian): vertical resolution + * 5th byte: frame rate + */ + + /* :0 s b8 81 1800 0003 0003 3 < + * :0 0 3 = 030104 + * QUERY SIGNAL AND DETECTED LINES, maybe INPUT + */ + +enum hdpvr_video_std { + HDPVR_60HZ = 0, + HDPVR_50HZ, +}; + +enum hdpvr_video_input { + HDPVR_COMPONENT = 0, + HDPVR_SVIDEO, + HDPVR_COMPOSITE, + HDPVR_VIDEO_INPUTS +}; + +enum hdpvr_audio_inputs { + HDPVR_RCA_BACK = 0, + HDPVR_RCA_FRONT, + HDPVR_SPDIF, + HDPVR_AUDIO_INPUTS +}; + +enum hdpvr_bitrate_mode { + HDPVR_CONSTANT = 1, + HDPVR_VARIABLE_PEAK, + HDPVR_VARIABLE_AVERAGE, +}; + +enum hdpvr_gop_mode { + HDPVR_ADVANCED_IDR_GOP = 0, + HDPVR_SIMPLE_IDR_GOP, + HDPVR_ADVANCED_NOIDR_GOP, + HDPVR_SIMPLE_NOIDR_GOP, +}; + +void hdpvr_delete(struct hdpvr_device *dev); + +/*========================================================================*/ +/* hardware control functions */ +int hdpvr_set_options(struct hdpvr_device *dev); + +int hdpvr_set_bitrate(struct hdpvr_device *dev); + +int hdpvr_set_audio(struct hdpvr_device *dev, u8 input, + enum v4l2_mpeg_audio_encoding codec); + +int hdpvr_config_call(struct hdpvr_device *dev, uint value, + unsigned char valbuf); + +struct hdpvr_video_info *get_video_info(struct hdpvr_device *dev); + +/* :0 s b8 81 1800 0003 0003 3 < */ +/* :0 0 3 = 0301ff */ +int get_input_lines_info(struct hdpvr_device *dev); + + +/*========================================================================*/ +/* v4l2 registration */ +int hdpvr_register_videodev(struct hdpvr_device *dev, int devnumber); + +int hdpvr_cancel_queue(struct hdpvr_device *dev); + +/*========================================================================*/ +/* i2c adapter registration */ +int hdpvr_register_i2c_adapter(struct hdpvr_device *dev); + +/*========================================================================*/ +/* buffer management */ +int hdpvr_free_buffers(struct hdpvr_device *dev); +int hdpvr_alloc_buffers(struct hdpvr_device *dev, uint count); diff --git a/include/linux/i2c-id.h b/include/linux/i2c-id.h index 17d9af070f06..f27604af8378 100644 --- a/include/linux/i2c-id.h +++ b/include/linux/i2c-id.h @@ -88,6 +88,7 @@ #define I2C_HW_B_CX2341X 0x010020 /* Conexant CX2341X MPEG encoder cards */ #define I2C_HW_B_CX23885 0x010022 /* conexant 23885 based tv cards (bus1) */ #define I2C_HW_B_AU0828 0x010023 /* auvitek au0828 usb bridge */ +#define I2C_HW_B_HDPVR 0x010025 /* Hauppauge HD PVR */ /* --- SGI adapters */ #define I2C_HW_SGI_VINO 0x160000 -- cgit v1.2.3 From 76717b887cccc77d04357fc0d6ac98f894e3eb3c Mon Sep 17 00:00:00 2001 From: Janne Grunau Date: Wed, 18 Mar 2009 20:57:04 -0300 Subject: V4L/DVB (11097): use video_ioctl2 as ioctl handler directly The encoder commands ioctls are available in v4l2_ioctl_ops. Use them and get rid of the custom ioctl handler and use video_ioctl2. Signed-off-by: Janne Grunau Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/hdpvr/hdpvr-video.c | 85 ++++++++++++++++----------------- 1 file changed, 41 insertions(+), 44 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/hdpvr/hdpvr-video.c b/drivers/media/video/hdpvr/hdpvr-video.c index ee481495e4fc..6dd11f490735 100644 --- a/drivers/media/video/hdpvr/hdpvr-video.c +++ b/drivers/media/video/hdpvr/hdpvr-video.c @@ -524,56 +524,13 @@ static unsigned int hdpvr_poll(struct file *filp, poll_table *wait) } -static long hdpvr_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) -{ - struct hdpvr_fh *fh = (struct hdpvr_fh *)filp->private_data; - struct hdpvr_device *dev = fh->dev; - int res; - - if (video_is_unregistered(dev->video_dev)) - return -EIO; - - mutex_lock(&dev->io_mutex); - switch (cmd) { - case VIDIOC_TRY_ENCODER_CMD: - case VIDIOC_ENCODER_CMD: { - struct v4l2_encoder_cmd *enc = (struct v4l2_encoder_cmd *)arg; - int try = cmd == VIDIOC_TRY_ENCODER_CMD; - - memset(&enc->raw, 0, sizeof(enc->raw)); - switch (enc->cmd) { - case V4L2_ENC_CMD_START: - enc->flags = 0; - if (try) - return 0; - res = hdpvr_start_streaming(dev); - break; - case V4L2_ENC_CMD_STOP: - if (try) - return 0; - res = hdpvr_stop_streaming(dev); - break; - default: - v4l2_dbg(MSG_INFO, hdpvr_debug, dev->video_dev, - "Unsupported encoder cmd %d\n", enc->cmd); - return -EINVAL; - } - break; - } - default: - res = video_ioctl2(filp, cmd, arg); - } - mutex_unlock(&dev->io_mutex); - return res; -} - static const struct v4l2_file_operations hdpvr_fops = { .owner = THIS_MODULE, .open = hdpvr_open, .release = hdpvr_release, .read = hdpvr_read, .poll = hdpvr_poll, - .unlocked_ioctl = hdpvr_ioctl, + .unlocked_ioctl = video_ioctl2, }; /*=======================================================================*/ @@ -1163,6 +1120,44 @@ static int vidioc_g_fmt_vid_cap(struct file *file, void *private_data, return 0; } +static int vidioc_encoder_cmd(struct file *filp, void *priv, + struct v4l2_encoder_cmd *a) +{ + struct hdpvr_fh *fh = filp->private_data; + struct hdpvr_device *dev = fh->dev; + int res; + + mutex_lock(&dev->io_mutex); + + memset(&a->raw, 0, sizeof(a->raw)); + switch (a->cmd) { + case V4L2_ENC_CMD_START: + a->flags = 0; + res = hdpvr_start_streaming(dev); + break; + case V4L2_ENC_CMD_STOP: + res = hdpvr_stop_streaming(dev); + break; + default: + v4l2_dbg(MSG_INFO, hdpvr_debug, dev->video_dev, + "Unsupported encoder cmd %d\n", a->cmd); + return -EINVAL; + } + mutex_unlock(&dev->io_mutex); + return res; +} + +static int vidioc_try_encoder_cmd(struct file *filp, void *priv, + struct v4l2_encoder_cmd *a) +{ + switch (a->cmd) { + case V4L2_ENC_CMD_START: + case V4L2_ENC_CMD_STOP: + return 0; + default: + return -EINVAL; + } +} static const struct v4l2_ioctl_ops hdpvr_ioctl_ops = { .vidioc_querycap = vidioc_querycap, @@ -1181,6 +1176,8 @@ static const struct v4l2_ioctl_ops hdpvr_ioctl_ops = { .vidioc_try_ext_ctrls = vidioc_try_ext_ctrls, .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap, .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap, + .vidioc_encoder_cmd = vidioc_encoder_cmd, + .vidioc_try_encoder_cmd = vidioc_try_encoder_cmd, }; static void hdpvr_device_release(struct video_device *vdev) -- cgit v1.2.3 From d64260d58865004c6354e024da3450fdd607ea07 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 18 Mar 2009 15:48:01 -0300 Subject: V4L/DVB (11098): v4l2-common: remove incorrect MODULE test v4l2-common doesn't have to be a module for it to call request_module(). Just remove that test. Thanks-to: Guennadi Liakhovetski Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/v4l2-common.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/v4l2-common.c b/drivers/media/video/v4l2-common.c index b09782563c29..1da8cb836cb6 100644 --- a/drivers/media/video/v4l2-common.c +++ b/drivers/media/video/v4l2-common.c @@ -797,10 +797,10 @@ struct v4l2_subdev *v4l2_i2c_new_subdev(struct i2c_adapter *adapter, struct i2c_board_info info; BUG_ON(!dev); -#ifdef MODULE + if (module_name) request_module(module_name); -#endif + /* Setup the i2c board info with the device type and the device address. */ memset(&info, 0, sizeof(info)); @@ -850,10 +850,10 @@ struct v4l2_subdev *v4l2_i2c_new_probed_subdev(struct i2c_adapter *adapter, struct i2c_board_info info; BUG_ON(!dev); -#ifdef MODULE + if (module_name) request_module(module_name); -#endif + /* Setup the i2c board info with the device type and the device address. */ memset(&info, 0, sizeof(info)); -- cgit v1.2.3 From 0dc641dc9f7f168fc45f3032b22dcf7d5b57c47c Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Thu, 19 Mar 2009 05:55:22 -0300 Subject: V4L/DVB (11103): gspca - main: May have isochronous transfers on altsetting 0 Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/gspca.c | 12 +++++++----- drivers/media/video/gspca/gspca.h | 1 + 2 files changed, 8 insertions(+), 5 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/gspca/gspca.c b/drivers/media/video/gspca/gspca.c index ed18401fd8ba..66e91d896eda 100644 --- a/drivers/media/video/gspca/gspca.c +++ b/drivers/media/video/gspca/gspca.c @@ -474,14 +474,14 @@ static struct usb_host_endpoint *get_ep(struct gspca_dev *gspca_dev) i = gspca_dev->alt; /* previous alt setting */ /* try isoc */ - while (--i > 0) { /* alt 0 is unusable */ + while (--i >= 0) { ep = alt_xfer(&intf->altsetting[i], USB_ENDPOINT_XFER_ISOC); if (ep) break; } - /* if no isoc, try bulk */ + /* if no isoc, try bulk (alt 0 only) */ if (ep == NULL) { ep = alt_xfer(&intf->altsetting[0], USB_ENDPOINT_XFER_BULK); @@ -489,6 +489,8 @@ static struct usb_host_endpoint *get_ep(struct gspca_dev *gspca_dev) err("no transfer endpoint found"); return NULL; } + i = 0; + gspca_dev->bulk = 1; } PDEBUG(D_STREAM, "use alt %d ep 0x%02x", i, ep->desc.bEndpointAddress); @@ -515,7 +517,7 @@ static int create_urbs(struct gspca_dev *gspca_dev, /* calculate the packet size and the number of packets */ psize = le16_to_cpu(ep->desc.wMaxPacketSize); - if (gspca_dev->alt != 0) { /* isoc */ + if (!gspca_dev->bulk) { /* isoc */ /* See paragraph 5.9 / table 5-11 of the usb 2.0 spec. */ psize = (psize & 0x07ff) * (1 + ((psize >> 11) & 3)); @@ -615,7 +617,7 @@ static int gspca_init_transfer(struct gspca_dev *gspca_dev) goto out; /* clear the bulk endpoint */ - if (gspca_dev->alt == 0) /* if bulk transfer */ + if (gspca_dev->bulk) usb_clear_halt(gspca_dev->dev, gspca_dev->urb[0]->pipe); @@ -628,7 +630,7 @@ static int gspca_init_transfer(struct gspca_dev *gspca_dev) gspca_dev->streaming = 1; /* some bulk transfers are started by the subdriver */ - if (gspca_dev->alt == 0 && gspca_dev->cam.bulk_nurbs == 0) + if (gspca_dev->bulk && gspca_dev->cam.bulk_nurbs == 0) break; /* submit the URBs */ diff --git a/drivers/media/video/gspca/gspca.h b/drivers/media/video/gspca/gspca.h index 6f172e9e5fe9..e4d4cf6ce05a 100644 --- a/drivers/media/video/gspca/gspca.h +++ b/drivers/media/video/gspca/gspca.h @@ -167,6 +167,7 @@ struct gspca_dev { __u8 iface; /* USB interface number */ __u8 alt; /* USB alternate setting */ __u8 nbalt; /* number of USB alternate settings */ + u8 bulk; /* image transfer by 0:isoc / 1:bulk */ }; int gspca_dev_probe(struct usb_interface *intf, -- cgit v1.2.3 From 3481c19854cdb1de1842c6ea6d558006ac0b3b7d Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Thu, 19 Mar 2009 06:05:06 -0300 Subject: V4L/DVB (11104): gspca - ov534: Bad frame pointer after adding the last packet Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/ov534.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/gspca/ov534.c b/drivers/media/video/gspca/ov534.c index 054bdf02c386..ea2245626d53 100644 --- a/drivers/media/video/gspca/ov534.c +++ b/drivers/media/video/gspca/ov534.c @@ -487,8 +487,9 @@ scan_next: goto discard; } - gspca_frame_add(gspca_dev, LAST_PACKET, frame, NULL, 0); - } + frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame, + NULL, 0); + } /* Done this payload */ goto scan_next; -- cgit v1.2.3 From 84fbdf87ab8eaa4eaefb317a7eb437cd4d3d0ebf Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Thu, 19 Mar 2009 06:12:59 -0300 Subject: V4L/DVB (11105): gspca - ov534: Adjust the packet scan function - change max payload size to 2040 bytes (was 2048) - optimize Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/ov534.c | 115 +++++++++++++++++++------------------- 1 file changed, 57 insertions(+), 58 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/gspca/ov534.c b/drivers/media/video/gspca/ov534.c index ea2245626d53..647c448f492f 100644 --- a/drivers/media/video/gspca/ov534.c +++ b/drivers/media/video/gspca/ov534.c @@ -46,9 +46,9 @@ MODULE_LICENSE("GPL"); /* specific webcam descriptor */ struct sd { struct gspca_dev gspca_dev; /* !! must be the first item */ - __u32 last_fid; __u32 last_pts; - int frame_rate; + u16 last_fid; + u8 frame_rate; }; /* V4L2 controls supported by the driver */ @@ -428,76 +428,75 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, struct gspca_frame *frame, { struct sd *sd = (struct sd *) gspca_dev; __u32 this_pts; - int this_fid; + u16 this_fid; int remaining_len = len; - __u8 *next_data = data; -scan_next: - if (remaining_len <= 0) - return; - - data = next_data; - len = min(remaining_len, 2048); - remaining_len -= len; - next_data += len; - - /* Payloads are prefixed with a UVC-style header. We - consider a frame to start when the FID toggles, or the PTS - changes. A frame ends when EOF is set, and we've received - the correct number of bytes. */ - - /* Verify UVC header. Header length is always 12 */ - if (data[0] != 12 || len < 12) { - PDEBUG(D_PACK, "bad header"); - goto discard; - } + do { + len = min(remaining_len, 2040); /*fixme: was 2048*/ - /* Check errors */ - if (data[1] & UVC_STREAM_ERR) { - PDEBUG(D_PACK, "payload error"); - goto discard; - } + /* Payloads are prefixed with a UVC-style header. We + consider a frame to start when the FID toggles, or the PTS + changes. A frame ends when EOF is set, and we've received + the correct number of bytes. */ - /* Extract PTS and FID */ - if (!(data[1] & UVC_STREAM_PTS)) { - PDEBUG(D_PACK, "PTS not present"); - goto discard; - } - this_pts = (data[5] << 24) | (data[4] << 16) | (data[3] << 8) | data[2]; - this_fid = (data[1] & UVC_STREAM_FID) ? 1 : 0; - - /* If PTS or FID has changed, start a new frame. */ - if (this_pts != sd->last_pts || this_fid != sd->last_fid) { - gspca_frame_add(gspca_dev, FIRST_PACKET, frame, NULL, 0); - sd->last_pts = this_pts; - sd->last_fid = this_fid; - } - - /* Add the data from this payload */ - gspca_frame_add(gspca_dev, INTER_PACKET, frame, - data + 12, len - 12); + /* Verify UVC header. Header length is always 12 */ + if (data[0] != 12 || len < 12) { + PDEBUG(D_PACK, "bad header"); + goto discard; + } - /* If this packet is marked as EOF, end the frame */ - if (data[1] & UVC_STREAM_EOF) { - sd->last_pts = 0; + /* Check errors */ + if (data[1] & UVC_STREAM_ERR) { + PDEBUG(D_PACK, "payload error"); + goto discard; + } - if ((frame->data_end - frame->data) != - (gspca_dev->width * gspca_dev->height * 2)) { - PDEBUG(D_PACK, "short frame"); + /* Extract PTS and FID */ + if (!(data[1] & UVC_STREAM_PTS)) { + PDEBUG(D_PACK, "PTS not present"); goto discard; } + this_pts = (data[5] << 24) | (data[4] << 16) + | (data[3] << 8) | data[2]; + this_fid = (data[1] & UVC_STREAM_FID) ? 1 : 0; - frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame, + /* If PTS or FID has changed, start a new frame. */ + if (this_pts != sd->last_pts || this_fid != sd->last_fid) { + gspca_frame_add(gspca_dev, FIRST_PACKET, frame, NULL, 0); + sd->last_pts = this_pts; + sd->last_fid = this_fid; + } + + /* Add the data from this payload */ + gspca_frame_add(gspca_dev, INTER_PACKET, frame, + data + 12, len - 12); + + /* If this packet is marked as EOF, end the frame */ + if (data[1] & UVC_STREAM_EOF) { + sd->last_pts = 0; + + if (frame->data_end - frame->data != + gspca_dev->width * gspca_dev->height * 2) { + PDEBUG(D_PACK, "short frame"); + goto discard; + } + + frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame, + NULL, 0); } - /* Done this payload */ - goto scan_next; + /* Done this payload */ + goto scan_next; discard: - /* Discard data until a new frame starts. */ - gspca_frame_add(gspca_dev, DISCARD_PACKET, frame, NULL, 0); - goto scan_next; + /* Discard data until a new frame starts. */ + gspca_frame_add(gspca_dev, DISCARD_PACKET, frame, NULL, 0); + +scan_next: + remaining_len -= len; + data += len; + } while (remaining_len > 0); } /* get stream parameters (framerate) */ -- cgit v1.2.3 From 2ce949ec661efe1e9747ae1419932a4b6fb1e24b Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Thu, 19 Mar 2009 06:15:21 -0300 Subject: V4L/DVB (11106): gspca - ov534: New sensor ov965x and re-enable the webcam 06f8:3003 Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/ov534.c | 693 ++++++++++++++++++++++++++++++-------- 1 file changed, 548 insertions(+), 145 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/gspca/ov534.c b/drivers/media/video/gspca/ov534.c index 647c448f492f..19e0bc60de14 100644 --- a/drivers/media/video/gspca/ov534.c +++ b/drivers/media/video/gspca/ov534.c @@ -1,7 +1,8 @@ /* - * ov534/ov772x gspca driver + * ov534 gspca driver * Copyright (C) 2008 Antonio Ospite * Copyright (C) 2008 Jim Paris + * Copyright (C) 2009 Jean-Francois Moine http://moinejf.free.fr * * Based on a prototype written by Mark Ferrell * USB protocol reverse engineered by Jim Paris @@ -26,7 +27,7 @@ #include "gspca.h" -#define OV534_REG_ADDRESS 0xf1 /* ? */ +#define OV534_REG_ADDRESS 0xf1 /* sensor address */ #define OV534_REG_SUBADDR 0xf2 #define OV534_REG_WRITE 0xf3 #define OV534_REG_READ 0xf4 @@ -49,6 +50,10 @@ struct sd { __u32 last_pts; u16 last_fid; u8 frame_rate; + + u8 sensor; +#define SENSOR_OV772X 0 +#define SENSOR_OV965X 1 }; /* V4L2 controls supported by the driver */ @@ -63,114 +68,7 @@ static const struct v4l2_pix_format vga_mode[] = { .priv = 0}, }; -static void ov534_reg_write(struct gspca_dev *gspca_dev, u16 reg, u8 val) -{ - struct usb_device *udev = gspca_dev->dev; - int ret; - - PDEBUG(D_USBO, "reg=0x%04x, val=0%02x", reg, val); - gspca_dev->usb_buf[0] = val; - ret = usb_control_msg(udev, - usb_sndctrlpipe(udev, 0), - 0x1, - USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - 0x0, reg, gspca_dev->usb_buf, 1, CTRL_TIMEOUT); - if (ret < 0) - PDEBUG(D_ERR, "write failed"); -} - -static u8 ov534_reg_read(struct gspca_dev *gspca_dev, u16 reg) -{ - struct usb_device *udev = gspca_dev->dev; - int ret; - - ret = usb_control_msg(udev, - usb_rcvctrlpipe(udev, 0), - 0x1, - USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - 0x0, reg, gspca_dev->usb_buf, 1, CTRL_TIMEOUT); - PDEBUG(D_USBI, "reg=0x%04x, data=0x%02x", reg, gspca_dev->usb_buf[0]); - if (ret < 0) - PDEBUG(D_ERR, "read failed"); - return gspca_dev->usb_buf[0]; -} - -/* Two bits control LED: 0x21 bit 7 and 0x23 bit 7. - * (direction and output)? */ -static void ov534_set_led(struct gspca_dev *gspca_dev, int status) -{ - u8 data; - - PDEBUG(D_CONF, "led status: %d", status); - - data = ov534_reg_read(gspca_dev, 0x21); - data |= 0x80; - ov534_reg_write(gspca_dev, 0x21, data); - - data = ov534_reg_read(gspca_dev, 0x23); - if (status) - data |= 0x80; - else - data &= ~(0x80); - - ov534_reg_write(gspca_dev, 0x23, data); -} - -static int sccb_check_status(struct gspca_dev *gspca_dev) -{ - u8 data; - int i; - - for (i = 0; i < 5; i++) { - data = ov534_reg_read(gspca_dev, OV534_REG_STATUS); - - switch (data) { - case 0x00: - return 1; - case 0x04: - return 0; - case 0x03: - break; - default: - PDEBUG(D_ERR, "sccb status 0x%02x, attempt %d/5", - data, i + 1); - } - } - return 0; -} - -static void sccb_reg_write(struct gspca_dev *gspca_dev, u16 reg, u8 val) -{ - PDEBUG(D_USBO, "reg: 0x%04x, val: 0x%02x", reg, val); - ov534_reg_write(gspca_dev, OV534_REG_SUBADDR, reg); - ov534_reg_write(gspca_dev, OV534_REG_WRITE, val); - ov534_reg_write(gspca_dev, OV534_REG_OPERATION, OV534_OP_WRITE_3); - - if (!sccb_check_status(gspca_dev)) - PDEBUG(D_ERR, "sccb_reg_write failed"); -} - -#ifdef GSPCA_DEBUG -static u8 sccb_reg_read(struct gspca_dev *gspca_dev, u16 reg) -{ - ov534_reg_write(gspca_dev, OV534_REG_SUBADDR, reg); - ov534_reg_write(gspca_dev, OV534_REG_OPERATION, OV534_OP_WRITE_2); - if (!sccb_check_status(gspca_dev)) - PDEBUG(D_ERR, "sccb_reg_read failed 1"); - - ov534_reg_write(gspca_dev, OV534_REG_OPERATION, OV534_OP_READ_2); - if (!sccb_check_status(gspca_dev)) - PDEBUG(D_ERR, "sccb_reg_read failed 2"); - - return ov534_reg_read(gspca_dev, OV534_REG_READ); -} -#endif - -static const __u8 ov534_reg_initdata[][2] = { - { 0xe7, 0x3a }, - - { OV534_REG_ADDRESS, 0x42 }, /* select OV772x sensor */ - +static const u8 bridge_init_ov722x[][2] = { { 0xc2, 0x0c }, { 0x88, 0xf8 }, { 0xc3, 0x69 }, @@ -228,7 +126,7 @@ static const __u8 ov534_reg_initdata[][2] = { { 0xc2, 0x0c }, }; -static const __u8 ov772x_reg_initdata[][2] = { +static const u8 sensor_init_ov722x[][2] = { { 0x12, 0x80 }, { 0x11, 0x01 }, @@ -311,6 +209,456 @@ static const __u8 ov772x_reg_initdata[][2] = { { 0x0c, 0xd0 } }; +static const u8 bridge_init_ov965x[][2] = { + {0x88, 0xf8}, + {0x89, 0xff}, + {0x76, 0x03}, + {0x92, 0x03}, + {0x95, 0x10}, + {0xe2, 0x00}, + {0xe7, 0x3e}, + {0x8d, 0x1c}, + {0x8e, 0x00}, + {0x8f, 0x00}, + {0x1f, 0x00}, + {0xc3, 0xf9}, + {0x89, 0xff}, + {0x88, 0xf8}, + {0x76, 0x03}, + {0x92, 0x01}, + {0x93, 0x18}, + {0x1c, 0x0a}, + {0x1d, 0x48}, + {0xc0, 0x50}, + {0xc1, 0x3c}, + {0x34, 0x05}, + {0xc2, 0x0c}, + {0xc3, 0xf9}, + {0x34, 0x05}, + {0xe7, 0x2e}, + {0x31, 0xf9}, + {0x35, 0x02}, + {0xd9, 0x10}, + {0x25, 0x42}, + {0x94, 0x11}, +}; + +static const u8 sensor_init_ov965x[][2] = { + {0x12, 0x80}, /* com7 - reset */ + {0x00, 0x00}, /* gain */ + {0x01, 0x80}, /* blue */ + {0x02, 0x80}, /* red */ + {0x03, 0x1b}, /* vref */ + {0x04, 0x03}, /* com1 - exposure low bits */ + {0x0b, 0x57}, /* ver */ + {0x0e, 0x61}, /* com5 */ + {0x0f, 0x42}, /* com6 */ + {0x11, 0x00}, /* clkrc */ + {0x12, 0x02}, /* com7 */ + {0x13, 0xe7}, /* com8 - everything (AGC, AWB and AEC) */ + {0x14, 0x28}, /* com9 */ + {0x16, 0x24}, /* rsvd16 */ + {0x17, 0x1d}, /* hstart*/ + {0x18, 0xbd}, /* hstop */ + {0x19, 0x01}, /* vstrt */ + {0x1a, 0x81}, /* vstop*/ + {0x1e, 0x04}, /* mvfp */ + {0x24, 0x3c}, /* aew */ + {0x25, 0x36}, /* aeb */ + {0x26, 0x71}, /* vpt */ + {0x27, 0x08}, /* bbias */ + {0x28, 0x08}, /* gbbias */ + {0x29, 0x15}, /* gr com */ + {0x2a, 0x00}, + {0x2b, 0x00}, + {0x2c, 0x08}, /* rbias */ + {0x32, 0xff}, /* href */ + {0x33, 0x00}, /* chlf */ + {0x34, 0x3f}, /* arblm */ + {0x35, 0x00}, /* rsvd35 */ + {0x36, 0xf8}, /* rsvd36 */ + {0x38, 0x72}, /* acom38 */ + {0x39, 0x57}, /* ofon */ + {0x3a, 0x80}, /* tslb */ + {0x3b, 0xc4}, + {0x3d, 0x99}, /* com13 */ + {0x3f, 0xc1}, + {0x40, 0xc0}, /* com15 */ + {0x41, 0x40}, /* com16 */ + {0x42, 0xc0}, + {0x43, 0x0a}, + {0x44, 0xf0}, + {0x45, 0x46}, + {0x46, 0x62}, + {0x47, 0x2a}, + {0x48, 0x3c}, + {0x4a, 0xfc}, + {0x4b, 0xfc}, + {0x4c, 0x7f}, + {0x4d, 0x7f}, + {0x4e, 0x7f}, + {0x4f, 0x98}, + {0x50, 0x98}, + {0x51, 0x00}, + {0x52, 0x28}, + {0x53, 0x70}, + {0x54, 0x98}, + {0x58, 0x1a}, + {0x59, 0x85}, + {0x5a, 0xa9}, + {0x5b, 0x64}, + {0x5c, 0x84}, + {0x5d, 0x53}, + {0x5e, 0x0e}, + {0x5f, 0xf0}, + {0x60, 0xf0}, + {0x61, 0xf0}, + {0x62, 0x00}, /* lcc1 */ + {0x63, 0x00}, /* lcc2 */ + {0x64, 0x02}, /* lcc3 */ + {0x65, 0x16}, /* lcc4 */ + {0x66, 0x01}, /* lcc5 */ + {0x69, 0x02}, /* hv */ + {0x6b, 0x5a}, /* dbvl */ + {0x6c, 0x04}, + {0x6d, 0x55}, + {0x6e, 0x00}, + {0x6f, 0x9d}, + {0x70, 0x21}, + {0x71, 0x78}, + {0x72, 0x00}, + {0x73, 0x01}, + {0x74, 0x3a}, + {0x75, 0x35}, + {0x76, 0x01}, + {0x77, 0x02}, + {0x7a, 0x12}, + {0x7b, 0x08}, + {0x7c, 0x16}, + {0x7d, 0x30}, + {0x7e, 0x5e}, + {0x7f, 0x72}, + {0x80, 0x82}, + {0x81, 0x8e}, + {0x82, 0x9a}, + {0x83, 0xa4}, + {0x84, 0xac}, + {0x85, 0xb8}, + {0x86, 0xc3}, + {0x87, 0xd6}, + {0x88, 0xe6}, + {0x89, 0xf2}, + {0x8a, 0x03}, + {0x8c, 0x89}, + {0x14, 0x28}, /* com9 */ + {0x90, 0x7d}, + {0x91, 0x7b}, + {0x9d, 0x03}, + {0x9e, 0x04}, + {0x9f, 0x7a}, + {0xa0, 0x79}, + {0xa1, 0x40}, /* aechm */ + {0xa4, 0x50}, + {0xa5, 0x68}, /* com26 */ + {0xa6, 0x4a}, + {0xa8, 0xc1}, /* acoma8 */ + {0xa9, 0xef}, /* acoma9 */ + {0xaa, 0x92}, + {0xab, 0x04}, + {0xac, 0x80}, + {0xad, 0x80}, + {0xae, 0x80}, + {0xaf, 0x80}, + {0xb2, 0xf2}, + {0xb3, 0x20}, + {0xb4, 0x20}, + {0xb5, 0x00}, + {0xb6, 0xaf}, + {0xbb, 0xae}, + {0xbc, 0x7f}, + {0xdb, 0x7f}, + {0xbe, 0x7f}, + {0xbf, 0x7f}, + {0xc0, 0xe2}, + {0xc1, 0xc0}, + {0xc2, 0x01}, + {0xc3, 0x4e}, + {0xc6, 0x85}, + {0xc7, 0x80}, + {0xc9, 0xe0}, + {0xca, 0xe8}, + {0xcb, 0xf0}, + {0xcc, 0xd8}, + {0xcd, 0xf1}, + {0x4f, 0x98}, + {0x50, 0x98}, + {0x51, 0x00}, + {0x52, 0x28}, + {0x53, 0x70}, + {0x54, 0x98}, + {0x58, 0x1a}, + {0xff, 0x41}, /* read 41, write ff 00 */ + {0x41, 0x40}, /* com16 */ + {0xc5, 0x03}, + {0x6a, 0x02}, + + {0x12, 0x62}, /* com7 - VGA + CIF */ + {0x36, 0xfa}, /* rsvd36 */ + {0x69, 0x0a}, /* hv */ + {0x8c, 0x89}, /* com22 */ + {0x14, 0x28}, /* com9 */ + {0x3e, 0x0c}, + {0x41, 0x40}, /* com16 */ + {0x72, 0x00}, + {0x73, 0x00}, + {0x74, 0x3a}, + {0x75, 0x35}, + {0x76, 0x01}, + {0xc7, 0x80}, + {0x03, 0x12}, /* vref */ + {0x17, 0x16}, /* hstart */ + {0x18, 0x02}, /* hstop */ + {0x19, 0x01}, /* vstrt */ + {0x1a, 0x3d}, /* vstop */ + {0x32, 0xff}, /* href */ + {0xc0, 0xaa}, +}; + +static const u8 bridge_init_ov965x_2[][2] = { + {0x94, 0xaa}, + {0xf1, 0x60}, + {0xe5, 0x04}, + {0xc0, 0x50}, + {0xc1, 0x3c}, + {0x8c, 0x00}, + {0x8d, 0x1c}, + {0x34, 0x05}, + + {0xc2, 0x0c}, + {0xc3, 0xf9}, + {0xda, 0x01}, + {0x50, 0x00}, + {0x51, 0xa0}, + {0x52, 0x3c}, + {0x53, 0x00}, + {0x54, 0x00}, + {0x55, 0x00}, + {0x57, 0x00}, + {0x5c, 0x00}, + {0x5a, 0xa0}, + {0x5b, 0x78}, + {0x35, 0x02}, + {0xd9, 0x10}, + {0x94, 0x11}, +}; + +static const u8 sensor_init_ov965x_2[][2] = { + {0x3b, 0xc4}, + {0x1e, 0x04}, /* mvfp */ + {0x13, 0xe0}, /* com8 */ + {0x00, 0x00}, /* gain */ + {0x13, 0xe7}, /* com8 - everything (AGC, AWB and AEC) */ + {0x11, 0x03}, /* clkrc */ + {0x6b, 0x5a}, /* dblv */ + {0x6a, 0x05}, + {0xc5, 0x07}, + {0xa2, 0x4b}, + {0xa3, 0x3e}, + {0x2d, 0x00}, + {0xff, 0x42}, /* read 42, write ff 00 */ + {0x42, 0xc0}, + {0x2d, 0x00}, + {0xff, 0x42}, /* read 42, write ff 00 */ + {0x42, 0xc1}, + {0x3f, 0x01}, + {0xff, 0x42}, /* read 42, write ff 00 */ + {0x42, 0xc1}, + {0x4f, 0x98}, + {0x50, 0x98}, + {0x51, 0x00}, + {0x52, 0x28}, + {0x53, 0x70}, + {0x54, 0x98}, + {0x58, 0x1a}, + {0xff, 0x41}, /* read 41, write ff 00 */ + {0x41, 0x40}, /* com16 */ + {0x56, 0x40}, + {0x55, 0x8f}, + {0x10, 0x25}, /* aech - exposure high bits */ + {0xff, 0x13}, /* read 13, write ff 00 */ + {0x13, 0xe7}, /* com8 - everything (AGC, AWB and AEC) */ +}; + +static const u8 bridge_start_ov965x[][2] = { + {0xc2, 0x4c}, + {0xc3, 0xf9}, + {0x50, 0x00}, + {0x51, 0xa0}, + {0x52, 0x78}, + {0x53, 0x00}, + {0x54, 0x00}, + {0x55, 0x00}, + {0x57, 0x00}, + {0x5c, 0x00}, + {0x5a, 0x28}, + {0x5b, 0x1e}, + {0x35, 0x00}, + {0xd9, 0x21}, + {0x94, 0x11}, +}; + +static const u8 sensor_start_ov965x[][2] = { + {0x3b, 0xe4}, + {0x1e, 0x04}, /* mvfp */ + {0x13, 0xe0}, /* com8 */ + {0x00, 0x00}, + {0x13, 0xe7}, /* com8 - everything (AGC, AWB and AEC) */ + {0x11, 0x01}, /* clkrc */ + {0x6b, 0x5a}, /* dblv */ + {0x6a, 0x02}, + {0xc5, 0x03}, + {0xa2, 0x96}, + {0xa3, 0x7d}, + {0xff, 0x13}, /* read 13, write ff 00 */ + {0x13, 0xe7}, + {0x3a, 0x80}, + {0xff, 0x42}, /* read 42, write ff 00 */ + {0x42, 0xc1}, +}; + + +static void ov534_reg_write(struct gspca_dev *gspca_dev, u16 reg, u8 val) +{ + struct usb_device *udev = gspca_dev->dev; + int ret; + + PDEBUG(D_USBO, "reg=0x%04x, val=0%02x", reg, val); + gspca_dev->usb_buf[0] = val; + ret = usb_control_msg(udev, + usb_sndctrlpipe(udev, 0), + 0x01, + USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, + 0x00, reg, gspca_dev->usb_buf, 1, CTRL_TIMEOUT); + if (ret < 0) + PDEBUG(D_ERR, "write failed"); +} + +static u8 ov534_reg_read(struct gspca_dev *gspca_dev, u16 reg) +{ + struct usb_device *udev = gspca_dev->dev; + int ret; + + ret = usb_control_msg(udev, + usb_rcvctrlpipe(udev, 0), + 0x01, + USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, + 0x00, reg, gspca_dev->usb_buf, 1, CTRL_TIMEOUT); + PDEBUG(D_USBI, "reg=0x%04x, data=0x%02x", reg, gspca_dev->usb_buf[0]); + if (ret < 0) + PDEBUG(D_ERR, "read failed"); + return gspca_dev->usb_buf[0]; +} + +/* Two bits control LED: 0x21 bit 7 and 0x23 bit 7. + * (direction and output)? */ +static void ov534_set_led(struct gspca_dev *gspca_dev, int status) +{ + u8 data; + + PDEBUG(D_CONF, "led status: %d", status); + + data = ov534_reg_read(gspca_dev, 0x21); + data |= 0x80; + ov534_reg_write(gspca_dev, 0x21, data); + + data = ov534_reg_read(gspca_dev, 0x23); + if (status) + data |= 0x80; + else + data &= ~0x80; + + ov534_reg_write(gspca_dev, 0x23, data); + + if (!status) { + data = ov534_reg_read(gspca_dev, 0x21); + data &= ~0x80; + ov534_reg_write(gspca_dev, 0x21, data); + } +} + +static int sccb_check_status(struct gspca_dev *gspca_dev) +{ + u8 data; + int i; + + for (i = 0; i < 5; i++) { + data = ov534_reg_read(gspca_dev, OV534_REG_STATUS); + + switch (data) { + case 0x00: + return 1; + case 0x04: + return 0; + case 0x03: + break; + default: + PDEBUG(D_ERR, "sccb status 0x%02x, attempt %d/5", + data, i + 1); + } + } + return 0; +} + +static void sccb_reg_write(struct gspca_dev *gspca_dev, u8 reg, u8 val) +{ + PDEBUG(D_USBO, "reg: 0x%02x, val: 0x%02x", reg, val); + ov534_reg_write(gspca_dev, OV534_REG_SUBADDR, reg); + ov534_reg_write(gspca_dev, OV534_REG_WRITE, val); + ov534_reg_write(gspca_dev, OV534_REG_OPERATION, OV534_OP_WRITE_3); + + if (!sccb_check_status(gspca_dev)) + PDEBUG(D_ERR, "sccb_reg_write failed"); +} + +static u8 sccb_reg_read(struct gspca_dev *gspca_dev, u16 reg) +{ + ov534_reg_write(gspca_dev, OV534_REG_SUBADDR, reg); + ov534_reg_write(gspca_dev, OV534_REG_OPERATION, OV534_OP_WRITE_2); + if (!sccb_check_status(gspca_dev)) + PDEBUG(D_ERR, "sccb_reg_read failed 1"); + + ov534_reg_write(gspca_dev, OV534_REG_OPERATION, OV534_OP_READ_2); + if (!sccb_check_status(gspca_dev)) + PDEBUG(D_ERR, "sccb_reg_read failed 2"); + + return ov534_reg_read(gspca_dev, OV534_REG_READ); +} + +/* output a bridge sequence (reg - val) */ +static void reg_w_array(struct gspca_dev *gspca_dev, + const u8 (*data)[2], int len) +{ + while (--len >= 0) { + ov534_reg_write(gspca_dev, (*data)[0], (*data)[1]); + data++; + } +} + +/* output a sensor sequence (reg - val) */ +static void sccb_w_array(struct gspca_dev *gspca_dev, + const u8 (*data)[2], int len) +{ + while (--len >= 0) { + if ((*data)[0] != 0xff) { + sccb_reg_write(gspca_dev, (*data)[0], (*data)[1]); + } else { + sccb_reg_read(gspca_dev, (*data)[1]); + sccb_reg_write(gspca_dev, 0xff, 0x00); + } + data++; + } +} + /* set framerate */ static void ov534_set_frame_rate(struct gspca_dev *gspca_dev) { @@ -346,37 +694,15 @@ static void ov534_set_frame_rate(struct gspca_dev *gspca_dev) PDEBUG(D_PROBE, "frame_rate: %d", fr); } -/* setup method */ -static void ov534_setup(struct gspca_dev *gspca_dev) -{ - int i; - - /* Initialize bridge chip */ - for (i = 0; i < ARRAY_SIZE(ov534_reg_initdata); i++) - ov534_reg_write(gspca_dev, ov534_reg_initdata[i][0], - ov534_reg_initdata[i][1]); - - PDEBUG(D_PROBE, "sensor is ov%02x%02x", - sccb_reg_read(gspca_dev, 0x0a), - sccb_reg_read(gspca_dev, 0x0b)); - - ov534_set_led(gspca_dev, 1); - - /* Initialize sensor */ - for (i = 0; i < ARRAY_SIZE(ov772x_reg_initdata); i++) - sccb_reg_write(gspca_dev, ov772x_reg_initdata[i][0], - ov772x_reg_initdata[i][1]); - - ov534_reg_write(gspca_dev, 0xe0, 0x09); - ov534_set_led(gspca_dev, 0); -} - /* this function is called at probe time */ static int sd_config(struct gspca_dev *gspca_dev, const struct usb_device_id *id) { + struct sd *sd = (struct sd *) gspca_dev; struct cam *cam; + sd->sensor = id->driver_info; + cam = &gspca_dev->cam; cam->cam_mode = vga_mode; @@ -391,26 +717,102 @@ static int sd_config(struct gspca_dev *gspca_dev, /* this function is called at probe and resume time */ static int sd_init(struct gspca_dev *gspca_dev) { - ov534_setup(gspca_dev); - ov534_set_frame_rate(gspca_dev); + struct sd *sd = (struct sd *) gspca_dev; + u16 sensor_id; + static const u8 sensor_addr[2] = { + 0x42, /* 0 SENSOR_OV772X */ + 0x60, /* 1 SENSOR_OV965X */ + }; + + /* reset bridge */ + ov534_reg_write(gspca_dev, 0xe7, 0x3a); + ov534_reg_write(gspca_dev, 0xe0, 0x08); + msleep(100); + + /* initialize the sensor address */ + ov534_reg_write(gspca_dev, OV534_REG_ADDRESS, + sensor_addr[sd->sensor]); + + /* reset sensor */ + sccb_reg_write(gspca_dev, 0x12, 0x80); + msleep(10); + + /* probe the sensor */ + sccb_reg_read(gspca_dev, 0x0a); + sensor_id = sccb_reg_read(gspca_dev, 0x0a) << 8; + sccb_reg_read(gspca_dev, 0x0b); + sensor_id |= sccb_reg_read(gspca_dev, 0x0b); + PDEBUG(D_PROBE, "Sensor ID: %04x", sensor_id); + + /* initialize */ + switch (sd->sensor) { + case SENSOR_OV772X: + reg_w_array(gspca_dev, bridge_init_ov722x, + ARRAY_SIZE(bridge_init_ov722x)); + ov534_set_led(gspca_dev, 1); + sccb_w_array(gspca_dev, sensor_init_ov722x, + ARRAY_SIZE(sensor_init_ov722x)); + ov534_reg_write(gspca_dev, 0xe0, 0x09); + ov534_set_led(gspca_dev, 0); + ov534_set_frame_rate(gspca_dev); + break; + default: +/* case SENSOR_OV965X: */ + reg_w_array(gspca_dev, bridge_init_ov965x, + ARRAY_SIZE(bridge_init_ov965x)); + sccb_w_array(gspca_dev, sensor_init_ov965x, + ARRAY_SIZE(sensor_init_ov965x)); + reg_w_array(gspca_dev, bridge_init_ov965x_2, + ARRAY_SIZE(bridge_init_ov965x_2)); + sccb_w_array(gspca_dev, sensor_init_ov965x_2, + ARRAY_SIZE(sensor_init_ov965x_2)); + ov534_reg_write(gspca_dev, 0xe0, 0x00); + ov534_reg_write(gspca_dev, 0xe0, 0x01); + ov534_set_led(gspca_dev, 0); + ov534_reg_write(gspca_dev, 0xe0, 0x00); + } return 0; } static int sd_start(struct gspca_dev *gspca_dev) { - /* start streaming data */ - ov534_set_led(gspca_dev, 1); - ov534_reg_write(gspca_dev, 0xe0, 0x00); + struct sd *sd = (struct sd *) gspca_dev; + switch (sd->sensor) { + case SENSOR_OV772X: + ov534_set_led(gspca_dev, 1); + ov534_reg_write(gspca_dev, 0xe0, 0x00); + break; + default: +/* case SENSOR_OV965X: */ + reg_w_array(gspca_dev, bridge_start_ov965x, + ARRAY_SIZE(bridge_start_ov965x)); + sccb_w_array(gspca_dev, sensor_start_ov965x, + ARRAY_SIZE(sensor_start_ov965x)); + ov534_reg_write(gspca_dev, 0xe0, 0x00); + ov534_set_led(gspca_dev, 1); +/*fixme: other sensor start omitted*/ + } return 0; } static void sd_stopN(struct gspca_dev *gspca_dev) { - /* stop streaming data */ - ov534_reg_write(gspca_dev, 0xe0, 0x09); - ov534_set_led(gspca_dev, 0); + struct sd *sd = (struct sd *) gspca_dev; + + switch (sd->sensor) { + case SENSOR_OV772X: + ov534_reg_write(gspca_dev, 0xe0, 0x09); + ov534_set_led(gspca_dev, 0); + break; + default: +/* case SENSOR_OV965X: */ + ov534_reg_write(gspca_dev, 0xe0, 0x01); + ov534_set_led(gspca_dev, 0); + ov534_reg_write(gspca_dev, 0xe0, 0x00); + break; + } } /* Values for bmHeaderInfo (Video and Still Image Payload Headers, 2.4.3.3) */ @@ -555,7 +957,8 @@ static const struct sd_desc sd_desc = { /* -- module initialisation -- */ static const __devinitdata struct usb_device_id device_table[] = { - {USB_DEVICE(0x1415, 0x2000)}, /* Sony HD Eye for PS3 (SLEH 00201) */ + {USB_DEVICE(0x06f8, 0x3003), .driver_info = SENSOR_OV965X}, + {USB_DEVICE(0x1415, 0x2000), .driver_info = SENSOR_OV772X}, {} }; -- cgit v1.2.3 From 80c6e358c1b6da0b9aa97e10c82317b7104821bb Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 19 Mar 2009 19:26:23 -0300 Subject: V4L/DVB (11109): au0828: Fix compilation when VIDEO_ADV_DEBUG = n As reported by Kyle McMartin and Randy Dunlap: drivers/media/video/au0828/au0828-video.c:1438: error: 'const struct v4l2_subdev_core_ops' has no member named 'g_register' drivers/media/video/au0828/au0828-video.c:1453: error: 'const struct v4l2_subdev_core_ops' has no member named 's_register' This patch properly implements those two API ioctls only when debug is enabled. Cc: Devin Heitmueller Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/au0828/au0828-video.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/au0828/au0828-video.c b/drivers/media/video/au0828/au0828-video.c index 5de968e128f6..d3a388af46e7 100644 --- a/drivers/media/video/au0828/au0828-video.c +++ b/drivers/media/video/au0828/au0828-video.c @@ -1427,6 +1427,7 @@ static int vidioc_streamoff(struct file *file, void *priv, return 0; } +#ifdef CONFIG_VIDEO_ADV_DEBUG static int vidioc_g_register(struct file *file, void *priv, struct v4l2_dbg_register *reg) { @@ -1457,6 +1458,7 @@ static int vidioc_s_register(struct file *file, void *priv, } return 0; } +#endif static int vidioc_reqbufs(struct file *file, void *priv, struct v4l2_requestbuffers *rb) @@ -1578,8 +1580,8 @@ static const struct v4l2_ioctl_ops video_ioctl_ops = { #ifdef CONFIG_VIDEO_ADV_DEBUG .vidioc_g_register = vidioc_g_register, .vidioc_s_register = vidioc_s_register, - .vidioc_g_chip_ident = vidioc_g_chip_ident, #endif + .vidioc_g_chip_ident = vidioc_g_chip_ident, #ifdef CONFIG_VIDEO_V4L1_COMPAT .vidiocgmbuf = vidiocgmbuf, #endif -- cgit v1.2.3 From 6a39a38e338527effb2703e76aedd856cc7b3683 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 19 Mar 2009 21:03:09 -0300 Subject: V4L/DVB (11110): au8522/au0828: Fix Kconfig dependencies au8522 is now dependent of V4L2, as reported by Randy Dunlap : au8522_decoder.c:(.text+0x199898): undefined reference to `v4l2_ctrl_query_fill' au8522_decoder.c:(.text+0x1998b3): undefined reference to `v4l2_ctrl_query_fill' au8522_decoder.c:(.text+0x199944): undefined reference to `v4l2_device_unregister_subdev' au8522_decoder.c:(.text+0x19997c): undefined reference to `v4l2_chip_ident_i2c_client' au8522_decoder.c:(.text+0x199f1e): undefined reference to `v4l2_i2c_subdev_init' Cc: Devin Heitmueller Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/Kconfig | 2 +- drivers/media/video/au0828/Kconfig | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/dvb/frontends/Kconfig b/drivers/media/dvb/frontends/Kconfig index 5c78f6329d68..a206cee23f73 100644 --- a/drivers/media/dvb/frontends/Kconfig +++ b/drivers/media/dvb/frontends/Kconfig @@ -437,7 +437,7 @@ config DVB_S5H1409 config DVB_AU8522 tristate "Auvitek AU8522 based" - depends on DVB_CORE && I2C + depends on DVB_CORE && I2C && VIDEO_V4L2 default m if DVB_FE_CUSTOMISE help An ATSC 8VSB and QAM64/256 tuner module. Say Y when you want diff --git a/drivers/media/video/au0828/Kconfig b/drivers/media/video/au0828/Kconfig index 20993ae17d36..551f9ba63876 100644 --- a/drivers/media/video/au0828/Kconfig +++ b/drivers/media/video/au0828/Kconfig @@ -1,7 +1,7 @@ config VIDEO_AU0828 tristate "Auvitek AU0828 support" - depends on I2C && INPUT && DVB_CORE && USB + depends on I2C && INPUT && DVB_CORE && USB && VIDEO_V4L2 select I2C_ALGOBIT select VIDEO_TVEEPROM select DVB_AU8522 if !DVB_FE_CUSTOMISE -- cgit v1.2.3 From 2da9479aaa331bdfaadab0d14f75fd76bfa5e56a Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 6 Feb 2009 18:59:35 -0300 Subject: V4L/DVB (11112): v4l2-subdev: add support for TRY_FMT, ENUM_FMT and G/S_PARM. These ops are used by the ov7670 driver, so these need to be added. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/v4l2-subdev.c | 8 ++++++++ include/media/v4l2-subdev.h | 6 +++++- 2 files changed, 13 insertions(+), 1 deletion(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/v4l2-subdev.c b/drivers/media/video/v4l2-subdev.c index 923ec8d01991..dc881671d536 100644 --- a/drivers/media/video/v4l2-subdev.c +++ b/drivers/media/video/v4l2-subdev.c @@ -98,6 +98,10 @@ int v4l2_subdev_command(struct v4l2_subdev *sd, unsigned cmd, void *arg) return v4l2_subdev_call(sd, video, g_vbi_data, arg); case VIDIOC_G_SLICED_VBI_CAP: return v4l2_subdev_call(sd, video, g_sliced_vbi_cap, arg); + case VIDIOC_ENUM_FMT: + return v4l2_subdev_call(sd, video, enum_fmt, arg); + case VIDIOC_TRY_FMT: + return v4l2_subdev_call(sd, video, try_fmt, arg); case VIDIOC_S_FMT: return v4l2_subdev_call(sd, video, s_fmt, arg); case VIDIOC_G_FMT: @@ -112,6 +116,10 @@ int v4l2_subdev_command(struct v4l2_subdev *sd, unsigned cmd, void *arg) return v4l2_subdev_call(sd, video, s_stream, 1); case VIDIOC_STREAMOFF: return v4l2_subdev_call(sd, video, s_stream, 0); + case VIDIOC_S_PARM: + return v4l2_subdev_call(sd, video, s_parm, arg); + case VIDIOC_G_PARM: + return v4l2_subdev_call(sd, video, g_parm, arg); default: return v4l2_subdev_call(sd, core, ioctl, cmd, arg); diff --git a/include/media/v4l2-subdev.h b/include/media/v4l2-subdev.h index 1b97a2c33a73..d7a72d2d1f00 100644 --- a/include/media/v4l2-subdev.h +++ b/include/media/v4l2-subdev.h @@ -118,8 +118,12 @@ struct v4l2_subdev_video_ops { int (*querystd)(struct v4l2_subdev *sd, v4l2_std_id *std); int (*g_input_status)(struct v4l2_subdev *sd, u32 *status); int (*s_stream)(struct v4l2_subdev *sd, int enable); - int (*s_fmt)(struct v4l2_subdev *sd, struct v4l2_format *fmt); + int (*enum_fmt)(struct v4l2_subdev *sd, struct v4l2_fmtdesc *fmtdesc); int (*g_fmt)(struct v4l2_subdev *sd, struct v4l2_format *fmt); + int (*try_fmt)(struct v4l2_subdev *sd, struct v4l2_format *fmt); + int (*s_fmt)(struct v4l2_subdev *sd, struct v4l2_format *fmt); + int (*g_parm)(struct v4l2_subdev *sd, struct v4l2_streamparm *param); + int (*s_parm)(struct v4l2_subdev *sd, struct v4l2_streamparm *param); }; struct v4l2_subdev_ops { -- cgit v1.2.3 From 14386c2b7793652a656021a3345cff3b0f6771f9 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 18 Mar 2009 13:01:06 -0300 Subject: V4L/DVB (11113): ov7670: convert to v4l2_subdev Signed-off-by: Hans Verkuil Acked-by: Jonathan Corbet Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/ov7670.c | 376 +++++++++++++++++++++---------------------- 1 file changed, 180 insertions(+), 196 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/ov7670.c b/drivers/media/video/ov7670.c index 003120c07482..78bd430716c8 100644 --- a/drivers/media/video/ov7670.c +++ b/drivers/media/video/ov7670.c @@ -12,18 +12,22 @@ */ #include #include -#include +#include #include #include -#include +#include #include -#include +#include MODULE_AUTHOR("Jonathan Corbet "); MODULE_DESCRIPTION("A low-level driver for OmniVision ov7670 sensors"); MODULE_LICENSE("GPL"); +static int debug; +module_param(debug, bool, 0644); +MODULE_PARM_DESC(debug, "Debug level (0-1)"); + /* * Basic window sizes. These probably belong somewhere more globally * useful. @@ -189,11 +193,16 @@ MODULE_LICENSE("GPL"); */ struct ov7670_format_struct; /* coming later */ struct ov7670_info { + struct v4l2_subdev sd; struct ov7670_format_struct *fmt; /* Current format */ unsigned char sat; /* Saturation value */ int hue; /* Hue value */ }; +static inline struct ov7670_info *to_state(struct v4l2_subdev *sd) +{ + return container_of(sd, struct ov7670_info, sd); +} @@ -400,24 +409,27 @@ static struct regval_list ov7670_fmt_raw[] = { * Low-level register I/O. */ -static int ov7670_read(struct i2c_client *c, unsigned char reg, +static int ov7670_read(struct v4l2_subdev *sd, unsigned char reg, unsigned char *value) { + struct i2c_client *client = v4l2_get_subdevdata(sd); int ret; - ret = i2c_smbus_read_byte_data(c, reg); + ret = i2c_smbus_read_byte_data(client, reg); if (ret >= 0) { - *value = (unsigned char) ret; + *value = (unsigned char)ret; ret = 0; } return ret; } -static int ov7670_write(struct i2c_client *c, unsigned char reg, +static int ov7670_write(struct v4l2_subdev *sd, unsigned char reg, unsigned char value) { - int ret = i2c_smbus_write_byte_data(c, reg, value); + struct i2c_client *client = v4l2_get_subdevdata(sd); + int ret = i2c_smbus_write_byte_data(client, reg, value); + if (reg == REG_COM7 && (value & COM7_RESET)) msleep(2); /* Wait for reset to run */ return ret; @@ -427,10 +439,10 @@ static int ov7670_write(struct i2c_client *c, unsigned char reg, /* * Write a list of register settings; ff/ff stops the process. */ -static int ov7670_write_array(struct i2c_client *c, struct regval_list *vals) +static int ov7670_write_array(struct v4l2_subdev *sd, struct regval_list *vals) { while (vals->reg_num != 0xff || vals->value != 0xff) { - int ret = ov7670_write(c, vals->reg_num, vals->value); + int ret = ov7670_write(sd, vals->reg_num, vals->value); if (ret < 0) return ret; vals++; @@ -442,34 +454,35 @@ static int ov7670_write_array(struct i2c_client *c, struct regval_list *vals) /* * Stuff that knows about the sensor. */ -static void ov7670_reset(struct i2c_client *client) +static int ov7670_reset(struct v4l2_subdev *sd, u32 val) { - ov7670_write(client, REG_COM7, COM7_RESET); + ov7670_write(sd, REG_COM7, COM7_RESET); msleep(1); + return 0; } -static int ov7670_init(struct i2c_client *client) +static int ov7670_init(struct v4l2_subdev *sd, u32 val) { - return ov7670_write_array(client, ov7670_default_regs); + return ov7670_write_array(sd, ov7670_default_regs); } -static int ov7670_detect(struct i2c_client *client) +static int ov7670_detect(struct v4l2_subdev *sd) { unsigned char v; int ret; - ret = ov7670_init(client); + ret = ov7670_init(sd, 0); if (ret < 0) return ret; - ret = ov7670_read(client, REG_MIDH, &v); + ret = ov7670_read(sd, REG_MIDH, &v); if (ret < 0) return ret; if (v != 0x7f) /* OV manuf. id. */ return -ENODEV; - ret = ov7670_read(client, REG_MIDL, &v); + ret = ov7670_read(sd, REG_MIDL, &v); if (ret < 0) return ret; if (v != 0xa2) @@ -477,12 +490,12 @@ static int ov7670_detect(struct i2c_client *client) /* * OK, we know we have an OmniVision chip...but which one? */ - ret = ov7670_read(client, REG_PID, &v); + ret = ov7670_read(sd, REG_PID, &v); if (ret < 0) return ret; if (v != 0x76) /* PID + VER = 0x76 / 0x73 */ return -ENODEV; - ret = ov7670_read(client, REG_VER, &v); + ret = ov7670_read(sd, REG_VER, &v); if (ret < 0) return ret; if (v != 0x73) /* PID + VER = 0x76 / 0x73 */ @@ -627,7 +640,7 @@ static struct ov7670_win_size { /* * Store a set of start/stop values into the camera. */ -static int ov7670_set_hw(struct i2c_client *client, int hstart, int hstop, +static int ov7670_set_hw(struct v4l2_subdev *sd, int hstart, int hstop, int vstart, int vstop) { int ret; @@ -637,26 +650,26 @@ static int ov7670_set_hw(struct i2c_client *client, int hstart, int hstop, * hstart are in href[2:0], bottom 3 of hstop in href[5:3]. There is * a mystery "edge offset" value in the top two bits of href. */ - ret = ov7670_write(client, REG_HSTART, (hstart >> 3) & 0xff); - ret += ov7670_write(client, REG_HSTOP, (hstop >> 3) & 0xff); - ret += ov7670_read(client, REG_HREF, &v); + ret = ov7670_write(sd, REG_HSTART, (hstart >> 3) & 0xff); + ret += ov7670_write(sd, REG_HSTOP, (hstop >> 3) & 0xff); + ret += ov7670_read(sd, REG_HREF, &v); v = (v & 0xc0) | ((hstop & 0x7) << 3) | (hstart & 0x7); msleep(10); - ret += ov7670_write(client, REG_HREF, v); + ret += ov7670_write(sd, REG_HREF, v); /* * Vertical: similar arrangement, but only 10 bits. */ - ret += ov7670_write(client, REG_VSTART, (vstart >> 2) & 0xff); - ret += ov7670_write(client, REG_VSTOP, (vstop >> 2) & 0xff); - ret += ov7670_read(client, REG_VREF, &v); + ret += ov7670_write(sd, REG_VSTART, (vstart >> 2) & 0xff); + ret += ov7670_write(sd, REG_VSTOP, (vstop >> 2) & 0xff); + ret += ov7670_read(sd, REG_VREF, &v); v = (v & 0xf0) | ((vstop & 0x3) << 2) | (vstart & 0x3); msleep(10); - ret += ov7670_write(client, REG_VREF, v); + ret += ov7670_write(sd, REG_VREF, v); return ret; } -static int ov7670_enum_fmt(struct i2c_client *c, struct v4l2_fmtdesc *fmt) +static int ov7670_enum_fmt(struct v4l2_subdev *sd, struct v4l2_fmtdesc *fmt) { struct ov7670_format_struct *ofmt; @@ -671,7 +684,8 @@ static int ov7670_enum_fmt(struct i2c_client *c, struct v4l2_fmtdesc *fmt) } -static int ov7670_try_fmt(struct i2c_client *c, struct v4l2_format *fmt, +static int ov7670_try_fmt_internal(struct v4l2_subdev *sd, + struct v4l2_format *fmt, struct ov7670_format_struct **ret_fmt, struct ov7670_win_size **ret_wsize) { @@ -715,18 +729,23 @@ static int ov7670_try_fmt(struct i2c_client *c, struct v4l2_format *fmt, return 0; } +static int ov7670_try_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt) +{ + return ov7670_try_fmt_internal(sd, fmt, NULL, NULL); +} + /* * Set a format. */ -static int ov7670_s_fmt(struct i2c_client *c, struct v4l2_format *fmt) +static int ov7670_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt) { int ret; struct ov7670_format_struct *ovfmt; struct ov7670_win_size *wsize; - struct ov7670_info *info = i2c_get_clientdata(c); - unsigned char com7, clkrc; + struct ov7670_info *info = to_state(sd); + unsigned char com7, clkrc = 0; - ret = ov7670_try_fmt(c, fmt, &ovfmt, &wsize); + ret = ov7670_try_fmt_internal(sd, fmt, &ovfmt, &wsize); if (ret) return ret; /* @@ -735,7 +754,7 @@ static int ov7670_s_fmt(struct i2c_client *c, struct v4l2_format *fmt) * the colors. */ if (fmt->fmt.pix.pixelformat == V4L2_PIX_FMT_RGB565) { - ret = ov7670_read(c, REG_CLKRC, &clkrc); + ret = ov7670_read(sd, REG_CLKRC, &clkrc); if (ret) return ret; } @@ -747,20 +766,20 @@ static int ov7670_s_fmt(struct i2c_client *c, struct v4l2_format *fmt) */ com7 = ovfmt->regs[0].value; com7 |= wsize->com7_bit; - ov7670_write(c, REG_COM7, com7); + ov7670_write(sd, REG_COM7, com7); /* * Now write the rest of the array. Also store start/stops */ - ov7670_write_array(c, ovfmt->regs + 1); - ov7670_set_hw(c, wsize->hstart, wsize->hstop, wsize->vstart, + ov7670_write_array(sd, ovfmt->regs + 1); + ov7670_set_hw(sd, wsize->hstart, wsize->hstop, wsize->vstart, wsize->vstop); ret = 0; if (wsize->regs) - ret = ov7670_write_array(c, wsize->regs); + ret = ov7670_write_array(sd, wsize->regs); info->fmt = ovfmt; if (fmt->fmt.pix.pixelformat == V4L2_PIX_FMT_RGB565 && ret == 0) - ret = ov7670_write(c, REG_CLKRC, clkrc); + ret = ov7670_write(sd, REG_CLKRC, clkrc); return ret; } @@ -768,7 +787,7 @@ static int ov7670_s_fmt(struct i2c_client *c, struct v4l2_format *fmt) * Implement G/S_PARM. There is a "high quality" mode we could try * to do someday; for now, we just do the frame rate tweak. */ -static int ov7670_g_parm(struct i2c_client *c, struct v4l2_streamparm *parms) +static int ov7670_g_parm(struct v4l2_subdev *sd, struct v4l2_streamparm *parms) { struct v4l2_captureparm *cp = &parms->parm.capture; unsigned char clkrc; @@ -776,7 +795,7 @@ static int ov7670_g_parm(struct i2c_client *c, struct v4l2_streamparm *parms) if (parms->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) return -EINVAL; - ret = ov7670_read(c, REG_CLKRC, &clkrc); + ret = ov7670_read(sd, REG_CLKRC, &clkrc); if (ret < 0) return ret; memset(cp, 0, sizeof(struct v4l2_captureparm)); @@ -788,7 +807,7 @@ static int ov7670_g_parm(struct i2c_client *c, struct v4l2_streamparm *parms) return 0; } -static int ov7670_s_parm(struct i2c_client *c, struct v4l2_streamparm *parms) +static int ov7670_s_parm(struct v4l2_subdev *sd, struct v4l2_streamparm *parms) { struct v4l2_captureparm *cp = &parms->parm.capture; struct v4l2_fract *tpf = &cp->timeperframe; @@ -802,7 +821,7 @@ static int ov7670_s_parm(struct i2c_client *c, struct v4l2_streamparm *parms) /* * CLKRC has a reserved bit, so let's preserve it. */ - ret = ov7670_read(c, REG_CLKRC, &clkrc); + ret = ov7670_read(sd, REG_CLKRC, &clkrc); if (ret < 0) return ret; if (tpf->numerator == 0 || tpf->denominator == 0) @@ -816,7 +835,7 @@ static int ov7670_s_parm(struct i2c_client *c, struct v4l2_streamparm *parms) clkrc = (clkrc & 0x80) | div; tpf->numerator = 1; tpf->denominator = OV7670_FRAME_RATE/div; - return ov7670_write(c, REG_CLKRC, clkrc); + return ov7670_write(sd, REG_CLKRC, clkrc); } @@ -829,7 +848,7 @@ static int ov7670_s_parm(struct i2c_client *c, struct v4l2_streamparm *parms) -static int ov7670_store_cmatrix(struct i2c_client *client, +static int ov7670_store_cmatrix(struct v4l2_subdev *sd, int matrix[CMATRIX_LEN]) { int i, ret; @@ -839,7 +858,7 @@ static int ov7670_store_cmatrix(struct i2c_client *client, * Weird crap seems to exist in the upper part of * the sign bits register, so let's preserve it. */ - ret = ov7670_read(client, REG_CMATRIX_SIGN, &signbits); + ret = ov7670_read(sd, REG_CMATRIX_SIGN, &signbits); signbits &= 0xc0; for (i = 0; i < CMATRIX_LEN; i++) { @@ -858,9 +877,9 @@ static int ov7670_store_cmatrix(struct i2c_client *client, else raw = matrix[i] & 0xff; } - ret += ov7670_write(client, REG_CMATRIX_BASE + i, raw); + ret += ov7670_write(sd, REG_CMATRIX_BASE + i, raw); } - ret += ov7670_write(client, REG_CMATRIX_SIGN, signbits); + ret += ov7670_write(sd, REG_CMATRIX_SIGN, signbits); return ret; } @@ -943,29 +962,29 @@ static void ov7670_calc_cmatrix(struct ov7670_info *info, -static int ov7670_t_sat(struct i2c_client *client, int value) +static int ov7670_t_sat(struct v4l2_subdev *sd, int value) { - struct ov7670_info *info = i2c_get_clientdata(client); + struct ov7670_info *info = to_state(sd); int matrix[CMATRIX_LEN]; int ret; info->sat = value; ov7670_calc_cmatrix(info, matrix); - ret = ov7670_store_cmatrix(client, matrix); + ret = ov7670_store_cmatrix(sd, matrix); return ret; } -static int ov7670_q_sat(struct i2c_client *client, __s32 *value) +static int ov7670_q_sat(struct v4l2_subdev *sd, __s32 *value) { - struct ov7670_info *info = i2c_get_clientdata(client); + struct ov7670_info *info = to_state(sd); *value = info->sat; return 0; } -static int ov7670_t_hue(struct i2c_client *client, int value) +static int ov7670_t_hue(struct v4l2_subdev *sd, int value) { - struct ov7670_info *info = i2c_get_clientdata(client); + struct ov7670_info *info = to_state(sd); int matrix[CMATRIX_LEN]; int ret; @@ -973,14 +992,14 @@ static int ov7670_t_hue(struct i2c_client *client, int value) return -EINVAL; info->hue = value; ov7670_calc_cmatrix(info, matrix); - ret = ov7670_store_cmatrix(client, matrix); + ret = ov7670_store_cmatrix(sd, matrix); return ret; } -static int ov7670_q_hue(struct i2c_client *client, __s32 *value) +static int ov7670_q_hue(struct v4l2_subdev *sd, __s32 *value) { - struct ov7670_info *info = i2c_get_clientdata(client); + struct ov7670_info *info = to_state(sd); *value = info->hue; return 0; @@ -994,8 +1013,7 @@ static unsigned char ov7670_sm_to_abs(unsigned char v) { if ((v & 0x80) == 0) return v + 128; - else - return 128 - (v & 0x7f); + return 128 - (v & 0x7f); } @@ -1003,105 +1021,104 @@ static unsigned char ov7670_abs_to_sm(unsigned char v) { if (v > 127) return v & 0x7f; - else - return (128 - v) | 0x80; + return (128 - v) | 0x80; } -static int ov7670_t_brightness(struct i2c_client *client, int value) +static int ov7670_t_brightness(struct v4l2_subdev *sd, int value) { unsigned char com8 = 0, v; int ret; - ov7670_read(client, REG_COM8, &com8); + ov7670_read(sd, REG_COM8, &com8); com8 &= ~COM8_AEC; - ov7670_write(client, REG_COM8, com8); + ov7670_write(sd, REG_COM8, com8); v = ov7670_abs_to_sm(value); - ret = ov7670_write(client, REG_BRIGHT, v); + ret = ov7670_write(sd, REG_BRIGHT, v); return ret; } -static int ov7670_q_brightness(struct i2c_client *client, __s32 *value) +static int ov7670_q_brightness(struct v4l2_subdev *sd, __s32 *value) { unsigned char v = 0; - int ret = ov7670_read(client, REG_BRIGHT, &v); + int ret = ov7670_read(sd, REG_BRIGHT, &v); *value = ov7670_sm_to_abs(v); return ret; } -static int ov7670_t_contrast(struct i2c_client *client, int value) +static int ov7670_t_contrast(struct v4l2_subdev *sd, int value) { - return ov7670_write(client, REG_CONTRAS, (unsigned char) value); + return ov7670_write(sd, REG_CONTRAS, (unsigned char) value); } -static int ov7670_q_contrast(struct i2c_client *client, __s32 *value) +static int ov7670_q_contrast(struct v4l2_subdev *sd, __s32 *value) { unsigned char v = 0; - int ret = ov7670_read(client, REG_CONTRAS, &v); + int ret = ov7670_read(sd, REG_CONTRAS, &v); *value = v; return ret; } -static int ov7670_q_hflip(struct i2c_client *client, __s32 *value) +static int ov7670_q_hflip(struct v4l2_subdev *sd, __s32 *value) { int ret; unsigned char v = 0; - ret = ov7670_read(client, REG_MVFP, &v); + ret = ov7670_read(sd, REG_MVFP, &v); *value = (v & MVFP_MIRROR) == MVFP_MIRROR; return ret; } -static int ov7670_t_hflip(struct i2c_client *client, int value) +static int ov7670_t_hflip(struct v4l2_subdev *sd, int value) { unsigned char v = 0; int ret; - ret = ov7670_read(client, REG_MVFP, &v); + ret = ov7670_read(sd, REG_MVFP, &v); if (value) v |= MVFP_MIRROR; else v &= ~MVFP_MIRROR; msleep(10); /* FIXME */ - ret += ov7670_write(client, REG_MVFP, v); + ret += ov7670_write(sd, REG_MVFP, v); return ret; } -static int ov7670_q_vflip(struct i2c_client *client, __s32 *value) +static int ov7670_q_vflip(struct v4l2_subdev *sd, __s32 *value) { int ret; unsigned char v = 0; - ret = ov7670_read(client, REG_MVFP, &v); + ret = ov7670_read(sd, REG_MVFP, &v); *value = (v & MVFP_FLIP) == MVFP_FLIP; return ret; } -static int ov7670_t_vflip(struct i2c_client *client, int value) +static int ov7670_t_vflip(struct v4l2_subdev *sd, int value) { unsigned char v = 0; int ret; - ret = ov7670_read(client, REG_MVFP, &v); + ret = ov7670_read(sd, REG_MVFP, &v); if (value) v |= MVFP_FLIP; else v &= ~MVFP_FLIP; msleep(10); /* FIXME */ - ret += ov7670_write(client, REG_MVFP, v); + ret += ov7670_write(sd, REG_MVFP, v); return ret; } static struct ov7670_control { struct v4l2_queryctrl qc; - int (*query)(struct i2c_client *c, __s32 *value); - int (*tweak)(struct i2c_client *c, int value); + int (*query)(struct v4l2_subdev *sd, __s32 *value); + int (*tweak)(struct v4l2_subdev *sd, int value); } ov7670_controls[] = { { @@ -1200,7 +1217,7 @@ static struct ov7670_control *ov7670_find_control(__u32 id) } -static int ov7670_queryctrl(struct i2c_client *client, +static int ov7670_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qc) { struct ov7670_control *ctrl = ov7670_find_control(qc->id); @@ -1211,161 +1228,128 @@ static int ov7670_queryctrl(struct i2c_client *client, return 0; } -static int ov7670_g_ctrl(struct i2c_client *client, struct v4l2_control *ctrl) +static int ov7670_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) { struct ov7670_control *octrl = ov7670_find_control(ctrl->id); int ret; if (octrl == NULL) return -EINVAL; - ret = octrl->query(client, &ctrl->value); + ret = octrl->query(sd, &ctrl->value); if (ret >= 0) return 0; return ret; } -static int ov7670_s_ctrl(struct i2c_client *client, struct v4l2_control *ctrl) +static int ov7670_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) { struct ov7670_control *octrl = ov7670_find_control(ctrl->id); int ret; if (octrl == NULL) return -EINVAL; - ret = octrl->tweak(client, ctrl->value); + ret = octrl->tweak(sd, ctrl->value); if (ret >= 0) return 0; return ret; } +static int ov7670_g_chip_ident(struct v4l2_subdev *sd, + struct v4l2_dbg_chip_ident *chip) +{ + struct i2c_client *client = v4l2_get_subdevdata(sd); + + return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_OV7670, 0); +} + +static int ov7670_command(struct i2c_client *client, unsigned cmd, void *arg) +{ + return v4l2_subdev_command(i2c_get_clientdata(client), cmd, arg); +} +/* ----------------------------------------------------------------------- */ +static const struct v4l2_subdev_core_ops ov7670_core_ops = { + .g_chip_ident = ov7670_g_chip_ident, + .g_ctrl = ov7670_g_ctrl, + .s_ctrl = ov7670_s_ctrl, + .queryctrl = ov7670_queryctrl, + .reset = ov7670_reset, + .init = ov7670_init, +}; +static const struct v4l2_subdev_video_ops ov7670_video_ops = { + .enum_fmt = ov7670_enum_fmt, + .try_fmt = ov7670_try_fmt, + .s_fmt = ov7670_s_fmt, + .s_parm = ov7670_s_parm, + .g_parm = ov7670_g_parm, +}; +static const struct v4l2_subdev_ops ov7670_ops = { + .core = &ov7670_core_ops, + .video = &ov7670_video_ops, +}; -/* - * Basic i2c stuff. - */ -static struct i2c_driver ov7670_driver; +/* ----------------------------------------------------------------------- */ -static int ov7670_attach(struct i2c_adapter *adapter) +static int ov7670_probe(struct i2c_client *client, + const struct i2c_device_id *id) { - int ret; - struct i2c_client *client; + struct v4l2_subdev *sd; struct ov7670_info *info; + int ret; /* * For now: only deal with adapters we recognize. */ - if (adapter->id != I2C_HW_SMBUS_CAFE) + if (client->adapter->id != I2C_HW_SMBUS_CAFE) return -ENODEV; - - client = kzalloc(sizeof (struct i2c_client), GFP_KERNEL); - if (! client) + info = kzalloc(sizeof(struct ov7670_info), GFP_KERNEL); + if (info == NULL) return -ENOMEM; - client->adapter = adapter; - client->addr = OV7670_I2C_ADDR; - client->driver = &ov7670_driver, - strcpy(client->name, "OV7670"); - /* - * Set up our info structure. - */ - info = kzalloc(sizeof (struct ov7670_info), GFP_KERNEL); - if (! info) { - ret = -ENOMEM; - goto out_free; + sd = &info->sd; + v4l2_i2c_subdev_init(sd, client, &ov7670_ops); + + /* Make sure it's an ov7670 */ + ret = ov7670_detect(sd); + if (ret) { + v4l_dbg(1, debug, client, + "chip found @ 0x%x (%s) is not an ov7670 chip.\n", + client->addr << 1, client->adapter->name); + kfree(info); + return ret; } + v4l_info(client, "chip found @ 0x%02x (%s)\n", + client->addr << 1, client->adapter->name); + info->fmt = &ov7670_formats[0]; info->sat = 128; /* Review this */ - i2c_set_clientdata(client, info); - /* - * Make sure it's an ov7670 - */ - ret = ov7670_detect(client); - if (ret) - goto out_free_info; - ret = i2c_attach_client(client); - if (ret) - goto out_free_info; return 0; - - out_free_info: - kfree(info); - out_free: - kfree(client); - return ret; } -static int ov7670_detach(struct i2c_client *client) +static int ov7670_remove(struct i2c_client *client) { - i2c_detach_client(client); - kfree(i2c_get_clientdata(client)); - kfree(client); - return 0; -} + struct v4l2_subdev *sd = i2c_get_clientdata(client); - -static int ov7670_command(struct i2c_client *client, unsigned int cmd, - void *arg) -{ - switch (cmd) { - case VIDIOC_DBG_G_CHIP_IDENT: - return v4l2_chip_ident_i2c_client(client, arg, V4L2_IDENT_OV7670, 0); - - case VIDIOC_INT_RESET: - ov7670_reset(client); - return 0; - - case VIDIOC_INT_INIT: - return ov7670_init(client); - - case VIDIOC_ENUM_FMT: - return ov7670_enum_fmt(client, (struct v4l2_fmtdesc *) arg); - case VIDIOC_TRY_FMT: - return ov7670_try_fmt(client, (struct v4l2_format *) arg, NULL, NULL); - case VIDIOC_S_FMT: - return ov7670_s_fmt(client, (struct v4l2_format *) arg); - case VIDIOC_QUERYCTRL: - return ov7670_queryctrl(client, (struct v4l2_queryctrl *) arg); - case VIDIOC_S_CTRL: - return ov7670_s_ctrl(client, (struct v4l2_control *) arg); - case VIDIOC_G_CTRL: - return ov7670_g_ctrl(client, (struct v4l2_control *) arg); - case VIDIOC_S_PARM: - return ov7670_s_parm(client, (struct v4l2_streamparm *) arg); - case VIDIOC_G_PARM: - return ov7670_g_parm(client, (struct v4l2_streamparm *) arg); - } - return -EINVAL; + v4l2_device_unregister_subdev(sd); + kfree(to_state(sd)); + return 0; } - - -static struct i2c_driver ov7670_driver = { - .driver = { - .name = "ov7670", - }, - .id = I2C_DRIVERID_OV7670, - .attach_adapter = ov7670_attach, - .detach_client = ov7670_detach, - .command = ov7670_command, +static const struct i2c_device_id ov7670_id[] = { + { "ov7670", 0 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, ov7670_id); + +static struct v4l2_i2c_driver_data v4l2_i2c_data = { + .name = "ov7670", + .command = ov7670_command, + .probe = ov7670_probe, + .remove = ov7670_remove, + .legacy_class = I2C_CLASS_TV_ANALOG, + .id_table = ov7670_id, }; - - -/* - * Module initialization - */ -static int __init ov7670_mod_init(void) -{ - printk(KERN_NOTICE "OmniVision ov7670 sensor driver, at your service\n"); - return i2c_add_driver(&ov7670_driver); -} - -static void __exit ov7670_mod_exit(void) -{ - i2c_del_driver(&ov7670_driver); -} - -module_init(ov7670_mod_init); -module_exit(ov7670_mod_exit); -- cgit v1.2.3 From 21508b902b314e0cd9c081a9141b138e96c9f441 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 18 Mar 2009 13:13:09 -0300 Subject: V4L/DVB (11114): cafe_ccic: convert to v4l2_device. Convert this driver to v4l2_device and removed the unnecessary cafe_dev_list. Signed-off-by: Hans Verkuil Acked-by: Jonathan Corbet Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cafe_ccic.c | 158 ++++++++++++++-------------------------- 1 file changed, 54 insertions(+), 104 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/cafe_ccic.c b/drivers/media/video/cafe_ccic.c index 46fd573a4f15..600dde379efe 100644 --- a/drivers/media/video/cafe_ccic.c +++ b/drivers/media/video/cafe_ccic.c @@ -25,7 +25,7 @@ #include #include #include -#include +#include #include #include #include @@ -136,6 +136,7 @@ struct cafe_sio_buffer { */ struct cafe_camera { + struct v4l2_device v4l2_dev; enum cafe_state state; unsigned long flags; /* Buffer status, mainly (dev_lock) */ int users; /* How many open FDs */ @@ -145,7 +146,7 @@ struct cafe_camera * Subsystem structures. */ struct pci_dev *pdev; - struct video_device v4ldev; + struct video_device vdev; struct i2c_adapter i2c_adapter; struct i2c_client *sensor; @@ -196,6 +197,11 @@ struct cafe_camera #define CF_CONFIG_NEEDED 4 /* Must configure hardware */ +static inline struct cafe_camera *to_cam(struct v4l2_device *dev) +{ + return container_of(dev, struct cafe_camera, v4l2_dev); +} + /* * Start over with DMA buffers - dev_lock needed. @@ -238,59 +244,7 @@ static void cafe_set_config_needed(struct cafe_camera *cam, int needed) /* ---------------------------------------------------------------------*/ -/* - * We keep a simple list of known devices to search at open time. - */ -static LIST_HEAD(cafe_dev_list); -static DEFINE_MUTEX(cafe_dev_list_lock); - -static void cafe_add_dev(struct cafe_camera *cam) -{ - mutex_lock(&cafe_dev_list_lock); - list_add_tail(&cam->dev_list, &cafe_dev_list); - mutex_unlock(&cafe_dev_list_lock); -} - -static void cafe_remove_dev(struct cafe_camera *cam) -{ - mutex_lock(&cafe_dev_list_lock); - list_del(&cam->dev_list); - mutex_unlock(&cafe_dev_list_lock); -} - -static struct cafe_camera *cafe_find_dev(int minor) -{ - struct cafe_camera *cam; - mutex_lock(&cafe_dev_list_lock); - list_for_each_entry(cam, &cafe_dev_list, dev_list) { - if (cam->v4ldev.minor == minor) - goto done; - } - cam = NULL; - done: - mutex_unlock(&cafe_dev_list_lock); - return cam; -} - - -static struct cafe_camera *cafe_find_by_pdev(struct pci_dev *pdev) -{ - struct cafe_camera *cam; - - mutex_lock(&cafe_dev_list_lock); - list_for_each_entry(cam, &cafe_dev_list, dev_list) { - if (cam->pdev == pdev) - goto done; - } - cam = NULL; - done: - mutex_unlock(&cafe_dev_list_lock); - return cam; -} - - -/* ------------------------------------------------------------------------ */ /* * Device register I/O */ @@ -481,7 +435,8 @@ static int cafe_smbus_xfer(struct i2c_adapter *adapter, u16 addr, unsigned short flags, char rw, u8 command, int size, union i2c_smbus_data *data) { - struct cafe_camera *cam = i2c_get_adapdata(adapter); + struct v4l2_device *v4l2_dev = i2c_get_adapdata(adapter); + struct cafe_camera *cam = to_cam(v4l2_dev); int ret = -EINVAL; /* @@ -536,7 +491,8 @@ static void cafe_ctlr_power_down(struct cafe_camera *cam); static int cafe_smbus_attach(struct i2c_client *client) { - struct cafe_camera *cam = i2c_get_adapdata(client->adapter); + struct v4l2_device *v4l2_dev = i2c_get_adapdata(client->adapter); + struct cafe_camera *cam = to_cam(v4l2_dev); /* * Don't talk to chips we don't recognize. @@ -550,7 +506,8 @@ static int cafe_smbus_attach(struct i2c_client *client) static int cafe_smbus_detach(struct i2c_client *client) { - struct cafe_camera *cam = i2c_get_adapdata(client->adapter); + struct v4l2_device *v4l2_dev = i2c_get_adapdata(client->adapter); + struct cafe_camera *cam = to_cam(v4l2_dev); if (cam->sensor == client) { cafe_ctlr_stop_dma(cam); @@ -575,7 +532,7 @@ static int cafe_smbus_setup(struct cafe_camera *cam) adap->algo = &cafe_smbus_algo; strcpy(adap->name, "cafe_ccic"); adap->dev.parent = &cam->pdev->dev; - i2c_set_adapdata(adap, cam); + i2c_set_adapdata(adap, &cam->v4l2_dev); ret = i2c_add_adapter(adap); if (ret) printk(KERN_ERR "Unable to register cafe i2c adapter\n"); @@ -809,9 +766,9 @@ static void cafe_ctlr_power_up(struct cafe_camera *cam) * Control 1 is power down, set to 0 to operate. */ cafe_reg_write(cam, REG_GPR, GPR_C1EN|GPR_C0EN); /* pwr up, reset */ -// mdelay(1); /* Marvell says 1ms will do it */ +/* mdelay(1); */ /* Marvell says 1ms will do it */ cafe_reg_write(cam, REG_GPR, GPR_C1EN|GPR_C0EN|GPR_C0); -// mdelay(1); /* Enough? */ +/* mdelay(1); */ /* Enough? */ spin_unlock_irqrestore(&cam->dev_lock, flags); msleep(5); /* Just to be sure */ } @@ -874,7 +831,7 @@ static int cafe_cam_init(struct cafe_camera *cam) if (ret) goto out; cam->sensor_type = chip.ident; -// if (cam->sensor->addr != OV7xx0_SID) { +/* if (cam->sensor->addr != OV7xx0_SID) { */ if (cam->sensor_type != V4L2_IDENT_OV7670) { cam_err(cam, "Unsupported sensor type %d", cam->sensor->addr); ret = -EINVAL; @@ -1474,11 +1431,8 @@ static int cafe_v4l_mmap(struct file *filp, struct vm_area_struct *vma) static int cafe_v4l_open(struct file *filp) { - struct cafe_camera *cam; + struct cafe_camera *cam = video_drvdata(filp); - cam = cafe_find_dev(video_devdata(filp)->minor); - if (cam == NULL) - return -ENODEV; filp->private_data = cam; mutex_lock(&cam->s_mutex); @@ -1532,7 +1486,7 @@ static unsigned int cafe_v4l_poll(struct file *filp, static int cafe_vidioc_queryctrl(struct file *filp, void *priv, struct v4l2_queryctrl *qc) { - struct cafe_camera *cam = filp->private_data; + struct cafe_camera *cam = priv; int ret; mutex_lock(&cam->s_mutex); @@ -1545,7 +1499,7 @@ static int cafe_vidioc_queryctrl(struct file *filp, void *priv, static int cafe_vidioc_g_ctrl(struct file *filp, void *priv, struct v4l2_control *ctrl) { - struct cafe_camera *cam = filp->private_data; + struct cafe_camera *cam = priv; int ret; mutex_lock(&cam->s_mutex); @@ -1558,7 +1512,7 @@ static int cafe_vidioc_g_ctrl(struct file *filp, void *priv, static int cafe_vidioc_s_ctrl(struct file *filp, void *priv, struct v4l2_control *ctrl) { - struct cafe_camera *cam = filp->private_data; + struct cafe_camera *cam = priv; int ret; mutex_lock(&cam->s_mutex); @@ -1745,15 +1699,6 @@ static int cafe_vidioc_s_parm(struct file *filp, void *priv, return ret; } - -static void cafe_v4l_dev_release(struct video_device *vd) -{ - struct cafe_camera *cam = container_of(vd, struct cafe_camera, v4ldev); - - kfree(cam); -} - - /* * This template device holds all of those v4l2 methods; we * clone it for specific real devices. @@ -1800,15 +1745,10 @@ static struct video_device cafe_v4l_template = { .fops = &cafe_v4l_fops, .ioctl_ops = &cafe_v4l_ioctl_ops, - .release = cafe_v4l_dev_release, + .release = video_device_release_empty, }; - - - - - /* ---------------------------------------------------------------------- */ /* * Interrupt handler stuff @@ -2054,10 +1994,10 @@ static void cafe_dfs_cam_setup(struct cafe_camera *cam) if (!cafe_dfs_root) return; - sprintf(fname, "regs-%d", cam->v4ldev.num); + sprintf(fname, "regs-%d", cam->vdev.num); cam->dfs_regs = debugfs_create_file(fname, 0444, cafe_dfs_root, cam, &cafe_dfs_reg_ops); - sprintf(fname, "cam-%d", cam->v4ldev.num); + sprintf(fname, "cam-%d", cam->vdev.num); cam->dfs_cam_regs = debugfs_create_file(fname, 0444, cafe_dfs_root, cam, &cafe_dfs_cam_ops); } @@ -2100,6 +2040,10 @@ static int cafe_pci_probe(struct pci_dev *pdev, cam = kzalloc(sizeof(struct cafe_camera), GFP_KERNEL); if (cam == NULL) goto out; + ret = v4l2_device_register(&pdev->dev, &cam->v4l2_dev); + if (ret) + goto out_free; + mutex_init(&cam->s_mutex); mutex_lock(&cam->s_mutex); spin_lock_init(&cam->dev_lock); @@ -2118,14 +2062,14 @@ static int cafe_pci_probe(struct pci_dev *pdev, */ ret = pci_enable_device(pdev); if (ret) - goto out_free; + goto out_unreg; pci_set_master(pdev); ret = -EIO; cam->regs = pci_iomap(pdev, 0, 0); if (! cam->regs) { printk(KERN_ERR "Unable to ioremap cafe-ccic regs\n"); - goto out_free; + goto out_unreg; } ret = request_irq(pdev->irq, cafe_irq, IRQF_SHARED, "cafe-ccic", cam); if (ret) @@ -2149,13 +2093,15 @@ static int cafe_pci_probe(struct pci_dev *pdev, * Get the v4l2 setup done. */ mutex_lock(&cam->s_mutex); - cam->v4ldev = cafe_v4l_template; - cam->v4ldev.debug = 0; -// cam->v4ldev.debug = V4L2_DEBUG_IOCTL_ARG; - cam->v4ldev.parent = &pdev->dev; - ret = video_register_device(&cam->v4ldev, VFL_TYPE_GRABBER, -1); + cam->vdev = cafe_v4l_template; + cam->vdev.debug = 0; +/* cam->vdev.debug = V4L2_DEBUG_IOCTL_ARG;*/ + cam->vdev.v4l2_dev = &cam->v4l2_dev; + ret = video_register_device(&cam->vdev, VFL_TYPE_GRABBER, -1); if (ret) goto out_smbus; + video_set_drvdata(&cam->vdev, cam); + /* * If so requested, try to get our DMA buffers now. */ @@ -2167,19 +2113,20 @@ static int cafe_pci_probe(struct pci_dev *pdev, cafe_dfs_cam_setup(cam); mutex_unlock(&cam->s_mutex); - cafe_add_dev(cam); return 0; - out_smbus: +out_smbus: cafe_smbus_shutdown(cam); - out_freeirq: +out_freeirq: cafe_ctlr_power_down(cam); free_irq(pdev->irq, cam); - out_iounmap: +out_iounmap: pci_iounmap(pdev, cam->regs); - out_free: +out_free: + v4l2_device_unregister(&cam->v4l2_dev); +out_unreg: kfree(cam); - out: +out: return ret; } @@ -2194,21 +2141,20 @@ static void cafe_shutdown(struct cafe_camera *cam) if (cam->n_sbufs > 0) /* What if they are still mapped? Shouldn't be, but... */ cafe_free_sio_buffers(cam); - cafe_remove_dev(cam); cafe_ctlr_stop_dma(cam); cafe_ctlr_power_down(cam); cafe_smbus_shutdown(cam); cafe_free_dma_bufs(cam); free_irq(cam->pdev->irq, cam); pci_iounmap(cam->pdev, cam->regs); - video_unregister_device(&cam->v4ldev); - /* kfree(cam); done in v4l_release () */ + video_unregister_device(&cam->vdev); } static void cafe_pci_remove(struct pci_dev *pdev) { - struct cafe_camera *cam = cafe_find_by_pdev(pdev); + struct v4l2_device *v4l2_dev = dev_get_drvdata(&pdev->dev); + struct cafe_camera *cam = to_cam(v4l2_dev); if (cam == NULL) { printk(KERN_WARNING "pci_remove on unknown pdev %p\n", pdev); @@ -2218,6 +2164,8 @@ static void cafe_pci_remove(struct pci_dev *pdev) if (cam->users > 0) cam_warn(cam, "Removing a device with users!\n"); cafe_shutdown(cam); + v4l2_device_unregister(&cam->v4l2_dev); + kfree(cam); /* No unlock - it no longer exists */ } @@ -2228,7 +2176,8 @@ static void cafe_pci_remove(struct pci_dev *pdev) */ static int cafe_pci_suspend(struct pci_dev *pdev, pm_message_t state) { - struct cafe_camera *cam = cafe_find_by_pdev(pdev); + struct v4l2_device *v4l2_dev = dev_get_drvdata(&pdev->dev); + struct cafe_camera *cam = to_cam(v4l2_dev); int ret; enum cafe_state cstate; @@ -2246,7 +2195,8 @@ static int cafe_pci_suspend(struct pci_dev *pdev, pm_message_t state) static int cafe_pci_resume(struct pci_dev *pdev) { - struct cafe_camera *cam = cafe_find_by_pdev(pdev); + struct v4l2_device *v4l2_dev = dev_get_drvdata(&pdev->dev); + struct cafe_camera *cam = to_cam(v4l2_dev); int ret = 0; ret = pci_restore_state(pdev); -- cgit v1.2.3 From 8bcfd7af902eaa7c0029082247fe0682ce0c1a5b Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 18 Mar 2009 13:16:44 -0300 Subject: V4L/DVB (11115): cafe_ccic: use v4l2_subdev to talk to the ov7670 sensor. Signed-off-by: Hans Verkuil Acked-by: Jonathan Corbet Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cafe_ccic.c | 106 ++++++++++++---------------------------- 1 file changed, 32 insertions(+), 74 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/cafe_ccic.c b/drivers/media/video/cafe_ccic.c index 600dde379efe..3363e501d6d7 100644 --- a/drivers/media/video/cafe_ccic.c +++ b/drivers/media/video/cafe_ccic.c @@ -148,7 +148,8 @@ struct cafe_camera struct pci_dev *pdev; struct video_device vdev; struct i2c_adapter i2c_adapter; - struct i2c_client *sensor; + struct v4l2_subdev *sensor; + unsigned short sensor_addr; unsigned char __iomem *regs; struct list_head dev_list; /* link to other devices */ @@ -196,6 +197,8 @@ struct cafe_camera #define CF_DMA_ACTIVE 3 /* A frame is incoming */ #define CF_CONFIG_NEEDED 4 /* Must configure hardware */ +#define sensor_call(cam, o, f, args...) \ + v4l2_subdev_call(cam->sensor, o, f, ##args) static inline struct cafe_camera *to_cam(struct v4l2_device *dev) { @@ -439,14 +442,6 @@ static int cafe_smbus_xfer(struct i2c_adapter *adapter, u16 addr, struct cafe_camera *cam = to_cam(v4l2_dev); int ret = -EINVAL; - /* - * Refuse to talk to anything but OV cam chips. We should - * never even see an attempt to do so, but one never knows. - */ - if (cam->sensor && addr != cam->sensor->addr) { - cam_err(cam, "funky smbus addr %d\n", addr); - return -EINVAL; - } /* * This interface would appear to only do byte data ops. OK * it can do word too, but the cam chip has no use for that. @@ -485,40 +480,9 @@ static struct i2c_algorithm cafe_smbus_algo = { }; /* Somebody is on the bus */ -static int cafe_cam_init(struct cafe_camera *cam); static void cafe_ctlr_stop_dma(struct cafe_camera *cam); static void cafe_ctlr_power_down(struct cafe_camera *cam); -static int cafe_smbus_attach(struct i2c_client *client) -{ - struct v4l2_device *v4l2_dev = i2c_get_adapdata(client->adapter); - struct cafe_camera *cam = to_cam(v4l2_dev); - - /* - * Don't talk to chips we don't recognize. - */ - if (client->driver->id == I2C_DRIVERID_OV7670) { - cam->sensor = client; - return cafe_cam_init(cam); - } - return -EINVAL; -} - -static int cafe_smbus_detach(struct i2c_client *client) -{ - struct v4l2_device *v4l2_dev = i2c_get_adapdata(client->adapter); - struct cafe_camera *cam = to_cam(v4l2_dev); - - if (cam->sensor == client) { - cafe_ctlr_stop_dma(cam); - cafe_ctlr_power_down(cam); - cam_err(cam, "lost the sensor!\n"); - cam->sensor = NULL; /* Bummer, no camera */ - cam->state = S_NOTREADY; - } - return 0; -} - static int cafe_smbus_setup(struct cafe_camera *cam) { struct i2c_adapter *adap = &cam->i2c_adapter; @@ -527,8 +491,6 @@ static int cafe_smbus_setup(struct cafe_camera *cam) cafe_smbus_enable_irq(cam); adap->id = I2C_HW_SMBUS_CAFE; adap->owner = THIS_MODULE; - adap->client_register = cafe_smbus_attach; - adap->client_unregister = cafe_smbus_detach; adap->algo = &cafe_smbus_algo; strcpy(adap->name, "cafe_ccic"); adap->dev.parent = &cam->pdev->dev; @@ -790,23 +752,9 @@ static void cafe_ctlr_power_down(struct cafe_camera *cam) * Communications with the sensor. */ -static int __cafe_cam_cmd(struct cafe_camera *cam, int cmd, void *arg) -{ - struct i2c_client *sc = cam->sensor; - int ret; - - if (sc == NULL || sc->driver == NULL || sc->driver->command == NULL) - return -EINVAL; - ret = sc->driver->command(sc, cmd, arg); - if (ret == -EPERM) /* Unsupported command */ - return 0; - return ret; -} - static int __cafe_cam_reset(struct cafe_camera *cam) { - int zero = 0; - return __cafe_cam_cmd(cam, VIDIOC_INT_RESET, &zero); + return sensor_call(cam, core, reset, 0); } /* @@ -826,14 +774,13 @@ static int cafe_cam_init(struct cafe_camera *cam) if (ret) goto out; chip.match.type = V4L2_CHIP_MATCH_I2C_ADDR; - chip.match.addr = cam->sensor->addr; - ret = __cafe_cam_cmd(cam, VIDIOC_DBG_G_CHIP_IDENT, &chip); + chip.match.addr = cam->sensor_addr; + ret = sensor_call(cam, core, g_chip_ident, &chip); if (ret) goto out; cam->sensor_type = chip.ident; -/* if (cam->sensor->addr != OV7xx0_SID) { */ if (cam->sensor_type != V4L2_IDENT_OV7670) { - cam_err(cam, "Unsupported sensor type %d", cam->sensor->addr); + cam_err(cam, "Unsupported sensor type 0x%x", cam->sensor_type); ret = -EINVAL; goto out; } @@ -857,21 +804,21 @@ static int cafe_cam_set_flip(struct cafe_camera *cam) memset(&ctrl, 0, sizeof(ctrl)); ctrl.id = V4L2_CID_VFLIP; ctrl.value = flip; - return __cafe_cam_cmd(cam, VIDIOC_S_CTRL, &ctrl); + return sensor_call(cam, core, s_ctrl, &ctrl); } static int cafe_cam_configure(struct cafe_camera *cam) { struct v4l2_format fmt; - int ret, zero = 0; + int ret; if (cam->state != S_IDLE) return -EINVAL; fmt.fmt.pix = cam->pix_format; - ret = __cafe_cam_cmd(cam, VIDIOC_INT_INIT, &zero); + ret = sensor_call(cam, core, init, 0); if (ret == 0) - ret = __cafe_cam_cmd(cam, VIDIOC_S_FMT, &fmt); + ret = sensor_call(cam, video, s_fmt, &fmt); /* * OV7670 does weird things if flip is set *before* format... */ @@ -1490,7 +1437,7 @@ static int cafe_vidioc_queryctrl(struct file *filp, void *priv, int ret; mutex_lock(&cam->s_mutex); - ret = __cafe_cam_cmd(cam, VIDIOC_QUERYCTRL, qc); + ret = sensor_call(cam, core, queryctrl, qc); mutex_unlock(&cam->s_mutex); return ret; } @@ -1503,7 +1450,7 @@ static int cafe_vidioc_g_ctrl(struct file *filp, void *priv, int ret; mutex_lock(&cam->s_mutex); - ret = __cafe_cam_cmd(cam, VIDIOC_G_CTRL, ctrl); + ret = sensor_call(cam, core, g_ctrl, ctrl); mutex_unlock(&cam->s_mutex); return ret; } @@ -1516,7 +1463,7 @@ static int cafe_vidioc_s_ctrl(struct file *filp, void *priv, int ret; mutex_lock(&cam->s_mutex); - ret = __cafe_cam_cmd(cam, VIDIOC_S_CTRL, ctrl); + ret = sensor_call(cam, core, s_ctrl, ctrl); mutex_unlock(&cam->s_mutex); return ret; } @@ -1558,7 +1505,7 @@ static int cafe_vidioc_enum_fmt_vid_cap(struct file *filp, if (fmt->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) return -EINVAL; mutex_lock(&cam->s_mutex); - ret = __cafe_cam_cmd(cam, VIDIOC_ENUM_FMT, fmt); + ret = sensor_call(cam, video, enum_fmt, fmt); mutex_unlock(&cam->s_mutex); return ret; } @@ -1571,7 +1518,7 @@ static int cafe_vidioc_try_fmt_vid_cap(struct file *filp, void *priv, int ret; mutex_lock(&cam->s_mutex); - ret = __cafe_cam_cmd(cam, VIDIOC_TRY_FMT, fmt); + ret = sensor_call(cam, video, try_fmt, fmt); mutex_unlock(&cam->s_mutex); return ret; } @@ -1680,7 +1627,7 @@ static int cafe_vidioc_g_parm(struct file *filp, void *priv, int ret; mutex_lock(&cam->s_mutex); - ret = __cafe_cam_cmd(cam, VIDIOC_G_PARM, parms); + ret = sensor_call(cam, video, g_parm, parms); mutex_unlock(&cam->s_mutex); parms->parm.capture.readbuffers = n_dma_bufs; return ret; @@ -1693,7 +1640,7 @@ static int cafe_vidioc_s_parm(struct file *filp, void *priv, int ret; mutex_lock(&cam->s_mutex); - ret = __cafe_cam_cmd(cam, VIDIOC_S_PARM, parms); + ret = sensor_call(cam, video, s_parm, parms); mutex_unlock(&cam->s_mutex); parms->parm.capture.readbuffers = n_dma_bufs; return ret; @@ -1973,7 +1920,7 @@ static ssize_t cafe_dfs_read_cam(struct file *file, { u8 v; - cafe_smbus_read_data(cam, cam->sensor->addr, offset, &v); + cafe_smbus_read_data(cam, cam->sensor_addr, offset, &v); s += sprintf(s, "%02x: %02x\n", offset, v); } return simple_read_from_buffer(buf, count, ppos, cafe_debug_buf, @@ -2089,6 +2036,18 @@ static int cafe_pci_probe(struct pci_dev *pdev, ret = cafe_smbus_setup(cam); if (ret) goto out_freeirq; + + cam->sensor_addr = 0x42; + cam->sensor = v4l2_i2c_new_subdev(&cam->i2c_adapter, + "ov7670", "ov7670", cam->sensor_addr); + if (cam->sensor == NULL) { + ret = -ENODEV; + goto out_smbus; + } + ret = cafe_cam_init(cam); + if (ret) + goto out_smbus; + /* * Get the v4l2 setup done. */ @@ -2263,7 +2222,6 @@ static int __init cafe_init(void) printk(KERN_ERR "Unable to register cafe_ccic driver\n"); goto out; } - request_module("ov7670"); /* FIXME want something more general */ ret = 0; out: -- cgit v1.2.3 From ca07561ac70b00b5c2b5af727b3d0b6a4f91bee2 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 18 Mar 2009 13:23:13 -0300 Subject: V4L/DVB (11116): ov7670: cleanup and remove legacy code. v4l2-i2c-drv-legacy.h and ov7670_command are no longer needed after the cafe driver is converted to use v4l2_subdev. Rather than using a large ov7670_control array, just call the handlers via a simple switch and use v4l2_ctrl_query_fill() to handle queryctrl. Signed-off-by: Hans Verkuil Acked-by: Jonathan Corbet Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/ov7670.c | 210 ++++++++++++------------------------------- 1 file changed, 58 insertions(+), 152 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/ov7670.c b/drivers/media/video/ov7670.c index 78bd430716c8..ab245f71b195 100644 --- a/drivers/media/video/ov7670.c +++ b/drivers/media/video/ov7670.c @@ -17,7 +17,7 @@ #include #include #include -#include +#include MODULE_AUTHOR("Jonathan Corbet "); @@ -962,7 +962,7 @@ static void ov7670_calc_cmatrix(struct ov7670_info *info, -static int ov7670_t_sat(struct v4l2_subdev *sd, int value) +static int ov7670_s_sat(struct v4l2_subdev *sd, int value) { struct ov7670_info *info = to_state(sd); int matrix[CMATRIX_LEN]; @@ -974,7 +974,7 @@ static int ov7670_t_sat(struct v4l2_subdev *sd, int value) return ret; } -static int ov7670_q_sat(struct v4l2_subdev *sd, __s32 *value) +static int ov7670_g_sat(struct v4l2_subdev *sd, __s32 *value) { struct ov7670_info *info = to_state(sd); @@ -982,7 +982,7 @@ static int ov7670_q_sat(struct v4l2_subdev *sd, __s32 *value) return 0; } -static int ov7670_t_hue(struct v4l2_subdev *sd, int value) +static int ov7670_s_hue(struct v4l2_subdev *sd, int value) { struct ov7670_info *info = to_state(sd); int matrix[CMATRIX_LEN]; @@ -997,7 +997,7 @@ static int ov7670_t_hue(struct v4l2_subdev *sd, int value) } -static int ov7670_q_hue(struct v4l2_subdev *sd, __s32 *value) +static int ov7670_g_hue(struct v4l2_subdev *sd, __s32 *value) { struct ov7670_info *info = to_state(sd); @@ -1024,7 +1024,7 @@ static unsigned char ov7670_abs_to_sm(unsigned char v) return (128 - v) | 0x80; } -static int ov7670_t_brightness(struct v4l2_subdev *sd, int value) +static int ov7670_s_brightness(struct v4l2_subdev *sd, int value) { unsigned char com8 = 0, v; int ret; @@ -1037,7 +1037,7 @@ static int ov7670_t_brightness(struct v4l2_subdev *sd, int value) return ret; } -static int ov7670_q_brightness(struct v4l2_subdev *sd, __s32 *value) +static int ov7670_g_brightness(struct v4l2_subdev *sd, __s32 *value) { unsigned char v = 0; int ret = ov7670_read(sd, REG_BRIGHT, &v); @@ -1046,12 +1046,12 @@ static int ov7670_q_brightness(struct v4l2_subdev *sd, __s32 *value) return ret; } -static int ov7670_t_contrast(struct v4l2_subdev *sd, int value) +static int ov7670_s_contrast(struct v4l2_subdev *sd, int value) { return ov7670_write(sd, REG_CONTRAS, (unsigned char) value); } -static int ov7670_q_contrast(struct v4l2_subdev *sd, __s32 *value) +static int ov7670_g_contrast(struct v4l2_subdev *sd, __s32 *value) { unsigned char v = 0; int ret = ov7670_read(sd, REG_CONTRAS, &v); @@ -1060,7 +1060,7 @@ static int ov7670_q_contrast(struct v4l2_subdev *sd, __s32 *value) return ret; } -static int ov7670_q_hflip(struct v4l2_subdev *sd, __s32 *value) +static int ov7670_g_hflip(struct v4l2_subdev *sd, __s32 *value) { int ret; unsigned char v = 0; @@ -1071,7 +1071,7 @@ static int ov7670_q_hflip(struct v4l2_subdev *sd, __s32 *value) } -static int ov7670_t_hflip(struct v4l2_subdev *sd, int value) +static int ov7670_s_hflip(struct v4l2_subdev *sd, int value) { unsigned char v = 0; int ret; @@ -1088,7 +1088,7 @@ static int ov7670_t_hflip(struct v4l2_subdev *sd, int value) -static int ov7670_q_vflip(struct v4l2_subdev *sd, __s32 *value) +static int ov7670_g_vflip(struct v4l2_subdev *sd, __s32 *value) { int ret; unsigned char v = 0; @@ -1099,7 +1099,7 @@ static int ov7670_q_vflip(struct v4l2_subdev *sd, __s32 *value) } -static int ov7670_t_vflip(struct v4l2_subdev *sd, int value) +static int ov7670_s_vflip(struct v4l2_subdev *sd, int value) { unsigned char v = 0; int ret; @@ -1114,144 +1114,62 @@ static int ov7670_t_vflip(struct v4l2_subdev *sd, int value) return ret; } - -static struct ov7670_control { - struct v4l2_queryctrl qc; - int (*query)(struct v4l2_subdev *sd, __s32 *value); - int (*tweak)(struct v4l2_subdev *sd, int value); -} ov7670_controls[] = -{ - { - .qc = { - .id = V4L2_CID_BRIGHTNESS, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "Brightness", - .minimum = 0, - .maximum = 255, - .step = 1, - .default_value = 0x80, - .flags = V4L2_CTRL_FLAG_SLIDER - }, - .tweak = ov7670_t_brightness, - .query = ov7670_q_brightness, - }, - { - .qc = { - .id = V4L2_CID_CONTRAST, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "Contrast", - .minimum = 0, - .maximum = 127, - .step = 1, - .default_value = 0x40, /* XXX ov7670 spec */ - .flags = V4L2_CTRL_FLAG_SLIDER - }, - .tweak = ov7670_t_contrast, - .query = ov7670_q_contrast, - }, - { - .qc = { - .id = V4L2_CID_SATURATION, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "Saturation", - .minimum = 0, - .maximum = 256, - .step = 1, - .default_value = 0x80, - .flags = V4L2_CTRL_FLAG_SLIDER - }, - .tweak = ov7670_t_sat, - .query = ov7670_q_sat, - }, - { - .qc = { - .id = V4L2_CID_HUE, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "HUE", - .minimum = -180, - .maximum = 180, - .step = 5, - .default_value = 0, - .flags = V4L2_CTRL_FLAG_SLIDER - }, - .tweak = ov7670_t_hue, - .query = ov7670_q_hue, - }, - { - .qc = { - .id = V4L2_CID_VFLIP, - .type = V4L2_CTRL_TYPE_BOOLEAN, - .name = "Vertical flip", - .minimum = 0, - .maximum = 1, - .step = 1, - .default_value = 0, - }, - .tweak = ov7670_t_vflip, - .query = ov7670_q_vflip, - }, - { - .qc = { - .id = V4L2_CID_HFLIP, - .type = V4L2_CTRL_TYPE_BOOLEAN, - .name = "Horizontal mirror", - .minimum = 0, - .maximum = 1, - .step = 1, - .default_value = 0, - }, - .tweak = ov7670_t_hflip, - .query = ov7670_q_hflip, - }, -}; -#define N_CONTROLS (ARRAY_SIZE(ov7670_controls)) - -static struct ov7670_control *ov7670_find_control(__u32 id) -{ - int i; - - for (i = 0; i < N_CONTROLS; i++) - if (ov7670_controls[i].qc.id == id) - return ov7670_controls + i; - return NULL; -} - - static int ov7670_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qc) { - struct ov7670_control *ctrl = ov7670_find_control(qc->id); - - if (ctrl == NULL) - return -EINVAL; - *qc = ctrl->qc; - return 0; + /* Fill in min, max, step and default value for these controls. */ + switch (qc->id) { + case V4L2_CID_BRIGHTNESS: + return v4l2_ctrl_query_fill(qc, 0, 255, 1, 128); + case V4L2_CID_CONTRAST: + return v4l2_ctrl_query_fill(qc, 0, 127, 1, 64); + case V4L2_CID_VFLIP: + case V4L2_CID_HFLIP: + return v4l2_ctrl_query_fill(qc, 0, 1, 1, 0); + case V4L2_CID_SATURATION: + return v4l2_ctrl_query_fill(qc, 0, 256, 1, 128); + case V4L2_CID_HUE: + return v4l2_ctrl_query_fill(qc, -180, 180, 5, 0); + } + return -EINVAL; } static int ov7670_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) { - struct ov7670_control *octrl = ov7670_find_control(ctrl->id); - int ret; - - if (octrl == NULL) - return -EINVAL; - ret = octrl->query(sd, &ctrl->value); - if (ret >= 0) - return 0; - return ret; + switch (ctrl->id) { + case V4L2_CID_BRIGHTNESS: + return ov7670_g_brightness(sd, &ctrl->value); + case V4L2_CID_CONTRAST: + return ov7670_g_contrast(sd, &ctrl->value); + case V4L2_CID_SATURATION: + return ov7670_g_sat(sd, &ctrl->value); + case V4L2_CID_HUE: + return ov7670_g_hue(sd, &ctrl->value); + case V4L2_CID_VFLIP: + return ov7670_g_vflip(sd, &ctrl->value); + case V4L2_CID_HFLIP: + return ov7670_g_hflip(sd, &ctrl->value); + } + return -EINVAL; } static int ov7670_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) { - struct ov7670_control *octrl = ov7670_find_control(ctrl->id); - int ret; - - if (octrl == NULL) - return -EINVAL; - ret = octrl->tweak(sd, ctrl->value); - if (ret >= 0) - return 0; - return ret; + switch (ctrl->id) { + case V4L2_CID_BRIGHTNESS: + return ov7670_s_brightness(sd, ctrl->value); + case V4L2_CID_CONTRAST: + return ov7670_s_contrast(sd, ctrl->value); + case V4L2_CID_SATURATION: + return ov7670_s_sat(sd, ctrl->value); + case V4L2_CID_HUE: + return ov7670_s_hue(sd, ctrl->value); + case V4L2_CID_VFLIP: + return ov7670_s_vflip(sd, ctrl->value); + case V4L2_CID_HFLIP: + return ov7670_s_hflip(sd, ctrl->value); + } + return -EINVAL; } static int ov7670_g_chip_ident(struct v4l2_subdev *sd, @@ -1262,11 +1180,6 @@ static int ov7670_g_chip_ident(struct v4l2_subdev *sd, return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_OV7670, 0); } -static int ov7670_command(struct i2c_client *client, unsigned cmd, void *arg) -{ - return v4l2_subdev_command(i2c_get_clientdata(client), cmd, arg); -} - /* ----------------------------------------------------------------------- */ static const struct v4l2_subdev_core_ops ov7670_core_ops = { @@ -1300,11 +1213,6 @@ static int ov7670_probe(struct i2c_client *client, struct ov7670_info *info; int ret; - /* - * For now: only deal with adapters we recognize. - */ - if (client->adapter->id != I2C_HW_SMBUS_CAFE) - return -ENODEV; info = kzalloc(sizeof(struct ov7670_info), GFP_KERNEL); if (info == NULL) return -ENOMEM; @@ -1347,9 +1255,7 @@ MODULE_DEVICE_TABLE(i2c, ov7670_id); static struct v4l2_i2c_driver_data v4l2_i2c_data = { .name = "ov7670", - .command = ov7670_command, .probe = ov7670_probe, .remove = ov7670_remove, - .legacy_class = I2C_CLASS_TV_ANALOG, .id_table = ov7670_id, }; -- cgit v1.2.3 From b794aabff01a704df5c0bcf6537e6a7343a08465 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 18 Mar 2009 13:24:05 -0300 Subject: V4L/DVB (11117): ov7670: add support to get/set registers Signed-off-by: Hans Verkuil Acked-by: Jonathan Corbet Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/ov7670.c | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) (limited to 'drivers/media/video') diff --git a/drivers/media/video/ov7670.c b/drivers/media/video/ov7670.c index ab245f71b195..0e2184ec994e 100644 --- a/drivers/media/video/ov7670.c +++ b/drivers/media/video/ov7670.c @@ -1180,6 +1180,36 @@ static int ov7670_g_chip_ident(struct v4l2_subdev *sd, return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_OV7670, 0); } +#ifdef CONFIG_VIDEO_ADV_DEBUG +static int ov7670_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg) +{ + struct i2c_client *client = v4l2_get_subdevdata(sd); + unsigned char val = 0; + int ret; + + if (!v4l2_chip_match_i2c_client(client, ®->match)) + return -EINVAL; + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; + ret = ov7670_read(sd, reg->reg & 0xff, &val); + reg->val = val; + reg->size = 1; + return ret; +} + +static int ov7670_s_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg) +{ + struct i2c_client *client = v4l2_get_subdevdata(sd); + + if (!v4l2_chip_match_i2c_client(client, ®->match)) + return -EINVAL; + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; + ov7670_write(sd, reg->reg & 0xff, reg->val & 0xff); + return 0; +} +#endif + /* ----------------------------------------------------------------------- */ static const struct v4l2_subdev_core_ops ov7670_core_ops = { @@ -1189,6 +1219,10 @@ static const struct v4l2_subdev_core_ops ov7670_core_ops = { .queryctrl = ov7670_queryctrl, .reset = ov7670_reset, .init = ov7670_init, +#ifdef CONFIG_VIDEO_ADV_DEBUG + .g_register = ov7670_g_register, + .s_register = ov7670_s_register, +#endif }; static const struct v4l2_subdev_video_ops ov7670_video_ops = { -- cgit v1.2.3 From 69d94f7ec5edea85da0057c48c4f2877e5bb509e Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 18 Mar 2009 13:25:54 -0300 Subject: V4L/DVB (11118): cafe_ccic: replace debugfs with g/s_register ioctls. Using VIDIOC_DBG_S/G_REGISTER is the standard way of reading/writing register for advanced debugging under v4l2. In addition, using this means that the cafe_ccic driver doesn't need to have knowledge about the used sensor: the debug ioctl can be passed on to the sensor if it isn't for the host. Signed-off-by: Hans Verkuil Acked-by: Jonathan Corbet Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cafe_ccic.c | 176 +++++++++++----------------------------- include/media/v4l2-chip-ident.h | 27 +++--- 2 files changed, 61 insertions(+), 142 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/cafe_ccic.c b/drivers/media/video/cafe_ccic.c index 3363e501d6d7..2f4293771392 100644 --- a/drivers/media/video/cafe_ccic.c +++ b/drivers/media/video/cafe_ccic.c @@ -33,7 +33,6 @@ #include #include #include -#include #include #include @@ -182,10 +181,6 @@ struct cafe_camera /* Misc */ wait_queue_head_t smbus_wait; /* Waiting on i2c events */ wait_queue_head_t iowait; /* Waiting on frame data */ -#ifdef CONFIG_VIDEO_ADV_DEBUG - struct dentry *dfs_regs; - struct dentry *dfs_cam_regs; -#endif }; /* @@ -1646,6 +1641,47 @@ static int cafe_vidioc_s_parm(struct file *filp, void *priv, return ret; } +static int cafe_vidioc_g_chip_ident(struct file *file, void *priv, + struct v4l2_dbg_chip_ident *chip) +{ + struct cafe_camera *cam = priv; + + chip->ident = V4L2_IDENT_NONE; + chip->revision = 0; + if (v4l2_chip_match_host(&chip->match)) { + chip->ident = V4L2_IDENT_CAFE; + return 0; + } + return sensor_call(cam, core, g_chip_ident, chip); +} + +#ifdef CONFIG_VIDEO_ADV_DEBUG +static int cafe_vidioc_g_register(struct file *file, void *priv, + struct v4l2_dbg_register *reg) +{ + struct cafe_camera *cam = priv; + + if (v4l2_chip_match_host(®->match)) { + reg->val = cafe_reg_read(cam, reg->reg); + reg->size = 4; + return 0; + } + return sensor_call(cam, core, g_register, reg); +} + +static int cafe_vidioc_s_register(struct file *file, void *priv, + struct v4l2_dbg_register *reg) +{ + struct cafe_camera *cam = priv; + + if (v4l2_chip_match_host(®->match)) { + cafe_reg_write(cam, reg->reg, reg->val); + return 0; + } + return sensor_call(cam, core, s_register, reg); +} +#endif + /* * This template device holds all of those v4l2 methods; we * clone it for specific real devices. @@ -1682,6 +1718,11 @@ static const struct v4l2_ioctl_ops cafe_v4l_ioctl_ops = { .vidioc_s_ctrl = cafe_vidioc_s_ctrl, .vidioc_g_parm = cafe_vidioc_g_parm, .vidioc_s_parm = cafe_vidioc_s_parm, + .vidioc_g_chip_ident = cafe_vidioc_g_chip_ident, +#ifdef CONFIG_VIDEO_ADV_DEBUG + .vidioc_g_register = cafe_vidioc_g_register, + .vidioc_s_register = cafe_vidioc_s_register, +#endif }; static struct video_device cafe_v4l_template = { @@ -1849,127 +1890,6 @@ static irqreturn_t cafe_irq(int irq, void *data) /* -------------------------------------------------------------------------- */ -#ifdef CONFIG_VIDEO_ADV_DEBUG -/* - * Debugfs stuff. - */ - -static char cafe_debug_buf[1024]; -static struct dentry *cafe_dfs_root; - -static void cafe_dfs_setup(void) -{ - cafe_dfs_root = debugfs_create_dir("cafe_ccic", NULL); - if (IS_ERR(cafe_dfs_root)) { - cafe_dfs_root = NULL; /* Never mind */ - printk(KERN_NOTICE "cafe_ccic unable to set up debugfs\n"); - } -} - -static void cafe_dfs_shutdown(void) -{ - if (cafe_dfs_root) - debugfs_remove(cafe_dfs_root); -} - -static int cafe_dfs_open(struct inode *inode, struct file *file) -{ - file->private_data = inode->i_private; - return 0; -} - -static ssize_t cafe_dfs_read_regs(struct file *file, - char __user *buf, size_t count, loff_t *ppos) -{ - struct cafe_camera *cam = file->private_data; - char *s = cafe_debug_buf; - int offset; - - for (offset = 0; offset < 0x44; offset += 4) - s += sprintf(s, "%02x: %08x\n", offset, - cafe_reg_read(cam, offset)); - for (offset = 0x88; offset <= 0x90; offset += 4) - s += sprintf(s, "%02x: %08x\n", offset, - cafe_reg_read(cam, offset)); - for (offset = 0xb4; offset <= 0xbc; offset += 4) - s += sprintf(s, "%02x: %08x\n", offset, - cafe_reg_read(cam, offset)); - for (offset = 0x3000; offset <= 0x300c; offset += 4) - s += sprintf(s, "%04x: %08x\n", offset, - cafe_reg_read(cam, offset)); - return simple_read_from_buffer(buf, count, ppos, cafe_debug_buf, - s - cafe_debug_buf); -} - -static const struct file_operations cafe_dfs_reg_ops = { - .owner = THIS_MODULE, - .read = cafe_dfs_read_regs, - .open = cafe_dfs_open -}; - -static ssize_t cafe_dfs_read_cam(struct file *file, - char __user *buf, size_t count, loff_t *ppos) -{ - struct cafe_camera *cam = file->private_data; - char *s = cafe_debug_buf; - int offset; - - if (! cam->sensor) - return -EINVAL; - for (offset = 0x0; offset < 0x8a; offset++) - { - u8 v; - - cafe_smbus_read_data(cam, cam->sensor_addr, offset, &v); - s += sprintf(s, "%02x: %02x\n", offset, v); - } - return simple_read_from_buffer(buf, count, ppos, cafe_debug_buf, - s - cafe_debug_buf); -} - -static const struct file_operations cafe_dfs_cam_ops = { - .owner = THIS_MODULE, - .read = cafe_dfs_read_cam, - .open = cafe_dfs_open -}; - - - -static void cafe_dfs_cam_setup(struct cafe_camera *cam) -{ - char fname[40]; - - if (!cafe_dfs_root) - return; - sprintf(fname, "regs-%d", cam->vdev.num); - cam->dfs_regs = debugfs_create_file(fname, 0444, cafe_dfs_root, - cam, &cafe_dfs_reg_ops); - sprintf(fname, "cam-%d", cam->vdev.num); - cam->dfs_cam_regs = debugfs_create_file(fname, 0444, cafe_dfs_root, - cam, &cafe_dfs_cam_ops); -} - - -static void cafe_dfs_cam_shutdown(struct cafe_camera *cam) -{ - if (! IS_ERR(cam->dfs_regs)) - debugfs_remove(cam->dfs_regs); - if (! IS_ERR(cam->dfs_cam_regs)) - debugfs_remove(cam->dfs_cam_regs); -} - -#else - -#define cafe_dfs_setup() -#define cafe_dfs_shutdown() -#define cafe_dfs_cam_setup(cam) -#define cafe_dfs_cam_shutdown(cam) -#endif /* CONFIG_VIDEO_ADV_DEBUG */ - - - - -/* ------------------------------------------------------------------------*/ /* * PCI interface stuff. */ @@ -2070,7 +1990,6 @@ static int cafe_pci_probe(struct pci_dev *pdev, " will try again later."); } - cafe_dfs_cam_setup(cam); mutex_unlock(&cam->s_mutex); return 0; @@ -2096,7 +2015,6 @@ out: static void cafe_shutdown(struct cafe_camera *cam) { /* FIXME: Make sure we take care of everything here */ - cafe_dfs_cam_shutdown(cam); if (cam->n_sbufs > 0) /* What if they are still mapped? Shouldn't be, but... */ cafe_free_sio_buffers(cam); @@ -2216,7 +2134,6 @@ static int __init cafe_init(void) printk(KERN_NOTICE "Marvell M88ALP01 'CAFE' Camera Controller version %d\n", CAFE_VERSION); - cafe_dfs_setup(); ret = pci_register_driver(&cafe_pci_driver); if (ret) { printk(KERN_ERR "Unable to register cafe_ccic driver\n"); @@ -2232,7 +2149,6 @@ static int __init cafe_init(void) static void __exit cafe_exit(void) { pci_unregister_driver(&cafe_pci_driver); - cafe_dfs_shutdown(); } module_init(cafe_init); diff --git a/include/media/v4l2-chip-ident.h b/include/media/v4l2-chip-ident.h index ca2aa6d7e386..1be461a29077 100644 --- a/include/media/v4l2-chip-ident.h +++ b/include/media/v4l2-chip-ident.h @@ -146,21 +146,12 @@ enum { /* module tda9840: just ident 9840 */ V4L2_IDENT_TDA9840 = 9840, + /* module cafe_ccic, just ident 8801 */ + V4L2_IDENT_CAFE = 8801, + /* module tw9910: just ident 9910 */ V4L2_IDENT_TW9910 = 9910, - /* module cs53132a: just ident 53132 */ - V4L2_IDENT_CS53l32A = 53132, - - /* module upd64031a: just ident 64031 */ - V4L2_IDENT_UPD64031A = 64031, - - /* module upd64083: just ident 64083 */ - V4L2_IDENT_UPD64083 = 64083, - - /* module m52790: just ident 52790 */ - V4L2_IDENT_M52790 = 52790, - /* module msp3400: reserved range 34000-34999 and 44000-44999 */ V4L2_IDENT_MSPX4XX = 34000, /* generic MSPX4XX identifier, only use internally (tveeprom.c). */ @@ -237,6 +228,18 @@ enum { V4L2_IDENT_MT9V022IX7ATC = 45010, /* No way to detect "normal" I77ATx */ V4L2_IDENT_MT9V022IX7ATM = 45015, /* and "lead free" IA7ATx chips */ V4L2_IDENT_MT9T031 = 45020, + + /* module cs53132a: just ident 53132 */ + V4L2_IDENT_CS53l32A = 53132, + + /* module upd64031a: just ident 64031 */ + V4L2_IDENT_UPD64031A = 64031, + + /* module upd64083: just ident 64083 */ + V4L2_IDENT_UPD64083 = 64083, + + /* module m52790: just ident 52790 */ + V4L2_IDENT_M52790 = 52790, }; #endif -- cgit v1.2.3 From acc5d851b824c78df430537b6a2fc5951bec5daa Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 18 Mar 2009 13:31:56 -0300 Subject: V4L/DVB (11120): cafe_ccic: stick in a comment with a request for test results Due to lack of hardware this conversion to v4l2_device/v4l2_subdev is untested. If all goes well I should be able to test it in about a month, but just in case I can't manage that it should be made clear in the code that this isn't tested. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cafe_ccic.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers/media/video') diff --git a/drivers/media/video/cafe_ccic.c b/drivers/media/video/cafe_ccic.c index 2f4293771392..1c79369447f4 100644 --- a/drivers/media/video/cafe_ccic.c +++ b/drivers/media/video/cafe_ccic.c @@ -11,6 +11,12 @@ * * Written by Jonathan Corbet, corbet@lwn.net. * + * v4l2_device/v4l2_subdev conversion by: + * Copyright (C) 2009 Hans Verkuil + * + * Note: this conversion is untested! Please contact the linux-media + * mailinglist if you can test this, together with the test results. + * * This file may be distributed under the terms of the GNU General * Public License, version 2. */ -- cgit v1.2.3 From dceaddb978a7fcd2efbdf6775a509529757327c3 Mon Sep 17 00:00:00 2001 From: Alan McIvor Date: Thu, 12 Mar 2009 21:43:34 -0300 Subject: V4L/DVB (11124): Add support for ProVideo PV-183 to bttv Add support for ProVideo PV-183 to bttv This patch adds support for the ProVideo PV-183 card to the bttv device driver. The PV-183 is a PCI card with 8 BT878 devices plus a Hint Corp HiNT HB4 PCI-PCI Bridge. Each BT878 has two composite input channels available. There are no tuners on this card. Signed-off-by: Alan McIvor Signed-off-by: Mauro Carvalho Chehab --- Documentation/video4linux/CARDLIST.bttv | 1 + drivers/media/video/bt8xx/bttv-cards.c | 24 ++++++++++++++++++++++++ drivers/media/video/bt8xx/bttv.h | 1 + 3 files changed, 26 insertions(+) (limited to 'drivers/media/video') diff --git a/Documentation/video4linux/CARDLIST.bttv b/Documentation/video4linux/CARDLIST.bttv index e17750473e08..f11c583295e9 100644 --- a/Documentation/video4linux/CARDLIST.bttv +++ b/Documentation/video4linux/CARDLIST.bttv @@ -157,3 +157,4 @@ 156 -> IVCE-8784 [0000:f050,0001:f050,0002:f050,0003:f050] 157 -> Geovision GV-800(S) (master) [800a:763d] 158 -> Geovision GV-800(S) (slave) [800b:763d,800c:763d,800d:763d] +159 -> ProVideo PV183 [1830:1540,1831:1540,1832:1540,1833:1540,1834:1540,1835:1540,1836:1540,1837:1540] diff --git a/drivers/media/video/bt8xx/bttv-cards.c b/drivers/media/video/bt8xx/bttv-cards.c index 7725d9487abf..1536ab5a4a8d 100644 --- a/drivers/media/video/bt8xx/bttv-cards.c +++ b/drivers/media/video/bt8xx/bttv-cards.c @@ -320,6 +320,16 @@ static struct CARD { { 0x763d800b, BTTV_BOARD_GEOVISION_GV800S_SL, "GeoVision GV-800(S) (slave)" }, { 0x763d800c, BTTV_BOARD_GEOVISION_GV800S_SL, "GeoVision GV-800(S) (slave)" }, { 0x763d800d, BTTV_BOARD_GEOVISION_GV800S_SL, "GeoVision GV-800(S) (slave)" }, + + { 0x15401830, BTTV_BOARD_PV183, "Provideo PV183-1" }, + { 0x15401831, BTTV_BOARD_PV183, "Provideo PV183-2" }, + { 0x15401832, BTTV_BOARD_PV183, "Provideo PV183-3" }, + { 0x15401833, BTTV_BOARD_PV183, "Provideo PV183-4" }, + { 0x15401834, BTTV_BOARD_PV183, "Provideo PV183-5" }, + { 0x15401835, BTTV_BOARD_PV183, "Provideo PV183-6" }, + { 0x15401836, BTTV_BOARD_PV183, "Provideo PV183-7" }, + { 0x15401837, BTTV_BOARD_PV183, "Provideo PV183-8" }, + { 0, -1, NULL } }; @@ -2881,6 +2891,20 @@ struct tvcard bttv_tvcards[] = { .no_tda9875 = 1, .muxsel_hook = gv800s_muxsel, }, + [BTTV_BOARD_PV183] = { + .name = "ProVideo PV183", /* 0x9f */ + .video_inputs = 2, + /* .audio_inputs= 0, */ + .svhs = NO_SVHS, + .gpiomask = 0, + .muxsel = MUXSEL(2, 3), + .gpiomux = { 0 }, + .needs_tvaudio = 0, + .no_msp34xx = 1, + .pll = PLL_28, + .tuner_type = TUNER_ABSENT, + .tuner_addr = ADDR_UNSET, + }, }; static const unsigned int bttv_num_tvcards = ARRAY_SIZE(bttv_tvcards); diff --git a/drivers/media/video/bt8xx/bttv.h b/drivers/media/video/bt8xx/bttv.h index 85b0e3e9d382..fac5f86356d2 100644 --- a/drivers/media/video/bt8xx/bttv.h +++ b/drivers/media/video/bt8xx/bttv.h @@ -184,6 +184,7 @@ #define BTTV_BOARD_IVCE8784 0x9c #define BTTV_BOARD_GEOVISION_GV800S 0x9d #define BTTV_BOARD_GEOVISION_GV800S_SL 0x9e +#define BTTV_BOARD_PV183 0x9f /* more card-specific defines */ -- cgit v1.2.3 From e86da6f07ed6deebc199368bd0a47b3671829b80 Mon Sep 17 00:00:00 2001 From: Janne Grunau Date: Thu, 19 Mar 2009 19:00:35 -0300 Subject: V4L/DVB (11125): fix mispelled Hauppauge in HD PVR and PVR USB2 driver comments Signed-off-by: Janne Grunau Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/hdpvr/hdpvr-control.c | 2 +- drivers/media/video/hdpvr/hdpvr-core.c | 2 +- drivers/media/video/hdpvr/hdpvr-i2c.c | 2 +- drivers/media/video/hdpvr/hdpvr-video.c | 2 +- drivers/media/video/hdpvr/hdpvr.h | 2 +- drivers/media/video/pvrusb2/pvrusb2-encoder.c | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/hdpvr/hdpvr-control.c b/drivers/media/video/hdpvr/hdpvr-control.c index ecf02c621f13..51de74aebfcb 100644 --- a/drivers/media/video/hdpvr/hdpvr-control.c +++ b/drivers/media/video/hdpvr/hdpvr-control.c @@ -1,5 +1,5 @@ /* - * Hauppage HD PVR USB driver - video 4 linux 2 interface + * Hauppauge HD PVR USB driver - video 4 linux 2 interface * * Copyright (C) 2008 Janne Grunau (j@jannau.net) * diff --git a/drivers/media/video/hdpvr/hdpvr-core.c b/drivers/media/video/hdpvr/hdpvr-core.c index e7300b570bb7..1c93589bf595 100644 --- a/drivers/media/video/hdpvr/hdpvr-core.c +++ b/drivers/media/video/hdpvr/hdpvr-core.c @@ -1,5 +1,5 @@ /* - * Hauppage HD PVR USB driver + * Hauppauge HD PVR USB driver * * Copyright (C) 2001-2004 Greg Kroah-Hartman (greg@kroah.com) * Copyright (C) 2008 Janne Grunau (j@jannau.net) diff --git a/drivers/media/video/hdpvr/hdpvr-i2c.c b/drivers/media/video/hdpvr/hdpvr-i2c.c index 35096dec2411..c4b5d1515c10 100644 --- a/drivers/media/video/hdpvr/hdpvr-i2c.c +++ b/drivers/media/video/hdpvr/hdpvr-i2c.c @@ -1,6 +1,6 @@ /* - * Hauppage HD PVR USB driver + * Hauppauge HD PVR USB driver * * Copyright (C) 2008 Janne Grunau (j@jannau.net) * diff --git a/drivers/media/video/hdpvr/hdpvr-video.c b/drivers/media/video/hdpvr/hdpvr-video.c index 6dd11f490735..235978003e68 100644 --- a/drivers/media/video/hdpvr/hdpvr-video.c +++ b/drivers/media/video/hdpvr/hdpvr-video.c @@ -1,5 +1,5 @@ /* - * Hauppage HD PVR USB driver - video 4 linux 2 interface + * Hauppauge HD PVR USB driver - video 4 linux 2 interface * * Copyright (C) 2008 Janne Grunau (j@jannau.net) * diff --git a/drivers/media/video/hdpvr/hdpvr.h b/drivers/media/video/hdpvr/hdpvr.h index 17db74feb884..9bc8051b597d 100644 --- a/drivers/media/video/hdpvr/hdpvr.h +++ b/drivers/media/video/hdpvr/hdpvr.h @@ -1,5 +1,5 @@ /* - * Hauppage HD PVR USB driver + * Hauppauge HD PVR USB driver * * Copyright (C) 2008 Janne Grunau (j@jannau.net) * diff --git a/drivers/media/video/pvrusb2/pvrusb2-encoder.c b/drivers/media/video/pvrusb2/pvrusb2-encoder.c index 273d2a1aa220..54ac5349dee2 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-encoder.c +++ b/drivers/media/video/pvrusb2/pvrusb2-encoder.c @@ -347,7 +347,7 @@ static int pvr2_encoder_prep_config(struct pvr2_hdw *hdw) int encMisc3Arg = 0; #if 0 - /* This inexplicable bit happens in the Hauppage windows + /* This inexplicable bit happens in the Hauppauge windows driver (for both 24xxx and 29xxx devices). However I currently see no difference in behavior with or without this stuff. Leave this here as a note of its existence, -- cgit v1.2.3 From 1398ae1fe6048d49397dccaa4bc1a4101eecf643 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 20 Mar 2009 19:33:59 -0300 Subject: V4L/DVB (11127): Kconfig: replace all occurrences of CUSTOMIZE to CUSTOMISE There are several Kconfig items using CUSTOMIZE. Yet, most use the English writing CUSTOMISE. This generates lots of trouble, because people sometimes type the Kbuild item different. Let's standardise every occurrence using the same syntax. The changes were generated by this small shell script: for i in `find linux -type f`; do sed s,CUSTOMIZE,CUSTOMISE,g $i >/tmp/a && mv /tmp/a $i; done Signed-off-by: Mauro Carvalho Chehab --- drivers/media/common/tuners/Kconfig | 60 ++++++++++++++++++------------------- drivers/media/dvb/b2c2/Kconfig | 2 +- drivers/media/dvb/bt8xx/Kconfig | 2 +- drivers/media/dvb/dvb-usb/Kconfig | 48 ++++++++++++++--------------- drivers/media/dvb/ttpci/Kconfig | 2 +- drivers/media/video/au0828/Kconfig | 6 ++-- drivers/media/video/cx18/Kconfig | 2 +- drivers/media/video/cx23885/Kconfig | 10 +++---- drivers/media/video/cx88/Kconfig | 2 +- drivers/media/video/pvrusb2/Kconfig | 6 ++-- drivers/media/video/saa7134/Kconfig | 8 ++--- 11 files changed, 74 insertions(+), 74 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/common/tuners/Kconfig b/drivers/media/common/tuners/Kconfig index 724e6870c412..52c3f65b12d6 100644 --- a/drivers/media/common/tuners/Kconfig +++ b/drivers/media/common/tuners/Kconfig @@ -21,17 +21,17 @@ config MEDIA_TUNER tristate default VIDEO_MEDIA && I2C depends on VIDEO_MEDIA && I2C - select MEDIA_TUNER_XC2028 if !MEDIA_TUNER_CUSTOMIZE - select MEDIA_TUNER_XC5000 if !MEDIA_TUNER_CUSTOMIZE - select MEDIA_TUNER_MT20XX if !MEDIA_TUNER_CUSTOMIZE - select MEDIA_TUNER_TDA8290 if !MEDIA_TUNER_CUSTOMIZE - select MEDIA_TUNER_TEA5761 if !MEDIA_TUNER_CUSTOMIZE - select MEDIA_TUNER_TEA5767 if !MEDIA_TUNER_CUSTOMIZE - select MEDIA_TUNER_SIMPLE if !MEDIA_TUNER_CUSTOMIZE - select MEDIA_TUNER_TDA9887 if !MEDIA_TUNER_CUSTOMIZE - select MEDIA_TUNER_MC44S803 if !MEDIA_TUNER_CUSTOMIZE - -menuconfig MEDIA_TUNER_CUSTOMIZE + select MEDIA_TUNER_XC2028 if !MEDIA_TUNER_CUSTOMISE + select MEDIA_TUNER_XC5000 if !MEDIA_TUNER_CUSTOMISE + select MEDIA_TUNER_MT20XX if !MEDIA_TUNER_CUSTOMISE + select MEDIA_TUNER_TDA8290 if !MEDIA_TUNER_CUSTOMISE + select MEDIA_TUNER_TEA5761 if !MEDIA_TUNER_CUSTOMISE + select MEDIA_TUNER_TEA5767 if !MEDIA_TUNER_CUSTOMISE + select MEDIA_TUNER_SIMPLE if !MEDIA_TUNER_CUSTOMISE + select MEDIA_TUNER_TDA9887 if !MEDIA_TUNER_CUSTOMISE + select MEDIA_TUNER_MC44S803 if !MEDIA_TUNER_CUSTOMISE + +menuconfig MEDIA_TUNER_CUSTOMISE bool "Customize analog and hybrid tuner modules to build" depends on MEDIA_TUNER default n @@ -44,13 +44,13 @@ menuconfig MEDIA_TUNER_CUSTOMIZE If unsure say N. -if MEDIA_TUNER_CUSTOMIZE +if MEDIA_TUNER_CUSTOMISE config MEDIA_TUNER_SIMPLE tristate "Simple tuner support" depends on VIDEO_MEDIA && I2C select MEDIA_TUNER_TDA9887 - default m if MEDIA_TUNER_CUSTOMIZE + default m if MEDIA_TUNER_CUSTOMISE help Say Y here to include support for various simple tuners. @@ -59,28 +59,28 @@ config MEDIA_TUNER_TDA8290 depends on VIDEO_MEDIA && I2C select MEDIA_TUNER_TDA827X select MEDIA_TUNER_TDA18271 - default m if MEDIA_TUNER_CUSTOMIZE + default m if MEDIA_TUNER_CUSTOMISE help Say Y here to include support for Philips TDA8290+8275(a) tuner. config MEDIA_TUNER_TDA827X tristate "Philips TDA827X silicon tuner" depends on VIDEO_MEDIA && I2C - default m if MEDIA_TUNER_CUSTOMIZE + default m if MEDIA_TUNER_CUSTOMISE help A DVB-T silicon tuner module. Say Y when you want to support this tuner. config MEDIA_TUNER_TDA18271 tristate "NXP TDA18271 silicon tuner" depends on VIDEO_MEDIA && I2C - default m if MEDIA_TUNER_CUSTOMIZE + default m if MEDIA_TUNER_CUSTOMISE help A silicon tuner module. Say Y when you want to support this tuner. config MEDIA_TUNER_TDA9887 tristate "TDA 9885/6/7 analog IF demodulator" depends on VIDEO_MEDIA && I2C - default m if MEDIA_TUNER_CUSTOMIZE + default m if MEDIA_TUNER_CUSTOMISE help Say Y here to include support for Philips TDA9885/6/7 analog IF demodulator. @@ -89,63 +89,63 @@ config MEDIA_TUNER_TEA5761 tristate "TEA 5761 radio tuner (EXPERIMENTAL)" depends on VIDEO_MEDIA && I2C depends on EXPERIMENTAL - default m if MEDIA_TUNER_CUSTOMIZE + default m if MEDIA_TUNER_CUSTOMISE help Say Y here to include support for the Philips TEA5761 radio tuner. config MEDIA_TUNER_TEA5767 tristate "TEA 5767 radio tuner" depends on VIDEO_MEDIA && I2C - default m if MEDIA_TUNER_CUSTOMIZE + default m if MEDIA_TUNER_CUSTOMISE help Say Y here to include support for the Philips TEA5767 radio tuner. config MEDIA_TUNER_MT20XX tristate "Microtune 2032 / 2050 tuners" depends on VIDEO_MEDIA && I2C - default m if MEDIA_TUNER_CUSTOMIZE + default m if MEDIA_TUNER_CUSTOMISE help Say Y here to include support for the MT2032 / MT2050 tuner. config MEDIA_TUNER_MT2060 tristate "Microtune MT2060 silicon IF tuner" depends on VIDEO_MEDIA && I2C - default m if MEDIA_TUNER_CUSTOMIZE + default m if MEDIA_TUNER_CUSTOMISE help A driver for the silicon IF tuner MT2060 from Microtune. config MEDIA_TUNER_MT2266 tristate "Microtune MT2266 silicon tuner" depends on VIDEO_MEDIA && I2C - default m if MEDIA_TUNER_CUSTOMIZE + default m if MEDIA_TUNER_CUSTOMISE help A driver for the silicon baseband tuner MT2266 from Microtune. config MEDIA_TUNER_MT2131 tristate "Microtune MT2131 silicon tuner" depends on VIDEO_MEDIA && I2C - default m if MEDIA_TUNER_CUSTOMIZE + default m if MEDIA_TUNER_CUSTOMISE help A driver for the silicon baseband tuner MT2131 from Microtune. config MEDIA_TUNER_QT1010 tristate "Quantek QT1010 silicon tuner" depends on VIDEO_MEDIA && I2C - default m if MEDIA_TUNER_CUSTOMIZE + default m if MEDIA_TUNER_CUSTOMISE help A driver for the silicon tuner QT1010 from Quantek. config MEDIA_TUNER_XC2028 tristate "XCeive xc2028/xc3028 tuners" depends on VIDEO_MEDIA && I2C - default m if MEDIA_TUNER_CUSTOMIZE + default m if MEDIA_TUNER_CUSTOMISE help Say Y here to include support for the xc2028/xc3028 tuners. config MEDIA_TUNER_XC5000 tristate "Xceive XC5000 silicon tuner" depends on VIDEO_MEDIA && I2C - default m if MEDIA_TUNER_CUSTOMIZE + default m if MEDIA_TUNER_CUSTOMISE help A driver for the silicon tuner XC5000 from Xceive. This device is only used inside a SiP called togther with a @@ -154,22 +154,22 @@ config MEDIA_TUNER_XC5000 config MEDIA_TUNER_MXL5005S tristate "MaxLinear MSL5005S silicon tuner" depends on VIDEO_MEDIA && I2C - default m if MEDIA_TUNER_CUSTOMIZE + default m if MEDIA_TUNER_CUSTOMISE help A driver for the silicon tuner MXL5005S from MaxLinear. config MEDIA_TUNER_MXL5007T tristate "MaxLinear MxL5007T silicon tuner" depends on VIDEO_MEDIA && I2C - default m if MEDIA_TUNER_CUSTOMIZE + default m if MEDIA_TUNER_CUSTOMISE help A driver for the silicon tuner MxL5007T from MaxLinear. config MEDIA_TUNER_MC44S803 tristate "Freescale MC44S803 Low Power CMOS Broadband tuners" depends on VIDEO_MEDIA && I2C - default m if MEDIA_TUNER_CUSTOMIZE + default m if MEDIA_TUNER_CUSTOMISE help Say Y here to support the Freescale MC44S803 based tuners -endif # MEDIA_TUNER_CUSTOMIZE +endif # MEDIA_TUNER_CUSTOMISE diff --git a/drivers/media/dvb/b2c2/Kconfig b/drivers/media/dvb/b2c2/Kconfig index a8c6249c4099..9e5781400744 100644 --- a/drivers/media/dvb/b2c2/Kconfig +++ b/drivers/media/dvb/b2c2/Kconfig @@ -13,7 +13,7 @@ config DVB_B2C2_FLEXCOP select DVB_TUNER_ITD1000 if !DVB_FE_CUSTOMISE select DVB_ISL6421 if !DVB_FE_CUSTOMISE select DVB_CX24123 if !DVB_FE_CUSTOMISE - select MEDIA_TUNER_SIMPLE if !MEDIA_TUNER_CUSTOMIZE + select MEDIA_TUNER_SIMPLE if !MEDIA_TUNER_CUSTOMISE select DVB_TUNER_CX24113 if !DVB_FE_CUSTOMISE help Support for the digital TV receiver chip made by B2C2 Inc. included in diff --git a/drivers/media/dvb/bt8xx/Kconfig b/drivers/media/dvb/bt8xx/Kconfig index 27edb0ece587..8668e634c7ec 100644 --- a/drivers/media/dvb/bt8xx/Kconfig +++ b/drivers/media/dvb/bt8xx/Kconfig @@ -8,7 +8,7 @@ config DVB_BT8XX select DVB_OR51211 if !DVB_FE_CUSTOMISE select DVB_LGDT330X if !DVB_FE_CUSTOMISE select DVB_ZL10353 if !DVB_FE_CUSTOMISE - select MEDIA_TUNER_SIMPLE if !MEDIA_TUNER_CUSTOMIZE + select MEDIA_TUNER_SIMPLE if !MEDIA_TUNER_CUSTOMISE help Support for PCI cards based on the Bt8xx PCI bridge. Examples are the Nebula cards, the Pinnacle PCTV cards, the Twinhan DST cards, diff --git a/drivers/media/dvb/dvb-usb/Kconfig b/drivers/media/dvb/dvb-usb/Kconfig index b899d509adf6..5b0c8cc25fdf 100644 --- a/drivers/media/dvb/dvb-usb/Kconfig +++ b/drivers/media/dvb/dvb-usb/Kconfig @@ -25,7 +25,7 @@ config DVB_USB_A800 depends on DVB_USB select DVB_DIB3000MC select DVB_PLL if !DVB_FE_CUSTOMISE - select MEDIA_TUNER_MT2060 if !MEDIA_TUNER_CUSTOMIZE + select MEDIA_TUNER_MT2060 if !MEDIA_TUNER_CUSTOMISE help Say Y here to support the AVerMedia AverTV DVB-T USB 2.0 (A800) receiver. @@ -34,7 +34,7 @@ config DVB_USB_DIBUSB_MB depends on DVB_USB select DVB_PLL if !DVB_FE_CUSTOMISE select DVB_DIB3000MB - select MEDIA_TUNER_MT2060 if !MEDIA_TUNER_CUSTOMIZE + select MEDIA_TUNER_MT2060 if !MEDIA_TUNER_CUSTOMISE help Support for USB 1.1 and 2.0 DVB-T receivers based on reference designs made by DiBcom () equipped with a DiB3000M-B demodulator. @@ -55,7 +55,7 @@ config DVB_USB_DIBUSB_MC tristate "DiBcom USB DVB-T devices (based on the DiB3000M-C/P) (see help for device list)" depends on DVB_USB select DVB_DIB3000MC - select MEDIA_TUNER_MT2060 if !MEDIA_TUNER_CUSTOMIZE + select MEDIA_TUNER_MT2060 if !MEDIA_TUNER_CUSTOMISE help Support for USB2.0 DVB-T receivers based on reference designs made by DiBcom () equipped with a DiB3000M-C/P demodulator. @@ -75,11 +75,11 @@ config DVB_USB_DIB0700 select DVB_S5H1411 if !DVB_FE_CUSTOMISE select DVB_LGDT3305 if !DVB_FE_CUSTOMISE select DVB_TUNER_DIB0070 if !DVB_FE_CUSTOMISE - select MEDIA_TUNER_MT2060 if !MEDIA_TUNER_CUSTOMIZE - select MEDIA_TUNER_MT2266 if !MEDIA_TUNER_CUSTOMIZE - select MEDIA_TUNER_XC2028 if !MEDIA_TUNER_CUSTOMIZE - select MEDIA_TUNER_XC5000 if !MEDIA_TUNER_CUSTOMIZE - select MEDIA_TUNER_MXL5007T if !MEDIA_TUNER_CUSTOMIZE + select MEDIA_TUNER_MT2060 if !MEDIA_TUNER_CUSTOMISE + select MEDIA_TUNER_MT2266 if !MEDIA_TUNER_CUSTOMISE + select MEDIA_TUNER_XC2028 if !MEDIA_TUNER_CUSTOMISE + select MEDIA_TUNER_XC5000 if !MEDIA_TUNER_CUSTOMISE + select MEDIA_TUNER_MXL5007T if !MEDIA_TUNER_CUSTOMISE help Support for USB2.0/1.1 DVB receivers based on the DiB0700 USB bridge. The USB bridge is also present in devices having the DiB7700 DVB-T-USB @@ -97,7 +97,7 @@ config DVB_USB_UMT_010 depends on DVB_USB select DVB_PLL if !DVB_FE_CUSTOMISE select DVB_DIB3000MC - select MEDIA_TUNER_MT2060 if !MEDIA_TUNER_CUSTOMIZE + select MEDIA_TUNER_MT2060 if !MEDIA_TUNER_CUSTOMISE select DVB_MT352 if !DVB_FE_CUSTOMISE help Say Y here to support the HanfTek UMT-010 USB2.0 stick-sized DVB-T receiver. @@ -113,9 +113,9 @@ config DVB_USB_CXUSB select DVB_DIB7000P if !DVB_FE_CUSTOMISE select DVB_LGS8GL5 if !DVB_FE_CUSTOMISE select DVB_TUNER_DIB0070 if !DVB_FE_CUSTOMISE - select MEDIA_TUNER_SIMPLE if !MEDIA_TUNER_CUSTOMIZE - select MEDIA_TUNER_XC2028 if !MEDIA_TUNER_CUSTOMIZE - select MEDIA_TUNER_MXL5005S if !MEDIA_TUNER_CUSTOMIZE + select MEDIA_TUNER_SIMPLE if !MEDIA_TUNER_CUSTOMISE + select MEDIA_TUNER_XC2028 if !MEDIA_TUNER_CUSTOMISE + select MEDIA_TUNER_MXL5005S if !MEDIA_TUNER_CUSTOMISE help Say Y here to support the Conexant USB2.0 hybrid reference design. Currently, only DVB and ATSC modes are supported, analog mode @@ -129,8 +129,8 @@ config DVB_USB_M920X depends on DVB_USB select DVB_MT352 if !DVB_FE_CUSTOMISE select DVB_TDA1004X if !DVB_FE_CUSTOMISE - select MEDIA_TUNER_QT1010 if !MEDIA_TUNER_CUSTOMIZE - select MEDIA_TUNER_TDA827X if !MEDIA_TUNER_CUSTOMIZE + select MEDIA_TUNER_QT1010 if !MEDIA_TUNER_CUSTOMISE + select MEDIA_TUNER_TDA827X if !MEDIA_TUNER_CUSTOMISE help Say Y here to support the MSI Mega Sky 580 USB2.0 DVB-T receiver. Currently, only devices with a product id of @@ -141,7 +141,7 @@ config DVB_USB_GL861 tristate "Genesys Logic GL861 USB2.0 support" depends on DVB_USB select DVB_ZL10353 if !DVB_FE_CUSTOMISE - select MEDIA_TUNER_QT1010 if !MEDIA_TUNER_CUSTOMIZE + select MEDIA_TUNER_QT1010 if !MEDIA_TUNER_CUSTOMISE help Say Y here to support the MSI Megasky 580 (55801) DVB-T USB2.0 receiver with USB ID 0db0:5581. @@ -150,7 +150,7 @@ config DVB_USB_AU6610 tristate "Alcor Micro AU6610 USB2.0 support" depends on DVB_USB select DVB_ZL10353 if !DVB_FE_CUSTOMISE - select MEDIA_TUNER_QT1010 if !MEDIA_TUNER_CUSTOMIZE + select MEDIA_TUNER_QT1010 if !MEDIA_TUNER_CUSTOMISE help Say Y here to support the Sigmatek DVB-110 DVB-T USB2.0 receiver. @@ -203,7 +203,7 @@ config DVB_USB_NOVA_T_USB2 depends on DVB_USB select DVB_DIB3000MC select DVB_PLL if !DVB_FE_CUSTOMISE - select MEDIA_TUNER_MT2060 if !MEDIA_TUNER_CUSTOMIZE + select MEDIA_TUNER_MT2060 if !MEDIA_TUNER_CUSTOMISE help Say Y here to support the Hauppauge WinTV-NOVA-T usb2 DVB-T USB2.0 receiver. @@ -239,8 +239,8 @@ config DVB_USB_OPERA1 config DVB_USB_AF9005 tristate "Afatech AF9005 DVB-T USB1.1 support" depends on DVB_USB && EXPERIMENTAL - select MEDIA_TUNER_MT2060 if !MEDIA_TUNER_CUSTOMIZE - select MEDIA_TUNER_QT1010 if !MEDIA_TUNER_CUSTOMIZE + select MEDIA_TUNER_MT2060 if !MEDIA_TUNER_CUSTOMISE + select MEDIA_TUNER_QT1010 if !MEDIA_TUNER_CUSTOMISE help Say Y here to support the Afatech AF9005 based DVB-T USB1.1 receiver and the TerraTec Cinergy T USB XE (Rev.1) @@ -288,7 +288,7 @@ config DVB_USB_DTV5100 tristate "AME DTV-5100 USB2.0 DVB-T support" depends on DVB_USB select DVB_ZL10353 if !DVB_FE_CUSTOMISE - select MEDIA_TUNER_QT1010 if !MEDIA_TUNER_CUSTOMIZE + select MEDIA_TUNER_QT1010 if !MEDIA_TUNER_CUSTOMISE help Say Y here to support the AME DTV-5100 USB2.0 DVB-T receiver. @@ -297,10 +297,10 @@ config DVB_USB_AF9015 depends on DVB_USB && EXPERIMENTAL select DVB_AF9013 select DVB_PLL if !DVB_FE_CUSTOMISE - select MEDIA_TUNER_MT2060 if !MEDIA_TUNER_CUSTOMIZE - select MEDIA_TUNER_QT1010 if !MEDIA_TUNER_CUSTOMIZE - select MEDIA_TUNER_TDA18271 if !MEDIA_TUNER_CUSTOMIZE - select MEDIA_TUNER_MXL5005S if !MEDIA_TUNER_CUSTOMIZE + select MEDIA_TUNER_MT2060 if !MEDIA_TUNER_CUSTOMISE + select MEDIA_TUNER_QT1010 if !MEDIA_TUNER_CUSTOMISE + select MEDIA_TUNER_TDA18271 if !MEDIA_TUNER_CUSTOMISE + select MEDIA_TUNER_MXL5005S if !MEDIA_TUNER_CUSTOMISE select MEDIA_TUNER_MC44S803 if !MEDIA_TUNER_CUSTOMISE help Say Y here to support the Afatech AF9015 based DVB-T USB2.0 receiver diff --git a/drivers/media/dvb/ttpci/Kconfig b/drivers/media/dvb/ttpci/Kconfig index ab0bcd208c78..772990415f99 100644 --- a/drivers/media/dvb/ttpci/Kconfig +++ b/drivers/media/dvb/ttpci/Kconfig @@ -108,7 +108,7 @@ config DVB_BUDGET_CI select DVB_STB6100 if !DVB_FE_CUSTOMISE select DVB_LNBP21 if !DVB_FE_CUSTOMISE select DVB_TDA10023 if !DVB_FE_CUSTOMISE - select MEDIA_TUNER_TDA827X if !MEDIA_TUNER_CUSTOMIZE + select MEDIA_TUNER_TDA827X if !MEDIA_TUNER_CUSTOMISE select VIDEO_IR help Support for simple SAA7146 based DVB cards diff --git a/drivers/media/video/au0828/Kconfig b/drivers/media/video/au0828/Kconfig index 551f9ba63876..05cdf494dfb0 100644 --- a/drivers/media/video/au0828/Kconfig +++ b/drivers/media/video/au0828/Kconfig @@ -5,9 +5,9 @@ config VIDEO_AU0828 select I2C_ALGOBIT select VIDEO_TVEEPROM select DVB_AU8522 if !DVB_FE_CUSTOMISE - select MEDIA_TUNER_XC5000 if !MEDIA_TUNER_CUSTOMIZE - select MEDIA_TUNER_MXL5007T if !MEDIA_TUNER_CUSTOMIZE - select MEDIA_TUNER_TDA18271 if !MEDIA_TUNER_CUSTOMIZE + select MEDIA_TUNER_XC5000 if !MEDIA_TUNER_CUSTOMISE + select MEDIA_TUNER_MXL5007T if !MEDIA_TUNER_CUSTOMISE + select MEDIA_TUNER_TDA18271 if !MEDIA_TUNER_CUSTOMISE ---help--- This is a video4linux driver for Auvitek's USB device. diff --git a/drivers/media/video/cx18/Kconfig b/drivers/media/video/cx18/Kconfig index 8940b5387dec..e8a50a611ebc 100644 --- a/drivers/media/video/cx18/Kconfig +++ b/drivers/media/video/cx18/Kconfig @@ -9,7 +9,7 @@ config VIDEO_CX18 select VIDEO_CX2341X select VIDEO_CS5345 select DVB_S5H1409 if !DVB_FE_CUSTOMISE - select MEDIA_TUNER_MXL5005S if !MEDIA_TUNER_CUSTOMIZE + select MEDIA_TUNER_MXL5005S if !MEDIA_TUNER_CUSTOMISE ---help--- This is a video4linux driver for Conexant cx23418 based PCI combo video recorder devices. diff --git a/drivers/media/video/cx23885/Kconfig b/drivers/media/video/cx23885/Kconfig index e603ceb2811b..fd3fc3e3198a 100644 --- a/drivers/media/video/cx23885/Kconfig +++ b/drivers/media/video/cx23885/Kconfig @@ -19,11 +19,11 @@ config VIDEO_CX23885 select DVB_LNBP21 if !DVB_FE_CUSTOMISE select DVB_STV6110 if !DVB_FE_CUSTOMISE select DVB_STV0900 if !DVB_FE_CUSTOMISE - select MEDIA_TUNER_MT2131 if !MEDIA_TUNER_CUSTOMIZE - select MEDIA_TUNER_XC2028 if !MEDIA_TUNER_CUSTOMIZE - select MEDIA_TUNER_TDA8290 if !MEDIA_TUNER_CUSTOMIZE - select MEDIA_TUNER_TDA18271 if !MEDIA_TUNER_CUSTOMIZE - select MEDIA_TUNER_XC5000 if !MEDIA_TUNER_CUSTOMIZE + select MEDIA_TUNER_MT2131 if !MEDIA_TUNER_CUSTOMISE + select MEDIA_TUNER_XC2028 if !MEDIA_TUNER_CUSTOMISE + select MEDIA_TUNER_TDA8290 if !MEDIA_TUNER_CUSTOMISE + select MEDIA_TUNER_TDA18271 if !MEDIA_TUNER_CUSTOMISE + select MEDIA_TUNER_XC5000 if !MEDIA_TUNER_CUSTOMISE ---help--- This is a video4linux driver for Conexant 23885 based TV cards. diff --git a/drivers/media/video/cx88/Kconfig b/drivers/media/video/cx88/Kconfig index 2d250a2a7bc3..49952980dab3 100644 --- a/drivers/media/video/cx88/Kconfig +++ b/drivers/media/video/cx88/Kconfig @@ -61,7 +61,7 @@ config VIDEO_CX88_DVB select DVB_STV0299 if !DVB_FE_CUSTOMISE select DVB_STV0288 if !DVB_FE_CUSTOMISE select DVB_STB6000 if !DVB_FE_CUSTOMISE - select MEDIA_TUNER_SIMPLE if !MEDIA_TUNER_CUSTOMIZE + select MEDIA_TUNER_SIMPLE if !MEDIA_TUNER_CUSTOMISE ---help--- This adds support for DVB/ATSC cards based on the Conexant 2388x chip. diff --git a/drivers/media/video/pvrusb2/Kconfig b/drivers/media/video/pvrusb2/Kconfig index 17cde17571c7..f9b6001e1dd7 100644 --- a/drivers/media/video/pvrusb2/Kconfig +++ b/drivers/media/video/pvrusb2/Kconfig @@ -41,9 +41,9 @@ config VIDEO_PVRUSB2_DVB select DVB_S5H1409 if !DVB_FE_CUSTOMISE select DVB_S5H1411 if !DVB_FE_CUSTOMISE select DVB_TDA10048 if !DVB_FE_CUSTOMISE - select MEDIA_TUNER_TDA18271 if !MEDIA_TUNER_CUSTOMIZE - select MEDIA_TUNER_SIMPLE if !MEDIA_TUNER_CUSTOMIZE - select MEDIA_TUNER_TDA8290 if !MEDIA_TUNER_CUSTOMIZE + select MEDIA_TUNER_TDA18271 if !MEDIA_TUNER_CUSTOMISE + select MEDIA_TUNER_SIMPLE if !MEDIA_TUNER_CUSTOMISE + select MEDIA_TUNER_TDA8290 if !MEDIA_TUNER_CUSTOMISE ---help--- This option enables a DVB interface for the pvrusb2 driver. diff --git a/drivers/media/video/saa7134/Kconfig b/drivers/media/video/saa7134/Kconfig index e62b2996768f..a2089acb0309 100644 --- a/drivers/media/video/saa7134/Kconfig +++ b/drivers/media/video/saa7134/Kconfig @@ -36,15 +36,15 @@ config VIDEO_SAA7134_DVB select DVB_TDA826X if !DVB_FE_CUSTOMISE select DVB_ISL6421 if !DVB_FE_CUSTOMISE select DVB_ISL6405 if !DVB_FE_CUSTOMISE - select MEDIA_TUNER_TDA827X if !MEDIA_TUNER_CUSTOMIZE - select MEDIA_TUNER_SIMPLE if !MEDIA_TUNER_CUSTOMIZE + select MEDIA_TUNER_TDA827X if !MEDIA_TUNER_CUSTOMISE + select MEDIA_TUNER_SIMPLE if !MEDIA_TUNER_CUSTOMISE select DVB_ZL10036 if !DVB_FE_CUSTOMISE select DVB_MT312 if !DVB_FE_CUSTOMISE select DVB_LNBP21 if !DVB_FE_CUSTOMISE select DVB_ZL10353 if !DVB_FE_CUSTOMISE select DVB_LGDT3305 if !DVB_FE_CUSTOMISE - select MEDIA_TUNER_TDA18271 if !MEDIA_TUNER_CUSTOMIZE - select MEDIA_TUNER_TDA8290 if !MEDIA_TUNER_CUSTOMIZE + select MEDIA_TUNER_TDA18271 if !MEDIA_TUNER_CUSTOMISE + select MEDIA_TUNER_TDA8290 if !MEDIA_TUNER_CUSTOMISE ---help--- This adds support for DVB cards based on the Philips saa7134 chip. -- cgit v1.2.3 From 62cfc346a325f60256f5eda93ac3b6e7ba6cdc1b Mon Sep 17 00:00:00 2001 From: Devin Heitmueller Date: Sun, 22 Mar 2009 22:58:46 -0300 Subject: V4L/DVB (11139): em28xx: add remote control definition for HVR-900 (both versions) The HVR-900 did not have a remote control defined, so it would not work. Add the line for both versions of the product. Thanks to Jens-Michael Hoffmann (#linuxtv user "jmho") for pointing out the issue and testing the patch. Signed-off-by: Devin Heitmueller Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/em28xx/em28xx-cards.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/media/video') diff --git a/drivers/media/video/em28xx/em28xx-cards.c b/drivers/media/video/em28xx/em28xx-cards.c index 650ccfda1428..0f48c0ff5ac3 100644 --- a/drivers/media/video/em28xx/em28xx-cards.c +++ b/drivers/media/video/em28xx/em28xx-cards.c @@ -619,6 +619,7 @@ struct em28xx_board em28xx_boards[] = { .mts_firmware = 1, .has_dvb = 1, .dvb_gpio = hauppauge_wintv_hvr_900_digital, + .ir_codes = ir_codes_hauppauge_new, .decoder = EM28XX_TVP5150, .input = { { .type = EM28XX_VMUX_TELEVISION, @@ -643,6 +644,7 @@ struct em28xx_board em28xx_boards[] = { .tuner_type = TUNER_XC2028, .tuner_gpio = default_tuner_gpio, .mts_firmware = 1, + .ir_codes = ir_codes_hauppauge_new, .decoder = EM28XX_TVP5150, .input = { { .type = EM28XX_VMUX_TELEVISION, -- cgit v1.2.3 From f876897015e15e879ad531f78260086a7fdee813 Mon Sep 17 00:00:00 2001 From: Devin Heitmueller Date: Sun, 22 Mar 2009 23:39:12 -0300 Subject: V4L/DVB (11140): usbvision: fix oops on ARM platform when allocating transfer buffers Add missing URB_NO_TRANSFER_DMA_MAP flag, since the use of consistent memory is not permitted for DMA on the ARM platform. Thanks to Paul Thomas for providing sample ARM hardware that was experiencing the oops (tested on the at91rm9200 based LinuxStamp). Thanks to David Brownell for providing insight into the ARM memory architecture. Signed-off-by: Devin Heitmueller Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/usbvision/usbvision-core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/usbvision/usbvision-core.c b/drivers/media/video/usbvision/usbvision-core.c index 71cb4aabdf7d..a0feb1c97736 100644 --- a/drivers/media/video/usbvision/usbvision-core.c +++ b/drivers/media/video/usbvision/usbvision-core.c @@ -2503,7 +2503,7 @@ int usbvision_init_isoc(struct usb_usbvision *usbvision) urb->dev = dev; urb->context = usbvision; urb->pipe = usb_rcvisocpipe(dev, usbvision->video_endp); - urb->transfer_flags = URB_ISO_ASAP; + urb->transfer_flags = URB_ISO_ASAP | URB_NO_TRANSFER_DMA_MAP; urb->interval = 1; urb->transfer_buffer = usbvision->sbuf[bufIdx].data; urb->complete = usbvision_isocIrq; -- cgit v1.2.3 From 9a4f8201a5d241dd725c1e1c796d826e49dcd396 Mon Sep 17 00:00:00 2001 From: Devin Heitmueller Date: Sun, 22 Mar 2009 23:41:28 -0300 Subject: V4L/DVB (11141): em28xx: fix oops on ARM platform when allocating transfer buffers Add missing URB_NO_TRANSFER_DMA_MAP flag, since the use of consistent memory is not permitted for DMA on the ARM platform. Thanks to Paul Thomas for providing sample ARM hardware that was experiencing the oops (tested on the at91rm9200 based LinuxStamp). Thanks to David Brownell for providing insight into the ARM memory architecture. Signed-off-by: Devin Heitmueller Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/em28xx/em28xx-core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/em28xx/em28xx-core.c b/drivers/media/video/em28xx/em28xx-core.c index c896d24032f5..8f1999ca4803 100644 --- a/drivers/media/video/em28xx/em28xx-core.c +++ b/drivers/media/video/em28xx/em28xx-core.c @@ -982,7 +982,7 @@ int em28xx_init_isoc(struct em28xx *dev, int max_packets, em28xx_irq_callback, dma_q, 1); urb->number_of_packets = max_packets; - urb->transfer_flags = URB_ISO_ASAP; + urb->transfer_flags = URB_ISO_ASAP | URB_NO_TRANSFER_DMA_MAP; k = 0; for (j = 0; j < max_packets; j++) { -- cgit v1.2.3 From fadadb7d7ad1d6c09863fcf24f83e59f596201ed Mon Sep 17 00:00:00 2001 From: Devin Heitmueller Date: Sun, 22 Mar 2009 23:42:26 -0300 Subject: V4L/DVB (11142): au0828: fix oops on ARM platform when allocating transfer buffers Add missing URB_NO_TRANSFER_DMA_MAP flag, since the use of consistent memory is not permitted for DMA on the ARM platform. Thanks to Paul Thomas for providing sample ARM hardware that was experiencing the oops (tested on the at91rm9200 based LinuxStamp). Thanks to David Brownell for providing insight into the ARM memory architecture. Signed-off-by: Devin Heitmueller Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/au0828/au0828-video.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/au0828/au0828-video.c b/drivers/media/video/au0828/au0828-video.c index d3a388af46e7..f7ad4958b94e 100644 --- a/drivers/media/video/au0828/au0828-video.c +++ b/drivers/media/video/au0828/au0828-video.c @@ -267,7 +267,7 @@ int au0828_init_isoc(struct au0828_dev *dev, int max_packets, au0828_irq_callback, dma_q, 1); urb->number_of_packets = max_packets; - urb->transfer_flags = URB_ISO_ASAP; + urb->transfer_flags = URB_ISO_ASAP | URB_NO_TRANSFER_DMA_MAP; k = 0; for (j = 0; j < max_packets; j++) { -- cgit v1.2.3 From 3da37e42baa8bd5953899ac078e36c97ba172e42 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Sun, 22 Mar 2009 16:29:36 -0300 Subject: V4L/DVB (11143): gspca - t613: Bad sensor detection. Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/t613.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/gspca/t613.c b/drivers/media/video/gspca/t613.c index 353931023ac8..9f312441092e 100644 --- a/drivers/media/video/gspca/t613.c +++ b/drivers/media/video/gspca/t613.c @@ -679,7 +679,7 @@ static int sd_init(struct gspca_dev *gspca_dev) sensor_id = (reg_r(gspca_dev, 0x06) << 8) | reg_r(gspca_dev, 0x07); - switch (sensor_id) { + switch (sensor_id & 0xff0f) { case 0x0801: PDEBUG(D_PROBE, "sensor tas5130a"); sd->sensor = SENSOR_TAS5130A; -- cgit v1.2.3 From 249fe889fd39801bd3a20cf245170dbd277a0501 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Sun, 22 Mar 2009 16:30:42 -0300 Subject: V4L/DVB (11144): gspca - t613: Don't re-read the ID registers at probe time. Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/t613.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/gspca/t613.c b/drivers/media/video/gspca/t613.c index 9f312441092e..f832f86b66de 100644 --- a/drivers/media/video/gspca/t613.c +++ b/drivers/media/video/gspca/t613.c @@ -639,7 +639,7 @@ static int sd_init(struct gspca_dev *gspca_dev) u16 reg80, reg8e; static const u8 read_indexs[] = - { 0x06, 0x07, 0x0a, 0x0b, 0x66, 0x80, 0x81, 0x8e, 0x8f, 0xa5, + { 0x0a, 0x0b, 0x66, 0x80, 0x81, 0x8e, 0x8f, 0xa5, 0xa6, 0xa8, 0xbb, 0xbc, 0xc6, 0x00 }; static const u8 n1[] = {0x08, 0x03, 0x09, 0x03, 0x12, 0x04}; -- cgit v1.2.3 From e30bdc669371ad511a5b4898aacfc01015553c5b Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Sun, 22 Mar 2009 16:31:32 -0300 Subject: V4L/DVB (11145): gspca - t613: Greater delay after om6802 reset. Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/t613.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/gspca/t613.c b/drivers/media/video/gspca/t613.c index f832f86b66de..f63e37e2e4fd 100644 --- a/drivers/media/video/gspca/t613.c +++ b/drivers/media/video/gspca/t613.c @@ -495,7 +495,7 @@ static void om6802_sensor_init(struct gspca_dev *gspca_dev) }; reg_w_buf(gspca_dev, sensor_reset, sizeof sensor_reset); - msleep(5); + msleep(100); i = 4; while (--i > 0) { byte = reg_r(gspca_dev, 0x0060); -- cgit v1.2.3 From 235d0ff2874091981c482d71bbce8b7c30cbc3b3 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Sun, 22 Mar 2009 16:33:47 -0300 Subject: V4L/DVB (11146): gspca - vc032x: Change the probe sequence. Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/vc032x.c | 73 ++++++++++++++++++++++++++------------ 1 file changed, 50 insertions(+), 23 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/gspca/vc032x.c b/drivers/media/video/gspca/vc032x.c index ca96cbc98794..728fff902f15 100644 --- a/drivers/media/video/gspca/vc032x.c +++ b/drivers/media/video/gspca/vc032x.c @@ -1877,26 +1877,42 @@ static const __u8 po1200_initVGA_data[][4] = { }; struct sensor_info { - int sensorId; - __u8 I2cAdd; - __u8 IdAdd; - __u16 VpId; - __u8 m1; - __u8 m2; - __u8 op; - }; + s8 sensorId; + u8 I2cAdd; + u8 IdAdd; + u16 VpId; + u8 m1; + u8 m2; + u8 op; +}; static const struct sensor_info sensor_info_data[] = { /* sensorId, I2cAdd, IdAdd, VpId, m1, m2, op */ - {SENSOR_HV7131R, 0x80 | 0x11, 0x00, 0x0209, 0x24, 0x25, 0x01}, - {SENSOR_OV7660, 0x80 | 0x21, 0x0a, 0x7660, 0x26, 0x26, 0x05}, + {-1, 0x80 | 0x30, 0x0a, 0x0000, 0x25, 0x24, 0x05}, + {-1, 0x80 | 0x20, 0x82, 0x0000, 0x24, 0x25, 0x01}, +/* (tested in vc032x_probe_sensor) */ +/* {-1, 0x80 | 0x20, 0x83, 0x0000, 0x24, 0x25, 0x01}, */ {SENSOR_PO3130NC, 0x80 | 0x76, 0x00, 0x3130, 0x24, 0x25, 0x01}, - {SENSOR_MI1320, 0x80 | 0xc8, 0x00, 0x148c, 0x64, 0x65, 0x01}, - {SENSOR_OV7670, 0x80 | 0x21, 0x0a, 0x7673, 0x66, 0x67, 0x05}, {SENSOR_MI1310_SOC, 0x80 | 0x5d, 0x00, 0x143a, 0x24, 0x25, 0x01}, /* (tested in vc032x_probe_sensor) */ /* {SENSOR_MI0360, 0x80 | 0x5d, 0x00, 0x8243, 0x24, 0x25, 0x01}, */ + {SENSOR_HV7131R, 0x80 | 0x11, 0x00, 0x0209, 0x24, 0x25, 0x01}, + {-1, 0x80 | 0x21, 0x0a, 0x0000, 0x21, 0x20, 0x05}, + {-1, 0x80 | 0x40, 0x00, 0x0000, 0x20, 0x22, 0x05}, + {SENSOR_OV7660, 0x80 | 0x21, 0x0a, 0x7660, 0x26, 0x26, 0x05}, +/* {SENSOR_PO3130NC, 0x80 | 0x76, 0x00, 0x0000, 0x24, 0x25, 0x01}, */ + {-1, 0x80 | 0x6e, 0x00, 0x0000, 0x24, 0x25, 0x01}, +/* {SENSOR_MI1310_SOC, 0x80 | 0x5d, 0x00, 0x0000, 0x24, 0x25, 0x01}, */ +/* {-1, 0x80 | 0x30, 0x0a, 0x0000, 0x25, 0x24, 0x05}, */ + {-1, 0x80 | 0x11, 0x39, 0x0000, 0x24, 0x25, 0x01}, {SENSOR_PO1200, 0x80 | 0x5c, 0x00, 0x1200, 0x67, 0x67, 0x01}, + {-1, 0x80 | 0x2d, 0x00, 0x0000, 0x65, 0x67, 0x01}, + {-1, 0x80 | 0x6e, 0x00, 0x0000, 0x24, 0x25, 0x01}, + {-1, 0x80 | 0x56, 0x01, 0x0000, 0x64, 0x67, 0x01}, + {-1, 0x80 | 0x48, 0x00, 0x0000, 0x64, 0x67, 0x01}, +/*fixme: not in the ms-win probe - may be found before?*/ + {SENSOR_MI1320, 0x80 | 0x48, 0x00, 0x148c, 0x64, 0x65, 0x01}, + {SENSOR_OV7670, 0x80 | 0x21, 0x0a, 0x7673, 0x66, 0x67, 0x05}, }; /* read 'len' bytes in gspca_dev->usb_buf */ @@ -1931,7 +1947,7 @@ static u16 read_sensor_register(struct gspca_dev *gspca_dev, u16 address) { struct usb_device *dev = gspca_dev->dev; - __u8 ldata, mdata, hdata; + u8 ldata, mdata, hdata; int retry = 50; reg_r(gspca_dev, 0xa1, 0xb33f, 1); @@ -1944,9 +1960,11 @@ static u16 read_sensor_register(struct gspca_dev *gspca_dev, reg_w(dev, 0xa0, 0x02, 0xb339); do { - msleep(8); reg_r(gspca_dev, 0xa1, 0xb33b, 1); - } while (retry-- && gspca_dev->usb_buf[0]); + if (gspca_dev->usb_buf[0] == 0x00) + break; + msleep(40); + } while (--retry >= 0); reg_r(gspca_dev, 0xa1, 0xb33e, 1); ldata = gspca_dev->usb_buf[0]; @@ -1967,7 +1985,7 @@ static int vc032x_probe_sensor(struct gspca_dev *gspca_dev) { struct usb_device *dev = gspca_dev->dev; int i; - __u16 value; + u16 value; const struct sensor_info *ptsensor_info; reg_r(gspca_dev, 0xa1, 0xbfcf, 1); @@ -1982,13 +2000,22 @@ static int vc032x_probe_sensor(struct gspca_dev *gspca_dev) reg_w(dev, 0xa0, ptsensor_info->I2cAdd, 0xb335); reg_w(dev, 0xa0, ptsensor_info->op, 0xb301); value = read_sensor_register(gspca_dev, ptsensor_info->IdAdd); - if (value == ptsensor_info->VpId) - return ptsensor_info->sensorId; - - /* special case for MI0360 */ - if (ptsensor_info->sensorId == SENSOR_MI1310_SOC - && value == 0x8243) - return SENSOR_MI0360; + if (value == 0 && ptsensor_info->IdAdd == 0x82) + value = read_sensor_register(gspca_dev, 0x83); + if (value != 0) { + PDEBUG(D_ERR|D_PROBE, "Sensor ID %04x (%d)", + value, i); + if (value == ptsensor_info->VpId) + return ptsensor_info->sensorId; + + switch (value) { + case 0x7673: + return SENSOR_OV7670; + case 0x8243: + return SENSOR_MI0360; + } +/*fixme: should return here*/ + } } return -1; } -- cgit v1.2.3 From c457377a3a18117aa99653f3715d81960a1c6bda Mon Sep 17 00:00:00 2001 From: Janne Grunau Date: Mon, 23 Mar 2009 18:18:54 -0300 Subject: V4L/DVB (11152): hdpvr: Fix build with Config_I2C not set Signed-off-by: Janne Grunau Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/hdpvr/Makefile | 4 +++- drivers/media/video/hdpvr/hdpvr-core.c | 10 ++++++++++ 2 files changed, 13 insertions(+), 1 deletion(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/hdpvr/Makefile b/drivers/media/video/hdpvr/Makefile index 79ad2e16cb8f..e0230fcb2e36 100644 --- a/drivers/media/video/hdpvr/Makefile +++ b/drivers/media/video/hdpvr/Makefile @@ -1,4 +1,6 @@ -hdpvr-objs := hdpvr-control.o hdpvr-core.o hdpvr-i2c.o hdpvr-video.o +hdpvr-objs := hdpvr-control.o hdpvr-core.o hdpvr-video.o + +hdpvr-$(CONFIG_I2C) += hdpvr-i2c.o obj-$(CONFIG_VIDEO_HDPVR) += hdpvr.o diff --git a/drivers/media/video/hdpvr/hdpvr-core.c b/drivers/media/video/hdpvr/hdpvr-core.c index 1c93589bf595..e96aed42d192 100644 --- a/drivers/media/video/hdpvr/hdpvr-core.c +++ b/drivers/media/video/hdpvr/hdpvr-core.c @@ -348,6 +348,14 @@ static int hdpvr_probe(struct usb_interface *interface, goto error; } +#ifdef CONFIG_I2C + /* until i2c is working properly */ + retval = 0; /* hdpvr_register_i2c_adapter(dev); */ + if (retval < 0) { + err("registering i2c adapter failed"); + goto error; + } +#endif /* CONFIG_I2C */ /* save our data pointer in this interface device */ usb_set_intfdata(interface, dev); @@ -389,12 +397,14 @@ static void hdpvr_disconnect(struct usb_interface *interface) mutex_unlock(&dev->io_mutex); /* deregister I2C adapter */ +#ifdef CONFIG_I2C mutex_lock(&dev->i2c_mutex); if (dev->i2c_adapter) i2c_del_adapter(dev->i2c_adapter); kfree(dev->i2c_adapter); dev->i2c_adapter = NULL; mutex_unlock(&dev->i2c_mutex); +#endif /* CONFIG_I2C */ atomic_dec(&dev_nr); -- cgit v1.2.3 From 59af33679592dd6e7bc7aa955098389724684a74 Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Sat, 7 Mar 2009 03:06:09 -0300 Subject: V4L/DVB (11154): pvrusb2: Split i2c module handling from i2c adapter This is the first step in the effort to move the pvrusb2 driver over to using the v4l2-subdev framework. This commit involves mainly splitting apart pvrusb2-i2c-core - part of it is the driver's I2C adapter driver and the rest is the old i2c module handling logic. The i2c module handling junk is moved out to pvrusb2-i2c-track and various header references are correspondingly updated. Yes, this patch has a huge pile of checkpatch complaints, but I'm NOT going to fix any of it. Why? First, I'm moving a large chunk of existing code and I'm not going to spend time adjusting it to match someone's idea of coding style. Second, in the end I expect all that moved code to go away by the time the rework is done so wasting time on it now to adhere to the standard is in the end a large waste of time. Signed-off-by: Mike Isely Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/pvrusb2/Makefile | 1 + drivers/media/video/pvrusb2/pvrusb2-audio.h | 2 +- drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.h | 2 +- drivers/media/video/pvrusb2/pvrusb2-debugifc.c | 2 +- drivers/media/video/pvrusb2/pvrusb2-hdw.c | 3 + .../media/video/pvrusb2/pvrusb2-i2c-chips-v4l2.c | 2 +- drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.h | 2 +- drivers/media/video/pvrusb2/pvrusb2-i2c-core.c | 417 +----------------- drivers/media/video/pvrusb2/pvrusb2-i2c-core.h | 57 +-- drivers/media/video/pvrusb2/pvrusb2-i2c-track.c | 480 +++++++++++++++++++++ drivers/media/video/pvrusb2/pvrusb2-i2c-track.h | 97 +++++ drivers/media/video/pvrusb2/pvrusb2-tuner.h | 2 +- drivers/media/video/pvrusb2/pvrusb2-video-v4l.h | 2 +- drivers/media/video/pvrusb2/pvrusb2-wm8775.h | 2 +- 14 files changed, 595 insertions(+), 476 deletions(-) create mode 100644 drivers/media/video/pvrusb2/pvrusb2-i2c-track.c create mode 100644 drivers/media/video/pvrusb2/pvrusb2-i2c-track.h (limited to 'drivers/media/video') diff --git a/drivers/media/video/pvrusb2/Makefile b/drivers/media/video/pvrusb2/Makefile index 4fda2de69ab7..931d9d1a0b4b 100644 --- a/drivers/media/video/pvrusb2/Makefile +++ b/drivers/media/video/pvrusb2/Makefile @@ -3,6 +3,7 @@ obj-pvrusb2-debugifc-$(CONFIG_VIDEO_PVRUSB2_DEBUGIFC) := pvrusb2-debugifc.o obj-pvrusb2-dvb-$(CONFIG_VIDEO_PVRUSB2_DVB) := pvrusb2-dvb.o pvrusb2-objs := pvrusb2-i2c-core.o pvrusb2-i2c-cmd-v4l2.o \ + pvrusb2-i2c-track.o \ pvrusb2-audio.o pvrusb2-i2c-chips-v4l2.o \ pvrusb2-encoder.o pvrusb2-video-v4l.o \ pvrusb2-eeprom.o pvrusb2-tuner.o \ diff --git a/drivers/media/video/pvrusb2/pvrusb2-audio.h b/drivers/media/video/pvrusb2/pvrusb2-audio.h index ac54eed3721b..f7f0a408a9b4 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-audio.h +++ b/drivers/media/video/pvrusb2/pvrusb2-audio.h @@ -22,7 +22,7 @@ #ifndef __PVRUSB2_AUDIO_H #define __PVRUSB2_AUDIO_H -#include "pvrusb2-i2c-core.h" +#include "pvrusb2-i2c-track.h" int pvr2_i2c_msp3400_setup(struct pvr2_hdw *,struct pvr2_i2c_client *); diff --git a/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.h b/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.h index 66abf77f51fd..f664f5942002 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.h +++ b/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.h @@ -34,7 +34,7 @@ -#include "pvrusb2-i2c-core.h" +#include "pvrusb2-i2c-track.h" int pvr2_i2c_cx2584x_v4l_setup(struct pvr2_hdw *,struct pvr2_i2c_client *); diff --git a/drivers/media/video/pvrusb2/pvrusb2-debugifc.c b/drivers/media/video/pvrusb2/pvrusb2-debugifc.c index ca892fb78a5b..cc4ef891b5b6 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-debugifc.c +++ b/drivers/media/video/pvrusb2/pvrusb2-debugifc.c @@ -23,7 +23,7 @@ #include "pvrusb2-debugifc.h" #include "pvrusb2-hdw.h" #include "pvrusb2-debug.h" -#include "pvrusb2-i2c-core.h" +#include "pvrusb2-i2c-track.h" struct debugifc_mask_item { const char *name; diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/drivers/media/video/pvrusb2/pvrusb2-hdw.c index ed8a4561e086..9441bcc37bc3 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-hdw.c +++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.c @@ -29,6 +29,7 @@ #include "pvrusb2-util.h" #include "pvrusb2-hdw.h" #include "pvrusb2-i2c-core.h" +#include "pvrusb2-i2c-track.h" #include "pvrusb2-tuner.h" #include "pvrusb2-eeprom.h" #include "pvrusb2-hdw-internal.h" @@ -1990,6 +1991,7 @@ static void pvr2_hdw_setup_low(struct pvr2_hdw *hdw) } // This step MUST happen after the earlier powerup step. + pvr2_i2c_track_init(hdw); pvr2_i2c_core_init(hdw); if (!pvr2_hdw_dev_ok(hdw)) return; @@ -2501,6 +2503,7 @@ void pvr2_hdw_destroy(struct pvr2_hdw *hdw) hdw->decoder_ctrl->detach(hdw->decoder_ctrl->ctxt); } pvr2_i2c_core_done(hdw); + pvr2_i2c_track_done(hdw); pvr2_hdw_remove_usb_stuff(hdw); mutex_lock(&pvr2_unit_mtx); do { if ((hdw->unit_number >= 0) && diff --git a/drivers/media/video/pvrusb2/pvrusb2-i2c-chips-v4l2.c b/drivers/media/video/pvrusb2/pvrusb2-i2c-chips-v4l2.c index 4cf980c49d01..8f32c2edb49a 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-i2c-chips-v4l2.c +++ b/drivers/media/video/pvrusb2/pvrusb2-i2c-chips-v4l2.c @@ -19,7 +19,7 @@ */ #include -#include "pvrusb2-i2c-core.h" +#include "pvrusb2-i2c-track.h" #include "pvrusb2-hdw-internal.h" #include "pvrusb2-debug.h" #include "pvrusb2-i2c-cmd-v4l2.h" diff --git a/drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.h b/drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.h index 69a63f2a8a7b..8472637e48eb 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.h +++ b/drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.h @@ -22,7 +22,7 @@ #ifndef __PVRUSB2_CMD_V4L2_H #define __PVRUSB2_CMD_V4L2_H -#include "pvrusb2-i2c-core.h" +#include "pvrusb2-i2c-track.h" extern const struct pvr2_i2c_op pvr2_i2c_op_v4l2_init; extern const struct pvr2_i2c_op pvr2_i2c_op_v4l2_standard; diff --git a/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c b/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c index 57a024737722..2ba429f1bc8e 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c +++ b/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c @@ -18,7 +18,9 @@ * */ +#include #include "pvrusb2-i2c-core.h" +#include "pvrusb2-i2c-track.h" #include "pvrusb2-hdw-internal.h" #include "pvrusb2-debug.h" #include "pvrusb2-fx2-cmd.h" @@ -29,8 +31,7 @@ /* This module attempts to implement a compliant I2C adapter for the pvrusb2 - device. By doing this we can then make use of existing functionality in - V4L (e.g. tuner.c) rather than rolling our own. + device. */ @@ -42,10 +43,6 @@ static int ir_mode[PVR_NUM] = { [0 ... PVR_NUM-1] = 1 }; module_param_array(ir_mode, int, NULL, 0444); MODULE_PARM_DESC(ir_mode,"specify: 0=disable IR reception, 1=normal IR"); -static unsigned int pvr2_i2c_client_describe(struct pvr2_i2c_client *cp, - unsigned int detail, - char *buf,unsigned int maxlen); - static int pvr2_i2c_write(struct pvr2_hdw *hdw, /* Context */ u8 i2c_addr, /* I2C address we're talking to */ u8 *data, /* Data to write */ @@ -524,414 +521,15 @@ static u32 pvr2_i2c_functionality(struct i2c_adapter *adap) return I2C_FUNC_SMBUS_EMUL | I2C_FUNC_I2C; } -static int pvr2_i2c_core_singleton(struct i2c_client *cp, - unsigned int cmd,void *arg) -{ - int stat; - if (!cp) return -EINVAL; - if (!(cp->driver)) return -EINVAL; - if (!(cp->driver->command)) return -EINVAL; - if (!try_module_get(cp->driver->driver.owner)) return -EAGAIN; - stat = cp->driver->command(cp,cmd,arg); - module_put(cp->driver->driver.owner); - return stat; -} - -int pvr2_i2c_client_cmd(struct pvr2_i2c_client *cp,unsigned int cmd,void *arg) -{ - int stat; - if (pvrusb2_debug & PVR2_TRACE_I2C_CMD) { - char buf[100]; - unsigned int cnt; - cnt = pvr2_i2c_client_describe(cp,PVR2_I2C_DETAIL_DEBUG, - buf,sizeof(buf)); - pvr2_trace(PVR2_TRACE_I2C_CMD, - "i2c COMMAND (code=%u 0x%x) to %.*s", - cmd,cmd,cnt,buf); - } - stat = pvr2_i2c_core_singleton(cp->client,cmd,arg); - if (pvrusb2_debug & PVR2_TRACE_I2C_CMD) { - char buf[100]; - unsigned int cnt; - cnt = pvr2_i2c_client_describe(cp,PVR2_I2C_DETAIL_DEBUG, - buf,sizeof(buf)); - pvr2_trace(PVR2_TRACE_I2C_CMD, - "i2c COMMAND to %.*s (ret=%d)",cnt,buf,stat); - } - return stat; -} - -int pvr2_i2c_core_cmd(struct pvr2_hdw *hdw,unsigned int cmd,void *arg) -{ - struct pvr2_i2c_client *cp, *ncp; - int stat = -EINVAL; - - if (!hdw) return stat; - - mutex_lock(&hdw->i2c_list_lock); - list_for_each_entry_safe(cp, ncp, &hdw->i2c_clients, list) { - if (!cp->recv_enable) continue; - mutex_unlock(&hdw->i2c_list_lock); - stat = pvr2_i2c_client_cmd(cp,cmd,arg); - mutex_lock(&hdw->i2c_list_lock); - } - mutex_unlock(&hdw->i2c_list_lock); - return stat; -} - - -static int handler_check(struct pvr2_i2c_client *cp) -{ - struct pvr2_i2c_handler *hp = cp->handler; - if (!hp) return 0; - if (!hp->func_table->check) return 0; - return hp->func_table->check(hp->func_data) != 0; -} - -#define BUFSIZE 500 - - -void pvr2_i2c_core_status_poll(struct pvr2_hdw *hdw) -{ - struct pvr2_i2c_client *cp; - mutex_lock(&hdw->i2c_list_lock); do { - struct v4l2_tuner *vtp = &hdw->tuner_signal_info; - memset(vtp,0,sizeof(*vtp)); - list_for_each_entry(cp, &hdw->i2c_clients, list) { - if (!cp->detected_flag) continue; - if (!cp->status_poll) continue; - cp->status_poll(cp); - } - hdw->tuner_signal_stale = 0; - pvr2_trace(PVR2_TRACE_CHIPS,"i2c status poll" - " type=%u strength=%u audio=0x%x cap=0x%x" - " low=%u hi=%u", - vtp->type, - vtp->signal,vtp->rxsubchans,vtp->capability, - vtp->rangelow,vtp->rangehigh); - } while (0); mutex_unlock(&hdw->i2c_list_lock); -} - - -/* Issue various I2C operations to bring chip-level drivers into sync with - state stored in this driver. */ -void pvr2_i2c_core_sync(struct pvr2_hdw *hdw) -{ - unsigned long msk; - unsigned int idx; - struct pvr2_i2c_client *cp, *ncp; - - if (!hdw->i2c_linked) return; - if (!(hdw->i2c_pend_types & PVR2_I2C_PEND_ALL)) { - return; - } - mutex_lock(&hdw->i2c_list_lock); do { - pvr2_trace(PVR2_TRACE_I2C_CORE,"i2c: core_sync BEGIN"); - if (hdw->i2c_pend_types & PVR2_I2C_PEND_DETECT) { - /* One or more I2C clients have attached since we - last synced. So scan the list and identify the - new clients. */ - char *buf; - unsigned int cnt; - unsigned long amask = 0; - buf = kmalloc(BUFSIZE,GFP_KERNEL); - pvr2_trace(PVR2_TRACE_I2C_CORE,"i2c: PEND_DETECT"); - hdw->i2c_pend_types &= ~PVR2_I2C_PEND_DETECT; - list_for_each_entry(cp, &hdw->i2c_clients, list) { - if (!cp->detected_flag) { - cp->ctl_mask = 0; - pvr2_i2c_probe(hdw,cp); - cp->detected_flag = !0; - msk = cp->ctl_mask; - cnt = 0; - if (buf) { - cnt = pvr2_i2c_client_describe( - cp, - PVR2_I2C_DETAIL_ALL, - buf,BUFSIZE); - } - trace_i2c("Probed: %.*s",cnt,buf); - if (handler_check(cp)) { - hdw->i2c_pend_types |= - PVR2_I2C_PEND_CLIENT; - } - cp->pend_mask = msk; - hdw->i2c_pend_mask |= msk; - hdw->i2c_pend_types |= - PVR2_I2C_PEND_REFRESH; - } - amask |= cp->ctl_mask; - } - hdw->i2c_active_mask = amask; - if (buf) kfree(buf); - } - if (hdw->i2c_pend_types & PVR2_I2C_PEND_STALE) { - /* Need to do one or more global updates. Arrange - for this to happen. */ - unsigned long m2; - pvr2_trace(PVR2_TRACE_I2C_CORE, - "i2c: PEND_STALE (0x%lx)", - hdw->i2c_stale_mask); - hdw->i2c_pend_types &= ~PVR2_I2C_PEND_STALE; - list_for_each_entry(cp, &hdw->i2c_clients, list) { - m2 = hdw->i2c_stale_mask; - m2 &= cp->ctl_mask; - m2 &= ~cp->pend_mask; - if (m2) { - pvr2_trace(PVR2_TRACE_I2C_CORE, - "i2c: cp=%p setting 0x%lx", - cp,m2); - cp->pend_mask |= m2; - } - } - hdw->i2c_pend_mask |= hdw->i2c_stale_mask; - hdw->i2c_stale_mask = 0; - hdw->i2c_pend_types |= PVR2_I2C_PEND_REFRESH; - } - if (hdw->i2c_pend_types & PVR2_I2C_PEND_CLIENT) { - /* One or more client handlers are asking for an - update. Run through the list of known clients - and update each one. */ - pvr2_trace(PVR2_TRACE_I2C_CORE,"i2c: PEND_CLIENT"); - hdw->i2c_pend_types &= ~PVR2_I2C_PEND_CLIENT; - list_for_each_entry_safe(cp, ncp, &hdw->i2c_clients, - list) { - if (!cp->handler) continue; - if (!cp->handler->func_table->update) continue; - pvr2_trace(PVR2_TRACE_I2C_CORE, - "i2c: cp=%p update",cp); - mutex_unlock(&hdw->i2c_list_lock); - cp->handler->func_table->update( - cp->handler->func_data); - mutex_lock(&hdw->i2c_list_lock); - /* If client's update function set some - additional pending bits, account for that - here. */ - if (cp->pend_mask & ~hdw->i2c_pend_mask) { - hdw->i2c_pend_mask |= cp->pend_mask; - hdw->i2c_pend_types |= - PVR2_I2C_PEND_REFRESH; - } - } - } - if (hdw->i2c_pend_types & PVR2_I2C_PEND_REFRESH) { - const struct pvr2_i2c_op *opf; - unsigned long pm; - /* Some actual updates are pending. Walk through - each update type and perform it. */ - pvr2_trace(PVR2_TRACE_I2C_CORE,"i2c: PEND_REFRESH" - " (0x%lx)",hdw->i2c_pend_mask); - hdw->i2c_pend_types &= ~PVR2_I2C_PEND_REFRESH; - pm = hdw->i2c_pend_mask; - hdw->i2c_pend_mask = 0; - for (idx = 0, msk = 1; pm; idx++, msk <<= 1) { - if (!(pm & msk)) continue; - pm &= ~msk; - list_for_each_entry(cp, &hdw->i2c_clients, - list) { - if (cp->pend_mask & msk) { - cp->pend_mask &= ~msk; - cp->recv_enable = !0; - } else { - cp->recv_enable = 0; - } - } - opf = pvr2_i2c_get_op(idx); - if (!opf) continue; - mutex_unlock(&hdw->i2c_list_lock); - opf->update(hdw); - mutex_lock(&hdw->i2c_list_lock); - } - } - pvr2_trace(PVR2_TRACE_I2C_CORE,"i2c: core_sync END"); - } while (0); mutex_unlock(&hdw->i2c_list_lock); -} - -int pvr2_i2c_core_check_stale(struct pvr2_hdw *hdw) -{ - unsigned long msk,sm,pm; - unsigned int idx; - const struct pvr2_i2c_op *opf; - struct pvr2_i2c_client *cp; - unsigned int pt = 0; - - pvr2_trace(PVR2_TRACE_I2C_CORE,"pvr2_i2c_core_check_stale BEGIN"); - - pm = hdw->i2c_active_mask; - sm = 0; - for (idx = 0, msk = 1; pm; idx++, msk <<= 1) { - if (!(msk & pm)) continue; - pm &= ~msk; - opf = pvr2_i2c_get_op(idx); - if (!(opf && opf->check)) continue; - if (opf->check(hdw)) { - sm |= msk; - } - } - if (sm) pt |= PVR2_I2C_PEND_STALE; - - list_for_each_entry(cp, &hdw->i2c_clients, list) - if (handler_check(cp)) - pt |= PVR2_I2C_PEND_CLIENT; - - if (pt) { - mutex_lock(&hdw->i2c_list_lock); do { - hdw->i2c_pend_types |= pt; - hdw->i2c_stale_mask |= sm; - hdw->i2c_pend_mask |= hdw->i2c_stale_mask; - } while (0); mutex_unlock(&hdw->i2c_list_lock); - } - - pvr2_trace(PVR2_TRACE_I2C_CORE, - "i2c: types=0x%x stale=0x%lx pend=0x%lx", - hdw->i2c_pend_types, - hdw->i2c_stale_mask, - hdw->i2c_pend_mask); - pvr2_trace(PVR2_TRACE_I2C_CORE,"pvr2_i2c_core_check_stale END"); - - return (hdw->i2c_pend_types & PVR2_I2C_PEND_ALL) != 0; -} - -static unsigned int pvr2_i2c_client_describe(struct pvr2_i2c_client *cp, - unsigned int detail, - char *buf,unsigned int maxlen) -{ - unsigned int ccnt,bcnt; - int spcfl = 0; - const struct pvr2_i2c_op *opf; - - ccnt = 0; - if (detail & PVR2_I2C_DETAIL_DEBUG) { - bcnt = scnprintf(buf,maxlen, - "ctxt=%p ctl_mask=0x%lx", - cp,cp->ctl_mask); - ccnt += bcnt; buf += bcnt; maxlen -= bcnt; - spcfl = !0; - } - bcnt = scnprintf(buf,maxlen, - "%s%s @ 0x%x", - (spcfl ? " " : ""), - cp->client->name, - cp->client->addr); - ccnt += bcnt; buf += bcnt; maxlen -= bcnt; - if ((detail & PVR2_I2C_DETAIL_HANDLER) && - cp->handler && cp->handler->func_table->describe) { - bcnt = scnprintf(buf,maxlen," ("); - ccnt += bcnt; buf += bcnt; maxlen -= bcnt; - bcnt = cp->handler->func_table->describe( - cp->handler->func_data,buf,maxlen); - ccnt += bcnt; buf += bcnt; maxlen -= bcnt; - bcnt = scnprintf(buf,maxlen,")"); - ccnt += bcnt; buf += bcnt; maxlen -= bcnt; - } - if ((detail & PVR2_I2C_DETAIL_CTLMASK) && cp->ctl_mask) { - unsigned int idx; - unsigned long msk,sm; - - bcnt = scnprintf(buf,maxlen," ["); - ccnt += bcnt; buf += bcnt; maxlen -= bcnt; - sm = 0; - spcfl = 0; - for (idx = 0, msk = 1; msk; idx++, msk <<= 1) { - if (!(cp->ctl_mask & msk)) continue; - opf = pvr2_i2c_get_op(idx); - if (opf) { - bcnt = scnprintf(buf,maxlen,"%s%s", - spcfl ? " " : "", - opf->name); - ccnt += bcnt; buf += bcnt; maxlen -= bcnt; - spcfl = !0; - } else { - sm |= msk; - } - } - if (sm) { - bcnt = scnprintf(buf,maxlen,"%s%lx", - idx != 0 ? " " : "",sm); - ccnt += bcnt; buf += bcnt; maxlen -= bcnt; - } - bcnt = scnprintf(buf,maxlen,"]"); - ccnt += bcnt; buf += bcnt; maxlen -= bcnt; - } - return ccnt; -} - -unsigned int pvr2_i2c_report(struct pvr2_hdw *hdw, - char *buf,unsigned int maxlen) -{ - unsigned int ccnt,bcnt; - struct pvr2_i2c_client *cp; - ccnt = 0; - mutex_lock(&hdw->i2c_list_lock); do { - list_for_each_entry(cp, &hdw->i2c_clients, list) { - bcnt = pvr2_i2c_client_describe( - cp, - (PVR2_I2C_DETAIL_HANDLER| - PVR2_I2C_DETAIL_CTLMASK), - buf,maxlen); - ccnt += bcnt; buf += bcnt; maxlen -= bcnt; - bcnt = scnprintf(buf,maxlen,"\n"); - ccnt += bcnt; buf += bcnt; maxlen -= bcnt; - } - } while (0); mutex_unlock(&hdw->i2c_list_lock); - return ccnt; -} - static int pvr2_i2c_attach_inform(struct i2c_client *client) { - struct pvr2_hdw *hdw = (struct pvr2_hdw *)(client->adapter->algo_data); - struct pvr2_i2c_client *cp; - int fl = !(hdw->i2c_pend_types & PVR2_I2C_PEND_ALL); - cp = kzalloc(sizeof(*cp),GFP_KERNEL); - trace_i2c("i2c_attach [client=%s @ 0x%x ctxt=%p]", - client->name, - client->addr,cp); - if (!cp) return -ENOMEM; - cp->hdw = hdw; - INIT_LIST_HEAD(&cp->list); - cp->client = client; - mutex_lock(&hdw->i2c_list_lock); do { - hdw->cropcap_stale = !0; - list_add_tail(&cp->list,&hdw->i2c_clients); - hdw->i2c_pend_types |= PVR2_I2C_PEND_DETECT; - } while (0); mutex_unlock(&hdw->i2c_list_lock); - if (fl) queue_work(hdw->workqueue,&hdw->worki2csync); + pvr2_i2c_track_attach_inform(client); return 0; } static int pvr2_i2c_detach_inform(struct i2c_client *client) { - struct pvr2_hdw *hdw = (struct pvr2_hdw *)(client->adapter->algo_data); - struct pvr2_i2c_client *cp, *ncp; - unsigned long amask = 0; - int foundfl = 0; - mutex_lock(&hdw->i2c_list_lock); do { - hdw->cropcap_stale = !0; - list_for_each_entry_safe(cp, ncp, &hdw->i2c_clients, list) { - if (cp->client == client) { - trace_i2c("pvr2_i2c_detach" - " [client=%s @ 0x%x ctxt=%p]", - client->name, - client->addr,cp); - if (cp->handler && - cp->handler->func_table->detach) { - cp->handler->func_table->detach( - cp->handler->func_data); - } - list_del(&cp->list); - kfree(cp); - foundfl = !0; - continue; - } - amask |= cp->ctl_mask; - } - hdw->i2c_active_mask = amask; - } while (0); mutex_unlock(&hdw->i2c_list_lock); - if (!foundfl) { - trace_i2c("pvr2_i2c_detach [client=%s @ 0x%x ctxt=]", - client->name, - client->addr); - } + pvr2_i2c_track_detach_inform(client); return 0; } @@ -1009,11 +607,6 @@ void pvr2_i2c_core_init(struct pvr2_hdw *hdw) hdw->i2c_adap.dev.parent = &hdw->usb_dev->dev; hdw->i2c_adap.algo = &hdw->i2c_algo; hdw->i2c_adap.algo_data = hdw; - hdw->i2c_pend_mask = 0; - hdw->i2c_stale_mask = 0; - hdw->i2c_active_mask = 0; - INIT_LIST_HEAD(&hdw->i2c_clients); - mutex_init(&hdw->i2c_list_lock); hdw->i2c_linked = !0; i2c_add_adapter(&hdw->i2c_adap); if (hdw->i2c_func[0x18] == i2c_24xxx_ir) { diff --git a/drivers/media/video/pvrusb2/pvrusb2-i2c-core.h b/drivers/media/video/pvrusb2/pvrusb2-i2c-core.h index 6ef7a1c0e935..6a75769200bd 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-i2c-core.h +++ b/drivers/media/video/pvrusb2/pvrusb2-i2c-core.h @@ -20,68 +20,13 @@ #ifndef __PVRUSB2_I2C_CORE_H #define __PVRUSB2_I2C_CORE_H -#include -#include - struct pvr2_hdw; -struct pvr2_i2c_client; -struct pvr2_i2c_handler; -struct pvr2_i2c_handler_functions; -struct pvr2_i2c_op; -struct pvr2_i2c_op_functions; - -struct pvr2_i2c_client { - struct i2c_client *client; - struct pvr2_i2c_handler *handler; - struct list_head list; - struct pvr2_hdw *hdw; - int detected_flag; - int recv_enable; - unsigned long pend_mask; - unsigned long ctl_mask; - void (*status_poll)(struct pvr2_i2c_client *); -}; - -struct pvr2_i2c_handler { - void *func_data; - const struct pvr2_i2c_handler_functions *func_table; -}; - -struct pvr2_i2c_handler_functions { - void (*detach)(void *); - int (*check)(void *); - void (*update)(void *); - unsigned int (*describe)(void *,char *,unsigned int); -}; - -struct pvr2_i2c_op { - int (*check)(struct pvr2_hdw *); - void (*update)(struct pvr2_hdw *); - const char *name; -}; void pvr2_i2c_core_init(struct pvr2_hdw *); void pvr2_i2c_core_done(struct pvr2_hdw *); -int pvr2_i2c_client_cmd(struct pvr2_i2c_client *,unsigned int cmd,void *arg); -int pvr2_i2c_core_cmd(struct pvr2_hdw *,unsigned int cmd,void *arg); - -int pvr2_i2c_core_check_stale(struct pvr2_hdw *); -void pvr2_i2c_core_sync(struct pvr2_hdw *); -void pvr2_i2c_core_status_poll(struct pvr2_hdw *); -unsigned int pvr2_i2c_report(struct pvr2_hdw *,char *buf,unsigned int maxlen); -#define PVR2_I2C_DETAIL_DEBUG 0x0001 -#define PVR2_I2C_DETAIL_HANDLER 0x0002 -#define PVR2_I2C_DETAIL_CTLMASK 0x0004 -#define PVR2_I2C_DETAIL_ALL (\ - PVR2_I2C_DETAIL_DEBUG |\ - PVR2_I2C_DETAIL_HANDLER |\ - PVR2_I2C_DETAIL_CTLMASK) - -void pvr2_i2c_probe(struct pvr2_hdw *,struct pvr2_i2c_client *); -const struct pvr2_i2c_op *pvr2_i2c_get_op(unsigned int idx); -#endif /* __PVRUSB2_I2C_CORE_H */ +#endif /* __PVRUSB2_I2C_ADAPTER_H */ /* diff --git a/drivers/media/video/pvrusb2/pvrusb2-i2c-track.c b/drivers/media/video/pvrusb2/pvrusb2-i2c-track.c new file mode 100644 index 000000000000..48cffa4a1b6a --- /dev/null +++ b/drivers/media/video/pvrusb2/pvrusb2-i2c-track.c @@ -0,0 +1,480 @@ +/* + * + * + * Copyright (C) 2005 Mike Isely + * + * 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 + * + * 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 + * + */ + +#include "pvrusb2-i2c-track.h" +#include "pvrusb2-hdw-internal.h" +#include "pvrusb2-debug.h" +#include "pvrusb2-fx2-cmd.h" +#include "pvrusb2.h" + +#define trace_i2c(...) pvr2_trace(PVR2_TRACE_I2C,__VA_ARGS__) + +/* + + This module implements the foundation of a rather large architecture for + tracking state in all the various V4L I2C modules. This is obsolete with + kernels later than roughly 2.6.24, but it is still present in the + standalone pvrusb2 driver to allow continued operation with older + kernel. + +*/ + +static unsigned int pvr2_i2c_client_describe(struct pvr2_i2c_client *cp, + unsigned int detail, + char *buf,unsigned int maxlen); + +static int pvr2_i2c_core_singleton(struct i2c_client *cp, + unsigned int cmd,void *arg) +{ + int stat; + if (!cp) return -EINVAL; + if (!(cp->driver)) return -EINVAL; + if (!(cp->driver->command)) return -EINVAL; + if (!try_module_get(cp->driver->driver.owner)) return -EAGAIN; + stat = cp->driver->command(cp,cmd,arg); + module_put(cp->driver->driver.owner); + return stat; +} + +int pvr2_i2c_client_cmd(struct pvr2_i2c_client *cp,unsigned int cmd,void *arg) +{ + int stat; + if (pvrusb2_debug & PVR2_TRACE_I2C_CMD) { + char buf[100]; + unsigned int cnt; + cnt = pvr2_i2c_client_describe(cp,PVR2_I2C_DETAIL_DEBUG, + buf,sizeof(buf)); + pvr2_trace(PVR2_TRACE_I2C_CMD, + "i2c COMMAND (code=%u 0x%x) to %.*s", + cmd,cmd,cnt,buf); + } + stat = pvr2_i2c_core_singleton(cp->client,cmd,arg); + if (pvrusb2_debug & PVR2_TRACE_I2C_CMD) { + char buf[100]; + unsigned int cnt; + cnt = pvr2_i2c_client_describe(cp,PVR2_I2C_DETAIL_DEBUG, + buf,sizeof(buf)); + pvr2_trace(PVR2_TRACE_I2C_CMD, + "i2c COMMAND to %.*s (ret=%d)",cnt,buf,stat); + } + return stat; +} + +int pvr2_i2c_core_cmd(struct pvr2_hdw *hdw,unsigned int cmd,void *arg) +{ + struct pvr2_i2c_client *cp, *ncp; + int stat = -EINVAL; + + if (!hdw) return stat; + + mutex_lock(&hdw->i2c_list_lock); + list_for_each_entry_safe(cp, ncp, &hdw->i2c_clients, list) { + if (!cp->recv_enable) continue; + mutex_unlock(&hdw->i2c_list_lock); + stat = pvr2_i2c_client_cmd(cp,cmd,arg); + mutex_lock(&hdw->i2c_list_lock); + } + mutex_unlock(&hdw->i2c_list_lock); + return stat; +} + + +static int handler_check(struct pvr2_i2c_client *cp) +{ + struct pvr2_i2c_handler *hp = cp->handler; + if (!hp) return 0; + if (!hp->func_table->check) return 0; + return hp->func_table->check(hp->func_data) != 0; +} + +#define BUFSIZE 500 + + +void pvr2_i2c_core_status_poll(struct pvr2_hdw *hdw) +{ + struct pvr2_i2c_client *cp; + mutex_lock(&hdw->i2c_list_lock); do { + struct v4l2_tuner *vtp = &hdw->tuner_signal_info; + memset(vtp,0,sizeof(*vtp)); + list_for_each_entry(cp, &hdw->i2c_clients, list) { + if (!cp->detected_flag) continue; + if (!cp->status_poll) continue; + cp->status_poll(cp); + } + hdw->tuner_signal_stale = 0; + pvr2_trace(PVR2_TRACE_CHIPS,"i2c status poll" + " type=%u strength=%u audio=0x%x cap=0x%x" + " low=%u hi=%u", + vtp->type, + vtp->signal,vtp->rxsubchans,vtp->capability, + vtp->rangelow,vtp->rangehigh); + } while (0); mutex_unlock(&hdw->i2c_list_lock); +} + + +/* Issue various I2C operations to bring chip-level drivers into sync with + state stored in this driver. */ +void pvr2_i2c_core_sync(struct pvr2_hdw *hdw) +{ + unsigned long msk; + unsigned int idx; + struct pvr2_i2c_client *cp, *ncp; + + if (!hdw->i2c_linked) return; + if (!(hdw->i2c_pend_types & PVR2_I2C_PEND_ALL)) { + return; + } + mutex_lock(&hdw->i2c_list_lock); do { + pvr2_trace(PVR2_TRACE_I2C_CORE,"i2c: core_sync BEGIN"); + if (hdw->i2c_pend_types & PVR2_I2C_PEND_DETECT) { + /* One or more I2C clients have attached since we + last synced. So scan the list and identify the + new clients. */ + char *buf; + unsigned int cnt; + unsigned long amask = 0; + buf = kmalloc(BUFSIZE,GFP_KERNEL); + pvr2_trace(PVR2_TRACE_I2C_CORE,"i2c: PEND_DETECT"); + hdw->i2c_pend_types &= ~PVR2_I2C_PEND_DETECT; + list_for_each_entry(cp, &hdw->i2c_clients, list) { + if (!cp->detected_flag) { + cp->ctl_mask = 0; + pvr2_i2c_probe(hdw,cp); + cp->detected_flag = !0; + msk = cp->ctl_mask; + cnt = 0; + if (buf) { + cnt = pvr2_i2c_client_describe( + cp, + PVR2_I2C_DETAIL_ALL, + buf,BUFSIZE); + } + trace_i2c("Probed: %.*s",cnt,buf); + if (handler_check(cp)) { + hdw->i2c_pend_types |= + PVR2_I2C_PEND_CLIENT; + } + cp->pend_mask = msk; + hdw->i2c_pend_mask |= msk; + hdw->i2c_pend_types |= + PVR2_I2C_PEND_REFRESH; + } + amask |= cp->ctl_mask; + } + hdw->i2c_active_mask = amask; + if (buf) kfree(buf); + } + if (hdw->i2c_pend_types & PVR2_I2C_PEND_STALE) { + /* Need to do one or more global updates. Arrange + for this to happen. */ + unsigned long m2; + pvr2_trace(PVR2_TRACE_I2C_CORE, + "i2c: PEND_STALE (0x%lx)", + hdw->i2c_stale_mask); + hdw->i2c_pend_types &= ~PVR2_I2C_PEND_STALE; + list_for_each_entry(cp, &hdw->i2c_clients, list) { + m2 = hdw->i2c_stale_mask; + m2 &= cp->ctl_mask; + m2 &= ~cp->pend_mask; + if (m2) { + pvr2_trace(PVR2_TRACE_I2C_CORE, + "i2c: cp=%p setting 0x%lx", + cp,m2); + cp->pend_mask |= m2; + } + } + hdw->i2c_pend_mask |= hdw->i2c_stale_mask; + hdw->i2c_stale_mask = 0; + hdw->i2c_pend_types |= PVR2_I2C_PEND_REFRESH; + } + if (hdw->i2c_pend_types & PVR2_I2C_PEND_CLIENT) { + /* One or more client handlers are asking for an + update. Run through the list of known clients + and update each one. */ + pvr2_trace(PVR2_TRACE_I2C_CORE,"i2c: PEND_CLIENT"); + hdw->i2c_pend_types &= ~PVR2_I2C_PEND_CLIENT; + list_for_each_entry_safe(cp, ncp, &hdw->i2c_clients, + list) { + if (!cp->handler) continue; + if (!cp->handler->func_table->update) continue; + pvr2_trace(PVR2_TRACE_I2C_CORE, + "i2c: cp=%p update",cp); + mutex_unlock(&hdw->i2c_list_lock); + cp->handler->func_table->update( + cp->handler->func_data); + mutex_lock(&hdw->i2c_list_lock); + /* If client's update function set some + additional pending bits, account for that + here. */ + if (cp->pend_mask & ~hdw->i2c_pend_mask) { + hdw->i2c_pend_mask |= cp->pend_mask; + hdw->i2c_pend_types |= + PVR2_I2C_PEND_REFRESH; + } + } + } + if (hdw->i2c_pend_types & PVR2_I2C_PEND_REFRESH) { + const struct pvr2_i2c_op *opf; + unsigned long pm; + /* Some actual updates are pending. Walk through + each update type and perform it. */ + pvr2_trace(PVR2_TRACE_I2C_CORE,"i2c: PEND_REFRESH" + " (0x%lx)",hdw->i2c_pend_mask); + hdw->i2c_pend_types &= ~PVR2_I2C_PEND_REFRESH; + pm = hdw->i2c_pend_mask; + hdw->i2c_pend_mask = 0; + for (idx = 0, msk = 1; pm; idx++, msk <<= 1) { + if (!(pm & msk)) continue; + pm &= ~msk; + list_for_each_entry(cp, &hdw->i2c_clients, + list) { + if (cp->pend_mask & msk) { + cp->pend_mask &= ~msk; + cp->recv_enable = !0; + } else { + cp->recv_enable = 0; + } + } + opf = pvr2_i2c_get_op(idx); + if (!opf) continue; + mutex_unlock(&hdw->i2c_list_lock); + opf->update(hdw); + mutex_lock(&hdw->i2c_list_lock); + } + } + pvr2_trace(PVR2_TRACE_I2C_CORE,"i2c: core_sync END"); + } while (0); mutex_unlock(&hdw->i2c_list_lock); +} + +int pvr2_i2c_core_check_stale(struct pvr2_hdw *hdw) +{ + unsigned long msk,sm,pm; + unsigned int idx; + const struct pvr2_i2c_op *opf; + struct pvr2_i2c_client *cp; + unsigned int pt = 0; + + pvr2_trace(PVR2_TRACE_I2C_CORE,"pvr2_i2c_core_check_stale BEGIN"); + + pm = hdw->i2c_active_mask; + sm = 0; + for (idx = 0, msk = 1; pm; idx++, msk <<= 1) { + if (!(msk & pm)) continue; + pm &= ~msk; + opf = pvr2_i2c_get_op(idx); + if (!(opf && opf->check)) continue; + if (opf->check(hdw)) { + sm |= msk; + } + } + if (sm) pt |= PVR2_I2C_PEND_STALE; + + list_for_each_entry(cp, &hdw->i2c_clients, list) + if (handler_check(cp)) + pt |= PVR2_I2C_PEND_CLIENT; + + if (pt) { + mutex_lock(&hdw->i2c_list_lock); do { + hdw->i2c_pend_types |= pt; + hdw->i2c_stale_mask |= sm; + hdw->i2c_pend_mask |= hdw->i2c_stale_mask; + } while (0); mutex_unlock(&hdw->i2c_list_lock); + } + + pvr2_trace(PVR2_TRACE_I2C_CORE, + "i2c: types=0x%x stale=0x%lx pend=0x%lx", + hdw->i2c_pend_types, + hdw->i2c_stale_mask, + hdw->i2c_pend_mask); + pvr2_trace(PVR2_TRACE_I2C_CORE,"pvr2_i2c_core_check_stale END"); + + return (hdw->i2c_pend_types & PVR2_I2C_PEND_ALL) != 0; +} + +static unsigned int pvr2_i2c_client_describe(struct pvr2_i2c_client *cp, + unsigned int detail, + char *buf,unsigned int maxlen) +{ + unsigned int ccnt,bcnt; + int spcfl = 0; + const struct pvr2_i2c_op *opf; + + ccnt = 0; + if (detail & PVR2_I2C_DETAIL_DEBUG) { + bcnt = scnprintf(buf,maxlen, + "ctxt=%p ctl_mask=0x%lx", + cp,cp->ctl_mask); + ccnt += bcnt; buf += bcnt; maxlen -= bcnt; + spcfl = !0; + } + bcnt = scnprintf(buf,maxlen, + "%s%s @ 0x%x", + (spcfl ? " " : ""), + cp->client->name, + cp->client->addr); + ccnt += bcnt; buf += bcnt; maxlen -= bcnt; + if ((detail & PVR2_I2C_DETAIL_HANDLER) && + cp->handler && cp->handler->func_table->describe) { + bcnt = scnprintf(buf,maxlen," ("); + ccnt += bcnt; buf += bcnt; maxlen -= bcnt; + bcnt = cp->handler->func_table->describe( + cp->handler->func_data,buf,maxlen); + ccnt += bcnt; buf += bcnt; maxlen -= bcnt; + bcnt = scnprintf(buf,maxlen,")"); + ccnt += bcnt; buf += bcnt; maxlen -= bcnt; + } + if ((detail & PVR2_I2C_DETAIL_CTLMASK) && cp->ctl_mask) { + unsigned int idx; + unsigned long msk,sm; + + bcnt = scnprintf(buf,maxlen," ["); + ccnt += bcnt; buf += bcnt; maxlen -= bcnt; + sm = 0; + spcfl = 0; + for (idx = 0, msk = 1; msk; idx++, msk <<= 1) { + if (!(cp->ctl_mask & msk)) continue; + opf = pvr2_i2c_get_op(idx); + if (opf) { + bcnt = scnprintf(buf,maxlen,"%s%s", + spcfl ? " " : "", + opf->name); + ccnt += bcnt; buf += bcnt; maxlen -= bcnt; + spcfl = !0; + } else { + sm |= msk; + } + } + if (sm) { + bcnt = scnprintf(buf,maxlen,"%s%lx", + idx != 0 ? " " : "",sm); + ccnt += bcnt; buf += bcnt; maxlen -= bcnt; + } + bcnt = scnprintf(buf,maxlen,"]"); + ccnt += bcnt; buf += bcnt; maxlen -= bcnt; + } + return ccnt; +} + +unsigned int pvr2_i2c_report(struct pvr2_hdw *hdw, + char *buf,unsigned int maxlen) +{ + unsigned int ccnt,bcnt; + struct pvr2_i2c_client *cp; + ccnt = 0; + mutex_lock(&hdw->i2c_list_lock); do { + list_for_each_entry(cp, &hdw->i2c_clients, list) { + bcnt = pvr2_i2c_client_describe( + cp, + (PVR2_I2C_DETAIL_HANDLER| + PVR2_I2C_DETAIL_CTLMASK), + buf,maxlen); + ccnt += bcnt; buf += bcnt; maxlen -= bcnt; + bcnt = scnprintf(buf,maxlen,"\n"); + ccnt += bcnt; buf += bcnt; maxlen -= bcnt; + } + } while (0); mutex_unlock(&hdw->i2c_list_lock); + return ccnt; +} + +void pvr2_i2c_track_attach_inform(struct i2c_client *client) +{ + struct pvr2_hdw *hdw = (struct pvr2_hdw *)(client->adapter->algo_data); + struct pvr2_i2c_client *cp; + int fl = !(hdw->i2c_pend_types & PVR2_I2C_PEND_ALL); + cp = kzalloc(sizeof(*cp),GFP_KERNEL); + trace_i2c("i2c_attach [client=%s @ 0x%x ctxt=%p]", + client->name, + client->addr,cp); + if (!cp) { + pvr2_trace(PVR2_TRACE_ERROR_LEGS, + "Unable to allocate tracking memory for incoming" + " i2c module; ignoring module. This is likely" + " going to be a problem."); + return; + } + cp->hdw = hdw; + INIT_LIST_HEAD(&cp->list); + cp->client = client; + mutex_lock(&hdw->i2c_list_lock); do { + hdw->cropcap_stale = !0; + list_add_tail(&cp->list,&hdw->i2c_clients); + hdw->i2c_pend_types |= PVR2_I2C_PEND_DETECT; + } while (0); mutex_unlock(&hdw->i2c_list_lock); + if (fl) queue_work(hdw->workqueue,&hdw->worki2csync); +} + +void pvr2_i2c_track_detach_inform(struct i2c_client *client) +{ + struct pvr2_hdw *hdw = (struct pvr2_hdw *)(client->adapter->algo_data); + struct pvr2_i2c_client *cp, *ncp; + unsigned long amask = 0; + int foundfl = 0; + mutex_lock(&hdw->i2c_list_lock); do { + hdw->cropcap_stale = !0; + list_for_each_entry_safe(cp, ncp, &hdw->i2c_clients, list) { + if (cp->client == client) { + trace_i2c("pvr2_i2c_detach" + " [client=%s @ 0x%x ctxt=%p]", + client->name, + client->addr,cp); + if (cp->handler && + cp->handler->func_table->detach) { + cp->handler->func_table->detach( + cp->handler->func_data); + } + list_del(&cp->list); + kfree(cp); + foundfl = !0; + continue; + } + amask |= cp->ctl_mask; + } + hdw->i2c_active_mask = amask; + } while (0); mutex_unlock(&hdw->i2c_list_lock); + if (!foundfl) { + trace_i2c("pvr2_i2c_detach [client=%s @ 0x%x ctxt=]", + client->name, + client->addr); + } +} + +void pvr2_i2c_track_init(struct pvr2_hdw *hdw) +{ + hdw->i2c_pend_mask = 0; + hdw->i2c_stale_mask = 0; + hdw->i2c_active_mask = 0; + INIT_LIST_HEAD(&hdw->i2c_clients); + mutex_init(&hdw->i2c_list_lock); +} + +void pvr2_i2c_track_done(struct pvr2_hdw *hdw) +{ + /* Empty for now */ +} + +/* + Stuff for Emacs to see, in order to encourage consistent editing style: + *** Local Variables: *** + *** mode: c *** + *** fill-column: 75 *** + *** tab-width: 8 *** + *** c-basic-offset: 8 *** + *** End: *** + */ diff --git a/drivers/media/video/pvrusb2/pvrusb2-i2c-track.h b/drivers/media/video/pvrusb2/pvrusb2-i2c-track.h new file mode 100644 index 000000000000..7d0e4fb63785 --- /dev/null +++ b/drivers/media/video/pvrusb2/pvrusb2-i2c-track.h @@ -0,0 +1,97 @@ +/* + * + * + * Copyright (C) 2005 Mike Isely + * + * 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 + * + * 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 + * + */ +#ifndef __PVRUSB2_I2C_TRACK_H +#define __PVRUSB2_I2C_TRACK_H + +#include +#include + +struct pvr2_hdw; +struct pvr2_i2c_client; +struct pvr2_i2c_handler; +struct pvr2_i2c_handler_functions; +struct pvr2_i2c_op; +struct pvr2_i2c_op_functions; + +struct pvr2_i2c_client { + struct i2c_client *client; + struct pvr2_i2c_handler *handler; + struct list_head list; + struct pvr2_hdw *hdw; + int detected_flag; + int recv_enable; + unsigned long pend_mask; + unsigned long ctl_mask; + void (*status_poll)(struct pvr2_i2c_client *); +}; + +struct pvr2_i2c_handler { + void *func_data; + const struct pvr2_i2c_handler_functions *func_table; +}; + +struct pvr2_i2c_handler_functions { + void (*detach)(void *); + int (*check)(void *); + void (*update)(void *); + unsigned int (*describe)(void *,char *,unsigned int); +}; + +struct pvr2_i2c_op { + int (*check)(struct pvr2_hdw *); + void (*update)(struct pvr2_hdw *); + const char *name; +}; + +void pvr2_i2c_track_init(struct pvr2_hdw *); +void pvr2_i2c_track_done(struct pvr2_hdw *); +void pvr2_i2c_track_attach_inform(struct i2c_client *); +void pvr2_i2c_track_detach_inform(struct i2c_client *); + +int pvr2_i2c_client_cmd(struct pvr2_i2c_client *,unsigned int cmd,void *arg); +int pvr2_i2c_core_cmd(struct pvr2_hdw *,unsigned int cmd,void *arg); + +int pvr2_i2c_core_check_stale(struct pvr2_hdw *); +void pvr2_i2c_core_sync(struct pvr2_hdw *); +void pvr2_i2c_core_status_poll(struct pvr2_hdw *); +unsigned int pvr2_i2c_report(struct pvr2_hdw *,char *buf,unsigned int maxlen); +#define PVR2_I2C_DETAIL_DEBUG 0x0001 +#define PVR2_I2C_DETAIL_HANDLER 0x0002 +#define PVR2_I2C_DETAIL_CTLMASK 0x0004 +#define PVR2_I2C_DETAIL_ALL (\ + PVR2_I2C_DETAIL_DEBUG |\ + PVR2_I2C_DETAIL_HANDLER |\ + PVR2_I2C_DETAIL_CTLMASK) + +void pvr2_i2c_probe(struct pvr2_hdw *,struct pvr2_i2c_client *); +const struct pvr2_i2c_op *pvr2_i2c_get_op(unsigned int idx); + +#endif /* __PVRUSB2_I2C_CORE_H */ + + +/* + Stuff for Emacs to see, in order to encourage consistent editing style: + *** Local Variables: *** + *** mode: c *** + *** fill-column: 75 *** + *** tab-width: 8 *** + *** c-basic-offset: 8 *** + *** End: *** + */ diff --git a/drivers/media/video/pvrusb2/pvrusb2-tuner.h b/drivers/media/video/pvrusb2/pvrusb2-tuner.h index ef4afaf37b0a..3643e2c7880f 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-tuner.h +++ b/drivers/media/video/pvrusb2/pvrusb2-tuner.h @@ -20,7 +20,7 @@ #ifndef __PVRUSB2_TUNER_H #define __PVRUSB2_TUNER_H -#include "pvrusb2-i2c-core.h" +#include "pvrusb2-i2c-track.h" int pvr2_i2c_tuner_setup(struct pvr2_hdw *,struct pvr2_i2c_client *); diff --git a/drivers/media/video/pvrusb2/pvrusb2-video-v4l.h b/drivers/media/video/pvrusb2/pvrusb2-video-v4l.h index 4ff5b892b303..b2cd3875bb5b 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-video-v4l.h +++ b/drivers/media/video/pvrusb2/pvrusb2-video-v4l.h @@ -33,7 +33,7 @@ -#include "pvrusb2-i2c-core.h" +#include "pvrusb2-i2c-track.h" int pvr2_i2c_decoder_v4l_setup(struct pvr2_hdw *,struct pvr2_i2c_client *); diff --git a/drivers/media/video/pvrusb2/pvrusb2-wm8775.h b/drivers/media/video/pvrusb2/pvrusb2-wm8775.h index 807090961255..5b2cb6183576 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-wm8775.h +++ b/drivers/media/video/pvrusb2/pvrusb2-wm8775.h @@ -34,7 +34,7 @@ -#include "pvrusb2-i2c-core.h" +#include "pvrusb2-i2c-track.h" int pvr2_i2c_wm8775_setup(struct pvr2_hdw *,struct pvr2_i2c_client *); -- cgit v1.2.3 From b72b7bf5cbb2ae77b3bf748456655fc284baf04c Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Fri, 6 Mar 2009 23:20:31 -0300 Subject: V4L/DVB (11155): pvrusb2: Set up v4l2_device instance Define a v4l2_device instance in the pvrusb2 driver and initialize / tear it down appropriately. This is a step in the v4l2-subdev adoption effort. Signed-off-by: Mike Isely Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h | 3 +++ drivers/media/video/pvrusb2/pvrusb2-hdw.c | 18 +++++++++++++++++- 2 files changed, 20 insertions(+), 1 deletion(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h b/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h index d96f0f51076e..09798403e9fd 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h +++ b/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h @@ -38,6 +38,7 @@ #include #include "pvrusb2-hdw.h" #include "pvrusb2-io.h" +#include #include #include "pvrusb2-devattr.h" @@ -179,6 +180,8 @@ struct pvr2_hdw { struct usb_device *usb_dev; struct usb_interface *usb_intf; + /* Our handle into the v4l2 sub-device architecture */ + struct v4l2_device v4l2_dev; /* Device description, anything that must adjust behavior based on device specific info will use information held here. */ const struct pvr2_device_desc *hdw_desc; diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/drivers/media/video/pvrusb2/pvrusb2-hdw.c index 9441bcc37bc3..b66ac1c49dbe 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-hdw.c +++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.c @@ -2192,11 +2192,14 @@ struct pvr2_hdw *pvr2_hdw_create(struct usb_interface *intf, struct pvr2_hdw *hdw = NULL; int valid_std_mask; struct pvr2_ctrl *cptr; + struct usb_device *usb_dev; const struct pvr2_device_desc *hdw_desc; __u8 ifnum; struct v4l2_queryctrl qctrl; struct pvr2_ctl_info *ciptr; + usb_dev = interface_to_usbdev(intf); + hdw_desc = (const struct pvr2_device_desc *)(devid->driver_info); if (hdw_desc == NULL) { @@ -2381,6 +2384,11 @@ struct pvr2_hdw *pvr2_hdw_create(struct usb_interface *intf, hdw->ctl_read_urb = usb_alloc_urb(0,GFP_KERNEL); if (!hdw->ctl_read_urb) goto fail; + if (v4l2_device_register(&usb_dev->dev, &hdw->v4l2_dev) != 0) { + pvr2_trace(PVR2_TRACE_ERROR_LEGS, + "Error registering with v4l core, giving up"); + goto fail; + } mutex_lock(&pvr2_unit_mtx); do { for (idx = 0; idx < PVR_NUM; idx++) { if (unit_pointers[idx]) continue; @@ -2412,7 +2420,7 @@ struct pvr2_hdw *pvr2_hdw_create(struct usb_interface *intf, hdw->flag_ok = !0; hdw->usb_intf = intf; - hdw->usb_dev = interface_to_usbdev(intf); + hdw->usb_dev = usb_dev; usb_make_path(hdw->usb_dev, hdw->bus_info, sizeof(hdw->bus_info)); @@ -2472,6 +2480,13 @@ static void pvr2_hdw_remove_usb_stuff(struct pvr2_hdw *hdw) hdw->ctl_write_buffer = NULL; } hdw->flag_disconnected = !0; + /* If we don't do this, then there will be a dangling struct device + reference to our disappearing device persisting inside the V4L + core... */ + if (hdw->v4l2_dev.dev) { + dev_set_drvdata(hdw->v4l2_dev.dev, NULL); + hdw->v4l2_dev.dev = NULL; + } hdw->usb_dev = NULL; hdw->usb_intf = NULL; pvr2_hdw_render_useless(hdw); @@ -2504,6 +2519,7 @@ void pvr2_hdw_destroy(struct pvr2_hdw *hdw) } pvr2_i2c_core_done(hdw); pvr2_i2c_track_done(hdw); + v4l2_device_unregister(&hdw->v4l2_dev); pvr2_hdw_remove_usb_stuff(hdw); mutex_lock(&pvr2_unit_mtx); do { if ((hdw->unit_number >= 0) && -- cgit v1.2.3 From a51f5000b791003e0ab9ecebbdecb87c4024156f Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Fri, 6 Mar 2009 23:30:37 -0300 Subject: V4L/DVB (11156): pvrusb2: Changes to further isolate old i2c layer This introduces some additional isolation in the pvrusb2 from the old i2c layer, a step along the way to separate the driver from that layer and to make it easier to introduce the common v4l2-subdev framework as the eventual replacement. Signed-off-by: Mike Isely Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h | 2 ++ drivers/media/video/pvrusb2/pvrusb2-hdw.c | 22 ++++++++++++++-------- drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.c | 4 +++- 3 files changed, 19 insertions(+), 9 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h b/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h index 09798403e9fd..b3cb0bbd8cf5 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h +++ b/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h @@ -408,6 +408,8 @@ struct pvr2_hdw { unsigned long pvr2_hdw_get_cur_freq(struct pvr2_hdw *); void pvr2_hdw_set_decoder(struct pvr2_hdw *,struct pvr2_decoder_ctrl *); +void pvr2_hdw_status_poll(struct pvr2_hdw *); + #endif /* __PVRUSB2_HDW_INTERNAL_H */ /* diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/drivers/media/video/pvrusb2/pvrusb2-hdw.c index b66ac1c49dbe..e6c4660786a6 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-hdw.c +++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.c @@ -643,7 +643,7 @@ static int ctrl_freq_max_get(struct pvr2_ctrl *cptr, int *vp) unsigned long fv; struct pvr2_hdw *hdw = cptr->hdw; if (hdw->tuner_signal_stale) { - pvr2_i2c_core_status_poll(hdw); + pvr2_hdw_status_poll(hdw); } fv = hdw->tuner_signal_info.rangehigh; if (!fv) { @@ -665,7 +665,7 @@ static int ctrl_freq_min_get(struct pvr2_ctrl *cptr, int *vp) unsigned long fv; struct pvr2_hdw *hdw = cptr->hdw; if (hdw->tuner_signal_stale) { - pvr2_i2c_core_status_poll(hdw); + pvr2_hdw_status_poll(hdw); } fv = hdw->tuner_signal_info.rangelow; if (!fv) { @@ -859,7 +859,7 @@ static void ctrl_stdcur_clear_dirty(struct pvr2_ctrl *cptr) static int ctrl_signal_get(struct pvr2_ctrl *cptr,int *vp) { struct pvr2_hdw *hdw = cptr->hdw; - pvr2_i2c_core_status_poll(hdw); + pvr2_hdw_status_poll(hdw); *vp = hdw->tuner_signal_info.signal; return 0; } @@ -869,7 +869,7 @@ static int ctrl_audio_modes_present_get(struct pvr2_ctrl *cptr,int *vp) int val = 0; unsigned int subchan; struct pvr2_hdw *hdw = cptr->hdw; - pvr2_i2c_core_status_poll(hdw); + pvr2_hdw_status_poll(hdw); subchan = hdw->tuner_signal_info.rxsubchans; if (subchan & V4L2_TUNER_SUB_MONO) { val |= (1 << V4L2_TUNER_MODE_MONO); @@ -3008,7 +3008,7 @@ int pvr2_hdw_is_hsm(struct pvr2_hdw *hdw) void pvr2_hdw_execute_tuner_poll(struct pvr2_hdw *hdw) { LOCK_TAKE(hdw->big_lock); do { - pvr2_i2c_core_status_poll(hdw); + pvr2_hdw_status_poll(hdw); } while (0); LOCK_GIVE(hdw->big_lock); } @@ -3018,7 +3018,7 @@ static int pvr2_hdw_check_cropcap(struct pvr2_hdw *hdw) if (!hdw->cropcap_stale) { return 0; } - pvr2_i2c_core_status_poll(hdw); + pvr2_hdw_status_poll(hdw); if (hdw->cropcap_stale) { return -EIO; } @@ -3045,7 +3045,7 @@ int pvr2_hdw_get_tuner_status(struct pvr2_hdw *hdw,struct v4l2_tuner *vtp) { LOCK_TAKE(hdw->big_lock); do { if (hdw->tuner_signal_stale) { - pvr2_i2c_core_status_poll(hdw); + pvr2_hdw_status_poll(hdw); } memcpy(vtp,&hdw->tuner_signal_info,sizeof(struct v4l2_tuner)); } while (0); LOCK_GIVE(hdw->big_lock); @@ -3067,8 +3067,8 @@ void pvr2_hdw_trigger_module_log(struct pvr2_hdw *hdw) hdw->log_requested = !0; printk(KERN_INFO "pvrusb2: ================= START STATUS CARD #%d =================\n", nr); pvr2_i2c_core_check_stale(hdw); - hdw->log_requested = 0; pvr2_i2c_core_sync(hdw); + hdw->log_requested = 0; pvr2_trace(PVR2_TRACE_INFO,"cx2341x config:"); cx2341x_log_status(&hdw->enc_ctl_state, "pvrusb2"); pvr2_hdw_state_log_state(hdw); @@ -4676,6 +4676,12 @@ int pvr2_hdw_gpio_chg_out(struct pvr2_hdw *hdw,u32 msk,u32 val) } +void pvr2_hdw_status_poll(struct pvr2_hdw *hdw) +{ + pvr2_i2c_core_status_poll(hdw); +} + + unsigned int pvr2_hdw_get_input_available(struct pvr2_hdw *hdw) { return hdw->input_avail_mask; diff --git a/drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.c b/drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.c index 0f2885440f2f..7afe513bebf9 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.c +++ b/drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.c @@ -25,6 +25,7 @@ #include #include + static void execute_init(struct pvr2_hdw *hdw) { u32 dummy = 0; @@ -184,7 +185,7 @@ static void set_frequency(struct pvr2_hdw *hdw) fv = pvr2_hdw_get_cur_freq(hdw); pvr2_trace(PVR2_TRACE_CHIPS,"i2c v4l2 set_freq(%lu)",fv); if (hdw->tuner_signal_stale) { - pvr2_i2c_core_status_poll(hdw); + pvr2_hdw_status_poll(hdw); } memset(&freq,0,sizeof(freq)); if (hdw->tuner_signal_info.capability & V4L2_TUNER_CAP_LOW) { @@ -325,6 +326,7 @@ void pvr2_v4l2_cmd_status_poll(struct pvr2_i2c_client *cp) } + /* Stuff for Emacs to see, in order to encourage consistent editing style: *** Local Variables: *** -- cgit v1.2.3 From acd92d40ccaf140d27e6bd5b83573294165ebbdf Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Fri, 6 Mar 2009 23:32:02 -0300 Subject: V4L/DVB (11157): pvrusb2: whitespace trivial tweaks Signed-off-by: Mike Isely Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/pvrusb2/pvrusb2-audio.c | 2 ++ drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.c | 1 + drivers/media/video/pvrusb2/pvrusb2-i2c-chips-v4l2.c | 2 ++ drivers/media/video/pvrusb2/pvrusb2-i2c-track.c | 2 ++ drivers/media/video/pvrusb2/pvrusb2-tuner.c | 1 + 5 files changed, 8 insertions(+) (limited to 'drivers/media/video') diff --git a/drivers/media/video/pvrusb2/pvrusb2-audio.c b/drivers/media/video/pvrusb2/pvrusb2-audio.c index cdedaa55f152..6159c7e3047d 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-audio.c +++ b/drivers/media/video/pvrusb2/pvrusb2-audio.c @@ -35,6 +35,7 @@ struct pvr2_msp3400_handler { + struct routing_scheme { const int *def; unsigned int cnt; @@ -180,6 +181,7 @@ int pvr2_i2c_msp3400_setup(struct pvr2_hdw *hdw,struct pvr2_i2c_client *cp) } + /* Stuff for Emacs to see, in order to encourage consistent editing style: *** Local Variables: *** diff --git a/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.c b/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.c index 895859ec495a..9494c6a5b5d8 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.c +++ b/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.c @@ -323,6 +323,7 @@ int pvr2_i2c_cx2584x_v4l_setup(struct pvr2_hdw *hdw, + /* Stuff for Emacs to see, in order to encourage consistent editing style: *** Local Variables: *** diff --git a/drivers/media/video/pvrusb2/pvrusb2-i2c-chips-v4l2.c b/drivers/media/video/pvrusb2/pvrusb2-i2c-chips-v4l2.c index 8f32c2edb49a..7e0628b988cc 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-i2c-chips-v4l2.c +++ b/drivers/media/video/pvrusb2/pvrusb2-i2c-chips-v4l2.c @@ -29,6 +29,7 @@ #include "pvrusb2-cx2584x-v4l.h" #include "pvrusb2-wm8775.h" + #define trace_i2c(...) pvr2_trace(PVR2_TRACE_I2C,__VA_ARGS__) #define OP_INIT 0 /* MUST come first so it is run first */ @@ -105,6 +106,7 @@ const struct pvr2_i2c_op *pvr2_i2c_get_op(unsigned int idx) } + /* Stuff for Emacs to see, in order to encourage consistent editing style: *** Local Variables: *** diff --git a/drivers/media/video/pvrusb2/pvrusb2-i2c-track.c b/drivers/media/video/pvrusb2/pvrusb2-i2c-track.c index 48cffa4a1b6a..4bb6f9453e0d 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-i2c-track.c +++ b/drivers/media/video/pvrusb2/pvrusb2-i2c-track.c @@ -26,6 +26,7 @@ #define trace_i2c(...) pvr2_trace(PVR2_TRACE_I2C,__VA_ARGS__) + /* This module implements the foundation of a rather large architecture for @@ -469,6 +470,7 @@ void pvr2_i2c_track_done(struct pvr2_hdw *hdw) /* Empty for now */ } + /* Stuff for Emacs to see, in order to encourage consistent editing style: *** Local Variables: *** diff --git a/drivers/media/video/pvrusb2/pvrusb2-tuner.c b/drivers/media/video/pvrusb2/pvrusb2-tuner.c index 07775d1aad4e..ee9c9c139a85 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-tuner.c +++ b/drivers/media/video/pvrusb2/pvrusb2-tuner.c @@ -28,6 +28,7 @@ #include #include + struct pvr2_tuner_handler { struct pvr2_hdw *hdw; struct pvr2_i2c_client *client; -- cgit v1.2.3 From e9c64a78dbd7c4f6c4a31c4040f340f732bf4ec5 Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Fri, 6 Mar 2009 23:42:20 -0300 Subject: V4L/DVB (11158): pvrusb2: New device attribute mechanism to specify sub-devices Set up new mechanism for declaring and loading appropriate sub-devices when driver initializes. This is another part of the v4l2-subdev adoption. Signed-off-by: Mike Isely Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/pvrusb2/pvrusb2-devattr.h | 28 ++++++ drivers/media/video/pvrusb2/pvrusb2-hdw.c | 119 ++++++++++++++++++++++++- drivers/media/video/pvrusb2/pvrusb2-i2c-core.c | 1 + 3 files changed, 144 insertions(+), 4 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/pvrusb2/pvrusb2-devattr.h b/drivers/media/video/pvrusb2/pvrusb2-devattr.h index cb3a33eb0276..f06923986824 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-devattr.h +++ b/drivers/media/video/pvrusb2/pvrusb2-devattr.h @@ -33,6 +33,31 @@ */ +#define PVR2_CLIENT_ID_MSP3400 1 +#define PVR2_CLIENT_ID_CX25840 2 +#define PVR2_CLIENT_ID_SAA7115 3 +#define PVR2_CLIENT_ID_TUNER 4 +#define PVR2_CLIENT_ID_CS53132A 5 + +struct pvr2_device_client_desc { + /* One ovr PVR2_CLIENT_ID_xxxx */ + unsigned char module_id; + + /* Null-terminated array of I2C addresses to try in order + initialize the module. It's safe to make this null terminated + since we're never going to encounter an i2c device with an + address of zero. If this is a null pointer or zero-length, + then no I2C addresses have been specified, in which case we'll + try some compiled in defaults for now. */ + unsigned char *i2c_address_list; +}; + +struct pvr2_device_client_table { + const struct pvr2_device_client_desc *lst; + unsigned char cnt; +}; + + struct pvr2_string_table { const char **lst; unsigned int cnt; @@ -66,6 +91,9 @@ struct pvr2_device_desc { /* List of additional client modules we need to load */ struct pvr2_string_table client_modules; + /* List of defined client modules we need to load */ + struct pvr2_device_client_table client_table; + /* List of FX2 firmware file names we should search; if empty then FX2 firmware check / load is skipped and we assume the device was initialized from internal ROM. */ diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/drivers/media/video/pvrusb2/pvrusb2-hdw.c index e6c4660786a6..faa94cef2c55 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-hdw.c +++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.c @@ -105,6 +105,20 @@ MODULE_PARM_DESC(radio_freq, "specify initial radio frequency"); /* size of a firmware chunk */ #define FIRMWARE_CHUNK_SIZE 0x2000 +static const char *module_names[] = { + [PVR2_CLIENT_ID_MSP3400] = "msp3400", + [PVR2_CLIENT_ID_CX25840] = "cx25840", + [PVR2_CLIENT_ID_SAA7115] = "saa7115", + [PVR2_CLIENT_ID_TUNER] = "tuner", + [PVR2_CLIENT_ID_CS53132A] = "cs53132a", +}; + + +static const unsigned char *module_i2c_addresses[] = { + [PVR2_CLIENT_ID_TUNER] = "\x60\x61\x62\x63", +}; + + /* Define the list of additional controls we'll dynamically construct based on query of the cx2341x module. */ struct pvr2_mpeg_ids { @@ -1934,6 +1948,105 @@ static void pvr2_hdw_setup_std(struct pvr2_hdw *hdw) } +static unsigned int pvr2_copy_i2c_addr_list( + unsigned short *dst, const unsigned char *src, + unsigned int dst_max) +{ + unsigned int cnt; + if (!src) return 0; + while (src[cnt] && (cnt + 1) < dst_max) { + dst[cnt] = src[cnt]; + cnt++; + } + dst[cnt] = I2C_CLIENT_END; + return cnt; +} + + +static void pvr2_hdw_load_subdev(struct pvr2_hdw *hdw, + const struct pvr2_device_client_desc *cd) +{ + const char *fname; + unsigned char mid; + struct v4l2_subdev *sd; + unsigned int i2ccnt; + const unsigned char *p; + /* Arbitrary count - max # i2c addresses we will probe */ + unsigned short i2caddr[25]; + + mid = cd->module_id; + fname = (mid < ARRAY_SIZE(module_names)) ? module_names[mid] : NULL; + if (!fname) { + pvr2_trace(PVR2_TRACE_ERROR_LEGS, + "Module ID %u for device %s is unknown" + " (this is probably a bad thing...)", + mid, + hdw->hdw_desc->description); + return; + } + + i2ccnt = pvr2_copy_i2c_addr_list(i2caddr, cd->i2c_address_list, + ARRAY_SIZE(i2caddr)); + if (!i2ccnt && ((p = (mid < ARRAY_SIZE(module_i2c_addresses)) ? + module_i2c_addresses[mid] : NULL) != NULL)) { + /* Second chance: Try default i2c address list */ + i2ccnt = pvr2_copy_i2c_addr_list(i2caddr, p, + ARRAY_SIZE(i2caddr)); + } + + if (!i2ccnt) { + pvr2_trace(PVR2_TRACE_ERROR_LEGS, + "Module ID %u for device %s:" + " No i2c addresses" + " (this is probably a bad thing...)", + mid, hdw->hdw_desc->description); + return; + } + + /* Note how the 2nd and 3rd arguments are the same for both + * v4l2_i2c_new_subdev() and v4l2_i2c_new_probed_subdev(). Why? + * Well the 2nd argument is the module name to load, while the 3rd + * argument is documented in the framework as being the "chipid" - + * and every other place where I can find examples of this, the + * "chipid" appears to just be the module name again. So here we + * just do the same thing. */ + if (i2ccnt == 1) { + sd = v4l2_i2c_new_subdev(&hdw->i2c_adap, + fname, fname, + i2caddr[0]); + } else { + sd = v4l2_i2c_new_probed_subdev(&hdw->i2c_adap, + fname, fname, + i2caddr); + } + + // ????? + /* Based on module ID, we should remember subdev pointers + so that we can send certain custom commands where + needed. */ + // ????? + +} + + +static void pvr2_hdw_load_modules(struct pvr2_hdw *hdw) +{ + unsigned int idx; + const struct pvr2_string_table *cm; + const struct pvr2_device_client_table *ct; + + cm = &hdw->hdw_desc->client_modules; + for (idx = 0; idx < cm->cnt; idx++) { + request_module(cm->lst[idx]); + } + + ct = &hdw->hdw_desc->client_table; + for (idx = 0; idx < ct->cnt; idx++) { + pvr2_hdw_load_subdev(hdw,&ct->lst[idx]); + } +} + + static void pvr2_hdw_setup_low(struct pvr2_hdw *hdw) { int ret; @@ -1973,10 +2086,6 @@ static void pvr2_hdw_setup_low(struct pvr2_hdw *hdw) if (!pvr2_hdw_dev_ok(hdw)) return; - for (idx = 0; idx < hdw->hdw_desc->client_modules.cnt; idx++) { - request_module(hdw->hdw_desc->client_modules.lst[idx]); - } - if (!hdw->hdw_desc->flag_no_powerup) { pvr2_hdw_cmd_powerup(hdw); if (!pvr2_hdw_dev_ok(hdw)) return; @@ -1995,6 +2104,8 @@ static void pvr2_hdw_setup_low(struct pvr2_hdw *hdw) pvr2_i2c_core_init(hdw); if (!pvr2_hdw_dev_ok(hdw)) return; + pvr2_hdw_load_modules(hdw); + for (idx = 0; idx < CTRLDEF_COUNT; idx++) { cptr = hdw->controls + idx; if (cptr->info->skip_init) continue; diff --git a/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c b/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c index 2ba429f1bc8e..1129fe40c04c 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c +++ b/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c @@ -608,6 +608,7 @@ void pvr2_i2c_core_init(struct pvr2_hdw *hdw) hdw->i2c_adap.algo = &hdw->i2c_algo; hdw->i2c_adap.algo_data = hdw; hdw->i2c_linked = !0; + i2c_set_adapdata(&hdw->i2c_adap, &hdw->v4l2_dev); i2c_add_adapter(&hdw->i2c_adap); if (hdw->i2c_func[0x18] == i2c_24xxx_ir) { /* Probe for a different type of IR receiver on this -- cgit v1.2.3 From a932f507463d996b6ec1647ee7d4e2fa1e6aeda6 Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Fri, 6 Mar 2009 23:47:10 -0300 Subject: V4L/DVB (11159): pvrusb2: Providing means to stop tracking an old i2c module This implements a temporary mechanism to "untrack" an i2c module from the old i2c layer. The v4l2-subdev related code in the driver will use this to remove a sub-device from the old i2c layer. In the end, once the old i2c layer is removed, this will also eventually go away. Signed-off-by: Mike Isely Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/pvrusb2/pvrusb2-hdw.c | 6 ++ drivers/media/video/pvrusb2/pvrusb2-i2c-track.c | 76 +++++++++++++++++-------- drivers/media/video/pvrusb2/pvrusb2-i2c-track.h | 5 ++ 3 files changed, 64 insertions(+), 23 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/drivers/media/video/pvrusb2/pvrusb2-hdw.c index faa94cef2c55..0e0d086bb278 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-hdw.c +++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.c @@ -2020,6 +2020,12 @@ static void pvr2_hdw_load_subdev(struct pvr2_hdw *hdw, i2caddr); } + /* If we have both old and new i2c layers enabled, make sure that + old layer isn't also tracking this module. This is a debugging + aid, in normal situations there's no reason for both mechanisms + to be enabled. */ + pvr2_i2c_untrack_subdev(hdw, sd); + // ????? /* Based on module ID, we should remember subdev pointers so that we can send certain custom commands where diff --git a/drivers/media/video/pvrusb2/pvrusb2-i2c-track.c b/drivers/media/video/pvrusb2/pvrusb2-i2c-track.c index 4bb6f9453e0d..3387897ed897 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-i2c-track.c +++ b/drivers/media/video/pvrusb2/pvrusb2-i2c-track.c @@ -421,41 +421,71 @@ void pvr2_i2c_track_attach_inform(struct i2c_client *client) if (fl) queue_work(hdw->workqueue,&hdw->worki2csync); } +static void pvr2_i2c_client_disconnect(struct pvr2_i2c_client *cp) +{ + if (cp->handler && cp->handler->func_table->detach) { + cp->handler->func_table->detach(cp->handler->func_data); + } + list_del(&cp->list); + kfree(cp); +} + void pvr2_i2c_track_detach_inform(struct i2c_client *client) { struct pvr2_hdw *hdw = (struct pvr2_hdw *)(client->adapter->algo_data); struct pvr2_i2c_client *cp, *ncp; unsigned long amask = 0; int foundfl = 0; - mutex_lock(&hdw->i2c_list_lock); do { - hdw->cropcap_stale = !0; - list_for_each_entry_safe(cp, ncp, &hdw->i2c_clients, list) { - if (cp->client == client) { - trace_i2c("pvr2_i2c_detach" - " [client=%s @ 0x%x ctxt=%p]", - client->name, - client->addr,cp); - if (cp->handler && - cp->handler->func_table->detach) { - cp->handler->func_table->detach( - cp->handler->func_data); - } - list_del(&cp->list); - kfree(cp); - foundfl = !0; - continue; - } - amask |= cp->ctl_mask; + mutex_lock(&hdw->i2c_list_lock); + hdw->cropcap_stale = !0; + list_for_each_entry_safe(cp, ncp, &hdw->i2c_clients, list) { + if (cp->client == client) { + trace_i2c("pvr2_i2c_detach" + " [client=%s @ 0x%x ctxt=%p]", + client->name, + client->addr, cp); + pvr2_i2c_client_disconnect(cp); + foundfl = !0; + continue; } - hdw->i2c_active_mask = amask; - } while (0); mutex_unlock(&hdw->i2c_list_lock); + amask |= cp->ctl_mask; + } + hdw->i2c_active_mask = amask; + mutex_unlock(&hdw->i2c_list_lock); if (!foundfl) { trace_i2c("pvr2_i2c_detach [client=%s @ 0x%x ctxt=]", - client->name, - client->addr); + client->name, client->addr); } } +/* This function is used to remove an i2c client from our tracking + structure if the client happens to be the specified v4l2 sub-device. + The idea here is to ensure that sub-devices are not also tracked with + the old tracking mechanism - it's one or the other not both. This is + only for debugging. In a "real" environment, only one of these two + mechanisms should even be compiled in. But by enabling both we can + incrementally test control of each sub-device. */ +void pvr2_i2c_untrack_subdev(struct pvr2_hdw *hdw, struct v4l2_subdev *sd) +{ + struct i2c_client *client; + struct pvr2_i2c_client *cp, *ncp; + unsigned long amask = 0; + mutex_lock(&hdw->i2c_list_lock); + list_for_each_entry_safe(cp, ncp, &hdw->i2c_clients, list) { + client = cp->client; + if (i2c_get_clientdata(client) == sd) { + trace_i2c("pvr2_i2c_detach (subdev active)" + " [client=%s @ 0x%x ctxt=%p]", + client->name, client->addr, cp); + pvr2_i2c_client_disconnect(cp); + continue; + } + amask |= cp->ctl_mask; + } + hdw->i2c_active_mask = amask; + mutex_unlock(&hdw->i2c_list_lock); +} + void pvr2_i2c_track_init(struct pvr2_hdw *hdw) { hdw->i2c_pend_mask = 0; diff --git a/drivers/media/video/pvrusb2/pvrusb2-i2c-track.h b/drivers/media/video/pvrusb2/pvrusb2-i2c-track.h index 7d0e4fb63785..eba48e4c9585 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-i2c-track.h +++ b/drivers/media/video/pvrusb2/pvrusb2-i2c-track.h @@ -22,6 +22,8 @@ #include #include +#include + struct pvr2_hdw; struct pvr2_i2c_client; @@ -83,6 +85,9 @@ unsigned int pvr2_i2c_report(struct pvr2_hdw *,char *buf,unsigned int maxlen); void pvr2_i2c_probe(struct pvr2_hdw *,struct pvr2_i2c_client *); const struct pvr2_i2c_op *pvr2_i2c_get_op(unsigned int idx); +void pvr2_i2c_untrack_subdev(struct pvr2_hdw *, struct v4l2_subdev *sd); + + #endif /* __PVRUSB2_I2C_CORE_H */ -- cgit v1.2.3 From 6063a4422cd80eef9cfdd2a57620a2fc73858b1c Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Fri, 6 Mar 2009 23:48:42 -0300 Subject: V4L/DVB (11160): pvrusb2: whitespace tweaks Signed-off-by: Mike Isely Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/pvrusb2/pvrusb2-audio.c | 2 +- drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.h | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/pvrusb2/pvrusb2-audio.c b/drivers/media/video/pvrusb2/pvrusb2-audio.c index 6159c7e3047d..c29206fa3d1b 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-audio.c +++ b/drivers/media/video/pvrusb2/pvrusb2-audio.c @@ -26,6 +26,7 @@ #include #include + struct pvr2_msp3400_handler { struct pvr2_hdw *hdw; struct pvr2_i2c_client *client; @@ -35,7 +36,6 @@ struct pvr2_msp3400_handler { - struct routing_scheme { const int *def; unsigned int cnt; diff --git a/drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.h b/drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.h index 8472637e48eb..fa42497b40b5 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.h +++ b/drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.h @@ -24,6 +24,7 @@ #include "pvrusb2-i2c-track.h" + extern const struct pvr2_i2c_op pvr2_i2c_op_v4l2_init; extern const struct pvr2_i2c_op pvr2_i2c_op_v4l2_standard; extern const struct pvr2_i2c_op pvr2_i2c_op_v4l2_radio; @@ -38,6 +39,7 @@ extern const struct pvr2_i2c_op pvr2_i2c_op_v4l2_log; void pvr2_v4l2_cmd_stream(struct pvr2_i2c_client *,int); void pvr2_v4l2_cmd_status_poll(struct pvr2_i2c_client *); + #endif /* __PVRUSB2_CMD_V4L2_H */ /* -- cgit v1.2.3 From 15b474423f0642e6ff78f1963b816155e80fc932 Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Fri, 6 Mar 2009 23:51:35 -0300 Subject: V4L/DVB (11161): pvrusb2: Set i2c autoprobing to be off by default In order to keep a sub-device from promiscuously attaching to the pvrusb2 driver, the i2c adapter's class must be cleared. This change clears that class by default. Signed-off-by: Mike Isely Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/pvrusb2/pvrusb2-i2c-core.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c b/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c index 1129fe40c04c..13d016efc0d1 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c +++ b/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c @@ -540,7 +540,7 @@ static struct i2c_algorithm pvr2_i2c_algo_template = { static struct i2c_adapter pvr2_i2c_adap_template = { .owner = THIS_MODULE, - .class = I2C_CLASS_TV_ANALOG, + .class = 0, .id = I2C_HW_B_BT848, .client_register = pvr2_i2c_attach_inform, .client_unregister = pvr2_i2c_detach_inform, @@ -607,6 +607,7 @@ void pvr2_i2c_core_init(struct pvr2_hdw *hdw) hdw->i2c_adap.dev.parent = &hdw->usb_dev->dev; hdw->i2c_adap.algo = &hdw->i2c_algo; hdw->i2c_adap.algo_data = hdw; + hdw->i2c_adap.class = I2C_CLASS_TV_ANALOG; hdw->i2c_linked = !0; i2c_set_adapdata(&hdw->i2c_adap, &hdw->v4l2_dev); i2c_add_adapter(&hdw->i2c_adap); -- cgit v1.2.3 From 446dfdc6cc62890098a1b92a4a84019a34dce0cc Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Fri, 6 Mar 2009 23:58:15 -0300 Subject: V4L/DVB (11162): pvrusb2: Tie up loose ends with v4l2-subdev setup Tie up loose ends with v4l2-subdev setup. Set attached module's group ID to match our internal ID, emit a few useful messages when sub-devices are dealt with, implement better error legs, and fix an error in the old i2c layer (caused by changes related to the v4l2-subdev work here). Signed-off-by: Mike Isely Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/pvrusb2/pvrusb2-hdw.c | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/drivers/media/video/pvrusb2/pvrusb2-hdw.c index 0e0d086bb278..c764f360a774 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-hdw.c +++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.c @@ -2020,17 +2020,26 @@ static void pvr2_hdw_load_subdev(struct pvr2_hdw *hdw, i2caddr); } + if (!sd) { + pvr2_trace(PVR2_TRACE_ERROR_LEGS, + "Module ID %u for device %s failed to load" + " (this is probably a bad thing...)", + mid, hdw->hdw_desc->description); + return; + } + + /* Tag this sub-device instance with the module ID we know about. + In other places we'll use that tag to determine if the instance + requires special handling. */ + sd->grp_id = mid; + /* If we have both old and new i2c layers enabled, make sure that old layer isn't also tracking this module. This is a debugging aid, in normal situations there's no reason for both mechanisms to be enabled. */ pvr2_i2c_untrack_subdev(hdw, sd); + pvr2_trace(PVR2_TRACE_INIT, "Attached sub-driver %s", fname); - // ????? - /* Based on module ID, we should remember subdev pointers - so that we can send certain custom commands where - needed. */ - // ????? } -- cgit v1.2.3 From 5ceaad14eac97662afd4ed1dddf343cfb322caa3 Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Sat, 7 Mar 2009 00:01:20 -0300 Subject: V4L/DVB (11163): pvrusb2: Lay foundation for triggering sub-device updates These changes set up the spot where we'll check for and set general updates to any attached sub-devices. Signed-off-by: Mike Isely Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/pvrusb2/pvrusb2-hdw.c | 25 ++++++++++++++++++------- 1 file changed, 18 insertions(+), 7 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/drivers/media/video/pvrusb2/pvrusb2-hdw.c index c764f360a774..4c24028856a3 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-hdw.c +++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.c @@ -2839,6 +2839,14 @@ static const char *get_ctrl_typename(enum pvr2_ctl_type tp) } +/* Execute whatever commands are required to update the state of all the + sub-devices so that it matches our current control values. */ +static void pvr2_subdev_update(struct pvr2_hdw *hdw) +{ + /* ????? */ +} + + /* Figure out if we need to commit control changes. If so, mark internal state flags to indicate this fact and return true. Otherwise do nothing else and return false. */ @@ -3009,12 +3017,6 @@ static int pvr2_hdw_commit_execute(struct pvr2_hdw *hdw) the client drivers in order to keep everything in sync */ pvr2_i2c_core_check_stale(hdw); - for (idx = 0; idx < hdw->control_cnt; idx++) { - cptr = hdw->controls + idx; - if (!cptr->info->clear_dirty) continue; - cptr->info->clear_dirty(cptr); - } - if (hdw->active_stream_type != hdw->desired_stream_type) { /* Handle any side effects of stream config here */ hdw->active_stream_type = hdw->desired_stream_type; @@ -3034,6 +3036,15 @@ static int pvr2_hdw_commit_execute(struct pvr2_hdw *hdw) } } + for (idx = 0; idx < hdw->control_cnt; idx++) { + cptr = hdw->controls + idx; + if (!cptr->info->clear_dirty) continue; + cptr->info->clear_dirty(cptr); + } + + /* Check and update state for all sub-devices. */ + pvr2_subdev_update(hdw); + /* Now execute i2c core update */ pvr2_i2c_core_sync(hdw); @@ -3190,8 +3201,8 @@ void pvr2_hdw_trigger_module_log(struct pvr2_hdw *hdw) { int nr = pvr2_hdw_get_unit_number(hdw); LOCK_TAKE(hdw->big_lock); do { - hdw->log_requested = !0; printk(KERN_INFO "pvrusb2: ================= START STATUS CARD #%d =================\n", nr); + hdw->log_requested = !0; pvr2_i2c_core_check_stale(hdw); pvr2_i2c_core_sync(hdw); hdw->log_requested = 0; -- cgit v1.2.3 From ed3261a85993a1f2009a63758e70ac54547b2697 Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Sat, 7 Mar 2009 00:02:33 -0300 Subject: V4L/DVB (11164): pvrusb2: Tie-in sub-device log requests Trigger a broadcast to attached sub-devices when a logging request is made. Signed-off-by: Mike Isely Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/pvrusb2/pvrusb2-hdw.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/media/video') diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/drivers/media/video/pvrusb2/pvrusb2-hdw.c index 4c24028856a3..9669d6a4fb9e 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-hdw.c +++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.c @@ -3206,6 +3206,7 @@ void pvr2_hdw_trigger_module_log(struct pvr2_hdw *hdw) pvr2_i2c_core_check_stale(hdw); pvr2_i2c_core_sync(hdw); hdw->log_requested = 0; + v4l2_device_call_all(&hdw->v4l2_dev, 0, core, log_status); pvr2_trace(PVR2_TRACE_INFO,"cx2341x config:"); cx2341x_log_status(&hdw->enc_ctl_state, "pvrusb2"); pvr2_hdw_state_log_state(hdw); -- cgit v1.2.3 From d8f5b9ba82482cab344c2d54c2c487b607e34864 Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Sat, 7 Mar 2009 00:05:00 -0300 Subject: V4L/DVB (11165): pvrusb2: Tie in debug register access to sub-devices Implement tie-in for v4l2 debug register access such that the appropriate attached sub-device is handled. Signed-off-by: Mike Isely Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/pvrusb2/pvrusb2-hdw.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/drivers/media/video/pvrusb2/pvrusb2-hdw.c index 9669d6a4fb9e..4e50e7bc5745 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-hdw.c +++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.c @@ -4925,7 +4925,10 @@ int pvr2_hdw_register_access(struct pvr2_hdw *hdw, req.match = *match; req.reg = reg_id; if (setFl) req.val = *val_ptr; - mutex_lock(&hdw->i2c_list_lock); do { + /* It would be nice to know if a sub-device answered the request */ + v4l2_device_call_all(&hdw->v4l2_dev, 0, core, g_register, &req); + if (!setFl) *val_ptr = req.val; + if (!okFl) mutex_lock(&hdw->i2c_list_lock); do { list_for_each_entry(cp, &hdw->i2c_clients, list) { if (!v4l2_chip_match_i2c_client( cp->client, -- cgit v1.2.3 From 40f07111be99b71c1e8d40c13cdc38445add787f Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Sat, 7 Mar 2009 00:08:17 -0300 Subject: V4L/DVB (11166): pvrusb2: Implement status fetching from sub-devices Implement status fetching operations in terms of calling out to sub-device(s). Signed-off-by: Mike Isely Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/pvrusb2/pvrusb2-hdw.c | 14 ++++++++++++++ drivers/media/video/pvrusb2/pvrusb2-i2c-track.c | 8 -------- 2 files changed, 14 insertions(+), 8 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/drivers/media/video/pvrusb2/pvrusb2-hdw.c index 4e50e7bc5745..d619e807a339 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-hdw.c +++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.c @@ -4816,7 +4816,21 @@ int pvr2_hdw_gpio_chg_out(struct pvr2_hdw *hdw,u32 msk,u32 val) void pvr2_hdw_status_poll(struct pvr2_hdw *hdw) { + struct v4l2_tuner *vtp = &hdw->tuner_signal_info; + memset(vtp, 0, sizeof(*vtp)); pvr2_i2c_core_status_poll(hdw); + /* Note: There apparently is no replacement for VIDIOC_CROPCAP + using v4l2-subdev - therefore we can't support that AT ALL right + now. (Of course, no sub-drivers seem to implement it either. + But now it's a a chicken and egg problem...) */ + v4l2_device_call_all(&hdw->v4l2_dev, 0, tuner, g_tuner, + &hdw->tuner_signal_info); + pvr2_trace(PVR2_TRACE_CHIPS, "client status poll" + " type=%u strength=%u audio=0x%x cap=0x%x" + " low=%u hi=%u", + vtp->type, + vtp->signal, vtp->rxsubchans, vtp->capability, + vtp->rangelow, vtp->rangehigh); } diff --git a/drivers/media/video/pvrusb2/pvrusb2-i2c-track.c b/drivers/media/video/pvrusb2/pvrusb2-i2c-track.c index 3387897ed897..7ca1b660cbe4 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-i2c-track.c +++ b/drivers/media/video/pvrusb2/pvrusb2-i2c-track.c @@ -112,20 +112,12 @@ void pvr2_i2c_core_status_poll(struct pvr2_hdw *hdw) { struct pvr2_i2c_client *cp; mutex_lock(&hdw->i2c_list_lock); do { - struct v4l2_tuner *vtp = &hdw->tuner_signal_info; - memset(vtp,0,sizeof(*vtp)); list_for_each_entry(cp, &hdw->i2c_clients, list) { if (!cp->detected_flag) continue; if (!cp->status_poll) continue; cp->status_poll(cp); } hdw->tuner_signal_stale = 0; - pvr2_trace(PVR2_TRACE_CHIPS,"i2c status poll" - " type=%u strength=%u audio=0x%x cap=0x%x" - " low=%u hi=%u", - vtp->type, - vtp->signal,vtp->rxsubchans,vtp->capability, - vtp->rangelow,vtp->rangehigh); } while (0); mutex_unlock(&hdw->i2c_list_lock); } -- cgit v1.2.3 From 2641df36212ebb29aa8d7e9a9ecac7b349108c6f Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Sat, 7 Mar 2009 00:13:25 -0300 Subject: V4L/DVB (11167): pvrusb2: Tie in various v4l2 operations into the sub-device mechanism This is another step in the v42l-subdev assimilation. This implements various call-outs to sub-devices based on state changes within the pvrusb2 driver. Signed-off-by: Mike Isely Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/pvrusb2/pvrusb2-hdw.c | 102 +++++++++++++++++++++++- drivers/media/video/pvrusb2/pvrusb2-i2c-track.c | 1 - 2 files changed, 99 insertions(+), 4 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/drivers/media/video/pvrusb2/pvrusb2-hdw.c index d619e807a339..8aeccb27019b 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-hdw.c +++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.c @@ -2839,11 +2839,102 @@ static const char *get_ctrl_typename(enum pvr2_ctl_type tp) } +static void pvr2_subdev_set_control(struct pvr2_hdw *hdw, int id, + const char *name, int val) +{ + struct v4l2_control ctrl; + pvr2_trace(PVR2_TRACE_CHIPS, "subdev v4l2 %s=%d", name, val); + memset(&ctrl, 0, sizeof(ctrl)); + ctrl.id = id; + ctrl.value = val; + v4l2_device_call_all(&hdw->v4l2_dev, 0, core, s_ctrl, &ctrl); +} + +#define PVR2_SUBDEV_SET_CONTROL(hdw, id, lab) \ + if ((hdw)->lab##_dirty) { \ + pvr2_subdev_set_control(hdw, id, #lab, (hdw)->lab##_val); \ + } + /* Execute whatever commands are required to update the state of all the - sub-devices so that it matches our current control values. */ + sub-devices so that they match our current control values. */ static void pvr2_subdev_update(struct pvr2_hdw *hdw) { - /* ????? */ + if (hdw->input_dirty || hdw->std_dirty) { + pvr2_trace(PVR2_TRACE_CHIPS,"subdev v4l2 set_standard"); + if (hdw->input_val == PVR2_CVAL_INPUT_RADIO) { + v4l2_device_call_all(&hdw->v4l2_dev, 0, + tuner, s_radio); + } else { + v4l2_std_id vs; + vs = hdw->std_mask_cur; + v4l2_device_call_all(&hdw->v4l2_dev, 0, + tuner, s_std, vs); + } + hdw->tuner_signal_stale = !0; + hdw->cropcap_stale = !0; + } + + PVR2_SUBDEV_SET_CONTROL(hdw, V4L2_CID_BRIGHTNESS, brightness); + PVR2_SUBDEV_SET_CONTROL(hdw, V4L2_CID_CONTRAST, contrast); + PVR2_SUBDEV_SET_CONTROL(hdw, V4L2_CID_SATURATION, saturation); + PVR2_SUBDEV_SET_CONTROL(hdw, V4L2_CID_HUE, hue); + PVR2_SUBDEV_SET_CONTROL(hdw, V4L2_CID_AUDIO_MUTE, mute); + PVR2_SUBDEV_SET_CONTROL(hdw, V4L2_CID_AUDIO_VOLUME, volume); + PVR2_SUBDEV_SET_CONTROL(hdw, V4L2_CID_AUDIO_BALANCE, balance); + PVR2_SUBDEV_SET_CONTROL(hdw, V4L2_CID_AUDIO_BASS, bass); + PVR2_SUBDEV_SET_CONTROL(hdw, V4L2_CID_AUDIO_TREBLE, treble); + + if (hdw->input_dirty || hdw->audiomode_dirty) { + struct v4l2_tuner vt; + memset(&vt, 0, sizeof(vt)); + vt.audmode = hdw->audiomode_val; + v4l2_device_call_all(&hdw->v4l2_dev, 0, tuner, s_tuner, &vt); + } + + if (hdw->freqDirty) { + unsigned long fv; + struct v4l2_frequency freq; + fv = pvr2_hdw_get_cur_freq(hdw); + pvr2_trace(PVR2_TRACE_CHIPS, "subdev v4l2 set_freq(%lu)", fv); + if (hdw->tuner_signal_stale) pvr2_hdw_status_poll(hdw); + memset(&freq, 0, sizeof(freq)); + if (hdw->tuner_signal_info.capability & V4L2_TUNER_CAP_LOW) { + /* ((fv * 1000) / 62500) */ + freq.frequency = (fv * 2) / 125; + } else { + freq.frequency = fv / 62500; + } + /* tuner-core currently doesn't seem to care about this, but + let's set it anyway for completeness. */ + if (hdw->input_val == PVR2_CVAL_INPUT_RADIO) { + freq.type = V4L2_TUNER_RADIO; + } else { + freq.type = V4L2_TUNER_ANALOG_TV; + } + freq.tuner = 0; + v4l2_device_call_all(&hdw->v4l2_dev, 0, tuner, + s_frequency, &freq); + } + + if (hdw->res_hor_dirty || hdw->res_ver_dirty) { + struct v4l2_format fmt; + memset(&fmt, 0, sizeof(fmt)); + fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + fmt.fmt.pix.width = hdw->res_hor_val; + fmt.fmt.pix.height = hdw->res_ver_val; + pvr2_trace(PVR2_TRACE_CHIPS,"subdev v4l2 set_size(%dx%d)", + fmt.fmt.pix.width, fmt.fmt.pix.height); + v4l2_device_call_all(&hdw->v4l2_dev, 0, video, s_fmt, &fmt); + } + + /* Unable to set crop parameters; there is apparently no equivalent + for VIDIOC_S_CROP */ + + /* ????? Cover special cases for specific sub-devices. */ + + if (hdw->tuner_signal_stale && hdw->cropcap_stale) { + pvr2_hdw_status_poll(hdw); + } } @@ -4818,6 +4909,7 @@ void pvr2_hdw_status_poll(struct pvr2_hdw *hdw) { struct v4l2_tuner *vtp = &hdw->tuner_signal_info; memset(vtp, 0, sizeof(*vtp)); + hdw->tuner_signal_stale = 0; pvr2_i2c_core_status_poll(hdw); /* Note: There apparently is no replacement for VIDIOC_CROPCAP using v4l2-subdev - therefore we can't support that AT ALL right @@ -4825,12 +4917,16 @@ void pvr2_hdw_status_poll(struct pvr2_hdw *hdw) But now it's a a chicken and egg problem...) */ v4l2_device_call_all(&hdw->v4l2_dev, 0, tuner, g_tuner, &hdw->tuner_signal_info); - pvr2_trace(PVR2_TRACE_CHIPS, "client status poll" + pvr2_trace(PVR2_TRACE_CHIPS, "subdev status poll" " type=%u strength=%u audio=0x%x cap=0x%x" " low=%u hi=%u", vtp->type, vtp->signal, vtp->rxsubchans, vtp->capability, vtp->rangelow, vtp->rangehigh); + + /* We have to do this to avoid getting into constant polling if + there's nobody to answer a poll of cropcap info. */ + hdw->cropcap_stale = 0; } diff --git a/drivers/media/video/pvrusb2/pvrusb2-i2c-track.c b/drivers/media/video/pvrusb2/pvrusb2-i2c-track.c index 7ca1b660cbe4..d0682c13b02a 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-i2c-track.c +++ b/drivers/media/video/pvrusb2/pvrusb2-i2c-track.c @@ -117,7 +117,6 @@ void pvr2_i2c_core_status_poll(struct pvr2_hdw *hdw) if (!cp->status_poll) continue; cp->status_poll(cp); } - hdw->tuner_signal_stale = 0; } while (0); mutex_unlock(&hdw->i2c_list_lock); } -- cgit v1.2.3 From e3e76cbb4d42b2e429401b17c95969c47e2db464 Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Sat, 7 Mar 2009 00:14:13 -0300 Subject: V4L/DVB (11168): pvrusb2: Define value for a null sub-device ID Signed-off-by: Mike Isely Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/pvrusb2/pvrusb2-devattr.h | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/media/video') diff --git a/drivers/media/video/pvrusb2/pvrusb2-devattr.h b/drivers/media/video/pvrusb2/pvrusb2-devattr.h index f06923986824..abf3e37fab2b 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-devattr.h +++ b/drivers/media/video/pvrusb2/pvrusb2-devattr.h @@ -33,6 +33,7 @@ */ +#define PVR2_CLIENT_ID_NULL 0 #define PVR2_CLIENT_ID_MSP3400 1 #define PVR2_CLIENT_ID_CX25840 2 #define PVR2_CLIENT_ID_SAA7115 3 -- cgit v1.2.3 From 00e5f73607d1dea12bf0ccbba9832c26a611213f Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Sat, 7 Mar 2009 00:17:11 -0300 Subject: V4L/DVB (11169): pvrusb2: Note who our video decoder sub-device is, and set it up Other code may need to treat the video decoder sub-device in a special manner, so this change implements code to recognize when such a sub-device is connected to the driver, does any special processing for it, and notes who the device is for future reference. Signed-off-by: Mike Isely Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h | 1 + drivers/media/video/pvrusb2/pvrusb2-hdw.c | 28 ++++++++++++++++++++++ 2 files changed, 29 insertions(+) (limited to 'drivers/media/video') diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h b/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h index b3cb0bbd8cf5..c8192d8a6083 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h +++ b/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h @@ -299,6 +299,7 @@ struct pvr2_hdw { int flag_tripped; /* Indicates overall failure to start */ struct pvr2_decoder_ctrl *decoder_ctrl; + unsigned int decoder_client_id; // CPU firmware info (used to help find / save firmware data) char *fw_buffer; diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/drivers/media/video/pvrusb2/pvrusb2-hdw.c index 8aeccb27019b..02db5d6ebb46 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-hdw.c +++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.c @@ -2041,6 +2041,34 @@ static void pvr2_hdw_load_subdev(struct pvr2_hdw *hdw, pvr2_trace(PVR2_TRACE_INIT, "Attached sub-driver %s", fname); + /* client-specific setup... */ + switch (mid) { + case PVR2_CLIENT_ID_CX25840: + hdw->decoder_client_id = mid; + { + /* + Mike Isely 19-Nov-2006 - This + bit of nuttiness for cx25840 causes that module + to correctly set up its video scaling. This is + really a problem in the cx25840 module itself, + but we work around it here. The problem has not + been seen in ivtv because there VBI is supported + and set up. We don't do VBI here (at least not + yet) and thus we never attempted to even set it + up. + */ + struct v4l2_format fmt; + memset(&fmt, 0, sizeof(fmt)); + fmt.type = V4L2_BUF_TYPE_SLICED_VBI_CAPTURE; + v4l2_device_call_all(&hdw->v4l2_dev, mid, + video, s_fmt, &fmt); + } + break; + case PVR2_CLIENT_ID_SAA7115: + hdw->decoder_client_id = mid; + break; + default: break; + } } -- cgit v1.2.3 From 6907205bcbe7b8bcdc0720bc75e1d2558162d017 Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Sat, 7 Mar 2009 00:19:43 -0300 Subject: V4L/DVB (11170): pvrusb2: Clean-up / placeholders inserted for additional development Signed-off-by: Mike Isely Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h | 2 -- drivers/media/video/pvrusb2/pvrusb2-hdw.c | 2 ++ 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h b/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h index c8192d8a6083..299bf58ad77a 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h +++ b/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h @@ -58,8 +58,6 @@ #define LOCK_TAKE(x) do { mutex_lock(&x##_mutex); x##_held = !0; } while (0) #define LOCK_GIVE(x) do { x##_held = 0; mutex_unlock(&x##_mutex); } while (0) -struct pvr2_decoder; - typedef int (*pvr2_ctlf_is_dirty)(struct pvr2_ctrl *); typedef void (*pvr2_ctlf_clear_dirty)(struct pvr2_ctrl *); typedef int (*pvr2_ctlf_check_value)(struct pvr2_ctrl *,int); diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/drivers/media/video/pvrusb2/pvrusb2-hdw.c index 02db5d6ebb46..65e65a4f2ec0 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-hdw.c +++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.c @@ -1666,6 +1666,7 @@ static int pvr2_decoder_enable(struct pvr2_hdw *hdw,int enablefl) return -EIO; } hdw->decoder_ctrl->enable(hdw->decoder_ctrl->ctxt,enablefl); + // ????? return 0; } @@ -4023,6 +4024,7 @@ int pvr2_hdw_cmd_decoder_reset(struct pvr2_hdw *hdw) pvr2_trace(PVR2_TRACE_INIT, "Requesting decoder reset"); hdw->decoder_ctrl->force_reset(hdw->decoder_ctrl->ctxt); + // ????? return 0; } -- cgit v1.2.3 From af78e16b5d5ba74566814ba0f50ee1d736d933a5 Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Sat, 7 Mar 2009 00:21:30 -0300 Subject: V4L/DVB (11171): pvrusb2: Tie in sub-device decoder start/stop Implement code to send appropriate streaming start/stop commands to attached sub-devices Signed-off-by: Mike Isely Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/pvrusb2/pvrusb2-hdw.c | 65 ++++++++++++++++++------------- 1 file changed, 39 insertions(+), 26 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/drivers/media/video/pvrusb2/pvrusb2-hdw.c index 65e65a4f2ec0..74b365f1cfd2 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-hdw.c +++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.c @@ -1655,19 +1655,29 @@ static const char *pvr2_get_state_name(unsigned int st) static int pvr2_decoder_enable(struct pvr2_hdw *hdw,int enablefl) { - if (!hdw->decoder_ctrl) { - if (!hdw->flag_decoder_missed) { - pvr2_trace(PVR2_TRACE_ERROR_LEGS, - "WARNING: No decoder present"); - hdw->flag_decoder_missed = !0; - trace_stbit("flag_decoder_missed", - hdw->flag_decoder_missed); - } - return -EIO; + if (hdw->decoder_ctrl) { + hdw->decoder_ctrl->enable(hdw->decoder_ctrl->ctxt, enablefl); + return 0; } - hdw->decoder_ctrl->enable(hdw->decoder_ctrl->ctxt,enablefl); - // ????? - return 0; + /* Even though we really only care about the video decoder chip at + this point, we'll broadcast stream on/off to all sub-devices + anyway, just in case somebody else wants to hear the + command... */ + v4l2_device_call_all(&hdw->v4l2_dev, 0, video, s_stream, enablefl); + if (hdw->decoder_client_id) { + /* We get here if the encoder has been noticed. Otherwise + we'll issue a warning to the user (which should + normally never happen). */ + return 0; + } + if (!hdw->flag_decoder_missed) { + pvr2_trace(PVR2_TRACE_ERROR_LEGS, + "WARNING: No decoder present"); + hdw->flag_decoder_missed = !0; + trace_stbit("flag_decoder_missed", + hdw->flag_decoder_missed); + } + return -EIO; } @@ -4009,23 +4019,26 @@ int pvr2_hdw_cmd_powerdown(struct pvr2_hdw *hdw) int pvr2_hdw_cmd_decoder_reset(struct pvr2_hdw *hdw) { - if (!hdw->decoder_ctrl) { - pvr2_trace(PVR2_TRACE_INIT, - "Unable to reset decoder: nothing attached"); - return -ENOTTY; + pvr2_trace(PVR2_TRACE_INIT, + "Requesting decoder reset"); + if (hdw->decoder_ctrl) { + if (!hdw->decoder_ctrl->force_reset) { + pvr2_trace(PVR2_TRACE_INIT, + "Unable to reset decoder: not implemented"); + return -ENOTTY; + } + hdw->decoder_ctrl->force_reset(hdw->decoder_ctrl->ctxt); + return 0; + } else { } - - if (!hdw->decoder_ctrl->force_reset) { - pvr2_trace(PVR2_TRACE_INIT, - "Unable to reset decoder: not implemented"); - return -ENOTTY; + if (hdw->decoder_client_id) { + v4l2_device_call_all(&hdw->v4l2_dev, hdw->decoder_client_id, + core, reset, 0); + return 0; } - pvr2_trace(PVR2_TRACE_INIT, - "Requesting decoder reset"); - hdw->decoder_ctrl->force_reset(hdw->decoder_ctrl->ctxt); - // ????? - return 0; + "Unable to reset decoder: nothing attached"); + return -ENOTTY; } -- cgit v1.2.3 From 1ab5e74fa3d41a3d49005e430f98cdff77a3cee6 Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Sat, 7 Mar 2009 00:24:24 -0300 Subject: V4L/DVB (11172): pvrusb2: Cause overall initialization to fail if sub-driver(s) fail Signed-off-by: Mike Isely Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/pvrusb2/pvrusb2-hdw.c | 32 ++++++++++++++++--------------- 1 file changed, 17 insertions(+), 15 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/drivers/media/video/pvrusb2/pvrusb2-hdw.c index 74b365f1cfd2..2f9667e62bb1 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-hdw.c +++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.c @@ -1974,8 +1974,8 @@ static unsigned int pvr2_copy_i2c_addr_list( } -static void pvr2_hdw_load_subdev(struct pvr2_hdw *hdw, - const struct pvr2_device_client_desc *cd) +static int pvr2_hdw_load_subdev(struct pvr2_hdw *hdw, + const struct pvr2_device_client_desc *cd) { const char *fname; unsigned char mid; @@ -1989,11 +1989,10 @@ static void pvr2_hdw_load_subdev(struct pvr2_hdw *hdw, fname = (mid < ARRAY_SIZE(module_names)) ? module_names[mid] : NULL; if (!fname) { pvr2_trace(PVR2_TRACE_ERROR_LEGS, - "Module ID %u for device %s is unknown" - " (this is probably a bad thing...)", + "Module ID %u for device %s has no name", mid, hdw->hdw_desc->description); - return; + return -EINVAL; } i2ccnt = pvr2_copy_i2c_addr_list(i2caddr, cd->i2c_address_list, @@ -2007,11 +2006,10 @@ static void pvr2_hdw_load_subdev(struct pvr2_hdw *hdw, if (!i2ccnt) { pvr2_trace(PVR2_TRACE_ERROR_LEGS, - "Module ID %u for device %s:" - " No i2c addresses" - " (this is probably a bad thing...)", - mid, hdw->hdw_desc->description); - return; + "Module ID %u (%s) for device %s:" + " No i2c addresses", + mid, fname, hdw->hdw_desc->description); + return -EINVAL; } /* Note how the 2nd and 3rd arguments are the same for both @@ -2033,10 +2031,9 @@ static void pvr2_hdw_load_subdev(struct pvr2_hdw *hdw, if (!sd) { pvr2_trace(PVR2_TRACE_ERROR_LEGS, - "Module ID %u for device %s failed to load" - " (this is probably a bad thing...)", - mid, hdw->hdw_desc->description); - return; + "Module ID %u (%s) for device %s failed to load", + mid, fname, hdw->hdw_desc->description); + return -EIO; } /* Tag this sub-device instance with the module ID we know about. @@ -2080,6 +2077,8 @@ static void pvr2_hdw_load_subdev(struct pvr2_hdw *hdw, break; default: break; } + + return 0; } @@ -2088,6 +2087,7 @@ static void pvr2_hdw_load_modules(struct pvr2_hdw *hdw) unsigned int idx; const struct pvr2_string_table *cm; const struct pvr2_device_client_table *ct; + int okFl = !0; cm = &hdw->hdw_desc->client_modules; for (idx = 0; idx < cm->cnt; idx++) { @@ -2096,8 +2096,9 @@ static void pvr2_hdw_load_modules(struct pvr2_hdw *hdw) ct = &hdw->hdw_desc->client_table; for (idx = 0; idx < ct->cnt; idx++) { - pvr2_hdw_load_subdev(hdw,&ct->lst[idx]); + if (!pvr2_hdw_load_subdev(hdw, &ct->lst[idx])) okFl = 0; } + if (!okFl) pvr2_hdw_render_useless(hdw); } @@ -2159,6 +2160,7 @@ static void pvr2_hdw_setup_low(struct pvr2_hdw *hdw) if (!pvr2_hdw_dev_ok(hdw)) return; pvr2_hdw_load_modules(hdw); + if (!pvr2_hdw_dev_ok(hdw)) return; for (idx = 0; idx < CTRLDEF_COUNT; idx++) { cptr = hdw->controls + idx; -- cgit v1.2.3 From 20ae26c84e48b95177e334fa9022f68aa3b77df6 Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Sat, 7 Mar 2009 00:26:24 -0300 Subject: V4L/DVB (11173): pvrusb2: Fix backwards function header comments Signed-off-by: Mike Isely Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/pvrusb2/pvrusb2-debugifc.h | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/pvrusb2/pvrusb2-debugifc.h b/drivers/media/video/pvrusb2/pvrusb2-debugifc.h index e24ff59f8605..2f8d46761cd0 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-debugifc.h +++ b/drivers/media/video/pvrusb2/pvrusb2-debugifc.h @@ -22,16 +22,16 @@ struct pvr2_hdw; -/* Non-intrusively print some useful debugging info from inside the - driver. This should work even if the driver appears to be - wedged. */ -int pvr2_debugifc_print_info(struct pvr2_hdw *, - char *buf_ptr,unsigned int buf_size); - /* Print general status of driver. This will also trigger a probe of the USB link. Unlike print_info(), this one synchronizes with the driver so the information should be self-consistent (but it will hang if the driver is wedged). */ +int pvr2_debugifc_print_info(struct pvr2_hdw *, + char *buf_ptr, unsigned int buf_size); + +/* Non-intrusively print some useful debugging info from inside the + driver. This should work even if the driver appears to be + wedged. */ int pvr2_debugifc_print_status(struct pvr2_hdw *, char *buf_ptr,unsigned int buf_size); -- cgit v1.2.3 From 858f910e869d1300c1ab0cadbe9908322f8bfb78 Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Sat, 7 Mar 2009 00:28:28 -0300 Subject: V4L/DVB (11174): pvrusb2: Implement reporting of connected sub-devices The pvrusb2 driver has a function that reports internal state. It can be accessed from either the debug interface or as the result of a v4l log status request. This change adds information listing sub-devices to the report. Signed-off-by: Mike Isely Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/pvrusb2/pvrusb2-hdw.c | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) (limited to 'drivers/media/video') diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/drivers/media/video/pvrusb2/pvrusb2-hdw.c index 2f9667e62bb1..bd4e374e37f8 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-hdw.c +++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.c @@ -4779,6 +4779,29 @@ static unsigned int pvr2_hdw_report_unlocked(struct pvr2_hdw *hdw,int which, stats.buffers_processed, stats.buffers_failed); } + case 6: { + struct v4l2_subdev *sd; + unsigned int tcnt = 0; + unsigned int ccnt; + const char *p; + unsigned int id; + ccnt = scnprintf(buf, + acnt, + "Associted v4l2_subdev drivers:"); + tcnt += ccnt; + v4l2_device_for_each_subdev(sd, &hdw->v4l2_dev) { + id = sd->grp_id; + p = NULL; + if (id < ARRAY_SIZE(module_names)) { + p = module_names[id]; + } + if (!p) p = "(unknown)"; + ccnt = scnprintf(buf + tcnt, + acnt - tcnt, + " %s (%u)", p, id); + } + return tcnt; + } default: break; } return 0; -- cgit v1.2.3 From edb9dcb885c6288813b62c20e6b578492845f9ad Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Sat, 7 Mar 2009 00:37:10 -0300 Subject: V4L/DVB (11175): pvrusb2: Implement sub-device specific update framework Lay down a foundation whereby it becomes possible to send customized updates to specific sub-devices. (This becomes useful for routing configuration, which is a very sub-device specific operation.) Signed-off-by: Mike Isely Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/pvrusb2/pvrusb2-hdw.c | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/drivers/media/video/pvrusb2/pvrusb2-hdw.c index bd4e374e37f8..36285ca48808 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-hdw.c +++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.c @@ -105,6 +105,13 @@ MODULE_PARM_DESC(radio_freq, "specify initial radio frequency"); /* size of a firmware chunk */ #define FIRMWARE_CHUNK_SIZE 0x2000 +typedef void (*pvr2_subdev_update_func)(struct pvr2_hdw *, + struct v4l2_subdev *); + +static const pvr2_subdev_update_func pvr2_module_update_functions[] = { + /* ????? */ +}; + static const char *module_names[] = { [PVR2_CLIENT_ID_MSP3400] = "msp3400", [PVR2_CLIENT_ID_CX25840] = "cx25840", @@ -2900,6 +2907,10 @@ static void pvr2_subdev_set_control(struct pvr2_hdw *hdw, int id, sub-devices so that they match our current control values. */ static void pvr2_subdev_update(struct pvr2_hdw *hdw) { + struct v4l2_subdev *sd; + unsigned int id; + pvr2_subdev_update_func fp; + if (hdw->input_dirty || hdw->std_dirty) { pvr2_trace(PVR2_TRACE_CHIPS,"subdev v4l2 set_standard"); if (hdw->input_val == PVR2_CVAL_INPUT_RADIO) { @@ -2971,7 +2982,13 @@ static void pvr2_subdev_update(struct pvr2_hdw *hdw) /* Unable to set crop parameters; there is apparently no equivalent for VIDIOC_S_CROP */ - /* ????? Cover special cases for specific sub-devices. */ + v4l2_device_for_each_subdev(sd, &hdw->v4l2_dev) { + id = sd->grp_id; + if (id >= ARRAY_SIZE(pvr2_module_update_functions)) continue; + fp = pvr2_module_update_functions[id]; + if (!fp) continue; + (*fp)(hdw, sd); + } if (hdw->tuner_signal_stale && hdw->cropcap_stale) { pvr2_hdw_status_poll(hdw); -- cgit v1.2.3 From 5f6dae802c0f6a943c2c873c203642d1d3c2fc3f Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Sat, 7 Mar 2009 00:39:34 -0300 Subject: V4L/DVB (11176): pvrusb2: Tie in wm8775 sub-device handling Signed-off-by: Mike Isely Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/pvrusb2/pvrusb2-devattr.h | 1 + drivers/media/video/pvrusb2/pvrusb2-hdw.c | 4 +++- drivers/media/video/pvrusb2/pvrusb2-wm8775.c | 26 ++++++++++++++++++++++++++ drivers/media/video/pvrusb2/pvrusb2-wm8775.h | 3 +++ 4 files changed, 33 insertions(+), 1 deletion(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/pvrusb2/pvrusb2-devattr.h b/drivers/media/video/pvrusb2/pvrusb2-devattr.h index abf3e37fab2b..1339a32a2a1b 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-devattr.h +++ b/drivers/media/video/pvrusb2/pvrusb2-devattr.h @@ -39,6 +39,7 @@ #define PVR2_CLIENT_ID_SAA7115 3 #define PVR2_CLIENT_ID_TUNER 4 #define PVR2_CLIENT_ID_CS53132A 5 +#define PVR2_CLIENT_ID_WM8775 6 struct pvr2_device_client_desc { /* One ovr PVR2_CLIENT_ID_xxxx */ diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/drivers/media/video/pvrusb2/pvrusb2-hdw.c index 36285ca48808..3a93860310ed 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-hdw.c +++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.c @@ -36,6 +36,7 @@ #include "pvrusb2-encoder.h" #include "pvrusb2-debug.h" #include "pvrusb2-fx2-cmd.h" +#include "pvrusb2-wm8775.h" #define TV_MIN_FREQ 55250000L #define TV_MAX_FREQ 850000000L @@ -109,7 +110,7 @@ typedef void (*pvr2_subdev_update_func)(struct pvr2_hdw *, struct v4l2_subdev *); static const pvr2_subdev_update_func pvr2_module_update_functions[] = { - /* ????? */ + [PVR2_CLIENT_ID_WM8775] = pvr2_wm8775_update, }; static const char *module_names[] = { @@ -118,6 +119,7 @@ static const char *module_names[] = { [PVR2_CLIENT_ID_SAA7115] = "saa7115", [PVR2_CLIENT_ID_TUNER] = "tuner", [PVR2_CLIENT_ID_CS53132A] = "cs53132a", + [PVR2_CLIENT_ID_WM8775] = "wm8775", }; diff --git a/drivers/media/video/pvrusb2/pvrusb2-wm8775.c b/drivers/media/video/pvrusb2/pvrusb2-wm8775.c index f6fcf0ac6118..40b221fe8027 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-wm8775.c +++ b/drivers/media/video/pvrusb2/pvrusb2-wm8775.c @@ -37,6 +37,8 @@ #include #include + + struct pvr2_v4l_wm8775 { struct pvr2_i2c_handler handler; struct pvr2_i2c_client *client; @@ -158,6 +160,30 @@ int pvr2_i2c_wm8775_setup(struct pvr2_hdw *hdw,struct pvr2_i2c_client *cp) } +void pvr2_wm8775_update(struct pvr2_hdw *hdw, struct v4l2_subdev *sd) +{ + if (hdw->input_dirty) { + struct v4l2_routing route; + + memset(&route, 0, sizeof(route)); + + switch (hdw->input_val) { + case PVR2_CVAL_INPUT_RADIO: + route.input = 1; + break; + default: + /* All other cases just use the second input */ + route.input = 2; + break; + } + pvr2_trace(PVR2_TRACE_CHIPS, "subdev wm8775" + " set_input(val=%d route=0x%x)", + hdw->input_val, route.input); + + sd->ops->audio->s_routing(sd, &route); + } +} + /* diff --git a/drivers/media/video/pvrusb2/pvrusb2-wm8775.h b/drivers/media/video/pvrusb2/pvrusb2-wm8775.h index 5b2cb6183576..d2d4e7eb1107 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-wm8775.h +++ b/drivers/media/video/pvrusb2/pvrusb2-wm8775.h @@ -37,6 +37,9 @@ #include "pvrusb2-i2c-track.h" int pvr2_i2c_wm8775_setup(struct pvr2_hdw *,struct pvr2_i2c_client *); +#include "pvrusb2-hdw-internal.h" + +void pvr2_wm8775_update(struct pvr2_hdw *, struct v4l2_subdev *sd); #endif /* __PVRUSB2_WM8775_H */ -- cgit v1.2.3 From 6f9565120f5c2944b3d31daf03a07c272e12867b Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Sat, 7 Mar 2009 00:43:26 -0300 Subject: V4L/DVB (11177): pvrusb2: Tie in saa7115 sub-device handling Signed-off-by: Mike Isely Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/pvrusb2/pvrusb2-hdw.c | 2 + drivers/media/video/pvrusb2/pvrusb2-video-v4l.c | 64 +++++++++++++++++++++---- drivers/media/video/pvrusb2/pvrusb2-video-v4l.h | 2 + 3 files changed, 58 insertions(+), 10 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/drivers/media/video/pvrusb2/pvrusb2-hdw.c index 3a93860310ed..e92ea6af8bc0 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-hdw.c +++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.c @@ -37,6 +37,7 @@ #include "pvrusb2-debug.h" #include "pvrusb2-fx2-cmd.h" #include "pvrusb2-wm8775.h" +#include "pvrusb2-video-v4l.h" #define TV_MIN_FREQ 55250000L #define TV_MAX_FREQ 850000000L @@ -111,6 +112,7 @@ typedef void (*pvr2_subdev_update_func)(struct pvr2_hdw *, static const pvr2_subdev_update_func pvr2_module_update_functions[] = { [PVR2_CLIENT_ID_WM8775] = pvr2_wm8775_update, + [PVR2_CLIENT_ID_SAA7115] = pvr2_saa7115_subdev_update, }; static const char *module_names[] = { diff --git a/drivers/media/video/pvrusb2/pvrusb2-video-v4l.c b/drivers/media/video/pvrusb2/pvrusb2-video-v4l.c index 4059648c7056..ad28c5d3ad83 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-video-v4l.c +++ b/drivers/media/video/pvrusb2/pvrusb2-video-v4l.c @@ -28,9 +28,10 @@ */ #include "pvrusb2-video-v4l.h" -#include "pvrusb2-i2c-cmd-v4l2.h" +#include "pvrusb2-i2c-cmd-v4l2.h" + #include "pvrusb2-hdw-internal.h" #include "pvrusb2-debug.h" #include @@ -39,15 +40,6 @@ #include #include -struct pvr2_v4l_decoder { - struct pvr2_i2c_handler handler; - struct pvr2_decoder_ctrl ctrl; - struct pvr2_i2c_client *client; - struct pvr2_hdw *hdw; - unsigned long stale_mask; -}; - - struct routing_scheme { const int *def; unsigned int cnt; @@ -70,6 +62,16 @@ static const struct routing_scheme routing_schemes[] = { }, }; +struct pvr2_v4l_decoder { + struct pvr2_i2c_handler handler; + struct pvr2_decoder_ctrl ctrl; + struct pvr2_i2c_client *client; + struct pvr2_hdw *hdw; + unsigned long stale_mask; +}; + + + static void set_input(struct pvr2_v4l_decoder *ctxt) { struct pvr2_hdw *hdw = ctxt->hdw; @@ -245,6 +247,48 @@ int pvr2_i2c_decoder_v4l_setup(struct pvr2_hdw *hdw, } +void pvr2_saa7115_subdev_update(struct pvr2_hdw *hdw, struct v4l2_subdev *sd) +{ + if (hdw->srate_dirty) { + u32 val; + pvr2_trace(PVR2_TRACE_CHIPS, "subdev v4l2 set_audio %d", + hdw->srate_val); + switch (hdw->srate_val) { + default: + case V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000: + val = 48000; + break; + case V4L2_MPEG_AUDIO_SAMPLING_FREQ_44100: + val = 44100; + break; + case V4L2_MPEG_AUDIO_SAMPLING_FREQ_32000: + val = 32000; + break; + } + sd->ops->audio->s_clock_freq(sd, val); + } + if (hdw->input_dirty) { + struct v4l2_routing route; + const struct routing_scheme *sp; + unsigned int sid = hdw->hdw_desc->signal_routing_scheme; + pvr2_trace(PVR2_TRACE_CHIPS, "subdev v4l2 set_input(%d)", + hdw->input_val); + if ((sid < ARRAY_SIZE(routing_schemes)) && + ((sp = routing_schemes + sid) != NULL) && + (hdw->input_val >= 0) && + (hdw->input_val < sp->cnt)) { + route.input = sp->def[hdw->input_val]; + } else { + pvr2_trace(PVR2_TRACE_ERROR_LEGS, + "*** WARNING *** subdev v4l2 set_input:" + " Invalid routing scheme (%u) and/or input (%d)", + sid, hdw->input_val); + return; + } + route.output = 0; + sd->ops->video->s_routing(sd, &route); + } +} /* diff --git a/drivers/media/video/pvrusb2/pvrusb2-video-v4l.h b/drivers/media/video/pvrusb2/pvrusb2-video-v4l.h index b2cd3875bb5b..dac4b1ad3664 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-video-v4l.h +++ b/drivers/media/video/pvrusb2/pvrusb2-video-v4l.h @@ -37,6 +37,8 @@ int pvr2_i2c_decoder_v4l_setup(struct pvr2_hdw *,struct pvr2_i2c_client *); +#include "pvrusb2-hdw-internal.h" +void pvr2_saa7115_subdev_update(struct pvr2_hdw *, struct v4l2_subdev *); #endif /* __PVRUSB2_VIDEO_V4L_H */ -- cgit v1.2.3 From 01c59df818001b0bd3a31e2301a92a8c73bccbce Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Sat, 7 Mar 2009 00:48:09 -0300 Subject: V4L/DVB (11178): pvrusb2: Make audio sample rate update into a sub-device broadcast The pvrusb2 driver had previously been using i2c module specific calls to set the sample rate (a long long time ago this was needed). These days it is safe to use a broadcast so let's just broadcast this when communicating audio sample rate to sub-devices. Signed-off-by: Mike Isely Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/pvrusb2/pvrusb2-hdw.c | 20 ++++++++++++++++++++ drivers/media/video/pvrusb2/pvrusb2-video-v4l.c | 18 ------------------ 2 files changed, 20 insertions(+), 18 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/drivers/media/video/pvrusb2/pvrusb2-hdw.c index e92ea6af8bc0..8a96f260af5b 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-hdw.c +++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.c @@ -2983,6 +2983,26 @@ static void pvr2_subdev_update(struct pvr2_hdw *hdw) v4l2_device_call_all(&hdw->v4l2_dev, 0, video, s_fmt, &fmt); } + if (hdw->srate_dirty) { + u32 val; + pvr2_trace(PVR2_TRACE_CHIPS, "subdev v4l2 set_audio %d", + hdw->srate_val); + switch (hdw->srate_val) { + default: + case V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000: + val = 48000; + break; + case V4L2_MPEG_AUDIO_SAMPLING_FREQ_44100: + val = 44100; + break; + case V4L2_MPEG_AUDIO_SAMPLING_FREQ_32000: + val = 32000; + break; + } + v4l2_device_call_all(&hdw->v4l2_dev, 0, + audio, s_clock_freq, val); + } + /* Unable to set crop parameters; there is apparently no equivalent for VIDIOC_S_CROP */ diff --git a/drivers/media/video/pvrusb2/pvrusb2-video-v4l.c b/drivers/media/video/pvrusb2/pvrusb2-video-v4l.c index ad28c5d3ad83..1c9ed5e85c80 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-video-v4l.c +++ b/drivers/media/video/pvrusb2/pvrusb2-video-v4l.c @@ -249,24 +249,6 @@ int pvr2_i2c_decoder_v4l_setup(struct pvr2_hdw *hdw, void pvr2_saa7115_subdev_update(struct pvr2_hdw *hdw, struct v4l2_subdev *sd) { - if (hdw->srate_dirty) { - u32 val; - pvr2_trace(PVR2_TRACE_CHIPS, "subdev v4l2 set_audio %d", - hdw->srate_val); - switch (hdw->srate_val) { - default: - case V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000: - val = 48000; - break; - case V4L2_MPEG_AUDIO_SAMPLING_FREQ_44100: - val = 44100; - break; - case V4L2_MPEG_AUDIO_SAMPLING_FREQ_32000: - val = 32000; - break; - } - sd->ops->audio->s_clock_freq(sd, val); - } if (hdw->input_dirty) { struct v4l2_routing route; const struct routing_scheme *sp; -- cgit v1.2.3 From 4ecbc28d3df967ee52dd9d060bc56d4a85196bdf Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Sat, 7 Mar 2009 00:49:19 -0300 Subject: V4L/DVB (11179): pvrusb2: make sub-device specific update function names uniform Signed-off-by: Mike Isely Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/pvrusb2/pvrusb2-hdw.c | 2 +- drivers/media/video/pvrusb2/pvrusb2-wm8775.c | 2 +- drivers/media/video/pvrusb2/pvrusb2-wm8775.h | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/drivers/media/video/pvrusb2/pvrusb2-hdw.c index 8a96f260af5b..7269110a3bc2 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-hdw.c +++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.c @@ -111,7 +111,7 @@ typedef void (*pvr2_subdev_update_func)(struct pvr2_hdw *, struct v4l2_subdev *); static const pvr2_subdev_update_func pvr2_module_update_functions[] = { - [PVR2_CLIENT_ID_WM8775] = pvr2_wm8775_update, + [PVR2_CLIENT_ID_WM8775] = pvr2_wm8775_subdev_update, [PVR2_CLIENT_ID_SAA7115] = pvr2_saa7115_subdev_update, }; diff --git a/drivers/media/video/pvrusb2/pvrusb2-wm8775.c b/drivers/media/video/pvrusb2/pvrusb2-wm8775.c index 40b221fe8027..a099bf1641e5 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-wm8775.c +++ b/drivers/media/video/pvrusb2/pvrusb2-wm8775.c @@ -160,7 +160,7 @@ int pvr2_i2c_wm8775_setup(struct pvr2_hdw *hdw,struct pvr2_i2c_client *cp) } -void pvr2_wm8775_update(struct pvr2_hdw *hdw, struct v4l2_subdev *sd) +void pvr2_wm8775_subdev_update(struct pvr2_hdw *hdw, struct v4l2_subdev *sd) { if (hdw->input_dirty) { struct v4l2_routing route; diff --git a/drivers/media/video/pvrusb2/pvrusb2-wm8775.h b/drivers/media/video/pvrusb2/pvrusb2-wm8775.h index d2d4e7eb1107..a304988b1e79 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-wm8775.h +++ b/drivers/media/video/pvrusb2/pvrusb2-wm8775.h @@ -39,7 +39,7 @@ int pvr2_i2c_wm8775_setup(struct pvr2_hdw *,struct pvr2_i2c_client *); #include "pvrusb2-hdw-internal.h" -void pvr2_wm8775_update(struct pvr2_hdw *, struct v4l2_subdev *sd); +void pvr2_wm8775_subdev_update(struct pvr2_hdw *, struct v4l2_subdev *sd); #endif /* __PVRUSB2_WM8775_H */ -- cgit v1.2.3 From 76891d65577a3bb429aca2d8cca834cc76353cd8 Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Sat, 7 Mar 2009 00:52:06 -0300 Subject: V4L/DVB (11180): pvrusb2: Tie in msp3400 sub-device support Signed-off-by: Mike Isely Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/pvrusb2/pvrusb2-audio.c | 47 +++++++++++++++++++++++------ drivers/media/video/pvrusb2/pvrusb2-audio.h | 2 ++ drivers/media/video/pvrusb2/pvrusb2-hdw.c | 2 ++ 3 files changed, 41 insertions(+), 10 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/pvrusb2/pvrusb2-audio.c b/drivers/media/video/pvrusb2/pvrusb2-audio.c index c29206fa3d1b..52966414327d 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-audio.c +++ b/drivers/media/video/pvrusb2/pvrusb2-audio.c @@ -27,15 +27,6 @@ #include -struct pvr2_msp3400_handler { - struct pvr2_hdw *hdw; - struct pvr2_i2c_client *client; - struct pvr2_i2c_handler i2c_handler; - unsigned long stale_mask; -}; - - - struct routing_scheme { const int *def; unsigned int cnt; @@ -64,6 +55,17 @@ static const struct routing_scheme routing_schemes[] = { }, }; + +struct pvr2_msp3400_handler { + struct pvr2_hdw *hdw; + struct pvr2_i2c_client *client; + struct pvr2_i2c_handler i2c_handler; + unsigned long stale_mask; +}; + + + + /* This function selects the correct audio input source */ static void set_stereo(struct pvr2_msp3400_handler *ctxt) { @@ -180,7 +182,32 @@ int pvr2_i2c_msp3400_setup(struct pvr2_hdw *hdw,struct pvr2_i2c_client *cp) return !0; } - +void pvr2_msp3400_subdev_update(struct pvr2_hdw *hdw, struct v4l2_subdev *sd) +{ + if (hdw->input_dirty) { + struct v4l2_routing route; + const struct routing_scheme *sp; + unsigned int sid = hdw->hdw_desc->signal_routing_scheme; + + pvr2_trace(PVR2_TRACE_CHIPS, "subdev msp3400 v4l2 set_stereo"); + + if ((sid < ARRAY_SIZE(routing_schemes)) && + ((sp = routing_schemes + sid) != NULL) && + (hdw->input_val >= 0) && + (hdw->input_val < sp->cnt)) { + route.input = sp->def[hdw->input_val]; + } else { + pvr2_trace(PVR2_TRACE_ERROR_LEGS, + "*** WARNING *** subdev msp3400 set_input:" + " Invalid routing scheme (%u)" + " and/or input (%d)", + sid, hdw->input_val); + return; + } + route.output = MSP_OUTPUT(MSP_SC_IN_DSP_SCART1); + sd->ops->audio->s_routing(sd, &route); + } +} /* Stuff for Emacs to see, in order to encourage consistent editing style: diff --git a/drivers/media/video/pvrusb2/pvrusb2-audio.h b/drivers/media/video/pvrusb2/pvrusb2-audio.h index f7f0a408a9b4..c47c8de3ba06 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-audio.h +++ b/drivers/media/video/pvrusb2/pvrusb2-audio.h @@ -26,6 +26,8 @@ int pvr2_i2c_msp3400_setup(struct pvr2_hdw *,struct pvr2_i2c_client *); +#include "pvrusb2-hdw-internal.h" +void pvr2_msp3400_subdev_update(struct pvr2_hdw *, struct v4l2_subdev *); #endif /* __PVRUSB2_AUDIO_H */ /* diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/drivers/media/video/pvrusb2/pvrusb2-hdw.c index 7269110a3bc2..ff7af062002b 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-hdw.c +++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.c @@ -38,6 +38,7 @@ #include "pvrusb2-fx2-cmd.h" #include "pvrusb2-wm8775.h" #include "pvrusb2-video-v4l.h" +#include "pvrusb2-audio.h" #define TV_MIN_FREQ 55250000L #define TV_MAX_FREQ 850000000L @@ -113,6 +114,7 @@ typedef void (*pvr2_subdev_update_func)(struct pvr2_hdw *, static const pvr2_subdev_update_func pvr2_module_update_functions[] = { [PVR2_CLIENT_ID_WM8775] = pvr2_wm8775_subdev_update, [PVR2_CLIENT_ID_SAA7115] = pvr2_saa7115_subdev_update, + [PVR2_CLIENT_ID_MSP3400] = pvr2_msp3400_subdev_update, }; static const char *module_names[] = { -- cgit v1.2.3 From 1e481cca49bf1c444562f5b86a0e5315d68640c7 Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Sat, 7 Mar 2009 00:52:42 -0300 Subject: V4L/DVB (11181): pvrusb2: Fix silly 80 column issue Signed-off-by: Mike Isely Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/pvrusb2/pvrusb2-video-v4l.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/pvrusb2/pvrusb2-video-v4l.c b/drivers/media/video/pvrusb2/pvrusb2-video-v4l.c index 1c9ed5e85c80..c7a1621cf140 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-video-v4l.c +++ b/drivers/media/video/pvrusb2/pvrusb2-video-v4l.c @@ -263,7 +263,8 @@ void pvr2_saa7115_subdev_update(struct pvr2_hdw *hdw, struct v4l2_subdev *sd) } else { pvr2_trace(PVR2_TRACE_ERROR_LEGS, "*** WARNING *** subdev v4l2 set_input:" - " Invalid routing scheme (%u) and/or input (%d)", + " Invalid routing scheme (%u)" + " and/or input (%d)", sid, hdw->input_val); return; } -- cgit v1.2.3 From 634ba268b965b57da1f60edbc57f14299a5326f6 Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Sat, 7 Mar 2009 00:54:02 -0300 Subject: V4L/DVB (11182): pvrusb2: Tie in cx25840 sub-device support Signed-off-by: Mike Isely Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.c | 52 +++++++++++++++++++---- drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.h | 5 +++ drivers/media/video/pvrusb2/pvrusb2-hdw.c | 2 + 3 files changed, 51 insertions(+), 8 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.c b/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.c index 9494c6a5b5d8..9df3623a3e4c 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.c +++ b/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.c @@ -39,14 +39,6 @@ #include #include -struct pvr2_v4l_cx2584x { - struct pvr2_i2c_handler handler; - struct pvr2_decoder_ctrl ctrl; - struct pvr2_i2c_client *client; - struct pvr2_hdw *hdw; - unsigned long stale_mask; -}; - struct routing_scheme_item { int vid; @@ -110,6 +102,15 @@ static const struct routing_scheme routing_schemes[] = { }, }; +struct pvr2_v4l_cx2584x { + struct pvr2_i2c_handler handler; + struct pvr2_decoder_ctrl ctrl; + struct pvr2_i2c_client *client; + struct pvr2_hdw *hdw; + unsigned long stale_mask; +}; + + static void set_input(struct pvr2_v4l_cx2584x *ctxt) { struct pvr2_hdw *hdw = ctxt->hdw; @@ -321,6 +322,41 @@ int pvr2_i2c_cx2584x_v4l_setup(struct pvr2_hdw *hdw, } +void pvr2_cx25840_subdev_update(struct pvr2_hdw *hdw, struct v4l2_subdev *sd) +{ + if (hdw->input_dirty) { + struct v4l2_routing route; + enum cx25840_video_input vid_input; + enum cx25840_audio_input aud_input; + const struct routing_scheme *sp; + unsigned int sid = hdw->hdw_desc->signal_routing_scheme; + + memset(&route, 0, sizeof(route)); + + if ((sid < ARRAY_SIZE(routing_schemes)) && + ((sp = routing_schemes + sid) != NULL) && + (hdw->input_val >= 0) && + (hdw->input_val < sp->cnt)) { + vid_input = sp->def[hdw->input_val].vid; + aud_input = sp->def[hdw->input_val].aud; + } else { + pvr2_trace(PVR2_TRACE_ERROR_LEGS, + "*** WARNING *** subdev cx2584x set_input:" + " Invalid routing scheme (%u)" + " and/or input (%d)", + sid, hdw->input_val); + return; + } + + pvr2_trace(PVR2_TRACE_CHIPS, + "i2c cx2584x set_input vid=0x%x aud=0x%x", + vid_input, aud_input); + route.input = (u32)vid_input; + sd->ops->video->s_routing(sd, &route); + route.input = (u32)aud_input; + sd->ops->audio->s_routing(sd, &route); + } +} diff --git a/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.h b/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.h index f664f5942002..e48ce808bfe5 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.h +++ b/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.h @@ -39,6 +39,11 @@ int pvr2_i2c_cx2584x_v4l_setup(struct pvr2_hdw *,struct pvr2_i2c_client *); +#include "pvrusb2-hdw-internal.h" + +void pvr2_cx25840_subdev_update(struct pvr2_hdw *, struct v4l2_subdev *sd); + + #endif /* __PVRUSB2_CX2584X_V4L_H */ /* diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/drivers/media/video/pvrusb2/pvrusb2-hdw.c index ff7af062002b..1158021b1e12 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-hdw.c +++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.c @@ -38,6 +38,7 @@ #include "pvrusb2-fx2-cmd.h" #include "pvrusb2-wm8775.h" #include "pvrusb2-video-v4l.h" +#include "pvrusb2-cx2584x-v4l.h" #include "pvrusb2-audio.h" #define TV_MIN_FREQ 55250000L @@ -115,6 +116,7 @@ static const pvr2_subdev_update_func pvr2_module_update_functions[] = { [PVR2_CLIENT_ID_WM8775] = pvr2_wm8775_subdev_update, [PVR2_CLIENT_ID_SAA7115] = pvr2_saa7115_subdev_update, [PVR2_CLIENT_ID_MSP3400] = pvr2_msp3400_subdev_update, + [PVR2_CLIENT_ID_CX25840] = pvr2_cx25840_subdev_update, }; static const char *module_names[] = { -- cgit v1.2.3 From bd14d4f8f436d686e0e915d55533a5e70769cdf4 Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Sat, 7 Mar 2009 00:56:52 -0300 Subject: V4L/DVB (11183): pvrusb2: Implement more sub-device loading trace and improve error handling Signed-off-by: Mike Isely Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/pvrusb2/pvrusb2-hdw.c | 26 ++++++++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/drivers/media/video/pvrusb2/pvrusb2-hdw.c index 1158021b1e12..b0987a63f67a 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-hdw.c +++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.c @@ -2009,6 +2009,10 @@ static int pvr2_hdw_load_subdev(struct pvr2_hdw *hdw, hdw->hdw_desc->description); return -EINVAL; } + pvr2_trace(PVR2_TRACE_INIT, + "Module ID %u (%s) for device %s being loaded...", + mid, fname, + hdw->hdw_desc->description); i2ccnt = pvr2_copy_i2c_addr_list(i2caddr, cd->i2c_address_list, ARRAY_SIZE(i2caddr)); @@ -2017,6 +2021,12 @@ static int pvr2_hdw_load_subdev(struct pvr2_hdw *hdw, /* Second chance: Try default i2c address list */ i2ccnt = pvr2_copy_i2c_addr_list(i2caddr, p, ARRAY_SIZE(i2caddr)); + if (i2ccnt) { + pvr2_trace(PVR2_TRACE_INIT, + "Module ID %u:" + " Using default i2c address list", + mid); + } } if (!i2ccnt) { @@ -2035,10 +2045,18 @@ static int pvr2_hdw_load_subdev(struct pvr2_hdw *hdw, * "chipid" appears to just be the module name again. So here we * just do the same thing. */ if (i2ccnt == 1) { + pvr2_trace(PVR2_TRACE_INIT, + "Module ID %u:" + " Setting up with specified i2c address 0x%x", + mid, i2caddr[0]); sd = v4l2_i2c_new_subdev(&hdw->i2c_adap, fname, fname, i2caddr[0]); } else { + pvr2_trace(PVR2_TRACE_INIT, + "Module ID %u:" + " Setting up with address probe list", + mid); sd = v4l2_i2c_new_probed_subdev(&hdw->i2c_adap, fname, fname, i2caddr); @@ -2061,7 +2079,7 @@ static int pvr2_hdw_load_subdev(struct pvr2_hdw *hdw, aid, in normal situations there's no reason for both mechanisms to be enabled. */ pvr2_i2c_untrack_subdev(hdw, sd); - pvr2_trace(PVR2_TRACE_INIT, "Attached sub-driver %s", fname); + pvr2_trace(PVR2_TRACE_INFO, "Attached sub-driver %s", fname); /* client-specific setup... */ @@ -2081,6 +2099,10 @@ static int pvr2_hdw_load_subdev(struct pvr2_hdw *hdw, up. */ struct v4l2_format fmt; + pvr2_trace(PVR2_TRACE_INIT, + "Module ID %u:" + " Executing cx25840 VBI hack", + mid); memset(&fmt, 0, sizeof(fmt)); fmt.type = V4L2_BUF_TYPE_SLICED_VBI_CAPTURE; v4l2_device_call_all(&hdw->v4l2_dev, mid, @@ -2111,7 +2133,7 @@ static void pvr2_hdw_load_modules(struct pvr2_hdw *hdw) ct = &hdw->hdw_desc->client_table; for (idx = 0; idx < ct->cnt; idx++) { - if (!pvr2_hdw_load_subdev(hdw, &ct->lst[idx])) okFl = 0; + if (pvr2_hdw_load_subdev(hdw, &ct->lst[idx]) < 0) okFl = 0; } if (!okFl) pvr2_hdw_render_useless(hdw); } -- cgit v1.2.3 From ae111f76f785eaa350f0172fac68cf5de2e9eae7 Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Sat, 7 Mar 2009 00:57:42 -0300 Subject: V4L/DVB (11184): pvrusb2: Define default i2c address for wm8775 sub-device Signed-off-by: Mike Isely Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/pvrusb2/pvrusb2-hdw.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/media/video') diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/drivers/media/video/pvrusb2/pvrusb2-hdw.c index b0987a63f67a..24b7413f5c99 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-hdw.c +++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.c @@ -131,6 +131,7 @@ static const char *module_names[] = { static const unsigned char *module_i2c_addresses[] = { [PVR2_CLIENT_ID_TUNER] = "\x60\x61\x62\x63", + [PVR2_CLIENT_ID_WM8775] = "\x1b", }; -- cgit v1.2.3 From 3ab8d295156a43fc2751483d2f82a63c97489f89 Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Sat, 7 Mar 2009 01:37:58 -0300 Subject: V4L/DVB (11185): pvrusb2: Fix uninitialized counter Signed-off-by: Mike Isely Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/pvrusb2/pvrusb2-hdw.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/drivers/media/video/pvrusb2/pvrusb2-hdw.c index 24b7413f5c99..937c85c5c037 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-hdw.c +++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.c @@ -1979,7 +1979,7 @@ static unsigned int pvr2_copy_i2c_addr_list( unsigned short *dst, const unsigned char *src, unsigned int dst_max) { - unsigned int cnt; + unsigned int cnt = 0; if (!src) return 0; while (src[cnt] && (cnt + 1) < dst_max) { dst[cnt] = src[cnt]; -- cgit v1.2.3 From 5f757ddd5f193f54a5a7498d32568b630583503e Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Sat, 7 Mar 2009 01:39:40 -0300 Subject: V4L/DVB (11186): pvrusb2: Fix bugs involved in listing of sub-devices Signed-off-by: Mike Isely Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/pvrusb2/pvrusb2-hdw.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/drivers/media/video/pvrusb2/pvrusb2-hdw.c index 937c85c5c037..b10b90d97578 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-hdw.c +++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.c @@ -4855,7 +4855,7 @@ static unsigned int pvr2_hdw_report_unlocked(struct pvr2_hdw *hdw,int which, unsigned int id; ccnt = scnprintf(buf, acnt, - "Associted v4l2_subdev drivers:"); + "Associated v4l2_subdev drivers:"); tcnt += ccnt; v4l2_device_for_each_subdev(sd, &hdw->v4l2_dev) { id = sd->grp_id; @@ -4863,10 +4863,16 @@ static unsigned int pvr2_hdw_report_unlocked(struct pvr2_hdw *hdw,int which, if (id < ARRAY_SIZE(module_names)) { p = module_names[id]; } - if (!p) p = "(unknown)"; - ccnt = scnprintf(buf + tcnt, - acnt - tcnt, - " %s (%u)", p, id); + if (p) { + ccnt = scnprintf(buf + tcnt, + acnt - tcnt, + " %s", p); + } else { + ccnt = scnprintf(buf + tcnt, + acnt - tcnt, + " (unknown id=%u)", id); + } + tcnt += ccnt; } return tcnt; } -- cgit v1.2.3 From 0db8556805bdaed865329e55b9a1ad05f9cbd856 Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Sat, 7 Mar 2009 01:42:40 -0300 Subject: V4L/DVB (11187): pvrusb2: Allow sub-devices to insert correctly A sub-device won't successfully attach to our I2C adapter if its class isn't set to zero. Right the class is still set to I2C_CLASS_TV_ANALOG in order to allow the old mechanism to still work. This change temporarily sets the class to zero during the interval when the sub-device attaches. This code will get removed when the old i2c layer is finally removed from the driver. Signed-off-by: Mike Isely Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/pvrusb2/pvrusb2-hdw.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/media/video') diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/drivers/media/video/pvrusb2/pvrusb2-hdw.c index b10b90d97578..e61e34821fd6 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-hdw.c +++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.c @@ -2045,6 +2045,7 @@ static int pvr2_hdw_load_subdev(struct pvr2_hdw *hdw, * and every other place where I can find examples of this, the * "chipid" appears to just be the module name again. So here we * just do the same thing. */ + hdw->i2c_adap.class = 0; if (i2ccnt == 1) { pvr2_trace(PVR2_TRACE_INIT, "Module ID %u:" @@ -2062,6 +2063,7 @@ static int pvr2_hdw_load_subdev(struct pvr2_hdw *hdw, fname, fname, i2caddr); } + hdw->i2c_adap.class = I2C_CLASS_TV_ANALOG; if (!sd) { pvr2_trace(PVR2_TRACE_ERROR_LEGS, -- cgit v1.2.3 From e68a619a1b216ed5398cbdf215a20d3411c988ea Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Sat, 7 Mar 2009 01:45:10 -0300 Subject: V4L/DVB (11188): pvrusb2: Sub-device update must happen BEFORE state dirty bits are cleared The sub-device update mechanism relies on various "dirty" bits in the driver in order to know what pieces of state need to be propagated out to the various sub-devices. But that won't work if the dirty bits are cleared before the update gets a chance to run. This change ensures that the update takes place before the dirty bits are cleared. Signed-off-by: Mike Isely Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/pvrusb2/pvrusb2-hdw.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/drivers/media/video/pvrusb2/pvrusb2-hdw.c index e61e34821fd6..627bc18f9bc1 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-hdw.c +++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.c @@ -3238,15 +3238,15 @@ static int pvr2_hdw_commit_execute(struct pvr2_hdw *hdw) } } + /* Check and update state for all sub-devices. */ + pvr2_subdev_update(hdw); + for (idx = 0; idx < hdw->control_cnt; idx++) { cptr = hdw->controls + idx; if (!cptr->info->clear_dirty) continue; cptr->info->clear_dirty(cptr); } - /* Check and update state for all sub-devices. */ - pvr2_subdev_update(hdw); - /* Now execute i2c core update */ pvr2_i2c_core_sync(hdw); -- cgit v1.2.3 From b481880bff1f98085a9f57362393463e6e3a3157 Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Sat, 7 Mar 2009 01:46:17 -0300 Subject: V4L/DVB (11189): pvrusb2: Deal with space-after-comma coding style idiocy Signed-off-by: Mike Isely Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/pvrusb2/pvrusb2-hdw.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/drivers/media/video/pvrusb2/pvrusb2-hdw.c index 627bc18f9bc1..029cdf411df0 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-hdw.c +++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.c @@ -2945,7 +2945,7 @@ static void pvr2_subdev_update(struct pvr2_hdw *hdw) pvr2_subdev_update_func fp; if (hdw->input_dirty || hdw->std_dirty) { - pvr2_trace(PVR2_TRACE_CHIPS,"subdev v4l2 set_standard"); + pvr2_trace(PVR2_TRACE_CHIPS, "subdev v4l2 set_standard"); if (hdw->input_val == PVR2_CVAL_INPUT_RADIO) { v4l2_device_call_all(&hdw->v4l2_dev, 0, tuner, s_radio); -- cgit v1.2.3 From 75212a02734155de3d25c91344a9083d7bf2aef1 Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Sat, 7 Mar 2009 01:48:42 -0300 Subject: V4L/DVB (11190): pvrusb2: Broadcast tuner type change to sub-devices The tuner sub-device isn't going to work very well unless we tell it the correct tuner type to use... Signed-off-by: Mike Isely Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/pvrusb2/pvrusb2-hdw.c | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/drivers/media/video/pvrusb2/pvrusb2-hdw.c index 029cdf411df0..8be5392e979b 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-hdw.c +++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.c @@ -24,6 +24,7 @@ #include #include #include +#include #include "pvrusb2.h" #include "pvrusb2-std.h" #include "pvrusb2-util.h" @@ -2261,7 +2262,6 @@ static void pvr2_hdw_setup_low(struct pvr2_hdw *hdw) } pvr2_i2c_core_check_stale(hdw); - hdw->tuner_updated = 0; if (!pvr2_hdw_dev_ok(hdw)) return; @@ -2944,6 +2944,21 @@ static void pvr2_subdev_update(struct pvr2_hdw *hdw) unsigned int id; pvr2_subdev_update_func fp; + pvr2_trace(PVR2_TRACE_CHIPS, "subdev update..."); + + if (hdw->tuner_updated) { + struct tuner_setup setup; + pvr2_trace(PVR2_TRACE_CHIPS, "subdev tuner set_type(%d)", + hdw->tuner_type); + if (((int)(hdw->tuner_type)) >= 0) { + setup.addr = ADDR_UNSET; + setup.type = hdw->tuner_type; + setup.mode_mask = T_RADIO | T_ANALOG_TV; + v4l2_device_call_all(&hdw->v4l2_dev, 0, + tuner, s_type_addr, &setup); + } + } + if (hdw->input_dirty || hdw->std_dirty) { pvr2_trace(PVR2_TRACE_CHIPS, "subdev v4l2 set_standard"); if (hdw->input_val == PVR2_CVAL_INPUT_RADIO) { @@ -3241,6 +3256,7 @@ static int pvr2_hdw_commit_execute(struct pvr2_hdw *hdw) /* Check and update state for all sub-devices. */ pvr2_subdev_update(hdw); + hdw->tuner_updated = 0; for (idx = 0; idx < hdw->control_cnt; idx++) { cptr = hdw->controls + idx; if (!cptr->info->clear_dirty) continue; -- cgit v1.2.3 From 0b467014990d53dc37fbf7432b729d2d45846248 Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Sat, 7 Mar 2009 01:49:37 -0300 Subject: V4L/DVB (11191): pvrusb2: Define default I2C address for cx25840 sub-device Signed-off-by: Mike Isely Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/pvrusb2/pvrusb2-hdw.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/media/video') diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/drivers/media/video/pvrusb2/pvrusb2-hdw.c index 8be5392e979b..4b1f1b5f4328 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-hdw.c +++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.c @@ -133,6 +133,7 @@ static const char *module_names[] = { static const unsigned char *module_i2c_addresses[] = { [PVR2_CLIENT_ID_TUNER] = "\x60\x61\x62\x63", [PVR2_CLIENT_ID_WM8775] = "\x1b", + [PVR2_CLIENT_ID_CX25840] = "\x44", }; -- cgit v1.2.3 From e260508d646d671a8d7edb82dadb68bc32c8e5da Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Sat, 7 Mar 2009 01:50:48 -0300 Subject: V4L/DVB (11192): pvrusb2: Implement trace print for stream on / off action Signed-off-by: Mike Isely Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/pvrusb2/pvrusb2-hdw.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/media/video') diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/drivers/media/video/pvrusb2/pvrusb2-hdw.c index 4b1f1b5f4328..89d5bb4f88bd 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-hdw.c +++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.c @@ -1681,6 +1681,8 @@ static int pvr2_decoder_enable(struct pvr2_hdw *hdw,int enablefl) this point, we'll broadcast stream on/off to all sub-devices anyway, just in case somebody else wants to hear the command... */ + pvr2_trace(PVR2_TRACE_CHIPS, "subdev v4l2 stream=%s", + (enablefl ? "on" : "off")); v4l2_device_call_all(&hdw->v4l2_dev, 0, video, s_stream, enablefl); if (hdw->decoder_client_id) { /* We get here if the encoder has been noticed. Otherwise -- cgit v1.2.3 From 5e430ca5d25e99f99c055bc43f8f140722a643b8 Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Sat, 7 Mar 2009 01:51:54 -0300 Subject: V4L/DVB (11193): pvrusb2: Correct some trace print inaccuracies Signed-off-by: Mike Isely Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.c b/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.c index 9df3623a3e4c..725f391cda5f 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.c +++ b/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.c @@ -324,6 +324,7 @@ int pvr2_i2c_cx2584x_v4l_setup(struct pvr2_hdw *hdw, void pvr2_cx25840_subdev_update(struct pvr2_hdw *hdw, struct v4l2_subdev *sd) { + pvr2_trace(PVR2_TRACE_CHIPS, "subdev cx2584x update..."); if (hdw->input_dirty) { struct v4l2_routing route; enum cx25840_video_input vid_input; @@ -349,7 +350,7 @@ void pvr2_cx25840_subdev_update(struct pvr2_hdw *hdw, struct v4l2_subdev *sd) } pvr2_trace(PVR2_TRACE_CHIPS, - "i2c cx2584x set_input vid=0x%x aud=0x%x", + "subdev cx2584x set_input vid=0x%x aud=0x%x", vid_input, aud_input); route.input = (u32)vid_input; sd->ops->video->s_routing(sd, &route); -- cgit v1.2.3 From 27764726a8fa72a7e8a7cdccbe9e4425747a96fa Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Sat, 7 Mar 2009 01:57:25 -0300 Subject: V4L/DVB (11194): pvrusb2: Implement mechanism to force a full sub-device update When a pvrusb2 driver instance first initializes, we need to be sure to send out a complete state update for everything to all attached modules. The old i2c layer did this by keeping a separate mask of "stale" bits for each attached module - and setting that mask to all stale when that module attaches. But the new sub-device adaptation I've implemented here no longer has per-module stale bits. So instead there's now a global "force dirty" bit that is set upon instance initialization, before the sub-devices are attached. After the first update, this bit is cleared, allowing for normal update-on-dirty behavior. In this manner, we ensure that all sub-devices have been properly synchronized at initialization. Signed-off-by: Mike Isely Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/pvrusb2/pvrusb2-audio.c | 2 +- drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.c | 2 +- drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h | 1 + drivers/media/video/pvrusb2/pvrusb2-hdw.c | 21 ++++++++++++--------- drivers/media/video/pvrusb2/pvrusb2-video-v4l.c | 2 +- drivers/media/video/pvrusb2/pvrusb2-wm8775.c | 2 +- 6 files changed, 17 insertions(+), 13 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/pvrusb2/pvrusb2-audio.c b/drivers/media/video/pvrusb2/pvrusb2-audio.c index 52966414327d..aca6b1d1561a 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-audio.c +++ b/drivers/media/video/pvrusb2/pvrusb2-audio.c @@ -184,7 +184,7 @@ int pvr2_i2c_msp3400_setup(struct pvr2_hdw *hdw,struct pvr2_i2c_client *cp) void pvr2_msp3400_subdev_update(struct pvr2_hdw *hdw, struct v4l2_subdev *sd) { - if (hdw->input_dirty) { + if (hdw->input_dirty || hdw->force_dirty) { struct v4l2_routing route; const struct routing_scheme *sp; unsigned int sid = hdw->hdw_desc->signal_routing_scheme; diff --git a/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.c b/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.c index 725f391cda5f..5adbf00323e5 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.c +++ b/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.c @@ -325,7 +325,7 @@ int pvr2_i2c_cx2584x_v4l_setup(struct pvr2_hdw *hdw, void pvr2_cx25840_subdev_update(struct pvr2_hdw *hdw, struct v4l2_subdev *sd) { pvr2_trace(PVR2_TRACE_CHIPS, "subdev cx2584x update..."); - if (hdw->input_dirty) { + if (hdw->input_dirty || hdw->force_dirty) { struct v4l2_routing route; enum cx25840_video_input vid_input; enum cx25840_audio_input aud_input; diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h b/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h index 299bf58ad77a..2afbd9bcedd3 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h +++ b/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h @@ -288,6 +288,7 @@ struct pvr2_hdw { wait_queue_head_t state_wait_data; + int force_dirty; /* consider all controls dirty if true */ int flag_ok; /* device in known good state */ int flag_disconnected; /* flag_ok == 0 due to disconnect */ int flag_init_ok; /* true if structure is fully initialized */ diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/drivers/media/video/pvrusb2/pvrusb2-hdw.c index 89d5bb4f88bd..1fb9ca560acf 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-hdw.c +++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.c @@ -2185,6 +2185,8 @@ static void pvr2_hdw_setup_low(struct pvr2_hdw *hdw) if (!pvr2_hdw_dev_ok(hdw)) return; + hdw->force_dirty = !0; + if (!hdw->hdw_desc->flag_no_powerup) { pvr2_hdw_cmd_powerup(hdw); if (!pvr2_hdw_dev_ok(hdw)) return; @@ -2935,7 +2937,7 @@ static void pvr2_subdev_set_control(struct pvr2_hdw *hdw, int id, } #define PVR2_SUBDEV_SET_CONTROL(hdw, id, lab) \ - if ((hdw)->lab##_dirty) { \ + if ((hdw)->lab##_dirty || (hdw)->force_dirty) { \ pvr2_subdev_set_control(hdw, id, #lab, (hdw)->lab##_val); \ } @@ -2949,7 +2951,7 @@ static void pvr2_subdev_update(struct pvr2_hdw *hdw) pvr2_trace(PVR2_TRACE_CHIPS, "subdev update..."); - if (hdw->tuner_updated) { + if (hdw->tuner_updated || hdw->force_dirty) { struct tuner_setup setup; pvr2_trace(PVR2_TRACE_CHIPS, "subdev tuner set_type(%d)", hdw->tuner_type); @@ -2962,7 +2964,7 @@ static void pvr2_subdev_update(struct pvr2_hdw *hdw) } } - if (hdw->input_dirty || hdw->std_dirty) { + if (hdw->input_dirty || hdw->std_dirty || hdw->force_dirty) { pvr2_trace(PVR2_TRACE_CHIPS, "subdev v4l2 set_standard"); if (hdw->input_val == PVR2_CVAL_INPUT_RADIO) { v4l2_device_call_all(&hdw->v4l2_dev, 0, @@ -2987,14 +2989,14 @@ static void pvr2_subdev_update(struct pvr2_hdw *hdw) PVR2_SUBDEV_SET_CONTROL(hdw, V4L2_CID_AUDIO_BASS, bass); PVR2_SUBDEV_SET_CONTROL(hdw, V4L2_CID_AUDIO_TREBLE, treble); - if (hdw->input_dirty || hdw->audiomode_dirty) { + if (hdw->input_dirty || hdw->audiomode_dirty || hdw->force_dirty) { struct v4l2_tuner vt; memset(&vt, 0, sizeof(vt)); vt.audmode = hdw->audiomode_val; v4l2_device_call_all(&hdw->v4l2_dev, 0, tuner, s_tuner, &vt); } - if (hdw->freqDirty) { + if (hdw->freqDirty || hdw->force_dirty) { unsigned long fv; struct v4l2_frequency freq; fv = pvr2_hdw_get_cur_freq(hdw); @@ -3019,7 +3021,7 @@ static void pvr2_subdev_update(struct pvr2_hdw *hdw) s_frequency, &freq); } - if (hdw->res_hor_dirty || hdw->res_ver_dirty) { + if (hdw->res_hor_dirty || hdw->res_ver_dirty || hdw->force_dirty) { struct v4l2_format fmt; memset(&fmt, 0, sizeof(fmt)); fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; @@ -3030,7 +3032,7 @@ static void pvr2_subdev_update(struct pvr2_hdw *hdw) v4l2_device_call_all(&hdw->v4l2_dev, 0, video, s_fmt, &fmt); } - if (hdw->srate_dirty) { + if (hdw->srate_dirty || hdw->force_dirty) { u32 val; pvr2_trace(PVR2_TRACE_CHIPS, "subdev v4l2 set_audio %d", hdw->srate_val); @@ -3061,7 +3063,7 @@ static void pvr2_subdev_update(struct pvr2_hdw *hdw) (*fp)(hdw, sd); } - if (hdw->tuner_signal_stale && hdw->cropcap_stale) { + if (hdw->tuner_signal_stale || hdw->cropcap_stale) { pvr2_hdw_status_poll(hdw); } } @@ -3075,7 +3077,7 @@ static int pvr2_hdw_commit_setup(struct pvr2_hdw *hdw) unsigned int idx; struct pvr2_ctrl *cptr; int value; - int commit_flag = 0; + int commit_flag = hdw->force_dirty; char buf[100]; unsigned int bcnt,ccnt; @@ -3260,6 +3262,7 @@ static int pvr2_hdw_commit_execute(struct pvr2_hdw *hdw) pvr2_subdev_update(hdw); hdw->tuner_updated = 0; + hdw->force_dirty = 0; for (idx = 0; idx < hdw->control_cnt; idx++) { cptr = hdw->controls + idx; if (!cptr->info->clear_dirty) continue; diff --git a/drivers/media/video/pvrusb2/pvrusb2-video-v4l.c b/drivers/media/video/pvrusb2/pvrusb2-video-v4l.c index c7a1621cf140..4e0c0881b7b1 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-video-v4l.c +++ b/drivers/media/video/pvrusb2/pvrusb2-video-v4l.c @@ -249,7 +249,7 @@ int pvr2_i2c_decoder_v4l_setup(struct pvr2_hdw *hdw, void pvr2_saa7115_subdev_update(struct pvr2_hdw *hdw, struct v4l2_subdev *sd) { - if (hdw->input_dirty) { + if (hdw->input_dirty || hdw->force_dirty) { struct v4l2_routing route; const struct routing_scheme *sp; unsigned int sid = hdw->hdw_desc->signal_routing_scheme; diff --git a/drivers/media/video/pvrusb2/pvrusb2-wm8775.c b/drivers/media/video/pvrusb2/pvrusb2-wm8775.c index a099bf1641e5..0068566876ec 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-wm8775.c +++ b/drivers/media/video/pvrusb2/pvrusb2-wm8775.c @@ -162,7 +162,7 @@ int pvr2_i2c_wm8775_setup(struct pvr2_hdw *hdw,struct pvr2_i2c_client *cp) void pvr2_wm8775_subdev_update(struct pvr2_hdw *hdw, struct v4l2_subdev *sd) { - if (hdw->input_dirty) { + if (hdw->input_dirty || hdw->force_dirty) { struct v4l2_routing route; memset(&route, 0, sizeof(route)); -- cgit v1.2.3 From 5c6cb4e2512fa50693a28a2edefdaa5cf6c10950 Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Sat, 7 Mar 2009 01:59:34 -0300 Subject: V4L/DVB (11195): pvrusb2: Issue required core init broadcast to all sub-devices The v4l2-subdev infrastructure requires that an initialization call must be issued to all attached sub-devices before normal operation can start. This change satisfies that requirement. Signed-off-by: Mike Isely Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/pvrusb2/pvrusb2-hdw.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/media/video') diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/drivers/media/video/pvrusb2/pvrusb2-hdw.c index 1fb9ca560acf..bd46b40eefdc 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-hdw.c +++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.c @@ -2208,6 +2208,8 @@ static void pvr2_hdw_setup_low(struct pvr2_hdw *hdw) pvr2_hdw_load_modules(hdw); if (!pvr2_hdw_dev_ok(hdw)) return; + v4l2_device_call_all(&hdw->v4l2_dev, 0, core, init, 0); + for (idx = 0; idx < CTRLDEF_COUNT; idx++) { cptr = hdw->controls + idx; if (cptr->info->skip_init) continue; -- cgit v1.2.3 From 1dfe6c77940c27cf6655acc332906b03c0c2b683 Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Sat, 7 Mar 2009 02:00:21 -0300 Subject: V4L/DVB (11196): pvrusb2: Define default I2C addresses for msp3400 and saa7115 sub-devices Signed-off-by: Mike Isely Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/pvrusb2/pvrusb2-hdw.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/media/video') diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/drivers/media/video/pvrusb2/pvrusb2-hdw.c index bd46b40eefdc..f4cf485abc6b 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-hdw.c +++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.c @@ -132,6 +132,8 @@ static const char *module_names[] = { static const unsigned char *module_i2c_addresses[] = { [PVR2_CLIENT_ID_TUNER] = "\x60\x61\x62\x63", + [PVR2_CLIENT_ID_MSP3400] = "\x40", + [PVR2_CLIENT_ID_SAA7115] = "\x21", [PVR2_CLIENT_ID_WM8775] = "\x1b", [PVR2_CLIENT_ID_CX25840] = "\x44", }; -- cgit v1.2.3 From 851981a1ee0b7cf3726eb6aed267035b4f094336 Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Sat, 7 Mar 2009 02:02:32 -0300 Subject: V4L/DVB (11197): pvrusb2: Fix incorrectly named sub-device ID Signed-off-by: Mike Isely Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/pvrusb2/pvrusb2-devattr.h | 2 +- drivers/media/video/pvrusb2/pvrusb2-hdw.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/pvrusb2/pvrusb2-devattr.h b/drivers/media/video/pvrusb2/pvrusb2-devattr.h index 1339a32a2a1b..30aa7a440990 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-devattr.h +++ b/drivers/media/video/pvrusb2/pvrusb2-devattr.h @@ -38,7 +38,7 @@ #define PVR2_CLIENT_ID_CX25840 2 #define PVR2_CLIENT_ID_SAA7115 3 #define PVR2_CLIENT_ID_TUNER 4 -#define PVR2_CLIENT_ID_CS53132A 5 +#define PVR2_CLIENT_ID_CS53L32A 5 #define PVR2_CLIENT_ID_WM8775 6 struct pvr2_device_client_desc { diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/drivers/media/video/pvrusb2/pvrusb2-hdw.c index f4cf485abc6b..dc79487fc099 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-hdw.c +++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.c @@ -125,7 +125,7 @@ static const char *module_names[] = { [PVR2_CLIENT_ID_CX25840] = "cx25840", [PVR2_CLIENT_ID_SAA7115] = "saa7115", [PVR2_CLIENT_ID_TUNER] = "tuner", - [PVR2_CLIENT_ID_CS53132A] = "cs53132a", + [PVR2_CLIENT_ID_CS53L32A] = "cs53l32a", [PVR2_CLIENT_ID_WM8775] = "wm8775", }; -- cgit v1.2.3 From 23334a22ea2c068b14f57e8b6781b1e96d2df02e Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Sat, 7 Mar 2009 02:03:28 -0300 Subject: V4L/DVB (11198): pvrusb2: Define default I2C address for CS53L32A sub-device Signed-off-by: Mike Isely Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/pvrusb2/pvrusb2-hdw.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/media/video') diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/drivers/media/video/pvrusb2/pvrusb2-hdw.c index dc79487fc099..099b0d439560 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-hdw.c +++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.c @@ -136,6 +136,7 @@ static const unsigned char *module_i2c_addresses[] = { [PVR2_CLIENT_ID_SAA7115] = "\x21", [PVR2_CLIENT_ID_WM8775] = "\x1b", [PVR2_CLIENT_ID_CX25840] = "\x44", + [PVR2_CLIENT_ID_CS53L32A] = "\x11", }; -- cgit v1.2.3 From dd5f322f35e2a9a4d8ca5dd7c192a4137a7f5031 Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Sat, 7 Mar 2009 02:07:12 -0300 Subject: V4L/DVB (11199): pvrusb2: Convert all device definitions to use new sub-device declarations Signed-off-by: Mike Isely Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/pvrusb2/pvrusb2-devattr.c | 86 +++++++++++++-------------- 1 file changed, 41 insertions(+), 45 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/pvrusb2/pvrusb2-devattr.c b/drivers/media/video/pvrusb2/pvrusb2-devattr.c index cbe2a3417851..de4daa7f48b0 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-devattr.c +++ b/drivers/media/video/pvrusb2/pvrusb2-devattr.c @@ -46,10 +46,10 @@ pvr2_device_desc structures. /*------------------------------------------------------------------------*/ /* Hauppauge PVR-USB2 Model 29xxx */ -static const char *pvr2_client_29xxx[] = { - "msp3400", - "saa7115", - "tuner", +static const struct pvr2_device_client_desc pvr2_cli_29xxx[] = { + { .module_id = PVR2_CLIENT_ID_SAA7115 }, + { .module_id = PVR2_CLIENT_ID_MSP3400 }, + { .module_id = PVR2_CLIENT_ID_TUNER }, }; static const char *pvr2_fw1_names_29xxx[] = { @@ -59,8 +59,8 @@ static const char *pvr2_fw1_names_29xxx[] = { static const struct pvr2_device_desc pvr2_device_29xxx = { .description = "WinTV PVR USB2 Model Category 29xxx", .shortname = "29xxx", - .client_modules.lst = pvr2_client_29xxx, - .client_modules.cnt = ARRAY_SIZE(pvr2_client_29xxx), + .client_table.lst = pvr2_cli_29xxx, + .client_table.cnt = ARRAY_SIZE(pvr2_cli_29xxx), .fx2_firmware.lst = pvr2_fw1_names_29xxx, .fx2_firmware.cnt = ARRAY_SIZE(pvr2_fw1_names_29xxx), .flag_has_hauppauge_rom = !0, @@ -77,10 +77,10 @@ static const struct pvr2_device_desc pvr2_device_29xxx = { /*------------------------------------------------------------------------*/ /* Hauppauge PVR-USB2 Model 24xxx */ -static const char *pvr2_client_24xxx[] = { - "cx25840", - "tuner", - "wm8775", +static const struct pvr2_device_client_desc pvr2_cli_24xxx[] = { + { .module_id = PVR2_CLIENT_ID_CX25840 }, + { .module_id = PVR2_CLIENT_ID_TUNER }, + { .module_id = PVR2_CLIENT_ID_WM8775 }, }; static const char *pvr2_fw1_names_24xxx[] = { @@ -90,8 +90,8 @@ static const char *pvr2_fw1_names_24xxx[] = { static const struct pvr2_device_desc pvr2_device_24xxx = { .description = "WinTV PVR USB2 Model Category 24xxx", .shortname = "24xxx", - .client_modules.lst = pvr2_client_24xxx, - .client_modules.cnt = ARRAY_SIZE(pvr2_client_24xxx), + .client_table.lst = pvr2_cli_24xxx, + .client_table.cnt = ARRAY_SIZE(pvr2_cli_24xxx), .fx2_firmware.lst = pvr2_fw1_names_24xxx, .fx2_firmware.cnt = ARRAY_SIZE(pvr2_fw1_names_24xxx), .flag_has_cx25840 = !0, @@ -111,16 +111,16 @@ static const struct pvr2_device_desc pvr2_device_24xxx = { /*------------------------------------------------------------------------*/ /* GOTVIEW USB2.0 DVD2 */ -static const char *pvr2_client_gotview_2[] = { - "cx25840", - "tuner", +static const struct pvr2_device_client_desc pvr2_cli_gotview_2[] = { + { .module_id = PVR2_CLIENT_ID_CX25840 }, + { .module_id = PVR2_CLIENT_ID_TUNER }, }; static const struct pvr2_device_desc pvr2_device_gotview_2 = { .description = "Gotview USB 2.0 DVD 2", .shortname = "gv2", - .client_modules.lst = pvr2_client_gotview_2, - .client_modules.cnt = ARRAY_SIZE(pvr2_client_gotview_2), + .client_table.lst = pvr2_cli_gotview_2, + .client_table.cnt = ARRAY_SIZE(pvr2_cli_gotview_2), .flag_has_cx25840 = !0, .default_tuner_type = TUNER_PHILIPS_FM1216ME_MK3, .flag_has_analogtuner = !0, @@ -140,8 +140,8 @@ static const struct pvr2_device_desc pvr2_device_gotview_2 = { static const struct pvr2_device_desc pvr2_device_gotview_2d = { .description = "Gotview USB 2.0 DVD Deluxe", .shortname = "gv2d", - .client_modules.lst = pvr2_client_gotview_2, - .client_modules.cnt = ARRAY_SIZE(pvr2_client_gotview_2), + .client_table.lst = pvr2_cli_gotview_2, + .client_table.cnt = ARRAY_SIZE(pvr2_cli_gotview_2), .flag_has_cx25840 = !0, .default_tuner_type = TUNER_PHILIPS_FM1216ME_MK3, .flag_has_analogtuner = !0, @@ -187,17 +187,17 @@ static struct pvr2_dvb_props pvr2_onair_creator_fe_props = { }; #endif -static const char *pvr2_client_onair_creator[] = { - "saa7115", - "tuner", - "cs53l32a", +static const struct pvr2_device_client_desc pvr2_cli_onair_creator[] = { + { .module_id = PVR2_CLIENT_ID_SAA7115 }, + { .module_id = PVR2_CLIENT_ID_CS53L32A }, + { .module_id = PVR2_CLIENT_ID_TUNER }, }; static const struct pvr2_device_desc pvr2_device_onair_creator = { .description = "OnAir Creator Hybrid USB tuner", .shortname = "oac", - .client_modules.lst = pvr2_client_onair_creator, - .client_modules.cnt = ARRAY_SIZE(pvr2_client_onair_creator), + .client_table.lst = pvr2_cli_onair_creator, + .client_table.cnt = ARRAY_SIZE(pvr2_cli_onair_creator), .default_tuner_type = TUNER_LG_TDVS_H06XF, .flag_has_analogtuner = !0, .flag_has_composite = !0, @@ -247,17 +247,17 @@ static struct pvr2_dvb_props pvr2_onair_usb2_fe_props = { }; #endif -static const char *pvr2_client_onair_usb2[] = { - "saa7115", - "tuner", - "cs53l32a", +static const struct pvr2_device_client_desc pvr2_cli_onair_usb2[] = { + { .module_id = PVR2_CLIENT_ID_SAA7115 }, + { .module_id = PVR2_CLIENT_ID_CS53L32A }, + { .module_id = PVR2_CLIENT_ID_TUNER }, }; static const struct pvr2_device_desc pvr2_device_onair_usb2 = { .description = "OnAir USB2 Hybrid USB tuner", .shortname = "oa2", - .client_modules.lst = pvr2_client_onair_usb2, - .client_modules.cnt = ARRAY_SIZE(pvr2_client_onair_usb2), + .client_table.lst = pvr2_cli_onair_usb2, + .client_table.cnt = ARRAY_SIZE(pvr2_cli_onair_usb2), .default_tuner_type = TUNER_PHILIPS_FCV1236D, .flag_has_analogtuner = !0, .flag_has_composite = !0, @@ -320,9 +320,10 @@ static struct pvr2_dvb_props pvr2_73xxx_dvb_props = { }; #endif -static const char *pvr2_client_73xxx[] = { - "cx25840", - "tuner", +static const struct pvr2_device_client_desc pvr2_cli_73xxx[] = { + { .module_id = PVR2_CLIENT_ID_CX25840 }, + { .module_id = PVR2_CLIENT_ID_TUNER, + .i2c_address_list = "\x42"}, }; static const char *pvr2_fw1_names_73xxx[] = { @@ -332,8 +333,8 @@ static const char *pvr2_fw1_names_73xxx[] = { static const struct pvr2_device_desc pvr2_device_73xxx = { .description = "WinTV HVR-1900 Model Category 73xxx", .shortname = "73xxx", - .client_modules.lst = pvr2_client_73xxx, - .client_modules.cnt = ARRAY_SIZE(pvr2_client_73xxx), + .client_table.lst = pvr2_cli_73xxx, + .client_table.cnt = ARRAY_SIZE(pvr2_cli_73xxx), .fx2_firmware.lst = pvr2_fw1_names_73xxx, .fx2_firmware.cnt = ARRAY_SIZE(pvr2_fw1_names_73xxx), .flag_has_cx25840 = !0, @@ -429,11 +430,6 @@ static struct pvr2_dvb_props pvr2_751xx_dvb_props = { }; #endif -static const char *pvr2_client_75xxx[] = { - "cx25840", - "tuner", -}; - static const char *pvr2_fw1_names_75xxx[] = { "v4l-pvrusb2-73xxx-01.fw", }; @@ -441,8 +437,8 @@ static const char *pvr2_fw1_names_75xxx[] = { static const struct pvr2_device_desc pvr2_device_750xx = { .description = "WinTV HVR-1950 Model Category 750xx", .shortname = "750xx", - .client_modules.lst = pvr2_client_75xxx, - .client_modules.cnt = ARRAY_SIZE(pvr2_client_75xxx), + .client_table.lst = pvr2_cli_73xxx, + .client_table.cnt = ARRAY_SIZE(pvr2_cli_73xxx), .fx2_firmware.lst = pvr2_fw1_names_75xxx, .fx2_firmware.cnt = ARRAY_SIZE(pvr2_fw1_names_75xxx), .flag_has_cx25840 = !0, @@ -463,8 +459,8 @@ static const struct pvr2_device_desc pvr2_device_750xx = { static const struct pvr2_device_desc pvr2_device_751xx = { .description = "WinTV HVR-1950 Model Category 751xx", .shortname = "751xx", - .client_modules.lst = pvr2_client_75xxx, - .client_modules.cnt = ARRAY_SIZE(pvr2_client_75xxx), + .client_table.lst = pvr2_cli_73xxx, + .client_table.cnt = ARRAY_SIZE(pvr2_cli_73xxx), .fx2_firmware.lst = pvr2_fw1_names_75xxx, .fx2_firmware.cnt = ARRAY_SIZE(pvr2_fw1_names_75xxx), .flag_has_cx25840 = !0, -- cgit v1.2.3 From 69ea3c1cbc1d78d9f522e18e20c73e6ef9f8e39f Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Sat, 7 Mar 2009 02:08:58 -0300 Subject: V4L/DVB (11200): pvrusb2: Make a bunch of dvb config structures const (trivial) Signed-off-by: Mike Isely Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/pvrusb2/pvrusb2-devattr.c | 10 +++++----- drivers/media/video/pvrusb2/pvrusb2-devattr.h | 2 +- drivers/media/video/pvrusb2/pvrusb2-dvb.c | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/pvrusb2/pvrusb2-devattr.c b/drivers/media/video/pvrusb2/pvrusb2-devattr.c index de4daa7f48b0..e6c876f3a35a 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-devattr.c +++ b/drivers/media/video/pvrusb2/pvrusb2-devattr.c @@ -181,7 +181,7 @@ static int pvr2_lgh06xf_attach(struct pvr2_dvb_adapter *adap) return 0; } -static struct pvr2_dvb_props pvr2_onair_creator_fe_props = { +static const struct pvr2_dvb_props pvr2_onair_creator_fe_props = { .frontend_attach = pvr2_lgdt3303_attach, .tuner_attach = pvr2_lgh06xf_attach, }; @@ -241,7 +241,7 @@ static int pvr2_fcv1236d_attach(struct pvr2_dvb_adapter *adap) return 0; } -static struct pvr2_dvb_props pvr2_onair_usb2_fe_props = { +static const struct pvr2_dvb_props pvr2_onair_usb2_fe_props = { .frontend_attach = pvr2_lgdt3302_attach, .tuner_attach = pvr2_fcv1236d_attach, }; @@ -314,7 +314,7 @@ static int pvr2_73xxx_tda18271_8295_attach(struct pvr2_dvb_adapter *adap) return 0; } -static struct pvr2_dvb_props pvr2_73xxx_dvb_props = { +static const struct pvr2_dvb_props pvr2_73xxx_dvb_props = { .frontend_attach = pvr2_tda10048_attach, .tuner_attach = pvr2_73xxx_tda18271_8295_attach, }; @@ -419,12 +419,12 @@ static int pvr2_tda18271_8295_attach(struct pvr2_dvb_adapter *adap) return 0; } -static struct pvr2_dvb_props pvr2_750xx_dvb_props = { +static const struct pvr2_dvb_props pvr2_750xx_dvb_props = { .frontend_attach = pvr2_s5h1409_attach, .tuner_attach = pvr2_tda18271_8295_attach, }; -static struct pvr2_dvb_props pvr2_751xx_dvb_props = { +static const struct pvr2_dvb_props pvr2_751xx_dvb_props = { .frontend_attach = pvr2_s5h1411_attach, .tuner_attach = pvr2_tda18271_8295_attach, }; diff --git a/drivers/media/video/pvrusb2/pvrusb2-devattr.h b/drivers/media/video/pvrusb2/pvrusb2-devattr.h index 30aa7a440990..ed9cdedcc71b 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-devattr.h +++ b/drivers/media/video/pvrusb2/pvrusb2-devattr.h @@ -103,7 +103,7 @@ struct pvr2_device_desc { #ifdef CONFIG_VIDEO_PVRUSB2_DVB /* callback functions to handle attachment of digital tuner & demod */ - struct pvr2_dvb_props *dvb_props; + const struct pvr2_dvb_props *dvb_props; #endif /* Initial standard bits to use for this device, if not zero. diff --git a/drivers/media/video/pvrusb2/pvrusb2-dvb.c b/drivers/media/video/pvrusb2/pvrusb2-dvb.c index 77b3c3385066..b7f5c49b1dbc 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-dvb.c +++ b/drivers/media/video/pvrusb2/pvrusb2-dvb.c @@ -321,7 +321,7 @@ static int pvr2_dvb_adapter_exit(struct pvr2_dvb_adapter *adap) static int pvr2_dvb_frontend_init(struct pvr2_dvb_adapter *adap) { struct pvr2_hdw *hdw = adap->channel.hdw; - struct pvr2_dvb_props *dvb_props = hdw->hdw_desc->dvb_props; + const struct pvr2_dvb_props *dvb_props = hdw->hdw_desc->dvb_props; int ret = 0; if (dvb_props == NULL) { -- cgit v1.2.3 From 7dfdf1ee14c245180f26d23231e690a80b2c6225 Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Sat, 7 Mar 2009 02:11:12 -0300 Subject: V4L/DVB (11201): pvrusb2: Fix space-after-comma idiocy Signed-off-by: Mike Isely Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/pvrusb2/pvrusb2-hdw.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/drivers/media/video/pvrusb2/pvrusb2-hdw.c index 099b0d439560..0cfe0eec34ea 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-hdw.c +++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.c @@ -3032,7 +3032,7 @@ static void pvr2_subdev_update(struct pvr2_hdw *hdw) fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; fmt.fmt.pix.width = hdw->res_hor_val; fmt.fmt.pix.height = hdw->res_ver_val; - pvr2_trace(PVR2_TRACE_CHIPS,"subdev v4l2 set_size(%dx%d)", + pvr2_trace(PVR2_TRACE_CHIPS, "subdev v4l2 set_size(%dx%d)", fmt.fmt.pix.width, fmt.fmt.pix.height); v4l2_device_call_all(&hdw->v4l2_dev, 0, video, s_fmt, &fmt); } -- cgit v1.2.3 From fd28aeafd6aecf203d750871616902cbdb537e99 Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Sun, 8 Mar 2009 18:22:48 -0300 Subject: V4L/DVB (11202): pvrusb2: Fix slightly mis-leading header in debug interface output Signed-off-by: Mike Isely Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/pvrusb2/pvrusb2-debugifc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/pvrusb2/pvrusb2-debugifc.c b/drivers/media/video/pvrusb2/pvrusb2-debugifc.c index cc4ef891b5b6..2074ce05c76a 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-debugifc.c +++ b/drivers/media/video/pvrusb2/pvrusb2-debugifc.c @@ -147,7 +147,7 @@ int pvr2_debugifc_print_info(struct pvr2_hdw *hdw,char *buf,unsigned int acnt) bcnt += ccnt; acnt -= ccnt; buf += ccnt; ccnt = pvr2_hdw_state_report(hdw,buf,acnt); bcnt += ccnt; acnt -= ccnt; buf += ccnt; - ccnt = scnprintf(buf,acnt,"Attached I2C modules:\n"); + ccnt = scnprintf(buf, acnt, "Attached old-style I2C modules:\n"); bcnt += ccnt; acnt -= ccnt; buf += ccnt; ccnt = pvr2_i2c_report(hdw,buf,acnt); bcnt += ccnt; acnt -= ccnt; buf += ccnt; -- cgit v1.2.3 From 2eb563b7e726b517ef86213df436f50ec6c1740c Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Sun, 8 Mar 2009 18:25:46 -0300 Subject: V4L/DVB (11203): pvrusb2: Implement better reporting on attached sub-devices Signed-off-by: Mike Isely Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/pvrusb2/pvrusb2-hdw.c | 115 ++++++++++++++++++++++-------- 1 file changed, 86 insertions(+), 29 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/drivers/media/video/pvrusb2/pvrusb2-hdw.c index 0cfe0eec34ea..b0383153e3ce 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-hdw.c +++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.c @@ -4876,38 +4876,82 @@ static unsigned int pvr2_hdw_report_unlocked(struct pvr2_hdw *hdw,int which, stats.buffers_processed, stats.buffers_failed); } - case 6: { - struct v4l2_subdev *sd; - unsigned int tcnt = 0; - unsigned int ccnt; - const char *p; - unsigned int id; - ccnt = scnprintf(buf, - acnt, - "Associated v4l2_subdev drivers:"); + default: break; + } + return 0; +} + + +/* Generate report containing info about attached sub-devices and attached + i2c clients, including an indication of which attached i2c clients are + actually sub-devices. */ +static unsigned int pvr2_hdw_report_clients(struct pvr2_hdw *hdw, + char *buf, unsigned int acnt) +{ + struct v4l2_subdev *sd; + unsigned int tcnt = 0; + unsigned int ccnt; + struct i2c_client *client; + struct list_head *item; + void *cd; + const char *p; + unsigned int id; + + ccnt = scnprintf(buf, acnt, "Associated v4l2-subdev drivers:"); + tcnt += ccnt; + v4l2_device_for_each_subdev(sd, &hdw->v4l2_dev) { + id = sd->grp_id; + p = NULL; + if (id < ARRAY_SIZE(module_names)) p = module_names[id]; + if (p) { + ccnt = scnprintf(buf + tcnt, acnt - tcnt, " %s", p); + tcnt += ccnt; + } else { + ccnt = scnprintf(buf + tcnt, acnt - tcnt, + " (unknown id=%u)", id); + tcnt += ccnt; + } + } + ccnt = scnprintf(buf + tcnt, acnt - tcnt, "\n"); + tcnt += ccnt; + + ccnt = scnprintf(buf + tcnt, acnt - tcnt, "I2C clients:\n"); + tcnt += ccnt; + + mutex_lock(&hdw->i2c_adap.clist_lock); + list_for_each(item, &hdw->i2c_adap.clients) { + client = list_entry(item, struct i2c_client, list); + ccnt = scnprintf(buf + tcnt, acnt - tcnt, + " %s: i2c=%02x", client->name, client->addr); tcnt += ccnt; + cd = i2c_get_clientdata(client); v4l2_device_for_each_subdev(sd, &hdw->v4l2_dev) { - id = sd->grp_id; - p = NULL; - if (id < ARRAY_SIZE(module_names)) { - p = module_names[id]; - } - if (p) { - ccnt = scnprintf(buf + tcnt, - acnt - tcnt, - " %s", p); - } else { - ccnt = scnprintf(buf + tcnt, - acnt - tcnt, - " (unknown id=%u)", id); + if (cd == sd) { + id = sd->grp_id; + p = NULL; + if (id < ARRAY_SIZE(module_names)) { + p = module_names[id]; + } + if (p) { + ccnt = scnprintf(buf + tcnt, + acnt - tcnt, + " subdev=%s", p); + tcnt += ccnt; + } else { + ccnt = scnprintf(buf + tcnt, + acnt - tcnt, + " subdev= id %u)", + id); + tcnt += ccnt; + } + break; } - tcnt += ccnt; } - return tcnt; - } - default: break; + ccnt = scnprintf(buf + tcnt, acnt - tcnt, "\n"); + tcnt += ccnt; } - return 0; + mutex_unlock(&hdw->i2c_adap.clist_lock); + return tcnt; } @@ -4925,6 +4969,8 @@ unsigned int pvr2_hdw_state_report(struct pvr2_hdw *hdw, buf[0] = '\n'; ccnt = 1; bcnt += ccnt; acnt -= ccnt; buf += ccnt; } + ccnt = pvr2_hdw_report_clients(hdw, buf, acnt); + bcnt += ccnt; acnt -= ccnt; buf += ccnt; LOCK_GIVE(hdw->big_lock); return bcnt; } @@ -4932,14 +4978,25 @@ unsigned int pvr2_hdw_state_report(struct pvr2_hdw *hdw, static void pvr2_hdw_state_log_state(struct pvr2_hdw *hdw) { - char buf[128]; - unsigned int idx,ccnt; + char buf[256]; + unsigned int idx, ccnt; + unsigned int lcnt, ucnt; for (idx = 0; ; idx++) { ccnt = pvr2_hdw_report_unlocked(hdw,idx,buf,sizeof(buf)); if (!ccnt) break; printk(KERN_INFO "%s %.*s\n",hdw->name,ccnt,buf); } + ccnt = pvr2_hdw_report_clients(hdw, buf, sizeof(buf)); + ucnt = 0; + while (ucnt < ccnt) { + lcnt = 0; + while ((lcnt + ucnt < ccnt) && (buf[lcnt + ucnt] != '\n')) { + lcnt++; + } + printk(KERN_INFO "%s %.*s\n", hdw->name, lcnt, buf + ucnt); + ucnt += lcnt + 1; + } } -- cgit v1.2.3 From 5a3bab8eb02f9413b802540530ea390d8d063e43 Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Sun, 8 Mar 2009 18:47:47 -0300 Subject: V4L/DVB (11204): pvrusb2: Remove old i2c layer; we use v4l2-subdev now This change removes the old i2c module controlling layer from the pvrusb2 driver. This is code that first had appeared in the driver back in December 2005. It's history. Now we use v4l2-subdev. Please note also that with this change, the driver will no longer be usable in kernels older that 2.6.22. Signed-off-by: Mike Isely Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/pvrusb2/Makefile | 7 +- drivers/media/video/pvrusb2/pvrusb2-audio.c | 127 ------ drivers/media/video/pvrusb2/pvrusb2-audio.h | 4 - drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.c | 221 --------- drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.h | 5 - drivers/media/video/pvrusb2/pvrusb2-debugifc.c | 5 - drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h | 29 -- drivers/media/video/pvrusb2/pvrusb2-hdw.c | 85 ---- .../media/video/pvrusb2/pvrusb2-i2c-chips-v4l2.c | 118 ----- drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.c | 338 -------------- drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.h | 53 --- drivers/media/video/pvrusb2/pvrusb2-i2c-core.c | 4 - drivers/media/video/pvrusb2/pvrusb2-i2c-track.c | 503 --------------------- drivers/media/video/pvrusb2/pvrusb2-i2c-track.h | 102 ----- drivers/media/video/pvrusb2/pvrusb2-tuner.c | 121 ----- drivers/media/video/pvrusb2/pvrusb2-tuner.h | 37 -- drivers/media/video/pvrusb2/pvrusb2-video-v4l.c | 186 -------- drivers/media/video/pvrusb2/pvrusb2-video-v4l.h | 5 - drivers/media/video/pvrusb2/pvrusb2-wm8775.c | 124 ----- drivers/media/video/pvrusb2/pvrusb2-wm8775.h | 3 - 20 files changed, 3 insertions(+), 2074 deletions(-) delete mode 100644 drivers/media/video/pvrusb2/pvrusb2-i2c-chips-v4l2.c delete mode 100644 drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.c delete mode 100644 drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.h delete mode 100644 drivers/media/video/pvrusb2/pvrusb2-i2c-track.c delete mode 100644 drivers/media/video/pvrusb2/pvrusb2-i2c-track.h delete mode 100644 drivers/media/video/pvrusb2/pvrusb2-tuner.c delete mode 100644 drivers/media/video/pvrusb2/pvrusb2-tuner.h (limited to 'drivers/media/video') diff --git a/drivers/media/video/pvrusb2/Makefile b/drivers/media/video/pvrusb2/Makefile index 931d9d1a0b4b..a4478618a7fc 100644 --- a/drivers/media/video/pvrusb2/Makefile +++ b/drivers/media/video/pvrusb2/Makefile @@ -2,11 +2,10 @@ obj-pvrusb2-sysfs-$(CONFIG_VIDEO_PVRUSB2_SYSFS) := pvrusb2-sysfs.o obj-pvrusb2-debugifc-$(CONFIG_VIDEO_PVRUSB2_DEBUGIFC) := pvrusb2-debugifc.o obj-pvrusb2-dvb-$(CONFIG_VIDEO_PVRUSB2_DVB) := pvrusb2-dvb.o -pvrusb2-objs := pvrusb2-i2c-core.o pvrusb2-i2c-cmd-v4l2.o \ - pvrusb2-i2c-track.o \ - pvrusb2-audio.o pvrusb2-i2c-chips-v4l2.o \ +pvrusb2-objs := pvrusb2-i2c-core.o \ + pvrusb2-audio.o \ pvrusb2-encoder.o pvrusb2-video-v4l.o \ - pvrusb2-eeprom.o pvrusb2-tuner.o \ + pvrusb2-eeprom.o \ pvrusb2-main.o pvrusb2-hdw.o pvrusb2-v4l2.o \ pvrusb2-ctrl.o pvrusb2-std.o pvrusb2-devattr.o \ pvrusb2-context.o pvrusb2-io.o pvrusb2-ioread.o \ diff --git a/drivers/media/video/pvrusb2/pvrusb2-audio.c b/drivers/media/video/pvrusb2/pvrusb2-audio.c index aca6b1d1561a..ccf2a3c7ad06 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-audio.c +++ b/drivers/media/video/pvrusb2/pvrusb2-audio.c @@ -55,133 +55,6 @@ static const struct routing_scheme routing_schemes[] = { }, }; - -struct pvr2_msp3400_handler { - struct pvr2_hdw *hdw; - struct pvr2_i2c_client *client; - struct pvr2_i2c_handler i2c_handler; - unsigned long stale_mask; -}; - - - - -/* This function selects the correct audio input source */ -static void set_stereo(struct pvr2_msp3400_handler *ctxt) -{ - struct pvr2_hdw *hdw = ctxt->hdw; - struct v4l2_routing route; - const struct routing_scheme *sp; - unsigned int sid = hdw->hdw_desc->signal_routing_scheme; - - pvr2_trace(PVR2_TRACE_CHIPS,"i2c msp3400 v4l2 set_stereo"); - - if ((sid < ARRAY_SIZE(routing_schemes)) && - ((sp = routing_schemes + sid) != NULL) && - (hdw->input_val >= 0) && - (hdw->input_val < sp->cnt)) { - route.input = sp->def[hdw->input_val]; - } else { - pvr2_trace(PVR2_TRACE_ERROR_LEGS, - "*** WARNING *** i2c msp3400 v4l2 set_stereo:" - " Invalid routing scheme (%u) and/or input (%d)", - sid,hdw->input_val); - return; - } - route.output = MSP_OUTPUT(MSP_SC_IN_DSP_SCART1); - pvr2_i2c_client_cmd(ctxt->client,VIDIOC_INT_S_AUDIO_ROUTING,&route); -} - - -static int check_stereo(struct pvr2_msp3400_handler *ctxt) -{ - struct pvr2_hdw *hdw = ctxt->hdw; - return hdw->input_dirty; -} - - -struct pvr2_msp3400_ops { - void (*update)(struct pvr2_msp3400_handler *); - int (*check)(struct pvr2_msp3400_handler *); -}; - - -static const struct pvr2_msp3400_ops msp3400_ops[] = { - { .update = set_stereo, .check = check_stereo}, -}; - - -static int msp3400_check(struct pvr2_msp3400_handler *ctxt) -{ - unsigned long msk; - unsigned int idx; - - for (idx = 0; idx < ARRAY_SIZE(msp3400_ops); idx++) { - msk = 1 << idx; - if (ctxt->stale_mask & msk) continue; - if (msp3400_ops[idx].check(ctxt)) { - ctxt->stale_mask |= msk; - } - } - return ctxt->stale_mask != 0; -} - - -static void msp3400_update(struct pvr2_msp3400_handler *ctxt) -{ - unsigned long msk; - unsigned int idx; - - for (idx = 0; idx < ARRAY_SIZE(msp3400_ops); idx++) { - msk = 1 << idx; - if (!(ctxt->stale_mask & msk)) continue; - ctxt->stale_mask &= ~msk; - msp3400_ops[idx].update(ctxt); - } -} - - -static void pvr2_msp3400_detach(struct pvr2_msp3400_handler *ctxt) -{ - ctxt->client->handler = NULL; - kfree(ctxt); -} - - -static unsigned int pvr2_msp3400_describe(struct pvr2_msp3400_handler *ctxt, - char *buf,unsigned int cnt) -{ - return scnprintf(buf,cnt,"handler: pvrusb2-audio v4l2"); -} - - -static const struct pvr2_i2c_handler_functions msp3400_funcs = { - .detach = (void (*)(void *))pvr2_msp3400_detach, - .check = (int (*)(void *))msp3400_check, - .update = (void (*)(void *))msp3400_update, - .describe = (unsigned int (*)(void *,char *,unsigned int))pvr2_msp3400_describe, -}; - - -int pvr2_i2c_msp3400_setup(struct pvr2_hdw *hdw,struct pvr2_i2c_client *cp) -{ - struct pvr2_msp3400_handler *ctxt; - if (cp->handler) return 0; - - ctxt = kzalloc(sizeof(*ctxt),GFP_KERNEL); - if (!ctxt) return 0; - - ctxt->i2c_handler.func_data = ctxt; - ctxt->i2c_handler.func_table = &msp3400_funcs; - ctxt->client = cp; - ctxt->hdw = hdw; - ctxt->stale_mask = (1 << ARRAY_SIZE(msp3400_ops)) - 1; - cp->handler = &ctxt->i2c_handler; - pvr2_trace(PVR2_TRACE_CHIPS,"i2c 0x%x msp3400 V4L2 handler set up", - cp->client->addr); - return !0; -} - void pvr2_msp3400_subdev_update(struct pvr2_hdw *hdw, struct v4l2_subdev *sd) { if (hdw->input_dirty || hdw->force_dirty) { diff --git a/drivers/media/video/pvrusb2/pvrusb2-audio.h b/drivers/media/video/pvrusb2/pvrusb2-audio.h index c47c8de3ba06..e3e63d750891 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-audio.h +++ b/drivers/media/video/pvrusb2/pvrusb2-audio.h @@ -22,10 +22,6 @@ #ifndef __PVRUSB2_AUDIO_H #define __PVRUSB2_AUDIO_H -#include "pvrusb2-i2c-track.h" - -int pvr2_i2c_msp3400_setup(struct pvr2_hdw *,struct pvr2_i2c_client *); - #include "pvrusb2-hdw-internal.h" void pvr2_msp3400_subdev_update(struct pvr2_hdw *, struct v4l2_subdev *); #endif /* __PVRUSB2_AUDIO_H */ diff --git a/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.c b/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.c index 5adbf00323e5..4e017ff26c36 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.c +++ b/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.c @@ -28,7 +28,6 @@ #include "pvrusb2-cx2584x-v4l.h" #include "pvrusb2-video-v4l.h" -#include "pvrusb2-i2c-cmd-v4l2.h" #include "pvrusb2-hdw-internal.h" @@ -102,226 +101,6 @@ static const struct routing_scheme routing_schemes[] = { }, }; -struct pvr2_v4l_cx2584x { - struct pvr2_i2c_handler handler; - struct pvr2_decoder_ctrl ctrl; - struct pvr2_i2c_client *client; - struct pvr2_hdw *hdw; - unsigned long stale_mask; -}; - - -static void set_input(struct pvr2_v4l_cx2584x *ctxt) -{ - struct pvr2_hdw *hdw = ctxt->hdw; - struct v4l2_routing route; - enum cx25840_video_input vid_input; - enum cx25840_audio_input aud_input; - const struct routing_scheme *sp; - unsigned int sid = hdw->hdw_desc->signal_routing_scheme; - - memset(&route,0,sizeof(route)); - - if ((sid < ARRAY_SIZE(routing_schemes)) && - ((sp = routing_schemes + sid) != NULL) && - (hdw->input_val >= 0) && - (hdw->input_val < sp->cnt)) { - vid_input = sp->def[hdw->input_val].vid; - aud_input = sp->def[hdw->input_val].aud; - } else { - pvr2_trace(PVR2_TRACE_ERROR_LEGS, - "*** WARNING *** i2c cx2584x set_input:" - " Invalid routing scheme (%u) and/or input (%d)", - sid,hdw->input_val); - return; - } - - pvr2_trace(PVR2_TRACE_CHIPS,"i2c cx2584x set_input vid=0x%x aud=0x%x", - vid_input,aud_input); - route.input = (u32)vid_input; - pvr2_i2c_client_cmd(ctxt->client,VIDIOC_INT_S_VIDEO_ROUTING,&route); - route.input = (u32)aud_input; - pvr2_i2c_client_cmd(ctxt->client,VIDIOC_INT_S_AUDIO_ROUTING,&route); -} - - -static int check_input(struct pvr2_v4l_cx2584x *ctxt) -{ - struct pvr2_hdw *hdw = ctxt->hdw; - return hdw->input_dirty != 0; -} - - -static void set_audio(struct pvr2_v4l_cx2584x *ctxt) -{ - u32 val; - struct pvr2_hdw *hdw = ctxt->hdw; - - pvr2_trace(PVR2_TRACE_CHIPS,"i2c cx2584x set_audio %d", - hdw->srate_val); - switch (hdw->srate_val) { - default: - case V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000: - val = 48000; - break; - case V4L2_MPEG_AUDIO_SAMPLING_FREQ_44100: - val = 44100; - break; - case V4L2_MPEG_AUDIO_SAMPLING_FREQ_32000: - val = 32000; - break; - } - pvr2_i2c_client_cmd(ctxt->client,VIDIOC_INT_AUDIO_CLOCK_FREQ,&val); -} - - -static int check_audio(struct pvr2_v4l_cx2584x *ctxt) -{ - struct pvr2_hdw *hdw = ctxt->hdw; - return hdw->srate_dirty != 0; -} - - -struct pvr2_v4l_cx2584x_ops { - void (*update)(struct pvr2_v4l_cx2584x *); - int (*check)(struct pvr2_v4l_cx2584x *); -}; - - -static const struct pvr2_v4l_cx2584x_ops decoder_ops[] = { - { .update = set_input, .check = check_input}, - { .update = set_audio, .check = check_audio}, -}; - - -static void decoder_detach(struct pvr2_v4l_cx2584x *ctxt) -{ - ctxt->client->handler = NULL; - pvr2_hdw_set_decoder(ctxt->hdw,NULL); - kfree(ctxt); -} - - -static int decoder_check(struct pvr2_v4l_cx2584x *ctxt) -{ - unsigned long msk; - unsigned int idx; - - for (idx = 0; idx < ARRAY_SIZE(decoder_ops); idx++) { - msk = 1 << idx; - if (ctxt->stale_mask & msk) continue; - if (decoder_ops[idx].check(ctxt)) { - ctxt->stale_mask |= msk; - } - } - return ctxt->stale_mask != 0; -} - - -static void decoder_update(struct pvr2_v4l_cx2584x *ctxt) -{ - unsigned long msk; - unsigned int idx; - - for (idx = 0; idx < ARRAY_SIZE(decoder_ops); idx++) { - msk = 1 << idx; - if (!(ctxt->stale_mask & msk)) continue; - ctxt->stale_mask &= ~msk; - decoder_ops[idx].update(ctxt); - } -} - - -static void decoder_enable(struct pvr2_v4l_cx2584x *ctxt,int fl) -{ - pvr2_trace(PVR2_TRACE_CHIPS,"i2c cx25840 decoder_enable(%d)",fl); - pvr2_v4l2_cmd_stream(ctxt->client,fl); -} - - -static int decoder_detect(struct pvr2_i2c_client *cp) -{ - int ret; - /* Attempt to query the decoder - let's see if it will answer */ - struct v4l2_queryctrl qc; - - memset(&qc,0,sizeof(qc)); - - qc.id = V4L2_CID_BRIGHTNESS; - - ret = pvr2_i2c_client_cmd(cp,VIDIOC_QUERYCTRL,&qc); - return ret == 0; /* Return true if it answered */ -} - - -static unsigned int decoder_describe(struct pvr2_v4l_cx2584x *ctxt, - char *buf,unsigned int cnt) -{ - return scnprintf(buf,cnt,"handler: pvrusb2-cx2584x-v4l"); -} - - -static void decoder_reset(struct pvr2_v4l_cx2584x *ctxt) -{ - int ret; - ret = pvr2_i2c_client_cmd(ctxt->client,VIDIOC_INT_RESET,NULL); - pvr2_trace(PVR2_TRACE_CHIPS,"i2c cx25840 decoder_reset (ret=%d)",ret); -} - - -static const struct pvr2_i2c_handler_functions hfuncs = { - .detach = (void (*)(void *))decoder_detach, - .check = (int (*)(void *))decoder_check, - .update = (void (*)(void *))decoder_update, - .describe = (unsigned int (*)(void *,char *,unsigned int))decoder_describe, -}; - - -int pvr2_i2c_cx2584x_v4l_setup(struct pvr2_hdw *hdw, - struct pvr2_i2c_client *cp) -{ - struct pvr2_v4l_cx2584x *ctxt; - - if (hdw->decoder_ctrl) return 0; - if (cp->handler) return 0; - if (!decoder_detect(cp)) return 0; - - ctxt = kzalloc(sizeof(*ctxt),GFP_KERNEL); - if (!ctxt) return 0; - - ctxt->handler.func_data = ctxt; - ctxt->handler.func_table = &hfuncs; - ctxt->ctrl.ctxt = ctxt; - ctxt->ctrl.detach = (void (*)(void *))decoder_detach; - ctxt->ctrl.enable = (void (*)(void *,int))decoder_enable; - ctxt->ctrl.force_reset = (void (*)(void*))decoder_reset; - ctxt->client = cp; - ctxt->hdw = hdw; - ctxt->stale_mask = (1 << ARRAY_SIZE(decoder_ops)) - 1; - pvr2_hdw_set_decoder(hdw,&ctxt->ctrl); - cp->handler = &ctxt->handler; - { - /* - Mike Isely 19-Nov-2006 - This bit - of nuttiness for cx25840 causes that module to - correctly set up its video scaling. This is really - a problem in the cx25840 module itself, but we work - around it here. The problem has not been seen in - ivtv because there VBI is supported and set up. We - don't do VBI here (at least not yet) and thus we - never attempted to even set it up. - */ - struct v4l2_format fmt; - memset(&fmt,0,sizeof(fmt)); - fmt.type = V4L2_BUF_TYPE_SLICED_VBI_CAPTURE; - pvr2_i2c_client_cmd(ctxt->client,VIDIOC_S_FMT,&fmt); - } - pvr2_trace(PVR2_TRACE_CHIPS,"i2c 0x%x cx2584x V4L2 handler set up", - cp->client->addr); - return !0; -} - - void pvr2_cx25840_subdev_update(struct pvr2_hdw *hdw, struct v4l2_subdev *sd) { pvr2_trace(PVR2_TRACE_CHIPS, "subdev cx2584x update..."); diff --git a/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.h b/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.h index e48ce808bfe5..e35c2322a08c 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.h +++ b/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.h @@ -34,11 +34,6 @@ -#include "pvrusb2-i2c-track.h" - -int pvr2_i2c_cx2584x_v4l_setup(struct pvr2_hdw *,struct pvr2_i2c_client *); - - #include "pvrusb2-hdw-internal.h" void pvr2_cx25840_subdev_update(struct pvr2_hdw *, struct v4l2_subdev *sd); diff --git a/drivers/media/video/pvrusb2/pvrusb2-debugifc.c b/drivers/media/video/pvrusb2/pvrusb2-debugifc.c index 2074ce05c76a..fbe3856bdca6 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-debugifc.c +++ b/drivers/media/video/pvrusb2/pvrusb2-debugifc.c @@ -23,7 +23,6 @@ #include "pvrusb2-debugifc.h" #include "pvrusb2-hdw.h" #include "pvrusb2-debug.h" -#include "pvrusb2-i2c-track.h" struct debugifc_mask_item { const char *name; @@ -147,10 +146,6 @@ int pvr2_debugifc_print_info(struct pvr2_hdw *hdw,char *buf,unsigned int acnt) bcnt += ccnt; acnt -= ccnt; buf += ccnt; ccnt = pvr2_hdw_state_report(hdw,buf,acnt); bcnt += ccnt; acnt -= ccnt; buf += ccnt; - ccnt = scnprintf(buf, acnt, "Attached old-style I2C modules:\n"); - bcnt += ccnt; acnt -= ccnt; buf += ccnt; - ccnt = pvr2_i2c_report(hdw,buf,acnt); - bcnt += ccnt; acnt -= ccnt; buf += ccnt; return bcnt; } diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h b/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h index 2afbd9bcedd3..5d75eb5211b1 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h +++ b/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h @@ -138,22 +138,6 @@ struct pvr2_ctrl { }; -struct pvr2_decoder_ctrl { - void *ctxt; - void (*detach)(void *); - void (*enable)(void *,int); - void (*force_reset)(void *); -}; - -#define PVR2_I2C_PEND_DETECT 0x01 /* Need to detect a client type */ -#define PVR2_I2C_PEND_CLIENT 0x02 /* Client needs a specific update */ -#define PVR2_I2C_PEND_REFRESH 0x04 /* Client has specific pending bits */ -#define PVR2_I2C_PEND_STALE 0x08 /* Broadcast pending bits */ - -#define PVR2_I2C_PEND_ALL (PVR2_I2C_PEND_DETECT |\ - PVR2_I2C_PEND_CLIENT |\ - PVR2_I2C_PEND_REFRESH |\ - PVR2_I2C_PEND_STALE) /* Disposition of firmware1 loading situation */ #define FW1_STATE_UNKNOWN 0 @@ -187,7 +171,6 @@ struct pvr2_hdw { /* Kernel worker thread handling */ struct workqueue_struct *workqueue; struct work_struct workpoll; /* Update driver state */ - struct work_struct worki2csync; /* Update i2c clients */ /* Video spigot */ struct pvr2_stream *vid_stream; @@ -216,12 +199,6 @@ struct pvr2_hdw { pvr2_i2c_func i2c_func[PVR2_I2C_FUNC_CNT]; int i2c_cx25840_hack_state; int i2c_linked; - unsigned int i2c_pend_types; /* Which types of update are needed */ - unsigned long i2c_pend_mask; /* Change bits we need to scan */ - unsigned long i2c_stale_mask; /* Pending broadcast change bits */ - unsigned long i2c_active_mask; /* All change bits currently in use */ - struct list_head i2c_clients; - struct mutex i2c_list_lock; /* Frequency table */ unsigned int freqTable[FREQTABLE_SIZE]; @@ -297,7 +274,6 @@ struct pvr2_hdw { int flag_decoder_missed;/* We've noticed missing decoder */ int flag_tripped; /* Indicates overall failure to start */ - struct pvr2_decoder_ctrl *decoder_ctrl; unsigned int decoder_client_id; // CPU firmware info (used to help find / save firmware data) @@ -305,10 +281,6 @@ struct pvr2_hdw { unsigned int fw_size; int fw_cpu_flag; /* True if we are dealing with the CPU */ - // True if there is a request to trigger logging of state in each - // module. - int log_requested; - /* Tuner / frequency control stuff */ unsigned int tuner_type; int tuner_updated; @@ -406,7 +378,6 @@ struct pvr2_hdw { /* This function gets the current frequency */ unsigned long pvr2_hdw_get_cur_freq(struct pvr2_hdw *); -void pvr2_hdw_set_decoder(struct pvr2_hdw *,struct pvr2_decoder_ctrl *); void pvr2_hdw_status_poll(struct pvr2_hdw *); diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/drivers/media/video/pvrusb2/pvrusb2-hdw.c index b0383153e3ce..7c66779b1f42 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-hdw.c +++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.c @@ -30,8 +30,6 @@ #include "pvrusb2-util.h" #include "pvrusb2-hdw.h" #include "pvrusb2-i2c-core.h" -#include "pvrusb2-i2c-track.h" -#include "pvrusb2-tuner.h" #include "pvrusb2-eeprom.h" #include "pvrusb2-hdw-internal.h" #include "pvrusb2-encoder.h" @@ -313,7 +311,6 @@ static int pvr2_hdw_set_input(struct pvr2_hdw *hdw,int v); static void pvr2_hdw_state_sched(struct pvr2_hdw *); static int pvr2_hdw_state_eval(struct pvr2_hdw *); static void pvr2_hdw_set_cur_freq(struct pvr2_hdw *,unsigned long); -static void pvr2_hdw_worker_i2c(struct work_struct *work); static void pvr2_hdw_worker_poll(struct work_struct *work); static int pvr2_hdw_wait(struct pvr2_hdw *,int state); static int pvr2_hdw_untrip_unlocked(struct pvr2_hdw *); @@ -1676,10 +1673,6 @@ static const char *pvr2_get_state_name(unsigned int st) static int pvr2_decoder_enable(struct pvr2_hdw *hdw,int enablefl) { - if (hdw->decoder_ctrl) { - hdw->decoder_ctrl->enable(hdw->decoder_ctrl->ctxt, enablefl); - return 0; - } /* Even though we really only care about the video decoder chip at this point, we'll broadcast stream on/off to all sub-devices anyway, just in case somebody else wants to hear the @@ -1704,21 +1697,6 @@ static int pvr2_decoder_enable(struct pvr2_hdw *hdw,int enablefl) } -void pvr2_hdw_set_decoder(struct pvr2_hdw *hdw,struct pvr2_decoder_ctrl *ptr) -{ - if (hdw->decoder_ctrl == ptr) return; - hdw->decoder_ctrl = ptr; - if (hdw->decoder_ctrl && hdw->flag_decoder_missed) { - hdw->flag_decoder_missed = 0; - trace_stbit("flag_decoder_missed", - hdw->flag_decoder_missed); - pvr2_trace(PVR2_TRACE_ERROR_LEGS, - "Decoder has appeared"); - pvr2_hdw_state_sched(hdw); - } -} - - int pvr2_hdw_get_state(struct pvr2_hdw *hdw) { return hdw->master_state; @@ -2052,7 +2030,6 @@ static int pvr2_hdw_load_subdev(struct pvr2_hdw *hdw, * and every other place where I can find examples of this, the * "chipid" appears to just be the module name again. So here we * just do the same thing. */ - hdw->i2c_adap.class = 0; if (i2ccnt == 1) { pvr2_trace(PVR2_TRACE_INIT, "Module ID %u:" @@ -2070,7 +2047,6 @@ static int pvr2_hdw_load_subdev(struct pvr2_hdw *hdw, fname, fname, i2caddr); } - hdw->i2c_adap.class = I2C_CLASS_TV_ANALOG; if (!sd) { pvr2_trace(PVR2_TRACE_ERROR_LEGS, @@ -2084,11 +2060,6 @@ static int pvr2_hdw_load_subdev(struct pvr2_hdw *hdw, requires special handling. */ sd->grp_id = mid; - /* If we have both old and new i2c layers enabled, make sure that - old layer isn't also tracking this module. This is a debugging - aid, in normal situations there's no reason for both mechanisms - to be enabled. */ - pvr2_i2c_untrack_subdev(hdw, sd); pvr2_trace(PVR2_TRACE_INFO, "Attached sub-driver %s", fname); @@ -2204,7 +2175,6 @@ static void pvr2_hdw_setup_low(struct pvr2_hdw *hdw) } // This step MUST happen after the earlier powerup step. - pvr2_i2c_track_init(hdw); pvr2_i2c_core_init(hdw); if (!pvr2_hdw_dev_ok(hdw)) return; @@ -2271,7 +2241,6 @@ static void pvr2_hdw_setup_low(struct pvr2_hdw *hdw) hdw->tuner_type); } - pvr2_i2c_core_check_stale(hdw); if (!pvr2_hdw_dev_ok(hdw)) return; @@ -2628,7 +2597,6 @@ struct pvr2_hdw *pvr2_hdw_create(struct usb_interface *intf, hdw->workqueue = create_singlethread_workqueue(hdw->name); INIT_WORK(&hdw->workpoll,pvr2_hdw_worker_poll); - INIT_WORK(&hdw->worki2csync,pvr2_hdw_worker_i2c); pvr2_trace(PVR2_TRACE_INIT,"Driver unit number is %d, name is %s", hdw->unit_number,hdw->name); @@ -2731,11 +2699,7 @@ void pvr2_hdw_destroy(struct pvr2_hdw *hdw) pvr2_stream_destroy(hdw->vid_stream); hdw->vid_stream = NULL; } - if (hdw->decoder_ctrl) { - hdw->decoder_ctrl->detach(hdw->decoder_ctrl->ctxt); - } pvr2_i2c_core_done(hdw); - pvr2_i2c_track_done(hdw); v4l2_device_unregister(&hdw->v4l2_dev); pvr2_hdw_remove_usb_stuff(hdw); mutex_lock(&pvr2_unit_mtx); do { @@ -3238,12 +3202,6 @@ static int pvr2_hdw_commit_execute(struct pvr2_hdw *hdw) cx2341x_ext_ctrls(&hdw->enc_ctl_state, 0, &cs,VIDIOC_S_EXT_CTRLS); } - /* Scan i2c core at this point - before we clear all the dirty - bits. Various parts of the i2c core will notice dirty bits as - appropriate and arrange to broadcast or directly send updates to - the client drivers in order to keep everything in sync */ - pvr2_i2c_core_check_stale(hdw); - if (hdw->active_stream_type != hdw->desired_stream_type) { /* Handle any side effects of stream config here */ hdw->active_stream_type = hdw->desired_stream_type; @@ -3274,9 +3232,6 @@ static int pvr2_hdw_commit_execute(struct pvr2_hdw *hdw) cptr->info->clear_dirty(cptr); } - /* Now execute i2c core update */ - pvr2_i2c_core_sync(hdw); - if ((hdw->pathway_state == PVR2_PATHWAY_ANALOG) && hdw->state_encoder_run) { /* If encoder isn't running or it can't be touched, then @@ -3305,15 +3260,6 @@ int pvr2_hdw_commit_ctl(struct pvr2_hdw *hdw) } -static void pvr2_hdw_worker_i2c(struct work_struct *work) -{ - struct pvr2_hdw *hdw = container_of(work,struct pvr2_hdw,worki2csync); - LOCK_TAKE(hdw->big_lock); do { - pvr2_i2c_core_sync(hdw); - } while (0); LOCK_GIVE(hdw->big_lock); -} - - static void pvr2_hdw_worker_poll(struct work_struct *work) { int fl = 0; @@ -3431,10 +3377,6 @@ void pvr2_hdw_trigger_module_log(struct pvr2_hdw *hdw) int nr = pvr2_hdw_get_unit_number(hdw); LOCK_TAKE(hdw->big_lock); do { printk(KERN_INFO "pvrusb2: ================= START STATUS CARD #%d =================\n", nr); - hdw->log_requested = !0; - pvr2_i2c_core_check_stale(hdw); - pvr2_i2c_core_sync(hdw); - hdw->log_requested = 0; v4l2_device_call_all(&hdw->v4l2_dev, 0, core, log_status); pvr2_trace(PVR2_TRACE_INFO,"cx2341x config:"); cx2341x_log_status(&hdw->enc_ctl_state, "pvrusb2"); @@ -4120,16 +4062,6 @@ int pvr2_hdw_cmd_decoder_reset(struct pvr2_hdw *hdw) { pvr2_trace(PVR2_TRACE_INIT, "Requesting decoder reset"); - if (hdw->decoder_ctrl) { - if (!hdw->decoder_ctrl->force_reset) { - pvr2_trace(PVR2_TRACE_INIT, - "Unable to reset decoder: not implemented"); - return -ENOTTY; - } - hdw->decoder_ctrl->force_reset(hdw->decoder_ctrl->ctxt); - return 0; - } else { - } if (hdw->decoder_client_id) { v4l2_device_call_all(&hdw->v4l2_dev, hdw->decoder_client_id, core, reset, 0); @@ -5138,7 +5070,6 @@ void pvr2_hdw_status_poll(struct pvr2_hdw *hdw) struct v4l2_tuner *vtp = &hdw->tuner_signal_info; memset(vtp, 0, sizeof(*vtp)); hdw->tuner_signal_stale = 0; - pvr2_i2c_core_status_poll(hdw); /* Note: There apparently is no replacement for VIDIOC_CROPCAP using v4l2-subdev - therefore we can't support that AT ALL right now. (Of course, no sub-drivers seem to implement it either. @@ -5253,7 +5184,6 @@ int pvr2_hdw_register_access(struct pvr2_hdw *hdw, int setFl, u64 *val_ptr) { #ifdef CONFIG_VIDEO_ADV_DEBUG - struct pvr2_i2c_client *cp; struct v4l2_dbg_register req; int stat = 0; int okFl = 0; @@ -5266,21 +5196,6 @@ int pvr2_hdw_register_access(struct pvr2_hdw *hdw, /* It would be nice to know if a sub-device answered the request */ v4l2_device_call_all(&hdw->v4l2_dev, 0, core, g_register, &req); if (!setFl) *val_ptr = req.val; - if (!okFl) mutex_lock(&hdw->i2c_list_lock); do { - list_for_each_entry(cp, &hdw->i2c_clients, list) { - if (!v4l2_chip_match_i2c_client( - cp->client, - &req.match)) { - continue; - } - stat = pvr2_i2c_client_cmd( - cp,(setFl ? VIDIOC_DBG_S_REGISTER : - VIDIOC_DBG_G_REGISTER),&req); - if (!setFl) *val_ptr = req.val; - okFl = !0; - break; - } - } while (0); mutex_unlock(&hdw->i2c_list_lock); if (okFl) { return stat; } diff --git a/drivers/media/video/pvrusb2/pvrusb2-i2c-chips-v4l2.c b/drivers/media/video/pvrusb2/pvrusb2-i2c-chips-v4l2.c deleted file mode 100644 index 7e0628b988cc..000000000000 --- a/drivers/media/video/pvrusb2/pvrusb2-i2c-chips-v4l2.c +++ /dev/null @@ -1,118 +0,0 @@ -/* - * - * - * Copyright (C) 2005 Mike Isely - * - * 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 - * - * 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 - * - */ - -#include -#include "pvrusb2-i2c-track.h" -#include "pvrusb2-hdw-internal.h" -#include "pvrusb2-debug.h" -#include "pvrusb2-i2c-cmd-v4l2.h" -#include "pvrusb2-audio.h" -#include "pvrusb2-tuner.h" -#include "pvrusb2-video-v4l.h" -#include "pvrusb2-cx2584x-v4l.h" -#include "pvrusb2-wm8775.h" - - -#define trace_i2c(...) pvr2_trace(PVR2_TRACE_I2C,__VA_ARGS__) - -#define OP_INIT 0 /* MUST come first so it is run first */ -#define OP_STANDARD 1 -#define OP_AUDIOMODE 2 -#define OP_BCSH 3 -#define OP_VOLUME 4 -#define OP_FREQ 5 -#define OP_AUDIORATE 6 -#define OP_CROP 7 -#define OP_SIZE 8 -#define OP_LOG 9 - -static const struct pvr2_i2c_op * const ops[] = { - [OP_INIT] = &pvr2_i2c_op_v4l2_init, - [OP_STANDARD] = &pvr2_i2c_op_v4l2_standard, - [OP_AUDIOMODE] = &pvr2_i2c_op_v4l2_audiomode, - [OP_BCSH] = &pvr2_i2c_op_v4l2_bcsh, - [OP_VOLUME] = &pvr2_i2c_op_v4l2_volume, - [OP_FREQ] = &pvr2_i2c_op_v4l2_frequency, - [OP_CROP] = &pvr2_i2c_op_v4l2_crop, - [OP_SIZE] = &pvr2_i2c_op_v4l2_size, - [OP_LOG] = &pvr2_i2c_op_v4l2_log, -}; - -void pvr2_i2c_probe(struct pvr2_hdw *hdw,struct pvr2_i2c_client *cp) -{ - int id; - id = cp->client->driver->id; - cp->ctl_mask = ((1 << OP_INIT) | - (1 << OP_STANDARD) | - (1 << OP_AUDIOMODE) | - (1 << OP_BCSH) | - (1 << OP_VOLUME) | - (1 << OP_FREQ) | - (1 << OP_CROP) | - (1 << OP_SIZE) | - (1 << OP_LOG)); - cp->status_poll = pvr2_v4l2_cmd_status_poll; - - if (id == I2C_DRIVERID_MSP3400) { - if (pvr2_i2c_msp3400_setup(hdw,cp)) { - return; - } - } - if (id == I2C_DRIVERID_TUNER) { - if (pvr2_i2c_tuner_setup(hdw,cp)) { - return; - } - } - if (id == I2C_DRIVERID_CX25840) { - if (pvr2_i2c_cx2584x_v4l_setup(hdw,cp)) { - return; - } - } - if (id == I2C_DRIVERID_WM8775) { - if (pvr2_i2c_wm8775_setup(hdw,cp)) { - return; - } - } - if (id == I2C_DRIVERID_SAA711X) { - if (pvr2_i2c_decoder_v4l_setup(hdw,cp)) { - return; - } - } -} - - -const struct pvr2_i2c_op *pvr2_i2c_get_op(unsigned int idx) -{ - if (idx >= ARRAY_SIZE(ops)) - return NULL; - return ops[idx]; -} - - - -/* - Stuff for Emacs to see, in order to encourage consistent editing style: - *** Local Variables: *** - *** mode: c *** - *** fill-column: 75 *** - *** tab-width: 8 *** - *** c-basic-offset: 8 *** - *** End: *** - */ diff --git a/drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.c b/drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.c deleted file mode 100644 index 7afe513bebf9..000000000000 --- a/drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.c +++ /dev/null @@ -1,338 +0,0 @@ -/* - * - * - * Copyright (C) 2005 Mike Isely - * Copyright (C) 2004 Aurelien Alleaume - * - * 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 - * - * 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 - * - */ - -#include "pvrusb2-i2c-cmd-v4l2.h" -#include "pvrusb2-hdw-internal.h" -#include "pvrusb2-debug.h" -#include -#include - - -static void execute_init(struct pvr2_hdw *hdw) -{ - u32 dummy = 0; - pvr2_trace(PVR2_TRACE_CHIPS, "i2c v4l2 init"); - pvr2_i2c_core_cmd(hdw, VIDIOC_INT_INIT, &dummy); -} - - -const struct pvr2_i2c_op pvr2_i2c_op_v4l2_init = { - .update = execute_init, - .name = "v4l2_init", -}; - - -static void set_standard(struct pvr2_hdw *hdw) -{ - pvr2_trace(PVR2_TRACE_CHIPS,"i2c v4l2 set_standard"); - - if (hdw->input_val == PVR2_CVAL_INPUT_RADIO) { - pvr2_i2c_core_cmd(hdw,AUDC_SET_RADIO,NULL); - } else { - v4l2_std_id vs; - vs = hdw->std_mask_cur; - pvr2_i2c_core_cmd(hdw,VIDIOC_S_STD,&vs); - } - hdw->tuner_signal_stale = !0; - hdw->cropcap_stale = !0; -} - - -static int check_standard(struct pvr2_hdw *hdw) -{ - return (hdw->input_dirty != 0) || (hdw->std_dirty != 0); -} - - -const struct pvr2_i2c_op pvr2_i2c_op_v4l2_standard = { - .check = check_standard, - .update = set_standard, - .name = "v4l2_standard", -}; - - -static void set_bcsh(struct pvr2_hdw *hdw) -{ - struct v4l2_control ctrl; - pvr2_trace(PVR2_TRACE_CHIPS,"i2c v4l2 set_bcsh" - " b=%d c=%d s=%d h=%d", - hdw->brightness_val,hdw->contrast_val, - hdw->saturation_val,hdw->hue_val); - memset(&ctrl,0,sizeof(ctrl)); - ctrl.id = V4L2_CID_BRIGHTNESS; - ctrl.value = hdw->brightness_val; - pvr2_i2c_core_cmd(hdw,VIDIOC_S_CTRL,&ctrl); - ctrl.id = V4L2_CID_CONTRAST; - ctrl.value = hdw->contrast_val; - pvr2_i2c_core_cmd(hdw,VIDIOC_S_CTRL,&ctrl); - ctrl.id = V4L2_CID_SATURATION; - ctrl.value = hdw->saturation_val; - pvr2_i2c_core_cmd(hdw,VIDIOC_S_CTRL,&ctrl); - ctrl.id = V4L2_CID_HUE; - ctrl.value = hdw->hue_val; - pvr2_i2c_core_cmd(hdw,VIDIOC_S_CTRL,&ctrl); -} - - -static int check_bcsh(struct pvr2_hdw *hdw) -{ - return (hdw->brightness_dirty || - hdw->contrast_dirty || - hdw->saturation_dirty || - hdw->hue_dirty); -} - - -const struct pvr2_i2c_op pvr2_i2c_op_v4l2_bcsh = { - .check = check_bcsh, - .update = set_bcsh, - .name = "v4l2_bcsh", -}; - - -static void set_volume(struct pvr2_hdw *hdw) -{ - struct v4l2_control ctrl; - pvr2_trace(PVR2_TRACE_CHIPS, - "i2c v4l2 set_volume" - "(vol=%d bal=%d bas=%d treb=%d mute=%d)", - hdw->volume_val, - hdw->balance_val, - hdw->bass_val, - hdw->treble_val, - hdw->mute_val); - memset(&ctrl,0,sizeof(ctrl)); - ctrl.id = V4L2_CID_AUDIO_MUTE; - ctrl.value = hdw->mute_val ? 1 : 0; - pvr2_i2c_core_cmd(hdw,VIDIOC_S_CTRL,&ctrl); - ctrl.id = V4L2_CID_AUDIO_VOLUME; - ctrl.value = hdw->volume_val; - pvr2_i2c_core_cmd(hdw,VIDIOC_S_CTRL,&ctrl); - ctrl.id = V4L2_CID_AUDIO_BALANCE; - ctrl.value = hdw->balance_val; - pvr2_i2c_core_cmd(hdw,VIDIOC_S_CTRL,&ctrl); - ctrl.id = V4L2_CID_AUDIO_BASS; - ctrl.value = hdw->bass_val; - pvr2_i2c_core_cmd(hdw,VIDIOC_S_CTRL,&ctrl); - ctrl.id = V4L2_CID_AUDIO_TREBLE; - ctrl.value = hdw->treble_val; - pvr2_i2c_core_cmd(hdw,VIDIOC_S_CTRL,&ctrl); -} - - -static int check_volume(struct pvr2_hdw *hdw) -{ - return (hdw->volume_dirty || - hdw->balance_dirty || - hdw->bass_dirty || - hdw->treble_dirty || - hdw->mute_dirty); -} - - -const struct pvr2_i2c_op pvr2_i2c_op_v4l2_volume = { - .check = check_volume, - .update = set_volume, - .name = "v4l2_volume", -}; - - -static void set_audiomode(struct pvr2_hdw *hdw) -{ - struct v4l2_tuner vt; - memset(&vt,0,sizeof(vt)); - vt.audmode = hdw->audiomode_val; - pvr2_i2c_core_cmd(hdw,VIDIOC_S_TUNER,&vt); -} - - -static int check_audiomode(struct pvr2_hdw *hdw) -{ - return (hdw->input_dirty || - hdw->audiomode_dirty); -} - - -const struct pvr2_i2c_op pvr2_i2c_op_v4l2_audiomode = { - .check = check_audiomode, - .update = set_audiomode, - .name = "v4l2_audiomode", -}; - - -static void set_frequency(struct pvr2_hdw *hdw) -{ - unsigned long fv; - struct v4l2_frequency freq; - fv = pvr2_hdw_get_cur_freq(hdw); - pvr2_trace(PVR2_TRACE_CHIPS,"i2c v4l2 set_freq(%lu)",fv); - if (hdw->tuner_signal_stale) { - pvr2_hdw_status_poll(hdw); - } - memset(&freq,0,sizeof(freq)); - if (hdw->tuner_signal_info.capability & V4L2_TUNER_CAP_LOW) { - // ((fv * 1000) / 62500) - freq.frequency = (fv * 2) / 125; - } else { - freq.frequency = fv / 62500; - } - /* tuner-core currently doesn't seem to care about this, but - let's set it anyway for completeness. */ - if (hdw->input_val == PVR2_CVAL_INPUT_RADIO) { - freq.type = V4L2_TUNER_RADIO; - } else { - freq.type = V4L2_TUNER_ANALOG_TV; - } - freq.tuner = 0; - pvr2_i2c_core_cmd(hdw,VIDIOC_S_FREQUENCY,&freq); -} - - -static int check_frequency(struct pvr2_hdw *hdw) -{ - return hdw->freqDirty != 0; -} - - -const struct pvr2_i2c_op pvr2_i2c_op_v4l2_frequency = { - .check = check_frequency, - .update = set_frequency, - .name = "v4l2_freq", -}; - - -static void set_size(struct pvr2_hdw *hdw) -{ - struct v4l2_format fmt; - - memset(&fmt,0,sizeof(fmt)); - - fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - fmt.fmt.pix.width = hdw->res_hor_val; - fmt.fmt.pix.height = hdw->res_ver_val; - - pvr2_trace(PVR2_TRACE_CHIPS,"i2c v4l2 set_size(%dx%d)", - fmt.fmt.pix.width,fmt.fmt.pix.height); - - pvr2_i2c_core_cmd(hdw,VIDIOC_S_FMT,&fmt); -} - - -static int check_size(struct pvr2_hdw *hdw) -{ - return (hdw->res_hor_dirty || hdw->res_ver_dirty); -} - - -const struct pvr2_i2c_op pvr2_i2c_op_v4l2_size = { - .check = check_size, - .update = set_size, - .name = "v4l2_size", -}; - - -static void set_crop(struct pvr2_hdw *hdw) -{ - struct v4l2_crop crop; - - memset(&crop, 0, sizeof crop); - crop.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - crop.c.left = hdw->cropl_val; - crop.c.top = hdw->cropt_val; - crop.c.height = hdw->croph_val; - crop.c.width = hdw->cropw_val; - - pvr2_trace(PVR2_TRACE_CHIPS, - "i2c v4l2 set_crop crop=%d:%d:%d:%d", - crop.c.width, crop.c.height, crop.c.left, crop.c.top); - - pvr2_i2c_core_cmd(hdw, VIDIOC_S_CROP, &crop); -} - -static int check_crop(struct pvr2_hdw *hdw) -{ - return (hdw->cropl_dirty || hdw->cropt_dirty || - hdw->cropw_dirty || hdw->croph_dirty); -} - -const struct pvr2_i2c_op pvr2_i2c_op_v4l2_crop = { - .check = check_crop, - .update = set_crop, - .name = "v4l2_crop", -}; - - -static void do_log(struct pvr2_hdw *hdw) -{ - pvr2_trace(PVR2_TRACE_CHIPS,"i2c v4l2 do_log()"); - pvr2_i2c_core_cmd(hdw,VIDIOC_LOG_STATUS,NULL); - -} - - -static int check_log(struct pvr2_hdw *hdw) -{ - return hdw->log_requested != 0; -} - - -const struct pvr2_i2c_op pvr2_i2c_op_v4l2_log = { - .check = check_log, - .update = do_log, - .name = "v4l2_log", -}; - - -void pvr2_v4l2_cmd_stream(struct pvr2_i2c_client *cp,int fl) -{ - pvr2_i2c_client_cmd(cp, - (fl ? VIDIOC_STREAMON : VIDIOC_STREAMOFF),NULL); -} - - -void pvr2_v4l2_cmd_status_poll(struct pvr2_i2c_client *cp) -{ - int stat; - struct pvr2_hdw *hdw = cp->hdw; - if (hdw->cropcap_stale) { - hdw->cropcap_info.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - stat = pvr2_i2c_client_cmd(cp, VIDIOC_CROPCAP, - &hdw->cropcap_info); - if (stat == 0) { - /* Check was successful, so the data is no - longer considered stale. */ - hdw->cropcap_stale = 0; - } - } - pvr2_i2c_client_cmd(cp, VIDIOC_G_TUNER, &hdw->tuner_signal_info); -} - - - -/* - Stuff for Emacs to see, in order to encourage consistent editing style: - *** Local Variables: *** - *** mode: c *** - *** fill-column: 70 *** - *** tab-width: 8 *** - *** c-basic-offset: 8 *** - *** End: *** - */ diff --git a/drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.h b/drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.h deleted file mode 100644 index fa42497b40b5..000000000000 --- a/drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.h +++ /dev/null @@ -1,53 +0,0 @@ -/* - * - * - * Copyright (C) 2005 Mike Isely - * Copyright (C) 2004 Aurelien Alleaume - * - * 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 - * - * 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 - * - */ - -#ifndef __PVRUSB2_CMD_V4L2_H -#define __PVRUSB2_CMD_V4L2_H - -#include "pvrusb2-i2c-track.h" - - -extern const struct pvr2_i2c_op pvr2_i2c_op_v4l2_init; -extern const struct pvr2_i2c_op pvr2_i2c_op_v4l2_standard; -extern const struct pvr2_i2c_op pvr2_i2c_op_v4l2_radio; -extern const struct pvr2_i2c_op pvr2_i2c_op_v4l2_bcsh; -extern const struct pvr2_i2c_op pvr2_i2c_op_v4l2_volume; -extern const struct pvr2_i2c_op pvr2_i2c_op_v4l2_frequency; -extern const struct pvr2_i2c_op pvr2_i2c_op_v4l2_crop; -extern const struct pvr2_i2c_op pvr2_i2c_op_v4l2_size; -extern const struct pvr2_i2c_op pvr2_i2c_op_v4l2_audiomode; -extern const struct pvr2_i2c_op pvr2_i2c_op_v4l2_log; - -void pvr2_v4l2_cmd_stream(struct pvr2_i2c_client *,int); -void pvr2_v4l2_cmd_status_poll(struct pvr2_i2c_client *); - - -#endif /* __PVRUSB2_CMD_V4L2_H */ - -/* - Stuff for Emacs to see, in order to encourage consistent editing style: - *** Local Variables: *** - *** mode: c *** - *** fill-column: 70 *** - *** tab-width: 8 *** - *** c-basic-offset: 8 *** - *** End: *** - */ diff --git a/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c b/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c index 13d016efc0d1..9464862745fa 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c +++ b/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c @@ -20,7 +20,6 @@ #include #include "pvrusb2-i2c-core.h" -#include "pvrusb2-i2c-track.h" #include "pvrusb2-hdw-internal.h" #include "pvrusb2-debug.h" #include "pvrusb2-fx2-cmd.h" @@ -523,13 +522,11 @@ static u32 pvr2_i2c_functionality(struct i2c_adapter *adap) static int pvr2_i2c_attach_inform(struct i2c_client *client) { - pvr2_i2c_track_attach_inform(client); return 0; } static int pvr2_i2c_detach_inform(struct i2c_client *client) { - pvr2_i2c_track_detach_inform(client); return 0; } @@ -607,7 +604,6 @@ void pvr2_i2c_core_init(struct pvr2_hdw *hdw) hdw->i2c_adap.dev.parent = &hdw->usb_dev->dev; hdw->i2c_adap.algo = &hdw->i2c_algo; hdw->i2c_adap.algo_data = hdw; - hdw->i2c_adap.class = I2C_CLASS_TV_ANALOG; hdw->i2c_linked = !0; i2c_set_adapdata(&hdw->i2c_adap, &hdw->v4l2_dev); i2c_add_adapter(&hdw->i2c_adap); diff --git a/drivers/media/video/pvrusb2/pvrusb2-i2c-track.c b/drivers/media/video/pvrusb2/pvrusb2-i2c-track.c deleted file mode 100644 index d0682c13b02a..000000000000 --- a/drivers/media/video/pvrusb2/pvrusb2-i2c-track.c +++ /dev/null @@ -1,503 +0,0 @@ -/* - * - * - * Copyright (C) 2005 Mike Isely - * - * 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 - * - * 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 - * - */ - -#include "pvrusb2-i2c-track.h" -#include "pvrusb2-hdw-internal.h" -#include "pvrusb2-debug.h" -#include "pvrusb2-fx2-cmd.h" -#include "pvrusb2.h" - -#define trace_i2c(...) pvr2_trace(PVR2_TRACE_I2C,__VA_ARGS__) - - -/* - - This module implements the foundation of a rather large architecture for - tracking state in all the various V4L I2C modules. This is obsolete with - kernels later than roughly 2.6.24, but it is still present in the - standalone pvrusb2 driver to allow continued operation with older - kernel. - -*/ - -static unsigned int pvr2_i2c_client_describe(struct pvr2_i2c_client *cp, - unsigned int detail, - char *buf,unsigned int maxlen); - -static int pvr2_i2c_core_singleton(struct i2c_client *cp, - unsigned int cmd,void *arg) -{ - int stat; - if (!cp) return -EINVAL; - if (!(cp->driver)) return -EINVAL; - if (!(cp->driver->command)) return -EINVAL; - if (!try_module_get(cp->driver->driver.owner)) return -EAGAIN; - stat = cp->driver->command(cp,cmd,arg); - module_put(cp->driver->driver.owner); - return stat; -} - -int pvr2_i2c_client_cmd(struct pvr2_i2c_client *cp,unsigned int cmd,void *arg) -{ - int stat; - if (pvrusb2_debug & PVR2_TRACE_I2C_CMD) { - char buf[100]; - unsigned int cnt; - cnt = pvr2_i2c_client_describe(cp,PVR2_I2C_DETAIL_DEBUG, - buf,sizeof(buf)); - pvr2_trace(PVR2_TRACE_I2C_CMD, - "i2c COMMAND (code=%u 0x%x) to %.*s", - cmd,cmd,cnt,buf); - } - stat = pvr2_i2c_core_singleton(cp->client,cmd,arg); - if (pvrusb2_debug & PVR2_TRACE_I2C_CMD) { - char buf[100]; - unsigned int cnt; - cnt = pvr2_i2c_client_describe(cp,PVR2_I2C_DETAIL_DEBUG, - buf,sizeof(buf)); - pvr2_trace(PVR2_TRACE_I2C_CMD, - "i2c COMMAND to %.*s (ret=%d)",cnt,buf,stat); - } - return stat; -} - -int pvr2_i2c_core_cmd(struct pvr2_hdw *hdw,unsigned int cmd,void *arg) -{ - struct pvr2_i2c_client *cp, *ncp; - int stat = -EINVAL; - - if (!hdw) return stat; - - mutex_lock(&hdw->i2c_list_lock); - list_for_each_entry_safe(cp, ncp, &hdw->i2c_clients, list) { - if (!cp->recv_enable) continue; - mutex_unlock(&hdw->i2c_list_lock); - stat = pvr2_i2c_client_cmd(cp,cmd,arg); - mutex_lock(&hdw->i2c_list_lock); - } - mutex_unlock(&hdw->i2c_list_lock); - return stat; -} - - -static int handler_check(struct pvr2_i2c_client *cp) -{ - struct pvr2_i2c_handler *hp = cp->handler; - if (!hp) return 0; - if (!hp->func_table->check) return 0; - return hp->func_table->check(hp->func_data) != 0; -} - -#define BUFSIZE 500 - - -void pvr2_i2c_core_status_poll(struct pvr2_hdw *hdw) -{ - struct pvr2_i2c_client *cp; - mutex_lock(&hdw->i2c_list_lock); do { - list_for_each_entry(cp, &hdw->i2c_clients, list) { - if (!cp->detected_flag) continue; - if (!cp->status_poll) continue; - cp->status_poll(cp); - } - } while (0); mutex_unlock(&hdw->i2c_list_lock); -} - - -/* Issue various I2C operations to bring chip-level drivers into sync with - state stored in this driver. */ -void pvr2_i2c_core_sync(struct pvr2_hdw *hdw) -{ - unsigned long msk; - unsigned int idx; - struct pvr2_i2c_client *cp, *ncp; - - if (!hdw->i2c_linked) return; - if (!(hdw->i2c_pend_types & PVR2_I2C_PEND_ALL)) { - return; - } - mutex_lock(&hdw->i2c_list_lock); do { - pvr2_trace(PVR2_TRACE_I2C_CORE,"i2c: core_sync BEGIN"); - if (hdw->i2c_pend_types & PVR2_I2C_PEND_DETECT) { - /* One or more I2C clients have attached since we - last synced. So scan the list and identify the - new clients. */ - char *buf; - unsigned int cnt; - unsigned long amask = 0; - buf = kmalloc(BUFSIZE,GFP_KERNEL); - pvr2_trace(PVR2_TRACE_I2C_CORE,"i2c: PEND_DETECT"); - hdw->i2c_pend_types &= ~PVR2_I2C_PEND_DETECT; - list_for_each_entry(cp, &hdw->i2c_clients, list) { - if (!cp->detected_flag) { - cp->ctl_mask = 0; - pvr2_i2c_probe(hdw,cp); - cp->detected_flag = !0; - msk = cp->ctl_mask; - cnt = 0; - if (buf) { - cnt = pvr2_i2c_client_describe( - cp, - PVR2_I2C_DETAIL_ALL, - buf,BUFSIZE); - } - trace_i2c("Probed: %.*s",cnt,buf); - if (handler_check(cp)) { - hdw->i2c_pend_types |= - PVR2_I2C_PEND_CLIENT; - } - cp->pend_mask = msk; - hdw->i2c_pend_mask |= msk; - hdw->i2c_pend_types |= - PVR2_I2C_PEND_REFRESH; - } - amask |= cp->ctl_mask; - } - hdw->i2c_active_mask = amask; - if (buf) kfree(buf); - } - if (hdw->i2c_pend_types & PVR2_I2C_PEND_STALE) { - /* Need to do one or more global updates. Arrange - for this to happen. */ - unsigned long m2; - pvr2_trace(PVR2_TRACE_I2C_CORE, - "i2c: PEND_STALE (0x%lx)", - hdw->i2c_stale_mask); - hdw->i2c_pend_types &= ~PVR2_I2C_PEND_STALE; - list_for_each_entry(cp, &hdw->i2c_clients, list) { - m2 = hdw->i2c_stale_mask; - m2 &= cp->ctl_mask; - m2 &= ~cp->pend_mask; - if (m2) { - pvr2_trace(PVR2_TRACE_I2C_CORE, - "i2c: cp=%p setting 0x%lx", - cp,m2); - cp->pend_mask |= m2; - } - } - hdw->i2c_pend_mask |= hdw->i2c_stale_mask; - hdw->i2c_stale_mask = 0; - hdw->i2c_pend_types |= PVR2_I2C_PEND_REFRESH; - } - if (hdw->i2c_pend_types & PVR2_I2C_PEND_CLIENT) { - /* One or more client handlers are asking for an - update. Run through the list of known clients - and update each one. */ - pvr2_trace(PVR2_TRACE_I2C_CORE,"i2c: PEND_CLIENT"); - hdw->i2c_pend_types &= ~PVR2_I2C_PEND_CLIENT; - list_for_each_entry_safe(cp, ncp, &hdw->i2c_clients, - list) { - if (!cp->handler) continue; - if (!cp->handler->func_table->update) continue; - pvr2_trace(PVR2_TRACE_I2C_CORE, - "i2c: cp=%p update",cp); - mutex_unlock(&hdw->i2c_list_lock); - cp->handler->func_table->update( - cp->handler->func_data); - mutex_lock(&hdw->i2c_list_lock); - /* If client's update function set some - additional pending bits, account for that - here. */ - if (cp->pend_mask & ~hdw->i2c_pend_mask) { - hdw->i2c_pend_mask |= cp->pend_mask; - hdw->i2c_pend_types |= - PVR2_I2C_PEND_REFRESH; - } - } - } - if (hdw->i2c_pend_types & PVR2_I2C_PEND_REFRESH) { - const struct pvr2_i2c_op *opf; - unsigned long pm; - /* Some actual updates are pending. Walk through - each update type and perform it. */ - pvr2_trace(PVR2_TRACE_I2C_CORE,"i2c: PEND_REFRESH" - " (0x%lx)",hdw->i2c_pend_mask); - hdw->i2c_pend_types &= ~PVR2_I2C_PEND_REFRESH; - pm = hdw->i2c_pend_mask; - hdw->i2c_pend_mask = 0; - for (idx = 0, msk = 1; pm; idx++, msk <<= 1) { - if (!(pm & msk)) continue; - pm &= ~msk; - list_for_each_entry(cp, &hdw->i2c_clients, - list) { - if (cp->pend_mask & msk) { - cp->pend_mask &= ~msk; - cp->recv_enable = !0; - } else { - cp->recv_enable = 0; - } - } - opf = pvr2_i2c_get_op(idx); - if (!opf) continue; - mutex_unlock(&hdw->i2c_list_lock); - opf->update(hdw); - mutex_lock(&hdw->i2c_list_lock); - } - } - pvr2_trace(PVR2_TRACE_I2C_CORE,"i2c: core_sync END"); - } while (0); mutex_unlock(&hdw->i2c_list_lock); -} - -int pvr2_i2c_core_check_stale(struct pvr2_hdw *hdw) -{ - unsigned long msk,sm,pm; - unsigned int idx; - const struct pvr2_i2c_op *opf; - struct pvr2_i2c_client *cp; - unsigned int pt = 0; - - pvr2_trace(PVR2_TRACE_I2C_CORE,"pvr2_i2c_core_check_stale BEGIN"); - - pm = hdw->i2c_active_mask; - sm = 0; - for (idx = 0, msk = 1; pm; idx++, msk <<= 1) { - if (!(msk & pm)) continue; - pm &= ~msk; - opf = pvr2_i2c_get_op(idx); - if (!(opf && opf->check)) continue; - if (opf->check(hdw)) { - sm |= msk; - } - } - if (sm) pt |= PVR2_I2C_PEND_STALE; - - list_for_each_entry(cp, &hdw->i2c_clients, list) - if (handler_check(cp)) - pt |= PVR2_I2C_PEND_CLIENT; - - if (pt) { - mutex_lock(&hdw->i2c_list_lock); do { - hdw->i2c_pend_types |= pt; - hdw->i2c_stale_mask |= sm; - hdw->i2c_pend_mask |= hdw->i2c_stale_mask; - } while (0); mutex_unlock(&hdw->i2c_list_lock); - } - - pvr2_trace(PVR2_TRACE_I2C_CORE, - "i2c: types=0x%x stale=0x%lx pend=0x%lx", - hdw->i2c_pend_types, - hdw->i2c_stale_mask, - hdw->i2c_pend_mask); - pvr2_trace(PVR2_TRACE_I2C_CORE,"pvr2_i2c_core_check_stale END"); - - return (hdw->i2c_pend_types & PVR2_I2C_PEND_ALL) != 0; -} - -static unsigned int pvr2_i2c_client_describe(struct pvr2_i2c_client *cp, - unsigned int detail, - char *buf,unsigned int maxlen) -{ - unsigned int ccnt,bcnt; - int spcfl = 0; - const struct pvr2_i2c_op *opf; - - ccnt = 0; - if (detail & PVR2_I2C_DETAIL_DEBUG) { - bcnt = scnprintf(buf,maxlen, - "ctxt=%p ctl_mask=0x%lx", - cp,cp->ctl_mask); - ccnt += bcnt; buf += bcnt; maxlen -= bcnt; - spcfl = !0; - } - bcnt = scnprintf(buf,maxlen, - "%s%s @ 0x%x", - (spcfl ? " " : ""), - cp->client->name, - cp->client->addr); - ccnt += bcnt; buf += bcnt; maxlen -= bcnt; - if ((detail & PVR2_I2C_DETAIL_HANDLER) && - cp->handler && cp->handler->func_table->describe) { - bcnt = scnprintf(buf,maxlen," ("); - ccnt += bcnt; buf += bcnt; maxlen -= bcnt; - bcnt = cp->handler->func_table->describe( - cp->handler->func_data,buf,maxlen); - ccnt += bcnt; buf += bcnt; maxlen -= bcnt; - bcnt = scnprintf(buf,maxlen,")"); - ccnt += bcnt; buf += bcnt; maxlen -= bcnt; - } - if ((detail & PVR2_I2C_DETAIL_CTLMASK) && cp->ctl_mask) { - unsigned int idx; - unsigned long msk,sm; - - bcnt = scnprintf(buf,maxlen," ["); - ccnt += bcnt; buf += bcnt; maxlen -= bcnt; - sm = 0; - spcfl = 0; - for (idx = 0, msk = 1; msk; idx++, msk <<= 1) { - if (!(cp->ctl_mask & msk)) continue; - opf = pvr2_i2c_get_op(idx); - if (opf) { - bcnt = scnprintf(buf,maxlen,"%s%s", - spcfl ? " " : "", - opf->name); - ccnt += bcnt; buf += bcnt; maxlen -= bcnt; - spcfl = !0; - } else { - sm |= msk; - } - } - if (sm) { - bcnt = scnprintf(buf,maxlen,"%s%lx", - idx != 0 ? " " : "",sm); - ccnt += bcnt; buf += bcnt; maxlen -= bcnt; - } - bcnt = scnprintf(buf,maxlen,"]"); - ccnt += bcnt; buf += bcnt; maxlen -= bcnt; - } - return ccnt; -} - -unsigned int pvr2_i2c_report(struct pvr2_hdw *hdw, - char *buf,unsigned int maxlen) -{ - unsigned int ccnt,bcnt; - struct pvr2_i2c_client *cp; - ccnt = 0; - mutex_lock(&hdw->i2c_list_lock); do { - list_for_each_entry(cp, &hdw->i2c_clients, list) { - bcnt = pvr2_i2c_client_describe( - cp, - (PVR2_I2C_DETAIL_HANDLER| - PVR2_I2C_DETAIL_CTLMASK), - buf,maxlen); - ccnt += bcnt; buf += bcnt; maxlen -= bcnt; - bcnt = scnprintf(buf,maxlen,"\n"); - ccnt += bcnt; buf += bcnt; maxlen -= bcnt; - } - } while (0); mutex_unlock(&hdw->i2c_list_lock); - return ccnt; -} - -void pvr2_i2c_track_attach_inform(struct i2c_client *client) -{ - struct pvr2_hdw *hdw = (struct pvr2_hdw *)(client->adapter->algo_data); - struct pvr2_i2c_client *cp; - int fl = !(hdw->i2c_pend_types & PVR2_I2C_PEND_ALL); - cp = kzalloc(sizeof(*cp),GFP_KERNEL); - trace_i2c("i2c_attach [client=%s @ 0x%x ctxt=%p]", - client->name, - client->addr,cp); - if (!cp) { - pvr2_trace(PVR2_TRACE_ERROR_LEGS, - "Unable to allocate tracking memory for incoming" - " i2c module; ignoring module. This is likely" - " going to be a problem."); - return; - } - cp->hdw = hdw; - INIT_LIST_HEAD(&cp->list); - cp->client = client; - mutex_lock(&hdw->i2c_list_lock); do { - hdw->cropcap_stale = !0; - list_add_tail(&cp->list,&hdw->i2c_clients); - hdw->i2c_pend_types |= PVR2_I2C_PEND_DETECT; - } while (0); mutex_unlock(&hdw->i2c_list_lock); - if (fl) queue_work(hdw->workqueue,&hdw->worki2csync); -} - -static void pvr2_i2c_client_disconnect(struct pvr2_i2c_client *cp) -{ - if (cp->handler && cp->handler->func_table->detach) { - cp->handler->func_table->detach(cp->handler->func_data); - } - list_del(&cp->list); - kfree(cp); -} - -void pvr2_i2c_track_detach_inform(struct i2c_client *client) -{ - struct pvr2_hdw *hdw = (struct pvr2_hdw *)(client->adapter->algo_data); - struct pvr2_i2c_client *cp, *ncp; - unsigned long amask = 0; - int foundfl = 0; - mutex_lock(&hdw->i2c_list_lock); - hdw->cropcap_stale = !0; - list_for_each_entry_safe(cp, ncp, &hdw->i2c_clients, list) { - if (cp->client == client) { - trace_i2c("pvr2_i2c_detach" - " [client=%s @ 0x%x ctxt=%p]", - client->name, - client->addr, cp); - pvr2_i2c_client_disconnect(cp); - foundfl = !0; - continue; - } - amask |= cp->ctl_mask; - } - hdw->i2c_active_mask = amask; - mutex_unlock(&hdw->i2c_list_lock); - if (!foundfl) { - trace_i2c("pvr2_i2c_detach [client=%s @ 0x%x ctxt=]", - client->name, client->addr); - } -} - -/* This function is used to remove an i2c client from our tracking - structure if the client happens to be the specified v4l2 sub-device. - The idea here is to ensure that sub-devices are not also tracked with - the old tracking mechanism - it's one or the other not both. This is - only for debugging. In a "real" environment, only one of these two - mechanisms should even be compiled in. But by enabling both we can - incrementally test control of each sub-device. */ -void pvr2_i2c_untrack_subdev(struct pvr2_hdw *hdw, struct v4l2_subdev *sd) -{ - struct i2c_client *client; - struct pvr2_i2c_client *cp, *ncp; - unsigned long amask = 0; - mutex_lock(&hdw->i2c_list_lock); - list_for_each_entry_safe(cp, ncp, &hdw->i2c_clients, list) { - client = cp->client; - if (i2c_get_clientdata(client) == sd) { - trace_i2c("pvr2_i2c_detach (subdev active)" - " [client=%s @ 0x%x ctxt=%p]", - client->name, client->addr, cp); - pvr2_i2c_client_disconnect(cp); - continue; - } - amask |= cp->ctl_mask; - } - hdw->i2c_active_mask = amask; - mutex_unlock(&hdw->i2c_list_lock); -} - -void pvr2_i2c_track_init(struct pvr2_hdw *hdw) -{ - hdw->i2c_pend_mask = 0; - hdw->i2c_stale_mask = 0; - hdw->i2c_active_mask = 0; - INIT_LIST_HEAD(&hdw->i2c_clients); - mutex_init(&hdw->i2c_list_lock); -} - -void pvr2_i2c_track_done(struct pvr2_hdw *hdw) -{ - /* Empty for now */ -} - - -/* - Stuff for Emacs to see, in order to encourage consistent editing style: - *** Local Variables: *** - *** mode: c *** - *** fill-column: 75 *** - *** tab-width: 8 *** - *** c-basic-offset: 8 *** - *** End: *** - */ diff --git a/drivers/media/video/pvrusb2/pvrusb2-i2c-track.h b/drivers/media/video/pvrusb2/pvrusb2-i2c-track.h deleted file mode 100644 index eba48e4c9585..000000000000 --- a/drivers/media/video/pvrusb2/pvrusb2-i2c-track.h +++ /dev/null @@ -1,102 +0,0 @@ -/* - * - * - * Copyright (C) 2005 Mike Isely - * - * 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 - * - * 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 - * - */ -#ifndef __PVRUSB2_I2C_TRACK_H -#define __PVRUSB2_I2C_TRACK_H - -#include -#include -#include - - -struct pvr2_hdw; -struct pvr2_i2c_client; -struct pvr2_i2c_handler; -struct pvr2_i2c_handler_functions; -struct pvr2_i2c_op; -struct pvr2_i2c_op_functions; - -struct pvr2_i2c_client { - struct i2c_client *client; - struct pvr2_i2c_handler *handler; - struct list_head list; - struct pvr2_hdw *hdw; - int detected_flag; - int recv_enable; - unsigned long pend_mask; - unsigned long ctl_mask; - void (*status_poll)(struct pvr2_i2c_client *); -}; - -struct pvr2_i2c_handler { - void *func_data; - const struct pvr2_i2c_handler_functions *func_table; -}; - -struct pvr2_i2c_handler_functions { - void (*detach)(void *); - int (*check)(void *); - void (*update)(void *); - unsigned int (*describe)(void *,char *,unsigned int); -}; - -struct pvr2_i2c_op { - int (*check)(struct pvr2_hdw *); - void (*update)(struct pvr2_hdw *); - const char *name; -}; - -void pvr2_i2c_track_init(struct pvr2_hdw *); -void pvr2_i2c_track_done(struct pvr2_hdw *); -void pvr2_i2c_track_attach_inform(struct i2c_client *); -void pvr2_i2c_track_detach_inform(struct i2c_client *); - -int pvr2_i2c_client_cmd(struct pvr2_i2c_client *,unsigned int cmd,void *arg); -int pvr2_i2c_core_cmd(struct pvr2_hdw *,unsigned int cmd,void *arg); - -int pvr2_i2c_core_check_stale(struct pvr2_hdw *); -void pvr2_i2c_core_sync(struct pvr2_hdw *); -void pvr2_i2c_core_status_poll(struct pvr2_hdw *); -unsigned int pvr2_i2c_report(struct pvr2_hdw *,char *buf,unsigned int maxlen); -#define PVR2_I2C_DETAIL_DEBUG 0x0001 -#define PVR2_I2C_DETAIL_HANDLER 0x0002 -#define PVR2_I2C_DETAIL_CTLMASK 0x0004 -#define PVR2_I2C_DETAIL_ALL (\ - PVR2_I2C_DETAIL_DEBUG |\ - PVR2_I2C_DETAIL_HANDLER |\ - PVR2_I2C_DETAIL_CTLMASK) - -void pvr2_i2c_probe(struct pvr2_hdw *,struct pvr2_i2c_client *); -const struct pvr2_i2c_op *pvr2_i2c_get_op(unsigned int idx); - -void pvr2_i2c_untrack_subdev(struct pvr2_hdw *, struct v4l2_subdev *sd); - - -#endif /* __PVRUSB2_I2C_CORE_H */ - - -/* - Stuff for Emacs to see, in order to encourage consistent editing style: - *** Local Variables: *** - *** mode: c *** - *** fill-column: 75 *** - *** tab-width: 8 *** - *** c-basic-offset: 8 *** - *** End: *** - */ diff --git a/drivers/media/video/pvrusb2/pvrusb2-tuner.c b/drivers/media/video/pvrusb2/pvrusb2-tuner.c deleted file mode 100644 index ee9c9c139a85..000000000000 --- a/drivers/media/video/pvrusb2/pvrusb2-tuner.c +++ /dev/null @@ -1,121 +0,0 @@ -/* - * - * - * Copyright (C) 2005 Mike Isely - * Copyright (C) 2004 Aurelien Alleaume - * - * 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 - * - * 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 - * - */ - -#include "pvrusb2.h" -#include "pvrusb2-util.h" -#include "pvrusb2-tuner.h" -#include "pvrusb2-hdw-internal.h" -#include "pvrusb2-debug.h" -#include -#include -#include - - -struct pvr2_tuner_handler { - struct pvr2_hdw *hdw; - struct pvr2_i2c_client *client; - struct pvr2_i2c_handler i2c_handler; - int type_update_fl; -}; - - -static void set_type(struct pvr2_tuner_handler *ctxt) -{ - struct pvr2_hdw *hdw = ctxt->hdw; - struct tuner_setup setup; - pvr2_trace(PVR2_TRACE_CHIPS,"i2c tuner set_type(%d)",hdw->tuner_type); - if (((int)(hdw->tuner_type)) < 0) return; - - setup.addr = ADDR_UNSET; - setup.type = hdw->tuner_type; - setup.mode_mask = T_RADIO | T_ANALOG_TV; - /* We may really want mode_mask to be T_ANALOG_TV for now */ - pvr2_i2c_client_cmd(ctxt->client,TUNER_SET_TYPE_ADDR,&setup); - ctxt->type_update_fl = 0; -} - - -static int tuner_check(struct pvr2_tuner_handler *ctxt) -{ - struct pvr2_hdw *hdw = ctxt->hdw; - if (hdw->tuner_updated) ctxt->type_update_fl = !0; - return ctxt->type_update_fl != 0; -} - - -static void tuner_update(struct pvr2_tuner_handler *ctxt) -{ - if (ctxt->type_update_fl) set_type(ctxt); -} - - -static void pvr2_tuner_detach(struct pvr2_tuner_handler *ctxt) -{ - ctxt->client->handler = NULL; - kfree(ctxt); -} - - -static unsigned int pvr2_tuner_describe(struct pvr2_tuner_handler *ctxt,char *buf,unsigned int cnt) -{ - return scnprintf(buf,cnt,"handler: pvrusb2-tuner"); -} - - -static const struct pvr2_i2c_handler_functions tuner_funcs = { - .detach = (void (*)(void *))pvr2_tuner_detach, - .check = (int (*)(void *))tuner_check, - .update = (void (*)(void *))tuner_update, - .describe = (unsigned int (*)(void *,char *,unsigned int))pvr2_tuner_describe, -}; - - -int pvr2_i2c_tuner_setup(struct pvr2_hdw *hdw,struct pvr2_i2c_client *cp) -{ - struct pvr2_tuner_handler *ctxt; - if (cp->handler) return 0; - - ctxt = kzalloc(sizeof(*ctxt),GFP_KERNEL); - if (!ctxt) return 0; - - ctxt->i2c_handler.func_data = ctxt; - ctxt->i2c_handler.func_table = &tuner_funcs; - ctxt->type_update_fl = !0; - ctxt->client = cp; - ctxt->hdw = hdw; - cp->handler = &ctxt->i2c_handler; - pvr2_trace(PVR2_TRACE_CHIPS,"i2c 0x%x tuner handler set up", - cp->client->addr); - return !0; -} - - - - -/* - Stuff for Emacs to see, in order to encourage consistent editing style: - *** Local Variables: *** - *** mode: c *** - *** fill-column: 70 *** - *** tab-width: 8 *** - *** c-basic-offset: 8 *** - *** End: *** - */ diff --git a/drivers/media/video/pvrusb2/pvrusb2-tuner.h b/drivers/media/video/pvrusb2/pvrusb2-tuner.h deleted file mode 100644 index 3643e2c7880f..000000000000 --- a/drivers/media/video/pvrusb2/pvrusb2-tuner.h +++ /dev/null @@ -1,37 +0,0 @@ -/* - * - * - * Copyright (C) 2005 Mike Isely - * - * 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 - * - * 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 - * - */ -#ifndef __PVRUSB2_TUNER_H -#define __PVRUSB2_TUNER_H - -#include "pvrusb2-i2c-track.h" - -int pvr2_i2c_tuner_setup(struct pvr2_hdw *,struct pvr2_i2c_client *); - -#endif /* __PVRUSB2_TUNER_H */ - -/* - Stuff for Emacs to see, in order to encourage consistent editing style: - *** Local Variables: *** - *** mode: c *** - *** fill-column: 70 *** - *** tab-width: 8 *** - *** c-basic-offset: 8 *** - *** End: *** - */ diff --git a/drivers/media/video/pvrusb2/pvrusb2-video-v4l.c b/drivers/media/video/pvrusb2/pvrusb2-video-v4l.c index 4e0c0881b7b1..ce8332dd9cc9 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-video-v4l.c +++ b/drivers/media/video/pvrusb2/pvrusb2-video-v4l.c @@ -30,7 +30,6 @@ #include "pvrusb2-video-v4l.h" -#include "pvrusb2-i2c-cmd-v4l2.h" #include "pvrusb2-hdw-internal.h" #include "pvrusb2-debug.h" @@ -62,191 +61,6 @@ static const struct routing_scheme routing_schemes[] = { }, }; -struct pvr2_v4l_decoder { - struct pvr2_i2c_handler handler; - struct pvr2_decoder_ctrl ctrl; - struct pvr2_i2c_client *client; - struct pvr2_hdw *hdw; - unsigned long stale_mask; -}; - - - -static void set_input(struct pvr2_v4l_decoder *ctxt) -{ - struct pvr2_hdw *hdw = ctxt->hdw; - struct v4l2_routing route; - const struct routing_scheme *sp; - unsigned int sid = hdw->hdw_desc->signal_routing_scheme; - - pvr2_trace(PVR2_TRACE_CHIPS,"i2c v4l2 set_input(%d)",hdw->input_val); - - if ((sid < ARRAY_SIZE(routing_schemes)) && - ((sp = routing_schemes + sid) != NULL) && - (hdw->input_val >= 0) && - (hdw->input_val < sp->cnt)) { - route.input = sp->def[hdw->input_val]; - } else { - pvr2_trace(PVR2_TRACE_ERROR_LEGS, - "*** WARNING *** i2c v4l2 set_input:" - " Invalid routing scheme (%u) and/or input (%d)", - sid,hdw->input_val); - return; - } - - route.output = 0; - pvr2_i2c_client_cmd(ctxt->client,VIDIOC_INT_S_VIDEO_ROUTING,&route); -} - - -static int check_input(struct pvr2_v4l_decoder *ctxt) -{ - struct pvr2_hdw *hdw = ctxt->hdw; - return hdw->input_dirty != 0; -} - - -static void set_audio(struct pvr2_v4l_decoder *ctxt) -{ - u32 val; - struct pvr2_hdw *hdw = ctxt->hdw; - - pvr2_trace(PVR2_TRACE_CHIPS,"i2c v4l2 set_audio %d", - hdw->srate_val); - switch (hdw->srate_val) { - default: - case V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000: - val = 48000; - break; - case V4L2_MPEG_AUDIO_SAMPLING_FREQ_44100: - val = 44100; - break; - case V4L2_MPEG_AUDIO_SAMPLING_FREQ_32000: - val = 32000; - break; - } - pvr2_i2c_client_cmd(ctxt->client,VIDIOC_INT_AUDIO_CLOCK_FREQ,&val); -} - - -static int check_audio(struct pvr2_v4l_decoder *ctxt) -{ - struct pvr2_hdw *hdw = ctxt->hdw; - return hdw->srate_dirty != 0; -} - - -struct pvr2_v4l_decoder_ops { - void (*update)(struct pvr2_v4l_decoder *); - int (*check)(struct pvr2_v4l_decoder *); -}; - - -static const struct pvr2_v4l_decoder_ops decoder_ops[] = { - { .update = set_input, .check = check_input}, - { .update = set_audio, .check = check_audio}, -}; - - -static void decoder_detach(struct pvr2_v4l_decoder *ctxt) -{ - ctxt->client->handler = NULL; - pvr2_hdw_set_decoder(ctxt->hdw,NULL); - kfree(ctxt); -} - - -static int decoder_check(struct pvr2_v4l_decoder *ctxt) -{ - unsigned long msk; - unsigned int idx; - - for (idx = 0; idx < ARRAY_SIZE(decoder_ops); idx++) { - msk = 1 << idx; - if (ctxt->stale_mask & msk) continue; - if (decoder_ops[idx].check(ctxt)) { - ctxt->stale_mask |= msk; - } - } - return ctxt->stale_mask != 0; -} - - -static void decoder_update(struct pvr2_v4l_decoder *ctxt) -{ - unsigned long msk; - unsigned int idx; - - for (idx = 0; idx < ARRAY_SIZE(decoder_ops); idx++) { - msk = 1 << idx; - if (!(ctxt->stale_mask & msk)) continue; - ctxt->stale_mask &= ~msk; - decoder_ops[idx].update(ctxt); - } -} - - -static int decoder_detect(struct pvr2_i2c_client *cp) -{ - /* Attempt to query the decoder - let's see if it will answer */ - struct v4l2_tuner vt; - int ret; - - memset(&vt,0,sizeof(vt)); - ret = pvr2_i2c_client_cmd(cp,VIDIOC_G_TUNER,&vt); - return ret == 0; /* Return true if it answered */ -} - - -static void decoder_enable(struct pvr2_v4l_decoder *ctxt,int fl) -{ - pvr2_trace(PVR2_TRACE_CHIPS,"i2c v4l2 decoder_enable(%d)",fl); - pvr2_v4l2_cmd_stream(ctxt->client,fl); -} - - -static unsigned int decoder_describe(struct pvr2_v4l_decoder *ctxt,char *buf,unsigned int cnt) -{ - return scnprintf(buf,cnt,"handler: pvrusb2-video-v4l"); -} - - -static const struct pvr2_i2c_handler_functions hfuncs = { - .detach = (void (*)(void *))decoder_detach, - .check = (int (*)(void *))decoder_check, - .update = (void (*)(void *))decoder_update, - .describe = (unsigned int (*)(void *,char *,unsigned int))decoder_describe, -}; - - -int pvr2_i2c_decoder_v4l_setup(struct pvr2_hdw *hdw, - struct pvr2_i2c_client *cp) -{ - struct pvr2_v4l_decoder *ctxt; - - if (hdw->decoder_ctrl) return 0; - if (cp->handler) return 0; - if (!decoder_detect(cp)) return 0; - - ctxt = kzalloc(sizeof(*ctxt),GFP_KERNEL); - if (!ctxt) return 0; - - ctxt->handler.func_data = ctxt; - ctxt->handler.func_table = &hfuncs; - ctxt->ctrl.ctxt = ctxt; - ctxt->ctrl.detach = (void (*)(void *))decoder_detach; - ctxt->ctrl.enable = (void (*)(void *,int))decoder_enable; - ctxt->client = cp; - ctxt->hdw = hdw; - ctxt->stale_mask = (1 << ARRAY_SIZE(decoder_ops)) - 1; - pvr2_hdw_set_decoder(hdw,&ctxt->ctrl); - cp->handler = &ctxt->handler; - pvr2_trace(PVR2_TRACE_CHIPS,"i2c 0x%x saa711x V4L2 handler set up", - cp->client->addr); - return !0; -} - - void pvr2_saa7115_subdev_update(struct pvr2_hdw *hdw, struct v4l2_subdev *sd) { if (hdw->input_dirty || hdw->force_dirty) { diff --git a/drivers/media/video/pvrusb2/pvrusb2-video-v4l.h b/drivers/media/video/pvrusb2/pvrusb2-video-v4l.h index dac4b1ad3664..3b0bd5db602b 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-video-v4l.h +++ b/drivers/media/video/pvrusb2/pvrusb2-video-v4l.h @@ -32,11 +32,6 @@ */ - -#include "pvrusb2-i2c-track.h" - -int pvr2_i2c_decoder_v4l_setup(struct pvr2_hdw *,struct pvr2_i2c_client *); - #include "pvrusb2-hdw-internal.h" void pvr2_saa7115_subdev_update(struct pvr2_hdw *, struct v4l2_subdev *); diff --git a/drivers/media/video/pvrusb2/pvrusb2-wm8775.c b/drivers/media/video/pvrusb2/pvrusb2-wm8775.c index 0068566876ec..1670aa4051ce 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-wm8775.c +++ b/drivers/media/video/pvrusb2/pvrusb2-wm8775.c @@ -27,7 +27,6 @@ */ #include "pvrusb2-wm8775.h" -#include "pvrusb2-i2c-cmd-v4l2.h" #include "pvrusb2-hdw-internal.h" @@ -37,129 +36,6 @@ #include #include - - -struct pvr2_v4l_wm8775 { - struct pvr2_i2c_handler handler; - struct pvr2_i2c_client *client; - struct pvr2_hdw *hdw; - unsigned long stale_mask; -}; - - -static void set_input(struct pvr2_v4l_wm8775 *ctxt) -{ - struct v4l2_routing route; - struct pvr2_hdw *hdw = ctxt->hdw; - - memset(&route,0,sizeof(route)); - - switch(hdw->input_val) { - case PVR2_CVAL_INPUT_RADIO: - route.input = 1; - break; - default: - /* All other cases just use the second input */ - route.input = 2; - break; - } - pvr2_trace(PVR2_TRACE_CHIPS,"i2c wm8775 set_input(val=%d route=0x%x)", - hdw->input_val,route.input); - - pvr2_i2c_client_cmd(ctxt->client,VIDIOC_INT_S_AUDIO_ROUTING,&route); -} - -static int check_input(struct pvr2_v4l_wm8775 *ctxt) -{ - struct pvr2_hdw *hdw = ctxt->hdw; - return hdw->input_dirty != 0; -} - - -struct pvr2_v4l_wm8775_ops { - void (*update)(struct pvr2_v4l_wm8775 *); - int (*check)(struct pvr2_v4l_wm8775 *); -}; - - -static const struct pvr2_v4l_wm8775_ops wm8775_ops[] = { - { .update = set_input, .check = check_input}, -}; - - -static unsigned int wm8775_describe(struct pvr2_v4l_wm8775 *ctxt, - char *buf,unsigned int cnt) -{ - return scnprintf(buf,cnt,"handler: pvrusb2-wm8775"); -} - - -static void wm8775_detach(struct pvr2_v4l_wm8775 *ctxt) -{ - ctxt->client->handler = NULL; - kfree(ctxt); -} - - -static int wm8775_check(struct pvr2_v4l_wm8775 *ctxt) -{ - unsigned long msk; - unsigned int idx; - - for (idx = 0; idx < ARRAY_SIZE(wm8775_ops); idx++) { - msk = 1 << idx; - if (ctxt->stale_mask & msk) continue; - if (wm8775_ops[idx].check(ctxt)) { - ctxt->stale_mask |= msk; - } - } - return ctxt->stale_mask != 0; -} - - -static void wm8775_update(struct pvr2_v4l_wm8775 *ctxt) -{ - unsigned long msk; - unsigned int idx; - - for (idx = 0; idx < ARRAY_SIZE(wm8775_ops); idx++) { - msk = 1 << idx; - if (!(ctxt->stale_mask & msk)) continue; - ctxt->stale_mask &= ~msk; - wm8775_ops[idx].update(ctxt); - } -} - - -static const struct pvr2_i2c_handler_functions hfuncs = { - .detach = (void (*)(void *))wm8775_detach, - .check = (int (*)(void *))wm8775_check, - .update = (void (*)(void *))wm8775_update, - .describe = (unsigned int (*)(void *,char *,unsigned int))wm8775_describe, -}; - - -int pvr2_i2c_wm8775_setup(struct pvr2_hdw *hdw,struct pvr2_i2c_client *cp) -{ - struct pvr2_v4l_wm8775 *ctxt; - - if (cp->handler) return 0; - - ctxt = kzalloc(sizeof(*ctxt),GFP_KERNEL); - if (!ctxt) return 0; - - ctxt->handler.func_data = ctxt; - ctxt->handler.func_table = &hfuncs; - ctxt->client = cp; - ctxt->hdw = hdw; - ctxt->stale_mask = (1 << ARRAY_SIZE(wm8775_ops)) - 1; - cp->handler = &ctxt->handler; - pvr2_trace(PVR2_TRACE_CHIPS,"i2c 0x%x wm8775 V4L2 handler set up", - cp->client->addr); - return !0; -} - - void pvr2_wm8775_subdev_update(struct pvr2_hdw *hdw, struct v4l2_subdev *sd) { if (hdw->input_dirty || hdw->force_dirty) { diff --git a/drivers/media/video/pvrusb2/pvrusb2-wm8775.h b/drivers/media/video/pvrusb2/pvrusb2-wm8775.h index a304988b1e79..0577bc7246fb 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-wm8775.h +++ b/drivers/media/video/pvrusb2/pvrusb2-wm8775.h @@ -34,9 +34,6 @@ -#include "pvrusb2-i2c-track.h" - -int pvr2_i2c_wm8775_setup(struct pvr2_hdw *,struct pvr2_i2c_client *); #include "pvrusb2-hdw-internal.h" void pvr2_wm8775_subdev_update(struct pvr2_hdw *, struct v4l2_subdev *sd); -- cgit v1.2.3 From defeb0b94b6acf929e82b66dbc1fcb48b9204c70 Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Sun, 8 Mar 2009 19:14:07 -0300 Subject: V4L/DVB (11205): pvrusb2: Remove ancient IVTV specific ioctl functions Remove ancient IVTV_IOC_G_CODEC and IVTV_IOC_S_CODEC ioctl functions from the pvrusb2 driver. These are very very old, were non-standard, and were only present to keep MythTV happy (their implementation did nothing except to report success). That was long ago; no recent versions of MythTV should require this anymore. Signed-off-by: Mike Isely Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/pvrusb2/pvrusb2-v4l2.c | 4 ---- 1 file changed, 4 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/pvrusb2/pvrusb2-v4l2.c b/drivers/media/video/pvrusb2/pvrusb2-v4l2.c index b7caf135ed55..9e0f2b07b93b 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-v4l2.c +++ b/drivers/media/video/pvrusb2/pvrusb2-v4l2.c @@ -952,10 +952,6 @@ static long pvr2_v4l2_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { -/* Temporary hack : use ivtv api until a v4l2 one is available. */ -#define IVTV_IOC_G_CODEC 0xFFEE7703 -#define IVTV_IOC_S_CODEC 0xFFEE7704 - if (cmd == IVTV_IOC_G_CODEC || cmd == IVTV_IOC_S_CODEC) return 0; return video_usercopy(file, cmd, arg, pvr2_v4l2_do_ioctl); } -- cgit v1.2.3 From bb65242aa374e7ebcd32672bc9a0b890bd9117bb Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Sat, 14 Mar 2009 14:09:04 -0300 Subject: V4L/DVB (11206): pvrusb2: Add sub-device for demod Forgot to include the tda9887 component when moving to v4l2-subdev. I got fooled because its name is "tuner", the same as the tuner module. Silly me. Signed-off-by: Mike Isely Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/pvrusb2/pvrusb2-devattr.c | 2 ++ drivers/media/video/pvrusb2/pvrusb2-devattr.h | 1 + drivers/media/video/pvrusb2/pvrusb2-hdw.c | 2 ++ 3 files changed, 5 insertions(+) (limited to 'drivers/media/video') diff --git a/drivers/media/video/pvrusb2/pvrusb2-devattr.c b/drivers/media/video/pvrusb2/pvrusb2-devattr.c index e6c876f3a35a..7483c1746079 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-devattr.c +++ b/drivers/media/video/pvrusb2/pvrusb2-devattr.c @@ -50,6 +50,7 @@ static const struct pvr2_device_client_desc pvr2_cli_29xxx[] = { { .module_id = PVR2_CLIENT_ID_SAA7115 }, { .module_id = PVR2_CLIENT_ID_MSP3400 }, { .module_id = PVR2_CLIENT_ID_TUNER }, + { .module_id = PVR2_CLIENT_ID_DEMOD }, }; static const char *pvr2_fw1_names_29xxx[] = { @@ -81,6 +82,7 @@ static const struct pvr2_device_client_desc pvr2_cli_24xxx[] = { { .module_id = PVR2_CLIENT_ID_CX25840 }, { .module_id = PVR2_CLIENT_ID_TUNER }, { .module_id = PVR2_CLIENT_ID_WM8775 }, + { .module_id = PVR2_CLIENT_ID_DEMOD }, }; static const char *pvr2_fw1_names_24xxx[] = { diff --git a/drivers/media/video/pvrusb2/pvrusb2-devattr.h b/drivers/media/video/pvrusb2/pvrusb2-devattr.h index ed9cdedcc71b..13a59c4f9584 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-devattr.h +++ b/drivers/media/video/pvrusb2/pvrusb2-devattr.h @@ -40,6 +40,7 @@ #define PVR2_CLIENT_ID_TUNER 4 #define PVR2_CLIENT_ID_CS53L32A 5 #define PVR2_CLIENT_ID_WM8775 6 +#define PVR2_CLIENT_ID_DEMOD 7 struct pvr2_device_client_desc { /* One ovr PVR2_CLIENT_ID_xxxx */ diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/drivers/media/video/pvrusb2/pvrusb2-hdw.c index 7c66779b1f42..b8a2d332c6d0 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-hdw.c +++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.c @@ -123,6 +123,7 @@ static const char *module_names[] = { [PVR2_CLIENT_ID_CX25840] = "cx25840", [PVR2_CLIENT_ID_SAA7115] = "saa7115", [PVR2_CLIENT_ID_TUNER] = "tuner", + [PVR2_CLIENT_ID_DEMOD] = "tuner", [PVR2_CLIENT_ID_CS53L32A] = "cs53l32a", [PVR2_CLIENT_ID_WM8775] = "wm8775", }; @@ -130,6 +131,7 @@ static const char *module_names[] = { static const unsigned char *module_i2c_addresses[] = { [PVR2_CLIENT_ID_TUNER] = "\x60\x61\x62\x63", + [PVR2_CLIENT_ID_DEMOD] = "\x43", [PVR2_CLIENT_ID_MSP3400] = "\x40", [PVR2_CLIENT_ID_SAA7115] = "\x21", [PVR2_CLIENT_ID_WM8775] = "\x1b", -- cgit v1.2.3 From 2a6b627f8b4594987390ac35d3b344a96af3cfc9 Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Sun, 15 Mar 2009 17:53:29 -0300 Subject: V4L/DVB (11207): pvrusb2: Add composite and s-video input support for OnAir devices Signed-off-by: Mike Isely Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/pvrusb2/Makefile | 1 + drivers/media/video/pvrusb2/pvrusb2-cs53l32a.c | 95 +++++++++++++++++++++++++ drivers/media/video/pvrusb2/pvrusb2-cs53l32a.h | 48 +++++++++++++ drivers/media/video/pvrusb2/pvrusb2-devattr.c | 4 +- drivers/media/video/pvrusb2/pvrusb2-devattr.h | 1 + drivers/media/video/pvrusb2/pvrusb2-hdw.c | 2 + drivers/media/video/pvrusb2/pvrusb2-video-v4l.c | 11 +++ 7 files changed, 160 insertions(+), 2 deletions(-) create mode 100644 drivers/media/video/pvrusb2/pvrusb2-cs53l32a.c create mode 100644 drivers/media/video/pvrusb2/pvrusb2-cs53l32a.h (limited to 'drivers/media/video') diff --git a/drivers/media/video/pvrusb2/Makefile b/drivers/media/video/pvrusb2/Makefile index a4478618a7fc..de2fc14f043b 100644 --- a/drivers/media/video/pvrusb2/Makefile +++ b/drivers/media/video/pvrusb2/Makefile @@ -10,6 +10,7 @@ pvrusb2-objs := pvrusb2-i2c-core.o \ pvrusb2-ctrl.o pvrusb2-std.o pvrusb2-devattr.o \ pvrusb2-context.o pvrusb2-io.o pvrusb2-ioread.o \ pvrusb2-cx2584x-v4l.o pvrusb2-wm8775.o \ + pvrusb2-cs53l32a.o \ $(obj-pvrusb2-dvb-y) \ $(obj-pvrusb2-sysfs-y) $(obj-pvrusb2-debugifc-y) diff --git a/drivers/media/video/pvrusb2/pvrusb2-cs53l32a.c b/drivers/media/video/pvrusb2/pvrusb2-cs53l32a.c new file mode 100644 index 000000000000..b5c3428ebb9f --- /dev/null +++ b/drivers/media/video/pvrusb2/pvrusb2-cs53l32a.c @@ -0,0 +1,95 @@ +/* + * + * + * Copyright (C) 2005 Mike Isely + * Copyright (C) 2004 Aurelien Alleaume + * + * 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 + * + * 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 + * + */ + +/* + + This source file is specifically designed to interface with the + v4l-dvb cs53l32a module. + +*/ + +#include "pvrusb2-cs53l32a.h" + + +#include "pvrusb2-hdw-internal.h" +#include "pvrusb2-debug.h" +#include +#include +#include +#include + +struct routing_scheme { + const int *def; + unsigned int cnt; +}; + + +static const int routing_scheme1[] = { + [PVR2_CVAL_INPUT_TV] = 2, /* 1 or 2 seems to work here */ + [PVR2_CVAL_INPUT_RADIO] = 2, + [PVR2_CVAL_INPUT_COMPOSITE] = 0, + [PVR2_CVAL_INPUT_SVIDEO] = 0, +}; + +static const struct routing_scheme routing_schemes[] = { + [PVR2_ROUTING_SCHEME_ONAIR] = { + .def = routing_scheme1, + .cnt = ARRAY_SIZE(routing_scheme1), + }, +}; + + +void pvr2_cs53l32a_subdev_update(struct pvr2_hdw *hdw, struct v4l2_subdev *sd) +{ + if (hdw->input_dirty || hdw->force_dirty) { + struct v4l2_routing route; + const struct routing_scheme *sp; + unsigned int sid = hdw->hdw_desc->signal_routing_scheme; + pvr2_trace(PVR2_TRACE_CHIPS, "subdev v4l2 set_input(%d)", + hdw->input_val); + if ((sid < ARRAY_SIZE(routing_schemes)) && + ((sp = routing_schemes + sid) != NULL) && + (hdw->input_val >= 0) && + (hdw->input_val < sp->cnt)) { + route.input = sp->def[hdw->input_val]; + } else { + pvr2_trace(PVR2_TRACE_ERROR_LEGS, + "*** WARNING *** subdev v4l2 set_input:" + " Invalid routing scheme (%u)" + " and/or input (%d)", + sid, hdw->input_val); + return; + } + route.output = 0; + sd->ops->audio->s_routing(sd, &route); + } +} + + +/* + Stuff for Emacs to see, in order to encourage consistent editing style: + *** Local Variables: *** + *** mode: c *** + *** fill-column: 70 *** + *** tab-width: 8 *** + *** c-basic-offset: 8 *** + *** End: *** + */ diff --git a/drivers/media/video/pvrusb2/pvrusb2-cs53l32a.h b/drivers/media/video/pvrusb2/pvrusb2-cs53l32a.h new file mode 100644 index 000000000000..53ba548b72a7 --- /dev/null +++ b/drivers/media/video/pvrusb2/pvrusb2-cs53l32a.h @@ -0,0 +1,48 @@ +/* + * + * + * Copyright (C) 2005 Mike Isely + * Copyright (C) 2004 Aurelien Alleaume + * + * 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 + * + * 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 + * + */ + +#ifndef __PVRUSB2_CS53L32A_H +#define __PVRUSB2_CS53L32A_H + +/* + + This module connects the pvrusb2 driver to the I2C chip level + driver which handles device video processing. This interface is + used internally by the driver; higher level code should only + interact through the interface provided by pvrusb2-hdw.h. + +*/ + + +#include "pvrusb2-hdw-internal.h" +void pvr2_cs53l32a_subdev_update(struct pvr2_hdw *, struct v4l2_subdev *); + +#endif /* __PVRUSB2_AUDIO_CS53L32A_H */ + +/* + Stuff for Emacs to see, in order to encourage consistent editing style: + *** Local Variables: *** + *** mode: c *** + *** fill-column: 70 *** + *** tab-width: 8 *** + *** c-basic-offset: 8 *** + *** End: *** + */ diff --git a/drivers/media/video/pvrusb2/pvrusb2-devattr.c b/drivers/media/video/pvrusb2/pvrusb2-devattr.c index 7483c1746079..1cb6a260e8b0 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-devattr.c +++ b/drivers/media/video/pvrusb2/pvrusb2-devattr.c @@ -205,7 +205,7 @@ static const struct pvr2_device_desc pvr2_device_onair_creator = { .flag_has_composite = !0, .flag_has_svideo = !0, .flag_digital_requires_cx23416 = !0, - .signal_routing_scheme = PVR2_ROUTING_SCHEME_HAUPPAUGE, + .signal_routing_scheme = PVR2_ROUTING_SCHEME_ONAIR, .digital_control_scheme = PVR2_DIGITAL_SCHEME_ONAIR, .default_std_mask = V4L2_STD_NTSC_M, #ifdef CONFIG_VIDEO_PVRUSB2_DVB @@ -265,7 +265,7 @@ static const struct pvr2_device_desc pvr2_device_onair_usb2 = { .flag_has_composite = !0, .flag_has_svideo = !0, .flag_digital_requires_cx23416 = !0, - .signal_routing_scheme = PVR2_ROUTING_SCHEME_HAUPPAUGE, + .signal_routing_scheme = PVR2_ROUTING_SCHEME_ONAIR, .digital_control_scheme = PVR2_DIGITAL_SCHEME_ONAIR, .default_std_mask = V4L2_STD_NTSC_M, #ifdef CONFIG_VIDEO_PVRUSB2_DVB diff --git a/drivers/media/video/pvrusb2/pvrusb2-devattr.h b/drivers/media/video/pvrusb2/pvrusb2-devattr.h index 13a59c4f9584..3e553389cbc3 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-devattr.h +++ b/drivers/media/video/pvrusb2/pvrusb2-devattr.h @@ -68,6 +68,7 @@ struct pvr2_string_table { #define PVR2_ROUTING_SCHEME_HAUPPAUGE 0 #define PVR2_ROUTING_SCHEME_GOTVIEW 1 +#define PVR2_ROUTING_SCHEME_ONAIR 2 #define PVR2_DIGITAL_SCHEME_NONE 0 #define PVR2_DIGITAL_SCHEME_HAUPPAUGE 1 diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/drivers/media/video/pvrusb2/pvrusb2-hdw.c index b8a2d332c6d0..e35772125038 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-hdw.c +++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.c @@ -38,6 +38,7 @@ #include "pvrusb2-wm8775.h" #include "pvrusb2-video-v4l.h" #include "pvrusb2-cx2584x-v4l.h" +#include "pvrusb2-cs53l32a.h" #include "pvrusb2-audio.h" #define TV_MIN_FREQ 55250000L @@ -116,6 +117,7 @@ static const pvr2_subdev_update_func pvr2_module_update_functions[] = { [PVR2_CLIENT_ID_SAA7115] = pvr2_saa7115_subdev_update, [PVR2_CLIENT_ID_MSP3400] = pvr2_msp3400_subdev_update, [PVR2_CLIENT_ID_CX25840] = pvr2_cx25840_subdev_update, + [PVR2_CLIENT_ID_CS53L32A] = pvr2_cs53l32a_subdev_update, }; static const char *module_names[] = { diff --git a/drivers/media/video/pvrusb2/pvrusb2-video-v4l.c b/drivers/media/video/pvrusb2/pvrusb2-video-v4l.c index ce8332dd9cc9..b3862f5554bd 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-video-v4l.c +++ b/drivers/media/video/pvrusb2/pvrusb2-video-v4l.c @@ -54,11 +54,22 @@ static const int routing_scheme0[] = { [PVR2_CVAL_INPUT_SVIDEO] = SAA7115_SVIDEO2, }; +static const int routing_scheme1[] = { + [PVR2_CVAL_INPUT_TV] = SAA7115_COMPOSITE4, + [PVR2_CVAL_INPUT_RADIO] = SAA7115_COMPOSITE5, + [PVR2_CVAL_INPUT_COMPOSITE] = SAA7115_COMPOSITE3, + [PVR2_CVAL_INPUT_SVIDEO] = SAA7115_SVIDEO2, /* or SVIDEO0, it seems */ +}; + static const struct routing_scheme routing_schemes[] = { [PVR2_ROUTING_SCHEME_HAUPPAUGE] = { .def = routing_scheme0, .cnt = ARRAY_SIZE(routing_scheme0), }, + [PVR2_ROUTING_SCHEME_ONAIR] = { + .def = routing_scheme1, + .cnt = ARRAY_SIZE(routing_scheme1), + }, }; void pvr2_saa7115_subdev_update(struct pvr2_hdw *hdw, struct v4l2_subdev *sd) -- cgit v1.2.3 From dc070bccde5b0ab2f51124bf67e9a3b40a602cba Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Wed, 25 Mar 2009 00:30:45 -0300 Subject: V4L/DVB (11208): pvrusb2: Use v4l2_device_disconnect() Signed-off-by: Mike Isely Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/pvrusb2/pvrusb2-hdw.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/drivers/media/video/pvrusb2/pvrusb2-hdw.c index e35772125038..7a65b42a4f53 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-hdw.c +++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.c @@ -2672,10 +2672,7 @@ static void pvr2_hdw_remove_usb_stuff(struct pvr2_hdw *hdw) /* If we don't do this, then there will be a dangling struct device reference to our disappearing device persisting inside the V4L core... */ - if (hdw->v4l2_dev.dev) { - dev_set_drvdata(hdw->v4l2_dev.dev, NULL); - hdw->v4l2_dev.dev = NULL; - } + v4l2_device_disconnect(&hdw->v4l2_dev); hdw->usb_dev = NULL; hdw->usb_intf = NULL; pvr2_hdw_render_useless(hdw); -- cgit v1.2.3 From db786a3fde5fca025dc2ea96232e010baf335961 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Mon, 23 Mar 2009 06:03:52 -0300 Subject: V4L/DVB (11209): gspca - vc032x: New sensor mi1320_soc and webcam 15b8:6001 added. Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/vc032x.c | 427 +++++++++++++++++++++++++++++++++++-- 1 file changed, 415 insertions(+), 12 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/gspca/vc032x.c b/drivers/media/video/gspca/vc032x.c index 728fff902f15..cdd17bcf42c7 100644 --- a/drivers/media/video/gspca/vc032x.c +++ b/drivers/media/video/gspca/vc032x.c @@ -43,12 +43,13 @@ struct sd { char sensor; #define SENSOR_HV7131R 0 #define SENSOR_MI0360 1 -#define SENSOR_MI1320 2 -#define SENSOR_MI1310_SOC 3 -#define SENSOR_OV7660 4 -#define SENSOR_OV7670 5 -#define SENSOR_PO1200 6 -#define SENSOR_PO3130NC 7 +#define SENSOR_MI1310_SOC 2 +#define SENSOR_MI1320 3 +#define SENSOR_MI1320_SOC 4 +#define SENSOR_OV7660 5 +#define SENSOR_OV7670 6 +#define SENSOR_PO1200 7 +#define SENSOR_PO3130NC 8 }; /* V4L2 controls supported by the driver */ @@ -149,7 +150,7 @@ static const struct v4l2_pix_format vc0323_mode[] = { .sizeimage = 640 * 480 * 3 / 8 + 590, .colorspace = V4L2_COLORSPACE_JPEG, .priv = 0}, - {1280, 1024, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, /* mi1310_soc only */ + {1280, 1024, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, /* mi13x0_soc only */ .bytesperline = 1280, .sizeimage = 1280 * 1024 * 1 / 4 + 590, .colorspace = V4L2_COLORSPACE_JPEG, @@ -891,6 +892,383 @@ static const __u8 mi1320_initQVGA_data[][4] = { {} }; +static const u8 mi1320_soc_InitVGA_JPG[][4] = { + {0xb3, 0x01, 0x01, 0xcc}, + {0xb0, 0x03, 0x19, 0xcc}, + {0xb0, 0x04, 0x02, 0xcc}, + {0x00, 0x00, 0x30, 0xdd}, + {0xb3, 0x00, 0x64, 0xcc}, + {0xb3, 0x00, 0x67, 0xcc}, + {0xb3, 0x05, 0x01, 0xcc}, + {0xb3, 0x06, 0x01, 0xcc}, + {0xb3, 0x08, 0x01, 0xcc}, + {0xb3, 0x09, 0x0c, 0xcc}, + {0xb3, 0x34, 0x02, 0xcc}, + {0xb3, 0x35, 0xc8, 0xcc}, + {0xb3, 0x02, 0x00, 0xcc}, + {0xb3, 0x03, 0x0a, 0xcc}, + {0xb3, 0x04, 0x05, 0xcc}, + {0xb3, 0x20, 0x00, 0xcc}, + {0xb3, 0x21, 0x00, 0xcc}, + {0xb3, 0x22, 0x01, 0xcc}, + {0xb3, 0x23, 0xe0, 0xcc}, + {0xb3, 0x14, 0x00, 0xcc}, + {0xb3, 0x15, 0x00, 0xcc}, + {0xb3, 0x16, 0x02, 0xcc}, + {0xb3, 0x17, 0x7f, 0xcc}, + {0xb3, 0x00, 0x67, 0xcc}, + {0xb8, 0x00, 0x00, 0xcc}, + {0xbc, 0x00, 0x71, 0xcc}, + {0xbc, 0x01, 0x01, 0xcc}, + {0xb3, 0x5c, 0x01, 0xcc}, + {0xf0, 0x00, 0x02, 0xbb}, + {0x00, 0x00, 0x10, 0xdd}, + {0xc8, 0x00, 0x00, 0xbb}, + {0x00, 0x00, 0x30, 0xdd}, + {0xf0, 0x00, 0x00, 0xbb}, + {0x00, 0x00, 0x10, 0xdd}, + {0x07, 0x00, 0xe0, 0xbb}, + {0x08, 0x00, 0x0b, 0xbb}, + {0x21, 0x00, 0x0c, 0xbb}, + {0x20, 0x01, 0x03, 0xbb}, + {0xb6, 0x00, 0x00, 0xcc}, + {0xb6, 0x03, 0x02, 0xcc}, + {0xb6, 0x02, 0x80, 0xcc}, + {0xb6, 0x05, 0x01, 0xcc}, + {0xb6, 0x04, 0xe0, 0xcc}, + {0xb6, 0x12, 0xf8, 0xcc}, + {0xb6, 0x13, 0x05, 0xcc}, + {0xb6, 0x18, 0x02, 0xcc}, + {0xb6, 0x17, 0x58, 0xcc}, + {0xb6, 0x16, 0x00, 0xcc}, + {0xb6, 0x22, 0x12, 0xcc}, + {0xb6, 0x23, 0x0b, 0xcc}, + {0xbf, 0xc0, 0x39, 0xcc}, + {0xbf, 0xc1, 0x04, 0xcc}, + {0xbf, 0xcc, 0x00, 0xcc}, + {0xb3, 0x01, 0x41, 0xcc}, + {0xf0, 0x00, 0x00, 0xbb}, + {0x05, 0x01, 0x78, 0xbb}, + {0x06, 0x00, 0x11, 0xbb}, + {0x07, 0x01, 0x42, 0xbb}, + {0x08, 0x00, 0x11, 0xbb}, + {0x20, 0x01, 0x03, 0xbb}, + {0x21, 0x80, 0x00, 0xbb}, + {0x22, 0x0d, 0x0f, 0xbb}, + {0x24, 0x80, 0x00, 0xbb}, + {0x59, 0x00, 0xff, 0xbb}, + {0xf0, 0x00, 0x02, 0xbb}, + {0x39, 0x03, 0xca, 0xbb}, + {0x3a, 0x06, 0x80, 0xbb}, + {0x3b, 0x01, 0x52, 0xbb}, + {0x3c, 0x05, 0x40, 0xbb}, + {0x57, 0x01, 0x9c, 0xbb}, + {0x58, 0x01, 0xee, 0xbb}, + {0x59, 0x00, 0xf0, 0xbb}, + {0x5a, 0x01, 0x20, 0xbb}, + {0x5c, 0x1d, 0x17, 0xbb}, + {0x5d, 0x22, 0x1c, 0xbb}, + {0x64, 0x1e, 0x1c, 0xbb}, + {0x5b, 0x00, 0x00, 0xbb}, + {0xf0, 0x00, 0x02, 0xbb}, + {0x22, 0xa0, 0x78, 0xbb}, + {0x23, 0xa0, 0x78, 0xbb}, + {0x24, 0x7f, 0x00, 0xbb}, + {0x28, 0xea, 0x02, 0xbb}, + {0x29, 0x86, 0x7a, 0xbb}, + {0x5e, 0x52, 0x4c, 0xbb}, + {0x5f, 0x20, 0x24, 0xbb}, + {0x60, 0x00, 0x02, 0xbb}, + {0x02, 0x00, 0xee, 0xbb}, + {0x03, 0x39, 0x23, 0xbb}, + {0x04, 0x07, 0x24, 0xbb}, + {0x09, 0x00, 0xc0, 0xbb}, + {0x0a, 0x00, 0x79, 0xbb}, + {0x0b, 0x00, 0x04, 0xbb}, + {0x0c, 0x00, 0x5c, 0xbb}, + {0x0d, 0x00, 0xd9, 0xbb}, + {0x0e, 0x00, 0x53, 0xbb}, + {0x0f, 0x00, 0x21, 0xbb}, + {0x10, 0x00, 0xa4, 0xbb}, + {0x11, 0x00, 0xe5, 0xbb}, + {0x15, 0x00, 0x00, 0xbb}, + {0x16, 0x00, 0x00, 0xbb}, + {0x17, 0x00, 0x00, 0xbb}, + {0x18, 0x00, 0x00, 0xbb}, + {0x19, 0x00, 0x00, 0xbb}, + {0x1a, 0x00, 0x00, 0xbb}, + {0x1b, 0x00, 0x00, 0xbb}, + {0x1c, 0x00, 0x00, 0xbb}, + {0x1d, 0x00, 0x00, 0xbb}, + {0x1e, 0x00, 0x00, 0xbb}, + {0xf0, 0x00, 0x01, 0xbb}, + {0x06, 0xe0, 0x0e, 0xbb}, + {0x06, 0x60, 0x0e, 0xbb}, + {0xb3, 0x5c, 0x01, 0xcc}, + {} +}; +static const u8 mi1320_soc_InitQVGA_JPG[][4] = { + {0xb3, 0x01, 0x01, 0xcc}, + {0xb0, 0x03, 0x19, 0xcc}, + {0xb0, 0x04, 0x02, 0xcc}, + {0x00, 0x00, 0x30, 0xdd}, + {0xb3, 0x00, 0x64, 0xcc}, + {0xb3, 0x00, 0x67, 0xcc}, + {0xb3, 0x05, 0x01, 0xcc}, + {0xb3, 0x06, 0x01, 0xcc}, + {0xb3, 0x08, 0x01, 0xcc}, + {0xb3, 0x09, 0x0c, 0xcc}, + {0xb3, 0x34, 0x02, 0xcc}, + {0xb3, 0x35, 0xc8, 0xcc}, + {0xb3, 0x02, 0x00, 0xcc}, + {0xb3, 0x03, 0x0a, 0xcc}, + {0xb3, 0x04, 0x05, 0xcc}, + {0xb3, 0x20, 0x00, 0xcc}, + {0xb3, 0x21, 0x00, 0xcc}, + {0xb3, 0x22, 0x01, 0xcc}, + {0xb3, 0x23, 0xe0, 0xcc}, + {0xb3, 0x14, 0x00, 0xcc}, + {0xb3, 0x15, 0x00, 0xcc}, + {0xb3, 0x16, 0x02, 0xcc}, + {0xb3, 0x17, 0x7f, 0xcc}, + {0xb3, 0x00, 0x67, 0xcc}, + {0xb8, 0x00, 0x00, 0xcc}, + {0xbc, 0x00, 0xd1, 0xcc}, + {0xbc, 0x01, 0x01, 0xcc}, + {0xb3, 0x5c, 0x01, 0xcc}, + {0xf0, 0x00, 0x02, 0xbb}, + {0x00, 0x00, 0x10, 0xdd}, + {0xc8, 0x00, 0x00, 0xbb}, + {0x00, 0x00, 0x30, 0xdd}, + {0xf0, 0x00, 0x00, 0xbb}, + {0x00, 0x00, 0x10, 0xdd}, + {0x07, 0x00, 0xe0, 0xbb}, + {0x08, 0x00, 0x0b, 0xbb}, + {0x21, 0x00, 0x0c, 0xbb}, + {0x20, 0x01, 0x03, 0xbb}, + {0xb6, 0x00, 0x00, 0xcc}, + {0xb6, 0x03, 0x01, 0xcc}, + {0xb6, 0x02, 0x40, 0xcc}, + {0xb6, 0x05, 0x00, 0xcc}, + {0xb6, 0x04, 0xf0, 0xcc}, + {0xb6, 0x12, 0xf8, 0xcc}, + {0xb6, 0x13, 0x05, 0xcc}, + {0xb6, 0x18, 0x00, 0xcc}, + {0xb6, 0x17, 0x96, 0xcc}, + {0xb6, 0x16, 0x00, 0xcc}, + {0xb6, 0x22, 0x12, 0xcc}, + {0xb6, 0x23, 0x0b, 0xcc}, + {0xbf, 0xc0, 0x39, 0xcc}, + {0xbf, 0xc1, 0x04, 0xcc}, + {0xbf, 0xcc, 0x00, 0xcc}, + {0xbc, 0x02, 0x18, 0xcc}, + {0xbc, 0x03, 0x50, 0xcc}, + {0xbc, 0x04, 0x18, 0xcc}, + {0xbc, 0x05, 0x00, 0xcc}, + {0xbc, 0x06, 0x00, 0xcc}, + {0xbc, 0x08, 0x30, 0xcc}, + {0xbc, 0x09, 0x40, 0xcc}, + {0xbc, 0x0a, 0x10, 0xcc}, + {0xbc, 0x0b, 0x00, 0xcc}, + {0xbc, 0x0c, 0x00, 0xcc}, + {0xb3, 0x01, 0x41, 0xcc}, + {0xf0, 0x00, 0x00, 0xbb}, + {0x05, 0x01, 0x78, 0xbb}, + {0x06, 0x00, 0x11, 0xbb}, + {0x07, 0x01, 0x42, 0xbb}, + {0x08, 0x00, 0x11, 0xbb}, + {0x20, 0x01, 0x03, 0xbb}, + {0x21, 0x80, 0x00, 0xbb}, + {0x22, 0x0d, 0x0f, 0xbb}, + {0x24, 0x80, 0x00, 0xbb}, + {0x59, 0x00, 0xff, 0xbb}, + {0xf0, 0x00, 0x02, 0xbb}, + {0x39, 0x03, 0xca, 0xbb}, + {0x3a, 0x06, 0x80, 0xbb}, + {0x3b, 0x01, 0x52, 0xbb}, + {0x3c, 0x05, 0x40, 0xbb}, + {0x57, 0x01, 0x9c, 0xbb}, + {0x58, 0x01, 0xee, 0xbb}, + {0x59, 0x00, 0xf0, 0xbb}, + {0x5a, 0x01, 0x20, 0xbb}, + {0x5c, 0x1d, 0x17, 0xbb}, + {0x5d, 0x22, 0x1c, 0xbb}, + {0x64, 0x1e, 0x1c, 0xbb}, + {0x5b, 0x00, 0x00, 0xbb}, + {0xf0, 0x00, 0x02, 0xbb}, + {0x22, 0xa0, 0x78, 0xbb}, + {0x23, 0xa0, 0x78, 0xbb}, + {0x24, 0x7f, 0x00, 0xbb}, + {0x28, 0xea, 0x02, 0xbb}, + {0x29, 0x86, 0x7a, 0xbb}, + {0x5e, 0x52, 0x4c, 0xbb}, + {0x5f, 0x20, 0x24, 0xbb}, + {0x60, 0x00, 0x02, 0xbb}, + {0x02, 0x00, 0xee, 0xbb}, + {0x03, 0x39, 0x23, 0xbb}, + {0x04, 0x07, 0x24, 0xbb}, + {0x09, 0x00, 0xc0, 0xbb}, + {0x0a, 0x00, 0x79, 0xbb}, + {0x0b, 0x00, 0x04, 0xbb}, + {0x0c, 0x00, 0x5c, 0xbb}, + {0x0d, 0x00, 0xd9, 0xbb}, + {0x0e, 0x00, 0x53, 0xbb}, + {0x0f, 0x00, 0x21, 0xbb}, + {0x10, 0x00, 0xa4, 0xbb}, + {0x11, 0x00, 0xe5, 0xbb}, + {0x15, 0x00, 0x00, 0xbb}, + {0x16, 0x00, 0x00, 0xbb}, + {0x17, 0x00, 0x00, 0xbb}, + {0x18, 0x00, 0x00, 0xbb}, + {0x19, 0x00, 0x00, 0xbb}, + {0x1a, 0x00, 0x00, 0xbb}, + {0x1b, 0x00, 0x00, 0xbb}, + {0x1c, 0x00, 0x00, 0xbb}, + {0x1d, 0x00, 0x00, 0xbb}, + {0x1e, 0x00, 0x00, 0xbb}, + {0xf0, 0x00, 0x01, 0xbb}, + {0x06, 0xe0, 0x0e, 0xbb}, + {0x06, 0x60, 0x0e, 0xbb}, + {0xb3, 0x5c, 0x01, 0xcc}, + {} +}; +static const u8 mi1320_soc_InitSXGA_JPG[][4] = { + {0xb3, 0x01, 0x01, 0xcc}, + {0xb0, 0x03, 0x19, 0xcc}, + {0xb0, 0x04, 0x02, 0xcc}, + {0x00, 0x00, 0x33, 0xdd}, + {0xb3, 0x00, 0x64, 0xcc}, + {0xb3, 0x00, 0x67, 0xcc}, + {0xb3, 0x05, 0x00, 0xcc}, + {0xb3, 0x06, 0x00, 0xcc}, + {0xb3, 0x08, 0x01, 0xcc}, + {0xb3, 0x09, 0x0c, 0xcc}, + {0xb3, 0x34, 0x02, 0xcc}, + {0xb3, 0x35, 0xc8, 0xcc}, + {0xb3, 0x02, 0x00, 0xcc}, + {0xb3, 0x03, 0x0a, 0xcc}, + {0xb3, 0x04, 0x05, 0xcc}, + {0xb3, 0x20, 0x00, 0xcc}, + {0xb3, 0x21, 0x00, 0xcc}, + {0xb3, 0x22, 0x04, 0xcc}, + {0xb3, 0x23, 0x00, 0xcc}, + {0xb3, 0x14, 0x00, 0xcc}, + {0xb3, 0x15, 0x00, 0xcc}, + {0xb3, 0x16, 0x04, 0xcc}, + {0xb3, 0x17, 0xff, 0xcc}, + {0xb3, 0x00, 0x67, 0xcc}, + {0xbc, 0x00, 0x71, 0xcc}, + {0xbc, 0x01, 0x01, 0xcc}, + {0xf0, 0x00, 0x02, 0xbb}, + {0x00, 0x00, 0x30, 0xdd}, + {0xc8, 0x9f, 0x0b, 0xbb}, + {0x00, 0x00, 0x20, 0xdd}, + {0x5b, 0x00, 0x01, 0xbb}, + {0x00, 0x00, 0x20, 0xdd}, + {0xf0, 0x00, 0x00, 0xbb}, + {0x00, 0x00, 0x30, 0xdd}, + {0x20, 0x01, 0x03, 0xbb}, + {0x00, 0x00, 0x20, 0xdd}, + {0xb6, 0x00, 0x00, 0xcc}, + {0xb6, 0x03, 0x05, 0xcc}, + {0xb6, 0x02, 0x00, 0xcc}, + {0xb6, 0x05, 0x04, 0xcc}, + {0xb6, 0x04, 0x00, 0xcc}, + {0xb6, 0x12, 0xf8, 0xcc}, + {0xb6, 0x13, 0x29, 0xcc}, + {0xb6, 0x18, 0x0a, 0xcc}, + {0xb6, 0x17, 0x00, 0xcc}, + {0xb6, 0x16, 0x00, 0xcc}, + {0xb6, 0x22, 0x12, 0xcc}, + {0xb6, 0x23, 0x0b, 0xcc}, + {0xbf, 0xc0, 0x39, 0xcc}, + {0xbf, 0xc1, 0x04, 0xcc}, + {0xbf, 0xcc, 0x00, 0xcc}, + {0xb3, 0x5c, 0x01, 0xcc}, + {0xb3, 0x01, 0x41, 0xcc}, + {0xf0, 0x00, 0x00, 0xbb}, + {0x05, 0x01, 0x78, 0xbb}, + {0x06, 0x00, 0x11, 0xbb}, + {0x07, 0x01, 0x42, 0xbb}, + {0x08, 0x00, 0x11, 0xbb}, + {0x20, 0x01, 0x03, 0xbb}, + {0x21, 0x80, 0x00, 0xbb}, + {0x22, 0x0d, 0x0f, 0xbb}, + {0x24, 0x80, 0x00, 0xbb}, + {0x59, 0x00, 0xff, 0xbb}, + {0xf0, 0x00, 0x02, 0xbb}, + {0x39, 0x03, 0xca, 0xbb}, + {0x3a, 0x06, 0x80, 0xbb}, + {0x3b, 0x01, 0x52, 0xbb}, + {0x3c, 0x05, 0x40, 0xbb}, + {0x57, 0x01, 0x9c, 0xbb}, + {0x58, 0x01, 0xee, 0xbb}, + {0x59, 0x00, 0xf0, 0xbb}, + {0x5a, 0x01, 0x20, 0xbb}, + {0x5c, 0x1d, 0x17, 0xbb}, + {0x5d, 0x22, 0x1c, 0xbb}, + {0x64, 0x1e, 0x1c, 0xbb}, + {0x5b, 0x00, 0x00, 0xbb}, + {0xf0, 0x00, 0x02, 0xbb}, + {0x22, 0xa0, 0x78, 0xbb}, + {0x23, 0xa0, 0x78, 0xbb}, + {0x24, 0x7f, 0x00, 0xbb}, + {0x28, 0xea, 0x02, 0xbb}, + {0x29, 0x86, 0x7a, 0xbb}, + {0x5e, 0x52, 0x4c, 0xbb}, + {0x5f, 0x20, 0x24, 0xbb}, + {0x60, 0x00, 0x02, 0xbb}, + {0x02, 0x00, 0xee, 0xbb}, + {0x03, 0x39, 0x23, 0xbb}, + {0x04, 0x07, 0x24, 0xbb}, + {0x09, 0x00, 0xc0, 0xbb}, + {0x0a, 0x00, 0x79, 0xbb}, + {0x0b, 0x00, 0x04, 0xbb}, + {0x0c, 0x00, 0x5c, 0xbb}, + {0x0d, 0x00, 0xd9, 0xbb}, + {0x0e, 0x00, 0x53, 0xbb}, + {0x0f, 0x00, 0x21, 0xbb}, + {0x10, 0x00, 0xa4, 0xbb}, + {0x11, 0x00, 0xe5, 0xbb}, + {0x15, 0x00, 0x00, 0xbb}, + {0x16, 0x00, 0x00, 0xbb}, + {0x17, 0x00, 0x00, 0xbb}, + {0x18, 0x00, 0x00, 0xbb}, + {0x19, 0x00, 0x00, 0xbb}, + {0x1a, 0x00, 0x00, 0xbb}, + {0x1b, 0x00, 0x00, 0xbb}, + {0x1c, 0x00, 0x00, 0xbb}, + {0x1d, 0x00, 0x00, 0xbb}, + {0x1e, 0x00, 0x00, 0xbb}, + {0xf0, 0x00, 0x01, 0xbb}, + {0x06, 0xe0, 0x0e, 0xbb}, + {0x06, 0x60, 0x0e, 0xbb}, + {0xb3, 0x5c, 0x01, 0xcc}, + {0xf0, 0x00, 0x00, 0xbb}, + {0x05, 0x01, 0x13, 0xbb}, + {0x06, 0x00, 0x11, 0xbb}, + {0x07, 0x00, 0x85, 0xbb}, + {0x08, 0x00, 0x27, 0xbb}, + {0x20, 0x01, 0x03, 0xbb}, + {0x21, 0x80, 0x00, 0xbb}, + {0x22, 0x0d, 0x0f, 0xbb}, + {0x24, 0x80, 0x00, 0xbb}, + {0x59, 0x00, 0xff, 0xbb}, + {0xf0, 0x00, 0x02, 0xbb}, + {0x39, 0x03, 0x0d, 0xbb}, + {0x3a, 0x06, 0x1b, 0xbb}, + {0x3b, 0x00, 0x95, 0xbb}, + {0x3c, 0x04, 0xdb, 0xbb}, + {0x57, 0x02, 0x00, 0xbb}, + {0x58, 0x02, 0x66, 0xbb}, + {0x59, 0x00, 0xff, 0xbb}, + {0x5a, 0x01, 0x33, 0xbb}, + {0x5c, 0x12, 0x0d, 0xbb}, + {0x5d, 0x16, 0x11, 0xbb}, + {0x64, 0x5e, 0x1c, 0xbb}, + {0x2f, 0x90, 0x00, 0xbb}, + {} +}; static const __u8 po3130_gamma[17] = { 0x00, 0x13, 0x38, 0x59, 0x79, 0x92, 0xa7, 0xb9, 0xc8, 0xd4, 0xdf, 0xe7, 0xee, 0xf4, 0xf9, 0xfc, 0xff @@ -1909,9 +2287,10 @@ static const struct sensor_info sensor_info_data[] = { {-1, 0x80 | 0x2d, 0x00, 0x0000, 0x65, 0x67, 0x01}, {-1, 0x80 | 0x6e, 0x00, 0x0000, 0x24, 0x25, 0x01}, {-1, 0x80 | 0x56, 0x01, 0x0000, 0x64, 0x67, 0x01}, - {-1, 0x80 | 0x48, 0x00, 0x0000, 0x64, 0x67, 0x01}, -/*fixme: not in the ms-win probe - may be found before?*/ + {SENSOR_MI1320_SOC, 0x80 | 0x48, 0x00, 0x148c, 0x64, 0x67, 0x01}, +/*fixme: previously detected?*/ {SENSOR_MI1320, 0x80 | 0x48, 0x00, 0x148c, 0x64, 0x65, 0x01}, +/*fixme: not in the ms-win probe - may be found before?*/ {SENSOR_OV7670, 0x80 | 0x21, 0x0a, 0x7673, 0x66, 0x67, 0x05}, }; @@ -2129,6 +2508,9 @@ static int sd_config(struct gspca_dev *gspca_dev, case SENSOR_MI1320: PDEBUG(D_PROBE, "Find Sensor MI1320"); break; + case SENSOR_MI1320_SOC: + PDEBUG(D_PROBE, "Find Sensor MI1320_SOC"); + break; case SENSOR_OV7660: PDEBUG(D_PROBE, "Find Sensor OV7660"); break; @@ -2150,10 +2532,15 @@ static int sd_config(struct gspca_dev *gspca_dev, } else { if (sensor != SENSOR_PO1200) { cam->cam_mode = vc0323_mode; - if (sd->sensor != SENSOR_MI1310_SOC) + switch (sensor) { + case SENSOR_MI1310_SOC: + case SENSOR_MI1320_SOC: cam->nmodes = ARRAY_SIZE(vc0323_mode); - else /* no SXGA */ + break; + default: /* no SXGA */ cam->nmodes = ARRAY_SIZE(vc0323_mode) - 1; + break; + } } else { cam->cam_mode = svga_mode; cam->nmodes = ARRAY_SIZE(svga_mode); @@ -2313,7 +2700,7 @@ static int sd_start(struct gspca_dev *gspca_dev) init = mi1310_socinitVGA_JPG; /* 640x480 */ break; default: - init = mi1310_soc_InitSXGA_JPG; /* 1280xq024 */ + init = mi1310_soc_InitSXGA_JPG; /* 1280x1024 */ break; } break; @@ -2325,6 +2712,21 @@ static int sd_start(struct gspca_dev *gspca_dev) else init = mi1320_initVGA_data; /* 640x480 */ break; + case SENSOR_MI1320_SOC: + GammaT = mi1320_gamma; + MatrixT = mi1320_matrix; + switch (mode) { + case 1: + init = mi1320_soc_InitQVGA_JPG; /* 320x240 */ + break; + case 0: + init = mi1320_soc_InitVGA_JPG; /* 640x480 */ + break; + default: + init = mi1320_soc_InitSXGA_JPG; /* 1280x1024 */ + break; + } + break; case SENSOR_PO3130NC: GammaT = po3130_gamma; MatrixT = po3130_matrix; @@ -2533,6 +2935,7 @@ static const __devinitdata struct usb_device_id device_table[] = { {USB_DEVICE(0x0ac8, 0x0328), .driver_info = BRIDGE_VC0321}, {USB_DEVICE(0x0ac8, 0xc001), .driver_info = BRIDGE_VC0321}, {USB_DEVICE(0x0ac8, 0xc002), .driver_info = BRIDGE_VC0321}, + {USB_DEVICE(0x15b8, 0x6001), .driver_info = BRIDGE_VC0323}, {USB_DEVICE(0x15b8, 0x6002), .driver_info = BRIDGE_VC0323}, {USB_DEVICE(0x17ef, 0x4802), .driver_info = BRIDGE_VC0323}, {} -- cgit v1.2.3 From 33f5b07e30b1daf98416f2e621a6201f6fff9041 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Wed, 25 Mar 2009 07:04:11 -0300 Subject: V4L/DVB (11211): gspca - vc032x: Simplify the i2c write function. Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/vc032x.c | 24 +++++------------------- 1 file changed, 5 insertions(+), 19 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/gspca/vc032x.c b/drivers/media/video/gspca/vc032x.c index cdd17bcf42c7..8aab2fb95ac6 100644 --- a/drivers/media/video/gspca/vc032x.c +++ b/drivers/media/video/gspca/vc032x.c @@ -2400,33 +2400,19 @@ static int vc032x_probe_sensor(struct gspca_dev *gspca_dev) } static void i2c_write(struct gspca_dev *gspca_dev, - __u8 reg, const __u8 *val, __u8 size) + u8 reg, const u8 *val, + u8 size) /* 1 or 2 */ { struct usb_device *dev = gspca_dev->dev; int retry; -#ifdef GSPCA_DEBUG - if (size > 3 || size < 1) - return; -#endif reg_r(gspca_dev, 0xa1, 0xb33f, 1); +/*fixme:should check if (!(gspca_dev->usb_buf[0] & 0x02)) error*/ reg_w(dev, 0xa0, size, 0xb334); reg_w(dev, 0xa0, reg, 0xb33a); - switch (size) { - case 1: - reg_w(dev, 0xa0, val[0], 0xb336); - break; - case 2: - reg_w(dev, 0xa0, val[0], 0xb336); - reg_w(dev, 0xa0, val[1], 0xb337); - break; - default: -/* case 3: */ - reg_w(dev, 0xa0, val[0], 0xb336); + reg_w(dev, 0xa0, val[0], 0xb336); + if (size > 1) reg_w(dev, 0xa0, val[1], 0xb337); - reg_w(dev, 0xa0, val[2], 0xb338); - break; - } reg_w(dev, 0xa0, 0x01, 0xb339); retry = 4; do { -- cgit v1.2.3 From 58e2ded892cf05023bf533936cadc9d264e8a20f Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Wed, 25 Mar 2009 07:06:29 -0300 Subject: V4L/DVB (11212): gspca - vc032x: Use YVYU format for sensor mi1320_soc. Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/vc032x.c | 442 ++++++++++++++++++++++++++++++++++--- 1 file changed, 412 insertions(+), 30 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/gspca/vc032x.c b/drivers/media/video/gspca/vc032x.c index 8aab2fb95ac6..4c802fb12cd6 100644 --- a/drivers/media/video/gspca/vc032x.c +++ b/drivers/media/video/gspca/vc032x.c @@ -37,6 +37,8 @@ struct sd { __u8 lightfreq; __u8 sharpness; + u8 image_offset; + char bridge; #define BRIDGE_VC0321 0 #define BRIDGE_VC0323 1 @@ -156,7 +158,44 @@ static const struct v4l2_pix_format vc0323_mode[] = { .colorspace = V4L2_COLORSPACE_JPEG, .priv = 2}, }; - +static const struct v4l2_pix_format bi_mode[] = { +/*fixme: jeg does not work + {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, + .bytesperline = 320, + .sizeimage = 320 * 240 * 3 / 8 + 590, + .colorspace = V4L2_COLORSPACE_JPEG, + .priv = 5}, +*/ + {320, 240, V4L2_PIX_FMT_YVYU, V4L2_FIELD_NONE, + .bytesperline = 320, + .sizeimage = 320 * 240 * 2, + .colorspace = V4L2_COLORSPACE_SRGB, + .priv = 4}, +/* + {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, + .bytesperline = 640, + .sizeimage = 640 * 480 * 3 / 8 + 590, + .colorspace = V4L2_COLORSPACE_JPEG, + .priv = 3}, +*/ + {640, 480, V4L2_PIX_FMT_YVYU, V4L2_FIELD_NONE, + .bytesperline = 640, + .sizeimage = 640 * 480 * 2, + .colorspace = V4L2_COLORSPACE_SRGB, + .priv = 2}, +/* + {1280, 1024, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, + .bytesperline = 1280, + .sizeimage = 1280 * 1024 * 1 / 4 + 590, + .colorspace = V4L2_COLORSPACE_JPEG, + .priv = 1}, +*/ + {1280, 1024, V4L2_PIX_FMT_YVYU, V4L2_FIELD_NONE, + .bytesperline = 1280, + .sizeimage = 1280 * 1024 * 2, + .colorspace = V4L2_COLORSPACE_SRGB, + .priv = 0}, +}; static const struct v4l2_pix_format svga_mode[] = { {800, 600, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, .bytesperline = 800, @@ -892,6 +931,109 @@ static const __u8 mi1320_initQVGA_data[][4] = { {} }; +static const u8 mi1320_soc_InitVGA[][4] = { + {0xb3, 0x01, 0x01, 0xcc}, + {0xb0, 0x03, 0x19, 0xcc}, + {0xb0, 0x04, 0x02, 0xcc}, + {0x00, 0x00, 0x30, 0xdd}, + {0xb3, 0x00, 0x64, 0xcc}, + {0xb3, 0x00, 0x67, 0xcc}, + {0xb3, 0x05, 0x01, 0xcc}, + {0xb3, 0x06, 0x01, 0xcc}, + {0xb3, 0x08, 0x01, 0xcc}, + {0xb3, 0x09, 0x0c, 0xcc}, + {0xb3, 0x34, 0x02, 0xcc}, + {0xb3, 0x35, 0xc8, 0xcc}, + {0xb3, 0x02, 0x00, 0xcc}, + {0xb3, 0x03, 0x0a, 0xcc}, + {0xb3, 0x04, 0x05, 0xcc}, + {0xb3, 0x20, 0x00, 0xcc}, + {0xb3, 0x21, 0x00, 0xcc}, + {0xb3, 0x22, 0x01, 0xcc}, + {0xb3, 0x23, 0xe0, 0xcc}, + {0xb3, 0x14, 0x00, 0xcc}, + {0xb3, 0x15, 0x00, 0xcc}, + {0xb3, 0x16, 0x02, 0xcc}, + {0xb3, 0x17, 0x7f, 0xcc}, + {0xb3, 0x00, 0x67, 0xcc}, + {0xb8, 0x00, 0x00, 0xcc}, + {0xbc, 0x00, 0x71, 0xcc}, + {0xbc, 0x01, 0x01, 0xcc}, + {0xb3, 0x5c, 0x01, 0xcc}, + {0xf0, 0x00, 0x02, 0xbb}, + {0x00, 0x00, 0x10, 0xdd}, + {0xc8, 0x00, 0x00, 0xbb}, + {0x00, 0x00, 0x30, 0xdd}, + {0xf0, 0x00, 0x00, 0xbb}, + {0x00, 0x00, 0x10, 0xdd}, + {0x07, 0x00, 0xe0, 0xbb}, + {0x08, 0x00, 0x0b, 0xbb}, + {0x21, 0x00, 0x0c, 0xbb}, + {0x20, 0x01, 0x03, 0xbb}, + {0xbf, 0xc0, 0x26, 0xcc}, + {0xbf, 0xc1, 0x02, 0xcc}, + {0xbf, 0xcc, 0x04, 0xcc}, + {0xb3, 0x01, 0x41, 0xcc}, + {0xf0, 0x00, 0x00, 0xbb}, + {0x05, 0x01, 0x78, 0xbb}, + {0x06, 0x00, 0x11, 0xbb}, + {0x07, 0x01, 0x42, 0xbb}, + {0x08, 0x00, 0x11, 0xbb}, + {0x20, 0x01, 0x03, 0xbb}, + {0x21, 0x80, 0x00, 0xbb}, + {0x22, 0x0d, 0x0f, 0xbb}, + {0x24, 0x80, 0x00, 0xbb}, + {0x59, 0x00, 0xff, 0xbb}, + {0xf0, 0x00, 0x02, 0xbb}, + {0x39, 0x03, 0xca, 0xbb}, + {0x3a, 0x06, 0x80, 0xbb}, + {0x3b, 0x01, 0x52, 0xbb}, + {0x3c, 0x05, 0x40, 0xbb}, + {0x57, 0x01, 0x9c, 0xbb}, + {0x58, 0x01, 0xee, 0xbb}, + {0x59, 0x00, 0xf0, 0xbb}, + {0x5a, 0x01, 0x20, 0xbb}, + {0x5c, 0x1d, 0x17, 0xbb}, + {0x5d, 0x22, 0x1c, 0xbb}, + {0x64, 0x1e, 0x1c, 0xbb}, + {0x5b, 0x00, 0x00, 0xbb}, + {0xf0, 0x00, 0x02, 0xbb}, + {0x22, 0xa0, 0x78, 0xbb}, + {0x23, 0xa0, 0x78, 0xbb}, + {0x24, 0x7f, 0x00, 0xbb}, + {0x28, 0xea, 0x02, 0xbb}, + {0x29, 0x86, 0x7a, 0xbb}, + {0x5e, 0x52, 0x4c, 0xbb}, + {0x5f, 0x20, 0x24, 0xbb}, + {0x60, 0x00, 0x02, 0xbb}, + {0x02, 0x00, 0xee, 0xbb}, + {0x03, 0x39, 0x23, 0xbb}, + {0x04, 0x07, 0x24, 0xbb}, + {0x09, 0x00, 0xc0, 0xbb}, + {0x0a, 0x00, 0x79, 0xbb}, + {0x0b, 0x00, 0x04, 0xbb}, + {0x0c, 0x00, 0x5c, 0xbb}, + {0x0d, 0x00, 0xd9, 0xbb}, + {0x0e, 0x00, 0x53, 0xbb}, + {0x0f, 0x00, 0x21, 0xbb}, + {0x10, 0x00, 0xa4, 0xbb}, + {0x11, 0x00, 0xe5, 0xbb}, + {0x15, 0x00, 0x00, 0xbb}, + {0x16, 0x00, 0x00, 0xbb}, + {0x17, 0x00, 0x00, 0xbb}, + {0x18, 0x00, 0x00, 0xbb}, + {0x19, 0x00, 0x00, 0xbb}, + {0x1a, 0x00, 0x00, 0xbb}, + {0x1b, 0x00, 0x00, 0xbb}, + {0x1c, 0x00, 0x00, 0xbb}, + {0x1d, 0x00, 0x00, 0xbb}, + {0x1e, 0x00, 0x00, 0xbb}, + {0xf0, 0x00, 0x01, 0xbb}, + {0x06, 0xe0, 0x0e, 0xbb}, + {0x06, 0x60, 0x0e, 0xbb}, + {0xb3, 0x5c, 0x01, 0xcc}, + {} +}; static const u8 mi1320_soc_InitVGA_JPG[][4] = { {0xb3, 0x01, 0x01, 0xcc}, {0xb0, 0x03, 0x19, 0xcc}, @@ -1007,6 +1149,119 @@ static const u8 mi1320_soc_InitVGA_JPG[][4] = { {0xb3, 0x5c, 0x01, 0xcc}, {} }; +static const u8 mi1320_soc_InitQVGA[][4] = { + {0xb3, 0x01, 0x01, 0xcc}, + {0xb0, 0x03, 0x19, 0xcc}, + {0xb0, 0x04, 0x02, 0xcc}, + {0x00, 0x00, 0x30, 0xdd}, + {0xb3, 0x00, 0x64, 0xcc}, + {0xb3, 0x00, 0x67, 0xcc}, + {0xb3, 0x05, 0x01, 0xcc}, + {0xb3, 0x06, 0x01, 0xcc}, + {0xb3, 0x08, 0x01, 0xcc}, + {0xb3, 0x09, 0x0c, 0xcc}, + {0xb3, 0x34, 0x02, 0xcc}, + {0xb3, 0x35, 0xc8, 0xcc}, + {0xb3, 0x02, 0x00, 0xcc}, + {0xb3, 0x03, 0x0a, 0xcc}, + {0xb3, 0x04, 0x05, 0xcc}, + {0xb3, 0x20, 0x00, 0xcc}, + {0xb3, 0x21, 0x00, 0xcc}, + {0xb3, 0x22, 0x01, 0xcc}, + {0xb3, 0x23, 0xe0, 0xcc}, + {0xb3, 0x14, 0x00, 0xcc}, + {0xb3, 0x15, 0x00, 0xcc}, + {0xb3, 0x16, 0x02, 0xcc}, + {0xb3, 0x17, 0x7f, 0xcc}, + {0xb3, 0x00, 0x67, 0xcc}, + {0xb8, 0x00, 0x00, 0xcc}, + {0xbc, 0x00, 0xd1, 0xcc}, + {0xbc, 0x01, 0x01, 0xcc}, + {0xb3, 0x5c, 0x01, 0xcc}, + {0xf0, 0x00, 0x02, 0xbb}, + {0x00, 0x00, 0x10, 0xdd}, + {0xc8, 0x00, 0x00, 0xbb}, + {0x00, 0x00, 0x30, 0xdd}, + {0xf0, 0x00, 0x00, 0xbb}, + {0x00, 0x00, 0x10, 0xdd}, + {0x07, 0x00, 0xe0, 0xbb}, + {0x08, 0x00, 0x0b, 0xbb}, + {0x21, 0x00, 0x0c, 0xbb}, + {0x20, 0x01, 0x03, 0xbb}, + {0xbf, 0xc0, 0x26, 0xcc}, + {0xbf, 0xc1, 0x02, 0xcc}, + {0xbf, 0xcc, 0x04, 0xcc}, + {0xbc, 0x02, 0x18, 0xcc}, + {0xbc, 0x03, 0x50, 0xcc}, + {0xbc, 0x04, 0x18, 0xcc}, + {0xbc, 0x05, 0x00, 0xcc}, + {0xbc, 0x06, 0x00, 0xcc}, + {0xbc, 0x08, 0x30, 0xcc}, + {0xbc, 0x09, 0x40, 0xcc}, + {0xbc, 0x0a, 0x10, 0xcc}, + {0xbc, 0x0b, 0x00, 0xcc}, + {0xbc, 0x0c, 0x00, 0xcc}, + {0xb3, 0x01, 0x41, 0xcc}, + {0xf0, 0x00, 0x00, 0xbb}, + {0x05, 0x01, 0x78, 0xbb}, + {0x06, 0x00, 0x11, 0xbb}, + {0x07, 0x01, 0x42, 0xbb}, + {0x08, 0x00, 0x11, 0xbb}, + {0x20, 0x01, 0x03, 0xbb}, + {0x21, 0x80, 0x00, 0xbb}, + {0x22, 0x0d, 0x0f, 0xbb}, + {0x24, 0x80, 0x00, 0xbb}, + {0x59, 0x00, 0xff, 0xbb}, + {0xf0, 0x00, 0x02, 0xbb}, + {0x39, 0x03, 0xca, 0xbb}, + {0x3a, 0x06, 0x80, 0xbb}, + {0x3b, 0x01, 0x52, 0xbb}, + {0x3c, 0x05, 0x40, 0xbb}, + {0x57, 0x01, 0x9c, 0xbb}, + {0x58, 0x01, 0xee, 0xbb}, + {0x59, 0x00, 0xf0, 0xbb}, + {0x5a, 0x01, 0x20, 0xbb}, + {0x5c, 0x1d, 0x17, 0xbb}, + {0x5d, 0x22, 0x1c, 0xbb}, + {0x64, 0x1e, 0x1c, 0xbb}, + {0x5b, 0x00, 0x00, 0xbb}, + {0xf0, 0x00, 0x02, 0xbb}, + {0x22, 0xa0, 0x78, 0xbb}, + {0x23, 0xa0, 0x78, 0xbb}, + {0x24, 0x7f, 0x00, 0xbb}, + {0x28, 0xea, 0x02, 0xbb}, + {0x29, 0x86, 0x7a, 0xbb}, + {0x5e, 0x52, 0x4c, 0xbb}, + {0x5f, 0x20, 0x24, 0xbb}, + {0x60, 0x00, 0x02, 0xbb}, + {0x02, 0x00, 0xee, 0xbb}, + {0x03, 0x39, 0x23, 0xbb}, + {0x04, 0x07, 0x24, 0xbb}, + {0x09, 0x00, 0xc0, 0xbb}, + {0x0a, 0x00, 0x79, 0xbb}, + {0x0b, 0x00, 0x04, 0xbb}, + {0x0c, 0x00, 0x5c, 0xbb}, + {0x0d, 0x00, 0xd9, 0xbb}, + {0x0e, 0x00, 0x53, 0xbb}, + {0x0f, 0x00, 0x21, 0xbb}, + {0x10, 0x00, 0xa4, 0xbb}, + {0x11, 0x00, 0xe5, 0xbb}, + {0x15, 0x00, 0x00, 0xbb}, + {0x16, 0x00, 0x00, 0xbb}, + {0x17, 0x00, 0x00, 0xbb}, + {0x18, 0x00, 0x00, 0xbb}, + {0x19, 0x00, 0x00, 0xbb}, + {0x1a, 0x00, 0x00, 0xbb}, + {0x1b, 0x00, 0x00, 0xbb}, + {0x1c, 0x00, 0x00, 0xbb}, + {0x1d, 0x00, 0x00, 0xbb}, + {0x1e, 0x00, 0x00, 0xbb}, + {0xf0, 0x00, 0x01, 0xbb}, + {0x06, 0xe0, 0x0e, 0xbb}, + {0x06, 0x60, 0x0e, 0xbb}, + {0xb3, 0x5c, 0x01, 0xcc}, + {} +}; static const u8 mi1320_soc_InitQVGA_JPG[][4] = { {0xb3, 0x01, 0x01, 0xcc}, {0xb0, 0x03, 0x19, 0xcc}, @@ -1269,6 +1524,129 @@ static const u8 mi1320_soc_InitSXGA_JPG[][4] = { {0x2f, 0x90, 0x00, 0xbb}, {} }; +static const u8 mi1320_soc_InitSXGA[][4] = { + {0xb3, 0x01, 0x01, 0xcc}, + {0xb0, 0x03, 0x19, 0xcc}, + {0x00, 0x00, 0x30, 0xdd}, + {0xb3, 0x00, 0x64, 0xcc}, + {0xb3, 0x00, 0x67, 0xcc}, + {0xb3, 0x05, 0x01, 0xcc}, + {0xb3, 0x06, 0x01, 0xcc}, + {0xb3, 0x08, 0x01, 0xcc}, + {0xb3, 0x09, 0x0c, 0xcc}, + {0xb3, 0x34, 0x02, 0xcc}, + {0xb3, 0x35, 0xc8, 0xcc}, + {0xb3, 0x02, 0x00, 0xcc}, + {0xb3, 0x03, 0x0a, 0xcc}, + {0xb3, 0x04, 0x05, 0xcc}, + {0xb3, 0x20, 0x00, 0xcc}, + {0xb3, 0x21, 0x00, 0xcc}, + {0xb3, 0x22, 0x04, 0xcc}, + {0xb3, 0x23, 0x00, 0xcc}, + {0xb3, 0x14, 0x00, 0xcc}, + {0xb3, 0x15, 0x00, 0xcc}, + {0xb3, 0x16, 0x04, 0xcc}, + {0xb3, 0x17, 0xff, 0xcc}, + {0xb3, 0x00, 0x67, 0xcc}, + {0xbc, 0x00, 0x71, 0xcc}, + {0xbc, 0x01, 0x01, 0xcc}, + {0xb3, 0x5c, 0x01, 0xcc}, + {0xf0, 0x00, 0x02, 0xbb}, + {0x00, 0x00, 0x30, 0xdd}, + {0xc8, 0x9f, 0x0b, 0xbb}, + {0x00, 0x00, 0x20, 0xdd}, + {0x5b, 0x00, 0x01, 0xbb}, + {0x00, 0x00, 0x20, 0xdd}, + {0xf0, 0x00, 0x00, 0xbb}, + {0x00, 0x00, 0x30, 0xdd}, + {0x20, 0x01, 0x03, 0xbb}, + {0x00, 0x00, 0x20, 0xdd}, + {0xbf, 0xc0, 0x26, 0xcc}, + {0xbf, 0xc1, 0x02, 0xcc}, + {0xbf, 0xcc, 0x04, 0xcc}, + {0xb3, 0x01, 0x41, 0xcc}, + {0xf0, 0x00, 0x00, 0xbb}, + {0x05, 0x01, 0x78, 0xbb}, + {0x06, 0x00, 0x11, 0xbb}, + {0x07, 0x01, 0x42, 0xbb}, + {0x08, 0x00, 0x11, 0xbb}, + {0x20, 0x01, 0x03, 0xbb}, + {0x21, 0x80, 0x00, 0xbb}, + {0x22, 0x0d, 0x0f, 0xbb}, + {0x24, 0x80, 0x00, 0xbb}, + {0x59, 0x00, 0xff, 0xbb}, + {0xf0, 0x00, 0x02, 0xbb}, + {0x39, 0x03, 0xca, 0xbb}, + {0x3a, 0x06, 0x80, 0xbb}, + {0x3b, 0x01, 0x52, 0xbb}, + {0x3c, 0x05, 0x40, 0xbb}, + {0x57, 0x01, 0x9c, 0xbb}, + {0x58, 0x01, 0xee, 0xbb}, + {0x59, 0x00, 0xf0, 0xbb}, + {0x5a, 0x01, 0x20, 0xbb}, + {0x5c, 0x1d, 0x17, 0xbb}, + {0x5d, 0x22, 0x1c, 0xbb}, + {0x64, 0x1e, 0x1c, 0xbb}, + {0x5b, 0x00, 0x00, 0xbb}, + {0xf0, 0x00, 0x02, 0xbb}, + {0x22, 0xa0, 0x78, 0xbb}, + {0x23, 0xa0, 0x78, 0xbb}, + {0x24, 0x7f, 0x00, 0xbb}, + {0x28, 0xea, 0x02, 0xbb}, + {0x29, 0x86, 0x7a, 0xbb}, + {0x5e, 0x52, 0x4c, 0xbb}, + {0x5f, 0x20, 0x24, 0xbb}, + {0x60, 0x00, 0x02, 0xbb}, + {0x02, 0x00, 0xee, 0xbb}, + {0x03, 0x39, 0x23, 0xbb}, + {0x04, 0x07, 0x24, 0xbb}, + {0x09, 0x00, 0xc0, 0xbb}, + {0x0a, 0x00, 0x79, 0xbb}, + {0x0b, 0x00, 0x04, 0xbb}, + {0x0c, 0x00, 0x5c, 0xbb}, + {0x0d, 0x00, 0xd9, 0xbb}, + {0x0e, 0x00, 0x53, 0xbb}, + {0x0f, 0x00, 0x21, 0xbb}, + {0x10, 0x00, 0xa4, 0xbb}, + {0x11, 0x00, 0xe5, 0xbb}, + {0x15, 0x00, 0x00, 0xbb}, + {0x16, 0x00, 0x00, 0xbb}, + {0x17, 0x00, 0x00, 0xbb}, + {0x18, 0x00, 0x00, 0xbb}, + {0x19, 0x00, 0x00, 0xbb}, + {0x1a, 0x00, 0x00, 0xbb}, + {0x1b, 0x00, 0x00, 0xbb}, + {0x1c, 0x00, 0x00, 0xbb}, + {0x1d, 0x00, 0x00, 0xbb}, + {0x1e, 0x00, 0x00, 0xbb}, + {0xf0, 0x00, 0x01, 0xbb}, + {0x06, 0xe0, 0x0e, 0xbb}, + {0x06, 0x60, 0x0e, 0xbb}, + {0xb3, 0x5c, 0x01, 0xcc}, + {0xf0, 0x00, 0x00, 0xbb}, + {0x05, 0x01, 0x13, 0xbb}, + {0x06, 0x00, 0x11, 0xbb}, + {0x07, 0x00, 0x85, 0xbb}, + {0x08, 0x00, 0x27, 0xbb}, + {0x20, 0x01, 0x03, 0xbb}, + {0x21, 0x80, 0x00, 0xbb}, + {0x22, 0x0d, 0x0f, 0xbb}, + {0x24, 0x80, 0x00, 0xbb}, + {0x59, 0x00, 0xff, 0xbb}, + {0xf0, 0x00, 0x02, 0xbb}, + {0x39, 0x03, 0x0d, 0xbb}, + {0x3a, 0x06, 0x1b, 0xbb}, + {0x3b, 0x00, 0x95, 0xbb}, + {0x3c, 0x04, 0xdb, 0xbb}, + {0x57, 0x02, 0x00, 0xbb}, + {0x58, 0x02, 0x66, 0xbb}, + {0x59, 0x00, 0xff, 0xbb}, + {0x5a, 0x01, 0x33, 0xbb}, + {0x5c, 0x12, 0x0d, 0xbb}, + {0x5d, 0x16, 0x11, 0xbb}, + {0x64, 0x5e, 0x1c, 0xbb}, + {} +}; static const __u8 po3130_gamma[17] = { 0x00, 0x13, 0x38, 0x59, 0x79, 0x92, 0xa7, 0xb9, 0xc8, 0xd4, 0xdf, 0xe7, 0xee, 0xf4, 0xf9, 0xfc, 0xff @@ -2516,20 +2894,23 @@ static int sd_config(struct gspca_dev *gspca_dev, cam->cam_mode = vc0321_mode; cam->nmodes = ARRAY_SIZE(vc0321_mode); } else { - if (sensor != SENSOR_PO1200) { - cam->cam_mode = vc0323_mode; - switch (sensor) { - case SENSOR_MI1310_SOC: - case SENSOR_MI1320_SOC: - cam->nmodes = ARRAY_SIZE(vc0323_mode); - break; - default: /* no SXGA */ - cam->nmodes = ARRAY_SIZE(vc0323_mode) - 1; - break; - } - } else { + switch (sensor) { + case SENSOR_PO1200: cam->cam_mode = svga_mode; cam->nmodes = ARRAY_SIZE(svga_mode); + break; + case SENSOR_MI1310_SOC: + cam->cam_mode = vc0323_mode; + cam->nmodes = ARRAY_SIZE(vc0323_mode); + break; + case SENSOR_MI1320_SOC: + cam->cam_mode = bi_mode; + cam->nmodes = ARRAY_SIZE(bi_mode); + break; + default: + cam->cam_mode = vc0323_mode; + cam->nmodes = ARRAY_SIZE(vc0323_mode) - 1; + break; } } @@ -2632,6 +3013,14 @@ static int sd_start(struct gspca_dev *gspca_dev) const __u8 *GammaT = NULL; const __u8 *MatrixT = NULL; int mode; + static const u8 (*mi1320_soc_init[])[4] = { + mi1320_soc_InitSXGA, + mi1320_soc_InitSXGA_JPG, + mi1320_soc_InitVGA, + mi1320_soc_InitVGA_JPG, + mi1320_soc_InitQVGA, + mi1320_soc_InitQVGA_JPG + }; /* Assume start use the good resolution from gspca_dev->mode */ if (sd->bridge == BRIDGE_VC0321) { @@ -2639,6 +3028,13 @@ static int sd_start(struct gspca_dev *gspca_dev) reg_w(gspca_dev->dev, 0xa0, 0xff, 0xbfed); reg_w(gspca_dev->dev, 0xa0, 0xff, 0xbfee); reg_w(gspca_dev->dev, 0xa0, 0xff, 0xbfef); + sd->image_offset = 46; + } else { + if (gspca_dev->cam.cam_mode[gspca_dev->curr_mode].pixelformat + == V4L2_PIX_FMT_JPEG) + sd->image_offset = 0; + else + sd->image_offset = 32; } mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv; @@ -2701,17 +3097,7 @@ static int sd_start(struct gspca_dev *gspca_dev) case SENSOR_MI1320_SOC: GammaT = mi1320_gamma; MatrixT = mi1320_matrix; - switch (mode) { - case 1: - init = mi1320_soc_InitQVGA_JPG; /* 320x240 */ - break; - case 0: - init = mi1320_soc_InitVGA_JPG; /* 640x480 */ - break; - default: - init = mi1320_soc_InitSXGA_JPG; /* 1280x1024 */ - break; - } + init = mi1320_soc_init[mode]; break; case SENSOR_PO3130NC: GammaT = po3130_gamma; @@ -2783,12 +3169,8 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, "vc032x header packet found len %d", len); frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame, data, 0); - if (sd->bridge == BRIDGE_VC0321) { -#define VCHDRSZ 46 - data += VCHDRSZ; - len -= VCHDRSZ; -#undef VCHDRSZ - } + data += sd->image_offset; + len -= sd->image_offset; gspca_frame_add(gspca_dev, FIRST_PACKET, frame, data, len); return; -- cgit v1.2.3 From 14a19c0a2254ba58ed7559e072456ab94c9a2d3c Mon Sep 17 00:00:00 2001 From: Theodore Kilgore Date: Wed, 25 Mar 2009 07:13:13 -0300 Subject: V4L/DVB (11213): gspca - sq905c: New subdriver. The code in the new sq905c.c is based upon the structure of the code in gspca/sq905.c, and upon the code in libgphoto2/camlibs/digigr8, which supports the same set of cameras in stillcam mode. I am a co-author of gspca/sq905.c and I am the sole author of libgphoto2/camlibs/digigr8, which is licensed under the LGPL. I hereby give myself permission to use my own code from libgphoto2 in gspca/sq905c.c. Signed-off-by: Theodore Kilgore Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/Kconfig | 9 + drivers/media/video/gspca/Makefile | 2 + drivers/media/video/gspca/sq905c.c | 328 +++++++++++++++++++++++++++++++++++++ include/linux/videodev2.h | 1 + 4 files changed, 340 insertions(+) create mode 100644 drivers/media/video/gspca/sq905c.c (limited to 'drivers/media/video') diff --git a/drivers/media/video/gspca/Kconfig b/drivers/media/video/gspca/Kconfig index a0f05ef5ca70..578dc4ffc965 100644 --- a/drivers/media/video/gspca/Kconfig +++ b/drivers/media/video/gspca/Kconfig @@ -185,6 +185,15 @@ config USB_GSPCA_SQ905 To compile this driver as a module, choose M here: the module will be called gspca_sq905. +config USB_GSPCA_SQ905C + tristate "SQ Technologies SQ905C based USB Camera Driver" + depends on VIDEO_V4L2 && USB_GSPCA + help + Say Y here if you want support for cameras based on the SQ905C chip. + + To compile this driver as a module, choose M here: the + module will be called gspca_sq905c. + config USB_GSPCA_STK014 tristate "Syntek DV4000 (STK014) USB Camera Driver" depends on VIDEO_V4L2 && USB_GSPCA diff --git a/drivers/media/video/gspca/Makefile b/drivers/media/video/gspca/Makefile index b6ec61185736..8a6643e8eb96 100644 --- a/drivers/media/video/gspca/Makefile +++ b/drivers/media/video/gspca/Makefile @@ -17,6 +17,7 @@ obj-$(CONFIG_USB_GSPCA_SPCA506) += gspca_spca506.o obj-$(CONFIG_USB_GSPCA_SPCA508) += gspca_spca508.o obj-$(CONFIG_USB_GSPCA_SPCA561) += gspca_spca561.o obj-$(CONFIG_USB_GSPCA_SQ905) += gspca_sq905.o +obj-$(CONFIG_USB_GSPCA_SQ905C) += gspca_sq905c.o obj-$(CONFIG_USB_GSPCA_SUNPLUS) += gspca_sunplus.o obj-$(CONFIG_USB_GSPCA_STK014) += gspca_stk014.o obj-$(CONFIG_USB_GSPCA_T613) += gspca_t613.o @@ -43,6 +44,7 @@ gspca_spca506-objs := spca506.o gspca_spca508-objs := spca508.o gspca_spca561-objs := spca561.o gspca_sq905-objs := sq905.o +gspca_sq905c-objs := sq905c.o gspca_stk014-objs := stk014.o gspca_sunplus-objs := sunplus.o gspca_t613-objs := t613.o diff --git a/drivers/media/video/gspca/sq905c.c b/drivers/media/video/gspca/sq905c.c new file mode 100644 index 000000000000..0bcb74a1b143 --- /dev/null +++ b/drivers/media/video/gspca/sq905c.c @@ -0,0 +1,328 @@ +/* + * SQ905C subdriver + * + * Copyright (C) 2009 Theodore Kilgore + * + * 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 + * 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 + */ + +/* + * + * This driver uses work done in + * libgphoto2/camlibs/digigr8, Copyright (C) Theodore Kilgore. + * + * This driver has also used as a base the sq905c driver + * and may contain code fragments from it. + */ + +#define MODULE_NAME "sq905c" + +#include +#include "gspca.h" + +MODULE_AUTHOR("Theodore Kilgore "); +MODULE_DESCRIPTION("GSPCA/SQ905C USB Camera Driver"); +MODULE_LICENSE("GPL"); + +/* Default timeouts, in ms */ +#define SQ905C_CMD_TIMEOUT 500 +#define SQ905C_DATA_TIMEOUT 1000 + +/* Maximum transfer size to use. */ +#define SQ905C_MAX_TRANSFER 0x8000 + +#define FRAME_HEADER_LEN 0x50 + +/* Commands. These go in the "value" slot. */ +#define SQ905C_CLEAR 0xa0 /* clear everything */ +#define SQ905C_CAPTURE_LOW 0xa040 /* Starts capture at 160x120 */ +#define SQ905C_CAPTURE_MED 0x1440 /* Starts capture at 320x240 */ +#define SQ905C_CAPTURE_HI 0x2840 /* Starts capture at 320x240 */ + +/* For capture, this must go in the "index" slot. */ +#define SQ905C_CAPTURE_INDEX 0x110f + +/* Structure to hold all of our device specific stuff */ +struct sd { + struct gspca_dev gspca_dev; /* !! must be the first item */ + const struct v4l2_pix_format *cap_mode; + /* Driver stuff */ + struct work_struct work_struct; + struct workqueue_struct *work_thread; +}; + +/* + * Most of these cameras will do 640x480 and 320x240. 160x120 works + * in theory but gives very poor output. Therefore, not supported. + * The 0x2770:0x9050 cameras have max resolution of 320x240. + */ +static struct v4l2_pix_format sq905c_mode[] = { + { 320, 240, V4L2_PIX_FMT_SQ905C, V4L2_FIELD_NONE, + .bytesperline = 320, + .sizeimage = 320 * 240, + .colorspace = V4L2_COLORSPACE_SRGB, + .priv = 0}, + { 640, 480, V4L2_PIX_FMT_SQ905C, V4L2_FIELD_NONE, + .bytesperline = 640, + .sizeimage = 640 * 480, + .colorspace = V4L2_COLORSPACE_SRGB, + .priv = 0} +}; + +/* Send a command to the camera. */ +static int sq905c_command(struct gspca_dev *gspca_dev, u16 command, u16 index) +{ + int ret; + + ret = usb_control_msg(gspca_dev->dev, + usb_sndctrlpipe(gspca_dev->dev, 0), + USB_REQ_SYNCH_FRAME, /* request */ + USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, + command, index, NULL, 0, + SQ905C_CMD_TIMEOUT); + if (ret < 0) { + PDEBUG(D_ERR, "%s: usb_control_msg failed (%d)", + __func__, ret); + return ret; + } + + return 0; +} + +/* This function is called as a workqueue function and runs whenever the camera + * is streaming data. Because it is a workqueue function it is allowed to sleep + * so we can use synchronous USB calls. To avoid possible collisions with other + * threads attempting to use the camera's USB interface the gspca usb_lock is + * used when performing the one USB control operation inside the workqueue, + * which tells the camera to close the stream. In practice the only thing + * which needs to be protected against is the usb_set_interface call that + * gspca makes during stream_off. Otherwise the camera doesn't provide any + * controls that the user could try to change. + */ +static void sq905c_dostream(struct work_struct *work) +{ + struct sd *dev = container_of(work, struct sd, work_struct); + struct gspca_dev *gspca_dev = &dev->gspca_dev; + struct gspca_frame *frame; + int bytes_left; /* bytes remaining in current frame. */ + int data_len; /* size to use for the next read. */ + int act_len; + int discarding = 0; /* true if we failed to get space for frame. */ + int packet_type; + int ret; + u8 *buffer; + + buffer = kmalloc(SQ905C_MAX_TRANSFER, GFP_KERNEL | GFP_DMA); + if (!buffer) { + PDEBUG(D_ERR, "Couldn't allocate USB buffer"); + goto quit_stream; + } + + while (gspca_dev->present && gspca_dev->streaming) { + if (!gspca_dev->present) + goto quit_stream; + /* Request the header, which tells the size to download */ + ret = usb_bulk_msg(gspca_dev->dev, + usb_rcvbulkpipe(gspca_dev->dev, 0x81), + buffer, FRAME_HEADER_LEN, &act_len, + SQ905C_DATA_TIMEOUT); + PDEBUG(D_STREAM, + "Got %d bytes out of %d for header", + act_len, FRAME_HEADER_LEN); + if (ret < 0 || act_len < FRAME_HEADER_LEN) + goto quit_stream; + /* size is read from 4 bytes starting 0x40, little endian */ + bytes_left = buffer[0x40]|(buffer[0x41]<<8)|(buffer[0x42]<<16) + |(buffer[0x43]<<24); + PDEBUG(D_STREAM, "bytes_left = 0x%x", bytes_left); + /* We keep the header. It has other information, too. */ + packet_type = FIRST_PACKET; + frame = gspca_get_i_frame(gspca_dev); + if (frame && !discarding) { + gspca_frame_add(gspca_dev, packet_type, + frame, buffer, FRAME_HEADER_LEN); + } else + discarding = 1; + while (bytes_left > 0) { + data_len = bytes_left > SQ905C_MAX_TRANSFER ? + SQ905C_MAX_TRANSFER : bytes_left; + if (!gspca_dev->present) + goto quit_stream; + ret = usb_bulk_msg(gspca_dev->dev, + usb_rcvbulkpipe(gspca_dev->dev, 0x81), + buffer, data_len, &act_len, + SQ905C_DATA_TIMEOUT); + if (ret < 0 || act_len < data_len) + goto quit_stream; + PDEBUG(D_STREAM, + "Got %d bytes out of %d for frame", + data_len, bytes_left); + bytes_left -= data_len; + if (bytes_left == 0) + packet_type = LAST_PACKET; + else + packet_type = INTER_PACKET; + frame = gspca_get_i_frame(gspca_dev); + if (frame && !discarding) + gspca_frame_add(gspca_dev, packet_type, + frame, buffer, data_len); + else + discarding = 1; + } + } +quit_stream: + mutex_lock(&gspca_dev->usb_lock); + if (gspca_dev->present) + sq905c_command(gspca_dev, SQ905C_CLEAR, 0); + mutex_unlock(&gspca_dev->usb_lock); + kfree(buffer); +} + +/* This function is called at probe time just before sd_init */ +static int sd_config(struct gspca_dev *gspca_dev, + const struct usb_device_id *id) +{ + struct cam *cam = &gspca_dev->cam; + struct sd *dev = (struct sd *) gspca_dev; + + PDEBUG(D_PROBE, + "SQ9050 camera detected" + " (vid/pid 0x%04X:0x%04X)", id->idVendor, id->idProduct); + cam->cam_mode = sq905c_mode; + cam->nmodes = 2; + if (id->idProduct == 0x9050) + cam->nmodes = 1; + /* We don't use the buffer gspca allocates so make it small. */ + cam->bulk_size = 32; + INIT_WORK(&dev->work_struct, sq905c_dostream); + return 0; +} + +/* called on streamoff with alt==0 and on disconnect */ +/* the usb_lock is held at entry - restore on exit */ +static void sd_stop0(struct gspca_dev *gspca_dev) +{ + struct sd *dev = (struct sd *) gspca_dev; + + /* wait for the work queue to terminate */ + mutex_unlock(&gspca_dev->usb_lock); + /* This waits for sq905c_dostream to finish */ + destroy_workqueue(dev->work_thread); + dev->work_thread = NULL; + mutex_lock(&gspca_dev->usb_lock); +} + +/* this function is called at probe and resume time */ +static int sd_init(struct gspca_dev *gspca_dev) +{ + int ret; + + /* connect to the camera and reset it. */ + ret = sq905c_command(gspca_dev, SQ905C_CLEAR, 0); + return ret; +} + +/* Set up for getting frames. */ +static int sd_start(struct gspca_dev *gspca_dev) +{ + struct sd *dev = (struct sd *) gspca_dev; + int ret; + + dev->cap_mode = gspca_dev->cam.cam_mode; + /* "Open the shutter" and set size, to start capture */ + switch (gspca_dev->width) { + case 640: + PDEBUG(D_STREAM, "Start streaming at high resolution"); + dev->cap_mode++; + ret = sq905c_command(gspca_dev, SQ905C_CAPTURE_HI, + SQ905C_CAPTURE_INDEX); + break; + default: /* 320 */ + PDEBUG(D_STREAM, "Start streaming at medium resolution"); + ret = sq905c_command(gspca_dev, SQ905C_CAPTURE_MED, + SQ905C_CAPTURE_INDEX); + } + + if (ret < 0) { + PDEBUG(D_ERR, "Start streaming command failed"); + return ret; + } + /* Start the workqueue function to do the streaming */ + dev->work_thread = create_singlethread_workqueue(MODULE_NAME); + queue_work(dev->work_thread, &dev->work_struct); + + return 0; +} + +/* Table of supported USB devices */ +static const __devinitdata struct usb_device_id device_table[] = { + {USB_DEVICE(0x2770, 0x905c)}, + {USB_DEVICE(0x2770, 0x9050)}, + {USB_DEVICE(0x2770, 0x913d)}, + {} +}; + +MODULE_DEVICE_TABLE(usb, device_table); + +/* sub-driver description */ +static const struct sd_desc sd_desc = { + .name = MODULE_NAME, + .config = sd_config, + .init = sd_init, + .start = sd_start, + .stop0 = sd_stop0, +}; + +/* -- device connect -- */ +static int sd_probe(struct usb_interface *intf, + const struct usb_device_id *id) +{ + return gspca_dev_probe(intf, id, + &sd_desc, + sizeof(struct sd), + THIS_MODULE); +} + +static struct usb_driver sd_driver = { + .name = MODULE_NAME, + .id_table = device_table, + .probe = sd_probe, + .disconnect = gspca_disconnect, +#ifdef CONFIG_PM + .suspend = gspca_suspend, + .resume = gspca_resume, +#endif +}; + +/* -- module insert / remove -- */ +static int __init sd_mod_init(void) +{ + int ret; + + ret = usb_register(&sd_driver); + if (ret < 0) + return ret; + PDEBUG(D_PROBE, "registered"); + return 0; +} + +static void __exit sd_mod_exit(void) +{ + usb_deregister(&sd_driver); + PDEBUG(D_PROBE, "deregistered"); +} + +module_init(sd_mod_init); +module_exit(sd_mod_exit); diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h index 61f1a4921afd..139d234923cd 100644 --- a/include/linux/videodev2.h +++ b/include/linux/videodev2.h @@ -345,6 +345,7 @@ struct v4l2_pix_format { #define V4L2_PIX_FMT_SPCA561 v4l2_fourcc('S', '5', '6', '1') /* compressed GBRG bayer */ #define V4L2_PIX_FMT_PAC207 v4l2_fourcc('P', '2', '0', '7') /* compressed BGGR bayer */ #define V4L2_PIX_FMT_MR97310A v4l2_fourcc('M', '3', '1', '0') /* compressed BGGR bayer */ +#define V4L2_PIX_FMT_SQ905C v4l2_fourcc('9', '0', '5', 'C') /* compressed RGGB bayer */ #define V4L2_PIX_FMT_PJPG v4l2_fourcc('P', 'J', 'P', 'G') /* Pixart 73xx JPEG */ #define V4L2_PIX_FMT_YVYU v4l2_fourcc('Y', 'V', 'Y', 'U') /* 16 YVU 4:2:2 */ -- cgit v1.2.3 From f6b8332b5e90a8d9c42f224e60900c7eae474388 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Thu, 26 Mar 2009 05:01:48 -0300 Subject: V4L/DVB (11218): gspca - sq905: Update the frame pointer after adding the last packet. Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/sq905.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/gspca/sq905.c b/drivers/media/video/gspca/sq905.c index da60eea51e44..b1d377e495c2 100644 --- a/drivers/media/video/gspca/sq905.c +++ b/drivers/media/video/gspca/sq905.c @@ -270,13 +270,14 @@ static void sq905_dostream(struct work_struct *work) } frame = gspca_get_i_frame(gspca_dev); if (frame && !discarding) { - gspca_frame_add(gspca_dev, packet_type, + frame = gspca_frame_add(gspca_dev, packet_type, frame, data, data_len); /* If entire frame fits in one packet we still need to add a LAST_PACKET */ - if ((packet_type == FIRST_PACKET) && - (bytes_left == 0)) - gspca_frame_add(gspca_dev, LAST_PACKET, + if (packet_type == FIRST_PACKET && + bytes_left == 0) + frame = gspca_frame_add(gspca_dev, + LAST_PACKET, frame, data, 0); } else { discarding = 1; -- cgit v1.2.3 From 67e4542558ee589a5196a29640de1ba1157fb450 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Thu, 26 Mar 2009 05:03:13 -0300 Subject: V4L/DVB (11219): gspca - sq905: Optimize the resolution setting. Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/sq905.c | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/gspca/sq905.c b/drivers/media/video/gspca/sq905.c index b1d377e495c2..04e3ae57a2e3 100644 --- a/drivers/media/video/gspca/sq905.c +++ b/drivers/media/video/gspca/sq905.c @@ -82,8 +82,6 @@ MODULE_LICENSE("GPL"); struct sd { struct gspca_dev gspca_dev; /* !! must be the first item */ - const struct v4l2_pix_format *cap_mode; - /* * Driver stuff */ @@ -218,6 +216,7 @@ static void sq905_dostream(struct work_struct *work) int header_read; /* true if we have already read the frame header. */ int discarding; /* true if we failed to get space for frame. */ int packet_type; + int frame_sz; int ret; u8 *data; u8 *buffer; @@ -229,6 +228,9 @@ static void sq905_dostream(struct work_struct *work) goto quit_stream; } + frame_sz = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].sizeimage + + FRAME_HEADER_LEN; + while (gspca_dev->present && gspca_dev->streaming) { /* Need a short delay to ensure streaming flag was set by * gspca and to make sure gspca can grab the mutex. */ @@ -237,7 +239,7 @@ static void sq905_dostream(struct work_struct *work) /* request some data and then read it until we have * a complete frame. */ - bytes_left = dev->cap_mode->sizeimage + FRAME_HEADER_LEN; + bytes_left = frame_sz; header_read = 0; discarding = 0; @@ -367,21 +369,18 @@ static int sd_start(struct gspca_dev *gspca_dev) struct sd *dev = (struct sd *) gspca_dev; int ret; - /* Set capture mode based on selected resolution. */ - dev->cap_mode = gspca_dev->cam.cam_mode; /* "Open the shutter" and set size, to start capture */ - switch (gspca_dev->width) { - case 640: + switch (gspca_dev->curr_mode) { + default: +/* case 2: */ PDEBUG(D_STREAM, "Start streaming at high resolution"); - dev->cap_mode += 2; ret = sq905_command(&dev->gspca_dev, SQ905_CAPTURE_HIGH); break; - case 320: + case 1: PDEBUG(D_STREAM, "Start streaming at medium resolution"); - dev->cap_mode++; ret = sq905_command(&dev->gspca_dev, SQ905_CAPTURE_MED); break; - default: + case 0: PDEBUG(D_STREAM, "Start streaming at low resolution"); ret = sq905_command(&dev->gspca_dev, SQ905_CAPTURE_LOW); } -- cgit v1.2.3 From c0c4c8937a7e84ab366ed8d8ea8855b57cb698df Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Thu, 26 Mar 2009 05:06:50 -0300 Subject: V4L/DVB (11220): gspca - finepix: Use a workqueue for streaming. Tested-by: Frank Zago Acked-by: Frank Zago Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/finepix.c | 421 ++++++++++++------------------------ 1 file changed, 134 insertions(+), 287 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/gspca/finepix.c b/drivers/media/video/gspca/finepix.c index dc65c363aa87..00e6863ed666 100644 --- a/drivers/media/video/gspca/finepix.c +++ b/drivers/media/video/gspca/finepix.c @@ -27,7 +27,7 @@ MODULE_DESCRIPTION("Fujifilm FinePix USB V4L2 driver"); MODULE_LICENSE("GPL"); /* Default timeout, in ms */ -#define FPIX_TIMEOUT (HZ / 10) +#define FPIX_TIMEOUT 250 /* Maximum transfer size to use. The windows driver reads by chunks of * 0x2000 bytes, so do the same. Note: reading more seems to work @@ -38,38 +38,15 @@ MODULE_LICENSE("GPL"); struct usb_fpix { struct gspca_dev gspca_dev; /* !! must be the first item */ - /* - * USB stuff - */ - struct usb_ctrlrequest ctrlreq; - struct urb *control_urb; - struct timer_list bulk_timer; - - enum { - FPIX_NOP, /* inactive, else streaming */ - FPIX_RESET, /* must reset */ - FPIX_REQ_FRAME, /* requesting a frame */ - FPIX_READ_FRAME, /* reading frame */ - } state; - - /* - * Driver stuff - */ - struct delayed_work wqe; - struct completion can_close; - int streaming; + struct work_struct work_struct; + struct workqueue_struct *work_thread; }; /* Delay after which claim the next frame. If the delay is too small, * the camera will return old frames. On the 4800Z, 20ms is bad, 25ms - * will fail every 4 or 5 frames, but 30ms is perfect. */ -#define NEXT_FRAME_DELAY (((HZ * 30) + 999) / 1000) - -#define dev_new_state(new_state) { \ - PDEBUG(D_STREAM, "new state from %d to %d at %s:%d", \ - dev->state, new_state, __func__, __LINE__); \ - dev->state = new_state; \ -} + * will fail every 4 or 5 frames, but 30ms is perfect. On the A210, + * 30ms is bad while 35ms is perfect. */ +#define NEXT_FRAME_DELAY 35 /* These cameras only support 320x200. */ static const struct v4l2_pix_format fpix_mode[1] = { @@ -80,314 +57,183 @@ static const struct v4l2_pix_format fpix_mode[1] = { .priv = 0} }; -/* Reads part of a frame */ -static void read_frame_part(struct usb_fpix *dev) +/* send a command to the webcam */ +static int command(struct gspca_dev *gspca_dev, + int order) /* 0: reset, 1: frame request */ { - int ret; + static u8 order_values[2][12] = { + {0xc6, 0, 0, 0, 0, 0, 0, 0, 0x20, 0, 0, 0}, /* reset */ + {0xd3, 0, 0, 0, 0, 0, 0, 0x01, 0, 0, 0, 0}, /* fr req */ + }; - PDEBUG(D_STREAM, "read_frame_part"); - - /* Reads part of a frame */ - ret = usb_submit_urb(dev->gspca_dev.urb[0], GFP_ATOMIC); - if (ret) { - dev_new_state(FPIX_RESET); - schedule_delayed_work(&dev->wqe, 1); - PDEBUG(D_STREAM, "usb_submit_urb failed with %d", - ret); - } else { - /* Sometimes we never get a callback, so use a timer. - * Is this masking a bug somewhere else? */ - dev->bulk_timer.expires = jiffies + msecs_to_jiffies(150); - add_timer(&dev->bulk_timer); - } + memcpy(gspca_dev->usb_buf, order_values[order], 12); + return usb_control_msg(gspca_dev->dev, + usb_sndctrlpipe(gspca_dev->dev, 0), + USB_REQ_GET_STATUS, + USB_DIR_OUT | USB_TYPE_CLASS | + USB_RECIP_INTERFACE, 0, 0, gspca_dev->usb_buf, + 12, FPIX_TIMEOUT); } -/* Callback for URBs. */ -static void urb_callback(struct urb *urb) +/* workqueue */ +static void dostream(struct work_struct *work) { - struct gspca_dev *gspca_dev = urb->context; - struct usb_fpix *dev = (struct usb_fpix *) gspca_dev; - - PDEBUG(D_PACK, - "enter urb_callback - status=%d, length=%d", - urb->status, urb->actual_length); - - if (dev->state == FPIX_READ_FRAME) - del_timer(&dev->bulk_timer); - - if (urb->status != 0) { - /* We kill a stuck urb every 50 frames on average, so don't - * display a log message for that. */ - if (urb->status != -ECONNRESET) - PDEBUG(D_STREAM, "bad URB status %d", urb->status); - dev_new_state(FPIX_RESET); - schedule_delayed_work(&dev->wqe, 1); - } - - switch (dev->state) { - case FPIX_REQ_FRAME: - dev_new_state(FPIX_READ_FRAME); - read_frame_part(dev); - break; - - case FPIX_READ_FRAME: { - unsigned char *data = urb->transfer_buffer; - struct gspca_frame *frame; - - frame = gspca_get_i_frame(&dev->gspca_dev); - if (frame == NULL) - gspca_dev->last_packet_type = DISCARD_PACKET; - if (urb->actual_length < FPIX_MAX_TRANSFER || - (data[urb->actual_length-2] == 0xff && - data[urb->actual_length-1] == 0xd9)) { - - /* If the result is less than what was asked - * for, then it's the end of the - * frame. Sometime the jpeg is not complete, - * but there's nothing we can do. We also end - * here if the the jpeg ends right at the end - * of the frame. */ - if (frame) - gspca_frame_add(gspca_dev, LAST_PACKET, - frame, - data, urb->actual_length); - dev_new_state(FPIX_REQ_FRAME); - schedule_delayed_work(&dev->wqe, NEXT_FRAME_DELAY); - } else { + struct usb_fpix *dev = container_of(work, struct usb_fpix, work_struct); + struct gspca_dev *gspca_dev = &dev->gspca_dev; + struct urb *urb = gspca_dev->urb[0]; + u8 *data = urb->transfer_buffer; + struct gspca_frame *frame; + int ret = 0; + int len; + + /* synchronize with the main driver */ + mutex_lock(&gspca_dev->usb_lock); + mutex_unlock(&gspca_dev->usb_lock); + PDEBUG(D_STREAM, "dostream started"); + + /* loop reading a frame */ +again: + while (gspca_dev->present && gspca_dev->streaming) { + + /* request a frame */ + mutex_lock(&gspca_dev->usb_lock); + ret = command(gspca_dev, 1); + mutex_unlock(&gspca_dev->usb_lock); + if (ret < 0) + break; + if (!gspca_dev->present || !gspca_dev->streaming) + break; + + /* the frame comes in parts */ + for (;;) { + ret = usb_bulk_msg(gspca_dev->dev, + urb->pipe, + data, + FPIX_MAX_TRANSFER, + &len, FPIX_TIMEOUT); + if (ret < 0) { + /* Most of the time we get a timeout + * error. Just restart. */ + goto again; + } + if (!gspca_dev->present || !gspca_dev->streaming) + goto out; + frame = gspca_get_i_frame(&dev->gspca_dev); + if (frame == NULL) + gspca_dev->last_packet_type = DISCARD_PACKET; + + if (len < FPIX_MAX_TRANSFER || + (data[len - 2] == 0xff && + data[len - 1] == 0xd9)) { + + /* If the result is less than what was asked + * for, then it's the end of the + * frame. Sometimes the jpeg is not complete, + * but there's nothing we can do. We also end + * here if the the jpeg ends right at the end + * of the frame. */ + if (frame) + frame = gspca_frame_add(gspca_dev, + LAST_PACKET, + frame, + data, len); + break; + } /* got a partial image */ if (frame) gspca_frame_add(gspca_dev, gspca_dev->last_packet_type - == LAST_PACKET + == LAST_PACKET ? FIRST_PACKET : INTER_PACKET, - frame, - data, urb->actual_length); - read_frame_part(dev); + frame, data, len); } - break; - } - - case FPIX_NOP: - case FPIX_RESET: - PDEBUG(D_STREAM, "invalid state %d", dev->state); - break; - } -} - -/* Request a new frame */ -static void request_frame(struct usb_fpix *dev) -{ - int ret; - struct gspca_dev *gspca_dev = &dev->gspca_dev; - /* Setup command packet */ - memset(gspca_dev->usb_buf, 0, 12); - gspca_dev->usb_buf[0] = 0xd3; - gspca_dev->usb_buf[7] = 0x01; - - /* Request a frame */ - dev->ctrlreq.bRequestType = - USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE; - dev->ctrlreq.bRequest = USB_REQ_GET_STATUS; - dev->ctrlreq.wValue = 0; - dev->ctrlreq.wIndex = 0; - dev->ctrlreq.wLength = cpu_to_le16(12); - - usb_fill_control_urb(dev->control_urb, - gspca_dev->dev, - usb_sndctrlpipe(gspca_dev->dev, 0), - (unsigned char *) &dev->ctrlreq, - gspca_dev->usb_buf, - 12, urb_callback, gspca_dev); - - ret = usb_submit_urb(dev->control_urb, GFP_ATOMIC); - if (ret) { - dev_new_state(FPIX_RESET); - schedule_delayed_work(&dev->wqe, 1); - PDEBUG(D_STREAM, "usb_submit_urb failed with %d", ret); + /* We must wait before trying reading the next + * frame. If we don't, or if the delay is too short, + * the camera will disconnect. */ + msleep(NEXT_FRAME_DELAY); } -} - -/*--------------------------------------------------------------------------*/ -/* State machine. */ -static void fpix_sm(struct work_struct *work) -{ - struct usb_fpix *dev = container_of(work, struct usb_fpix, wqe.work); - - PDEBUG(D_STREAM, "fpix_sm state %d", dev->state); - - /* verify that the device wasn't unplugged */ - if (!dev->gspca_dev.present) { - PDEBUG(D_STREAM, "device is gone"); - dev_new_state(FPIX_NOP); - complete(&dev->can_close); - return; - } - - if (!dev->streaming) { - PDEBUG(D_STREAM, "stopping state machine"); - dev_new_state(FPIX_NOP); - complete(&dev->can_close); - return; - } - - switch (dev->state) { - case FPIX_RESET: - dev_new_state(FPIX_REQ_FRAME); - schedule_delayed_work(&dev->wqe, HZ / 10); - break; - - case FPIX_REQ_FRAME: - /* get an image */ - request_frame(dev); - break; - - case FPIX_NOP: - case FPIX_READ_FRAME: - PDEBUG(D_STREAM, "invalid state %d", dev->state); - break; - } +out: + PDEBUG(D_STREAM, "dostream stopped"); } /* this function is called at probe time */ static int sd_config(struct gspca_dev *gspca_dev, const struct usb_device_id *id) { + struct usb_fpix *dev = (struct usb_fpix *) gspca_dev; struct cam *cam = &gspca_dev->cam; cam->cam_mode = fpix_mode; cam->nmodes = 1; cam->bulk_size = FPIX_MAX_TRANSFER; -/* gspca_dev->nbalt = 1; * use bulk transfer */ - return 0; -} - -/* Stop streaming and free the ressources allocated by sd_start. */ -static void sd_stopN(struct gspca_dev *gspca_dev) -{ - struct usb_fpix *dev = (struct usb_fpix *) gspca_dev; + INIT_WORK(&dev->work_struct, dostream); - dev->streaming = 0; - - /* Stop the state machine */ - if (dev->state != FPIX_NOP) - wait_for_completion(&dev->can_close); -} - -/* called on streamoff with alt 0 and disconnect */ -static void sd_stop0(struct gspca_dev *gspca_dev) -{ - struct usb_fpix *dev = (struct usb_fpix *) gspca_dev; - - usb_free_urb(dev->control_urb); - dev->control_urb = NULL; -} - -/* Kill an URB that hasn't completed. */ -static void timeout_kill(unsigned long data) -{ - struct urb *urb = (struct urb *) data; - - usb_unlink_urb(urb); + return 0; } /* this function is called at probe and resume time */ static int sd_init(struct gspca_dev *gspca_dev) { - struct usb_fpix *dev = (struct usb_fpix *) gspca_dev; - - INIT_DELAYED_WORK(&dev->wqe, fpix_sm); - - init_timer(&dev->bulk_timer); - dev->bulk_timer.function = timeout_kill; - return 0; } +/* start the camera */ static int sd_start(struct gspca_dev *gspca_dev) { struct usb_fpix *dev = (struct usb_fpix *) gspca_dev; - int ret; - int size_ret; + int ret, len; /* Init the device */ - memset(gspca_dev->usb_buf, 0, 12); - gspca_dev->usb_buf[0] = 0xc6; - gspca_dev->usb_buf[8] = 0x20; - - ret = usb_control_msg(gspca_dev->dev, - usb_sndctrlpipe(gspca_dev->dev, 0), - USB_REQ_GET_STATUS, - USB_DIR_OUT | USB_TYPE_CLASS | - USB_RECIP_INTERFACE, 0, 0, gspca_dev->usb_buf, - 12, FPIX_TIMEOUT); - - if (ret != 12) { - PDEBUG(D_STREAM, "usb_control_msg failed (%d)", ret); - ret = -EIO; - goto error; + ret = command(gspca_dev, 0); + if (ret < 0) { + PDEBUG(D_STREAM, "init failed %d", ret); + return ret; } /* Read the result of the command. Ignore the result, for it * varies with the device. */ ret = usb_bulk_msg(gspca_dev->dev, gspca_dev->urb[0]->pipe, - gspca_dev->usb_buf, FPIX_MAX_TRANSFER, &size_ret, + gspca_dev->urb[0]->transfer_buffer, + FPIX_MAX_TRANSFER, &len, FPIX_TIMEOUT); - if (ret != 0) { - PDEBUG(D_STREAM, "usb_bulk_msg failed (%d)", ret); - ret = -EIO; - goto error; + if (ret < 0) { + PDEBUG(D_STREAM, "usb_bulk_msg failed %d", ret); + return ret; } /* Request a frame, but don't read it */ - memset(gspca_dev->usb_buf, 0, 12); - gspca_dev->usb_buf[0] = 0xd3; - gspca_dev->usb_buf[7] = 0x01; - - ret = usb_control_msg(gspca_dev->dev, - usb_sndctrlpipe(gspca_dev->dev, 0), - USB_REQ_GET_STATUS, - USB_DIR_OUT | USB_TYPE_CLASS | - USB_RECIP_INTERFACE, 0, 0, gspca_dev->usb_buf, - 12, FPIX_TIMEOUT); - if (ret != 12) { - PDEBUG(D_STREAM, "usb_control_msg failed (%d)", ret); - ret = -EIO; - goto error; + ret = command(gspca_dev, 1); + if (ret < 0) { + PDEBUG(D_STREAM, "frame request failed %d", ret); + return ret; } /* Again, reset bulk in endpoint */ usb_clear_halt(gspca_dev->dev, gspca_dev->urb[0]->pipe); - /* Allocate a control URB */ - dev->control_urb = usb_alloc_urb(0, GFP_KERNEL); - if (!dev->control_urb) { - PDEBUG(D_STREAM, "No free urbs available"); - ret = -EIO; - goto error; - } - - /* Various initializations. */ - init_completion(&dev->can_close); - dev->bulk_timer.data = (unsigned long)dev->gspca_dev.urb[0]; - dev->gspca_dev.urb[0]->complete = urb_callback; - dev->streaming = 1; - - /* Schedule a frame request. */ - dev_new_state(FPIX_REQ_FRAME); - schedule_delayed_work(&dev->wqe, 1); + /* Start the workqueue function to do the streaming */ + dev->work_thread = create_singlethread_workqueue(MODULE_NAME); + queue_work(dev->work_thread, &dev->work_struct); return 0; +} + +/* called on streamoff with alt==0 and on disconnect */ +/* the usb_lock is held at entry - restore on exit */ +static void sd_stop0(struct gspca_dev *gspca_dev) +{ + struct usb_fpix *dev = (struct usb_fpix *) gspca_dev; -error: - /* Free the ressources */ - sd_stopN(gspca_dev); - sd_stop0(gspca_dev); - return ret; + /* wait for the work queue to terminate */ + mutex_unlock(&gspca_dev->usb_lock); + destroy_workqueue(dev->work_thread); + mutex_lock(&gspca_dev->usb_lock); + dev->work_thread = NULL; } /* Table of supported USB devices */ @@ -422,12 +268,11 @@ MODULE_DEVICE_TABLE(usb, device_table); /* sub-driver description */ static const struct sd_desc sd_desc = { - .name = MODULE_NAME, + .name = MODULE_NAME, .config = sd_config, - .init = sd_init, - .start = sd_start, - .stopN = sd_stopN, - .stop0 = sd_stop0, + .init = sd_init, + .start = sd_start, + .stop0 = sd_stop0, }; /* -- device connect -- */ @@ -441,13 +286,13 @@ static int sd_probe(struct usb_interface *intf, } static struct usb_driver sd_driver = { - .name = MODULE_NAME, - .id_table = device_table, - .probe = sd_probe, + .name = MODULE_NAME, + .id_table = device_table, + .probe = sd_probe, .disconnect = gspca_disconnect, #ifdef CONFIG_PM .suspend = gspca_suspend, - .resume = gspca_resume, + .resume = gspca_resume, #endif }; @@ -455,12 +300,14 @@ static struct usb_driver sd_driver = { static int __init sd_mod_init(void) { int ret; + ret = usb_register(&sd_driver); if (ret < 0) return ret; PDEBUG(D_PROBE, "registered"); return 0; } + static void __exit sd_mod_exit(void) { usb_deregister(&sd_driver); -- cgit v1.2.3 From 3dee4dfed34b579ecc9533881cdabb961d92d5c7 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Thu, 26 Mar 2009 05:08:48 -0300 Subject: V4L/DVB (11221): gspca - sonixj: Prefer sonixj instead of sn9c102 for 0471:0327. Prefer the gspca sonixj driver for the Philips SPC600NC webcam instead of the sn9c102 driver. As we've got userreports that it works with the gspca driver, whereas it fails with the sn9c102 driver, see: https://bugzilla.redhat.com/show_bug.cgi?id=477111 Signed-off-by: Hans de Goede Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/sonixj.c | 2 -- drivers/media/video/sn9c102/sn9c102_devtable.h | 2 -- 2 files changed, 4 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/gspca/sonixj.c b/drivers/media/video/gspca/sonixj.c index 7d0d949b72ba..c72e19d3ac37 100644 --- a/drivers/media/video/gspca/sonixj.c +++ b/drivers/media/video/gspca/sonixj.c @@ -2189,9 +2189,7 @@ static const __devinitdata struct usb_device_id device_table[] = { #endif {USB_DEVICE(0x045e, 0x00f5), BSI(SN9C105, OV7660, 0x21)}, {USB_DEVICE(0x045e, 0x00f7), BSI(SN9C105, OV7660, 0x21)}, -#if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE {USB_DEVICE(0x0471, 0x0327), BSI(SN9C105, MI0360, 0x5d)}, -#endif {USB_DEVICE(0x0471, 0x0328), BSI(SN9C105, MI0360, 0x5d)}, {USB_DEVICE(0x0471, 0x0330), BSI(SN9C105, MI0360, 0x5d)}, {USB_DEVICE(0x06f8, 0x3004), BSI(SN9C105, OV7660, 0x21)}, diff --git a/drivers/media/video/sn9c102/sn9c102_devtable.h b/drivers/media/video/sn9c102/sn9c102_devtable.h index 41dfb60f4fb5..38a716020d7f 100644 --- a/drivers/media/video/sn9c102/sn9c102_devtable.h +++ b/drivers/media/video/sn9c102/sn9c102_devtable.h @@ -96,9 +96,7 @@ static const struct usb_device_id sn9c102_id_table[] = { #if !defined CONFIG_USB_GSPCA && !defined CONFIG_USB_GSPCA_MODULE { SN9C102_USB_DEVICE(0x045e, 0x00f5, BRIDGE_SN9C105), }, { SN9C102_USB_DEVICE(0x045e, 0x00f7, BRIDGE_SN9C105), }, -#endif { SN9C102_USB_DEVICE(0x0471, 0x0327, BRIDGE_SN9C105), }, -#if !defined CONFIG_USB_GSPCA && !defined CONFIG_USB_GSPCA_MODULE { SN9C102_USB_DEVICE(0x0471, 0x0328, BRIDGE_SN9C105), }, #endif { SN9C102_USB_DEVICE(0x0c45, 0x60c0, BRIDGE_SN9C105), }, -- cgit v1.2.3 From d99819d3f769baeb994d0e59f539c24d3c4ef504 Mon Sep 17 00:00:00 2001 From: Douglas Schilling Landgraf Date: Thu, 26 Mar 2009 05:10:55 -0300 Subject: V4L/DVB (11222): gspca - zc3xx: The webcam DLink DSB - C320 has the sensor pas106. Reported-by: Bruna Griebeler Tested-by: Bruna Griebeler Signed-off-by: Douglas Schilling Landgraf Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/zc3xx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/gspca/zc3xx.c b/drivers/media/video/gspca/zc3xx.c index e4c27a1e1e29..4fe01d8b6c87 100644 --- a/drivers/media/video/gspca/zc3xx.c +++ b/drivers/media/video/gspca/zc3xx.c @@ -7629,7 +7629,7 @@ static const __devinitdata struct usb_device_id device_table[] = { {USB_DEVICE(0x055f, 0xd004)}, {USB_DEVICE(0x0698, 0x2003)}, {USB_DEVICE(0x0ac8, 0x0301), .driver_info = SENSOR_PAS106}, - {USB_DEVICE(0x0ac8, 0x0302)}, + {USB_DEVICE(0x0ac8, 0x0302), .driver_info = SENSOR_PAS106}, {USB_DEVICE(0x0ac8, 0x301b)}, {USB_DEVICE(0x0ac8, 0x303b)}, {USB_DEVICE(0x0ac8, 0x305b), .driver_info = SENSOR_TAS5130C_VF0250}, -- cgit v1.2.3 From 031002d78b05c706272e4d5bc779f5c99d8348cf Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 26 Mar 2009 12:24:46 -0300 Subject: V4L/DVB (11226): avoid warnings for request_ihex_firmware on dabusb and vicam MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit drivers/media/video/usbvideo/vicam.c: In function ‘vicam_open’: drivers/media/video/usbvideo/vicam.c:194: warning: ‘fw’ may be used uninitialized in this function drivers/media/video/dabusb.c: In function ‘dabusb_probe’: drivers/media/video/dabusb.c:337: warning: ‘fw’ may be used uninitialized in this function Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/dabusb.c | 2 +- drivers/media/video/usbvideo/vicam.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/dabusb.c b/drivers/media/video/dabusb.c index f40c676489a4..a525a924edfa 100644 --- a/drivers/media/video/dabusb.c +++ b/drivers/media/video/dabusb.c @@ -334,7 +334,7 @@ static int dabusb_loadmem (pdabusb_t s, const char *fname) { int ret; const struct ihex_binrec *rec; - const struct firmware *fw; + const struct firmware *uninitialized_var(fw); dbg("Enter dabusb_loadmem (internal)"); diff --git a/drivers/media/video/usbvideo/vicam.c b/drivers/media/video/usbvideo/vicam.c index 2f1106338c08..8d73979596f9 100644 --- a/drivers/media/video/usbvideo/vicam.c +++ b/drivers/media/video/usbvideo/vicam.c @@ -191,7 +191,7 @@ initialize_camera(struct vicam_camera *cam) { int err; const struct ihex_binrec *rec; - const struct firmware *fw; + const struct firmware *uninitialized_var(fw); err = request_ihex_firmware(&fw, "vicam/firmware.fw", &cam->udev->dev); if (err) { -- cgit v1.2.3 From d211bfcbd0f13f1234aaa6e565013dba051a408c Mon Sep 17 00:00:00 2001 From: Janne Grunau Date: Thu, 26 Mar 2009 20:29:39 -0300 Subject: V4L/DVB (11228): hdpvr: use debugging macro for buffer status Signed-off-by: Janne Grunau Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/hdpvr/hdpvr-video.c | 27 ++++++++++----------------- 1 file changed, 10 insertions(+), 17 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/hdpvr/hdpvr-video.c b/drivers/media/video/hdpvr/hdpvr-video.c index 235978003e68..d63bfccf784e 100644 --- a/drivers/media/video/hdpvr/hdpvr-video.c +++ b/drivers/media/video/hdpvr/hdpvr-video.c @@ -28,6 +28,12 @@ #define BULK_URB_TIMEOUT 1250 /* 1.25 seconds */ +#define print_buffer_status() v4l2_dbg(MSG_BUFFER, hdpvr_debug, dev->video_dev,\ + "%s:%d buffer stat: %d free, %d proc\n",\ + __func__, __LINE__, \ + list_size(&dev->free_buff_list), \ + list_size(&dev->rec_buff_list)) + struct hdpvr_fh { struct hdpvr_device *dev; }; @@ -191,10 +197,7 @@ static int hdpvr_submit_buffers(struct hdpvr_device *dev) list_move_tail(&buf->buff_list, &dev->rec_buff_list); } err: - v4l2_dbg(MSG_BUFFER, hdpvr_debug, dev->video_dev, - "buffer queue stat: %d free, %d proc\n", - list_size(&dev->free_buff_list), - list_size(&dev->rec_buff_list)); + print_buffer_status(); mutex_unlock(&dev->io_mutex); return ret; } @@ -399,11 +402,7 @@ static ssize_t hdpvr_read(struct file *file, char __user *buffer, size_t count, mutex_unlock(&dev->io_mutex); goto err; } - - v4l2_dbg(MSG_BUFFER, hdpvr_debug, dev->video_dev, - "buffer queue stat: %d free, %d proc\n", - list_size(&dev->free_buff_list), - list_size(&dev->rec_buff_list)); + print_buffer_status(); } mutex_unlock(&dev->io_mutex); @@ -463,10 +462,7 @@ static ssize_t hdpvr_read(struct file *file, char __user *buffer, size_t count, list_move_tail(&buf->buff_list, &dev->free_buff_list); - v4l2_dbg(MSG_BUFFER, hdpvr_debug, dev->video_dev, - "buffer queue stat: %d free, %d proc\n", - list_size(&dev->free_buff_list), - list_size(&dev->rec_buff_list)); + print_buffer_status(); mutex_unlock(&dev->io_mutex); @@ -499,10 +495,7 @@ static unsigned int hdpvr_poll(struct file *filp, poll_table *wait) dev->status = STATUS_IDLE; } - v4l2_dbg(MSG_BUFFER, hdpvr_debug, dev->video_dev, - "buffer queue stat: %d free, %d proc\n", - list_size(&dev->free_buff_list), - list_size(&dev->rec_buff_list)); + print_buffer_status(); } mutex_unlock(&dev->io_mutex); -- cgit v1.2.3 From a50ab29185a9ec31e5a6999e53add0508653e889 Mon Sep 17 00:00:00 2001 From: Janne Grunau Date: Thu, 26 Mar 2009 14:40:55 -0300 Subject: V4L/DVB (11229): hdpvr: set usb interface dev as parent in struct video_device Signed-off-by: Janne Grunau Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/hdpvr/hdpvr-core.c | 2 +- drivers/media/video/hdpvr/hdpvr-video.c | 5 +++-- drivers/media/video/hdpvr/hdpvr.h | 3 ++- 3 files changed, 6 insertions(+), 4 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/hdpvr/hdpvr-core.c b/drivers/media/video/hdpvr/hdpvr-core.c index e96aed42d192..2c49862b6d32 100644 --- a/drivers/media/video/hdpvr/hdpvr-core.c +++ b/drivers/media/video/hdpvr/hdpvr-core.c @@ -342,7 +342,7 @@ static int hdpvr_probe(struct usb_interface *interface, } mutex_unlock(&dev->io_mutex); - if (hdpvr_register_videodev(dev, + if (hdpvr_register_videodev(dev, &interface->dev, video_nr[atomic_inc_return(&dev_nr)])) { err("registering videodev failed"); goto error; diff --git a/drivers/media/video/hdpvr/hdpvr-video.c b/drivers/media/video/hdpvr/hdpvr-video.c index d63bfccf784e..9560e19d7cf0 100644 --- a/drivers/media/video/hdpvr/hdpvr-video.c +++ b/drivers/media/video/hdpvr/hdpvr-video.c @@ -1193,7 +1193,8 @@ static const struct video_device hdpvr_video_template = { V4L2_STD_PAL_60, }; -int hdpvr_register_videodev(struct hdpvr_device *dev, int devnum) +int hdpvr_register_videodev(struct hdpvr_device *dev, struct device *parent, + int devnum) { /* setup and register video device */ dev->video_dev = video_device_alloc(); @@ -1204,7 +1205,7 @@ int hdpvr_register_videodev(struct hdpvr_device *dev, int devnum) *(dev->video_dev) = hdpvr_video_template; strcpy(dev->video_dev->name, "Hauppauge HD PVR"); - dev->video_dev->parent = &dev->udev->dev; + dev->video_dev->parent = parent; video_set_drvdata(dev->video_dev, dev); if (video_register_device(dev->video_dev, VFL_TYPE_GRABBER, devnum)) { diff --git a/drivers/media/video/hdpvr/hdpvr.h b/drivers/media/video/hdpvr/hdpvr.h index 9bc8051b597d..3af415d81df7 100644 --- a/drivers/media/video/hdpvr/hdpvr.h +++ b/drivers/media/video/hdpvr/hdpvr.h @@ -284,7 +284,8 @@ int get_input_lines_info(struct hdpvr_device *dev); /*========================================================================*/ /* v4l2 registration */ -int hdpvr_register_videodev(struct hdpvr_device *dev, int devnumber); +int hdpvr_register_videodev(struct hdpvr_device *dev, struct device *parent, + int devnumber); int hdpvr_cancel_queue(struct hdpvr_device *dev); -- cgit v1.2.3 From d2ff3ec81628cbf9470c496b3d0c0780165643f5 Mon Sep 17 00:00:00 2001 From: Janne Grunau Date: Thu, 26 Mar 2009 14:32:54 -0300 Subject: V4L/DVB (11230): hdpvr: return immediately from hdpvr_poll if data is available simplifies check for available data with hdpvr_get_next_buffer Signed-off-by: Janne Grunau Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/hdpvr/hdpvr-video.c | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/hdpvr/hdpvr-video.c b/drivers/media/video/hdpvr/hdpvr-video.c index 9560e19d7cf0..e9078cdedb28 100644 --- a/drivers/media/video/hdpvr/hdpvr-video.c +++ b/drivers/media/video/hdpvr/hdpvr-video.c @@ -479,6 +479,7 @@ err: static unsigned int hdpvr_poll(struct file *filp, poll_table *wait) { + struct hdpvr_buffer *buf = NULL; struct hdpvr_fh *fh = (struct hdpvr_fh *)filp->private_data; struct hdpvr_device *dev = fh->dev; unsigned int mask = 0; @@ -499,19 +500,14 @@ static unsigned int hdpvr_poll(struct file *filp, poll_table *wait) } mutex_unlock(&dev->io_mutex); - poll_wait(filp, &dev->wait_data, wait); - - mutex_lock(&dev->io_mutex); - if (!list_empty(&dev->rec_buff_list)) { - - struct hdpvr_buffer *buf = list_entry(dev->rec_buff_list.next, - struct hdpvr_buffer, - buff_list); - - if (buf->status == BUFSTAT_READY) - mask |= POLLIN | POLLRDNORM; + buf = hdpvr_get_next_buffer(dev); + /* only wait if no data is available */ + if (!buf || buf->status != BUFSTAT_READY) { + poll_wait(filp, &dev->wait_data, wait); + buf = hdpvr_get_next_buffer(dev); } - mutex_unlock(&dev->io_mutex); + if (buf && buf->status == BUFSTAT_READY) + mask |= POLLIN | POLLRDNORM; return mask; } -- cgit v1.2.3 From 48f98f7557d35d360470bf6d9fd7b00d04fba828 Mon Sep 17 00:00:00 2001 From: Janne Grunau Date: Thu, 26 Mar 2009 20:56:06 -0300 Subject: V4L/DVB (11231): hdpvr: locking fixes unlock io_mutex in hdpvr_stop_streaming hdpvr_disconnect to allow the streaming worker to stop before we flush the workqueue. do not return to user space with mutex held in vidioc_encoder_cmd with an unknown encoder command. Signed-off-by: Janne Grunau Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/hdpvr/hdpvr-core.c | 2 ++ drivers/media/video/hdpvr/hdpvr-video.c | 4 +++- 2 files changed, 5 insertions(+), 1 deletion(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/hdpvr/hdpvr-core.c b/drivers/media/video/hdpvr/hdpvr-core.c index 2c49862b6d32..547833eb6cec 100644 --- a/drivers/media/video/hdpvr/hdpvr-core.c +++ b/drivers/media/video/hdpvr/hdpvr-core.c @@ -390,8 +390,10 @@ static void hdpvr_disconnect(struct usb_interface *interface) video_unregister_device(dev->video_dev); wake_up_interruptible(&dev->wait_data); wake_up_interruptible(&dev->wait_buffer); + mutex_unlock(&dev->io_mutex); msleep(100); flush_workqueue(dev->workqueue); + mutex_lock(&dev->io_mutex); hdpvr_cancel_queue(dev); destroy_workqueue(dev->workqueue); mutex_unlock(&dev->io_mutex); diff --git a/drivers/media/video/hdpvr/hdpvr-video.c b/drivers/media/video/hdpvr/hdpvr-video.c index e9078cdedb28..2fe57303c0b5 100644 --- a/drivers/media/video/hdpvr/hdpvr-video.c +++ b/drivers/media/video/hdpvr/hdpvr-video.c @@ -300,12 +300,14 @@ static int hdpvr_stop_streaming(struct hdpvr_device *dev) dev->status = STATUS_SHUTTING_DOWN; hdpvr_config_call(dev, CTRL_STOP_STREAMING_VALUE, 0x00); + mutex_unlock(&dev->io_mutex); wake_up_interruptible(&dev->wait_buffer); msleep(50); flush_workqueue(dev->workqueue); + mutex_lock(&dev->io_mutex); /* kill the still outstanding urbs */ hdpvr_cancel_queue(dev); @@ -1130,7 +1132,7 @@ static int vidioc_encoder_cmd(struct file *filp, void *priv, default: v4l2_dbg(MSG_INFO, hdpvr_debug, dev->video_dev, "Unsupported encoder cmd %d\n", a->cmd); - return -EINVAL; + res = -EINVAL; } mutex_unlock(&dev->io_mutex); return res; -- cgit v1.2.3 From 5ed2b6419ef48efda66a71d4b26bd2fa6b6a1ac7 Mon Sep 17 00:00:00 2001 From: Stoyan Gaydarov Date: Tue, 24 Mar 2009 18:12:47 -0300 Subject: V4L/DVB (11235): changed ioctls to unlocked Signed-off-by: Stoyan Gaydarov Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/bt8xx/dst_ca.c | 7 +++++-- drivers/media/video/dabusb.c | 11 ++++++++--- 2 files changed, 13 insertions(+), 5 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/dvb/bt8xx/dst_ca.c b/drivers/media/dvb/bt8xx/dst_ca.c index 6c68f02c1709..607d7387fb6f 100644 --- a/drivers/media/dvb/bt8xx/dst_ca.c +++ b/drivers/media/dvb/bt8xx/dst_ca.c @@ -552,8 +552,10 @@ free_mem_and_exit: return result; } -static int dst_ca_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long ioctl_arg) +static long dst_ca_ioctl(struct file *file, unsigned int cmd, unsigned long ioctl_arg) { + lock_kernel(); + struct dvb_device* dvbdev = (struct dvb_device*) file->private_data; struct dst_state* state = (struct dst_state*) dvbdev->priv; struct ca_slot_info *p_ca_slot_info; @@ -647,6 +649,7 @@ static int dst_ca_ioctl(struct inode *inode, struct file *file, unsigned int cmd kfree (p_ca_slot_info); kfree (p_ca_caps); + unlock_kernel(); return result; } @@ -684,7 +687,7 @@ static ssize_t dst_ca_write(struct file *file, const char __user *buffer, size_t static const struct file_operations dst_ca_fops = { .owner = THIS_MODULE, - .ioctl = dst_ca_ioctl, + .unlocked_ioctl = dst_ca_ioctl, .open = dst_ca_open, .release = dst_ca_release, .read = dst_ca_read, diff --git a/drivers/media/video/dabusb.c b/drivers/media/video/dabusb.c index a525a924edfa..384da45807a0 100644 --- a/drivers/media/video/dabusb.c +++ b/drivers/media/video/dabusb.c @@ -673,8 +673,9 @@ static int dabusb_release (struct inode *inode, struct file *file) return 0; } -static int dabusb_ioctl (struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) +static long dabusb_ioctl (struct file *file, unsigned int cmd, unsigned long arg) { + lock_kernel(); pdabusb_t s = (pdabusb_t) file->private_data; pbulk_transfer_t pbulk; int ret = 0; @@ -682,13 +683,16 @@ static int dabusb_ioctl (struct inode *inode, struct file *file, unsigned int cm dbg("dabusb_ioctl"); - if (s->remove_pending) + if (s->remove_pending) { + unlock_kernel(); return -EIO; + } mutex_lock(&s->mutex); if (!s->usbdev) { mutex_unlock(&s->mutex); + unlock_kernel(); return -EIO; } @@ -729,6 +733,7 @@ static int dabusb_ioctl (struct inode *inode, struct file *file, unsigned int cm break; } mutex_unlock(&s->mutex); + unlock_kernel(); return ret; } @@ -737,7 +742,7 @@ static const struct file_operations dabusb_fops = .owner = THIS_MODULE, .llseek = no_llseek, .read = dabusb_read, - .ioctl = dabusb_ioctl, + .unlocked_ioctl = dabusb_ioctl, .open = dabusb_open, .release = dabusb_release, }; -- cgit v1.2.3 From 8737f66e6415e8dbe8c8b26d63692d87a4ad5b29 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Fri, 27 Mar 2009 14:01:11 -0300 Subject: V4L/DVB (11237): media/zoran: fix printk format Fix printk format warning: drivers/media/video/zoran/zoran_driver.c:345: warning: format '%lx' expects type 'long unsigned int', but argument 5 has type 'phys_addr_t' Signed-off-by: Randy Dunlap Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/zoran/zoran_driver.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/zoran/zoran_driver.c b/drivers/media/video/zoran/zoran_driver.c index 1e87fb9f7146..f16e57cf11e4 100644 --- a/drivers/media/video/zoran/zoran_driver.c +++ b/drivers/media/video/zoran/zoran_driver.c @@ -245,9 +245,9 @@ static int v4l_fbuffer_alloc(struct zoran_fh *fh) SetPageReserved(virt_to_page(mem + off)); dprintk(4, KERN_INFO - "%s: %s - V4L frame %d mem 0x%lx (bus: 0x%lx)\n", + "%s: %s - V4L frame %d mem 0x%lx (bus: 0x%llx)\n", ZR_DEVNAME(zr), __func__, i, (unsigned long) mem, - virt_to_bus(mem)); + (unsigned long long)virt_to_bus(mem)); } fh->buffers.allocated = 1; -- cgit v1.2.3 From c01f1a5a241604c35f93f10e06253ca70e88ee4e Mon Sep 17 00:00:00 2001 From: Daniel Glöckner Date: Thu, 26 Mar 2009 11:31:08 -0300 Subject: V4L/DVB (11242): allow v4l2 drivers to provide a get_unmapped_area handler MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Shared memory mappings on nommu machines require a get_unmapped_area file operation that suggests an address for the mapping. This patch adds a way for v4l2 drivers to provide this callback. Signed-off-by: Daniel Glöckner Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/v4l2-dev.c | 19 +++++++++++++++++++ include/media/v4l2-dev.h | 2 ++ 2 files changed, 21 insertions(+) (limited to 'drivers/media/video') diff --git a/drivers/media/video/v4l2-dev.c b/drivers/media/video/v4l2-dev.c index cdc8ce3c4e56..91228b3df07d 100644 --- a/drivers/media/video/v4l2-dev.c +++ b/drivers/media/video/v4l2-dev.c @@ -198,6 +198,23 @@ static long v4l2_unlocked_ioctl(struct file *filp, return vdev->fops->unlocked_ioctl(filp, cmd, arg); } +#ifdef CONFIG_MMU +#define v4l2_get_unmapped_area NULL +#else +static unsigned long v4l2_get_unmapped_area(struct file *filp, + unsigned long addr, unsigned long len, unsigned long pgoff, + unsigned long flags) +{ + struct video_device *vdev = video_devdata(filp); + + if (!vdev->fops->get_unmapped_area) + return -ENOSYS; + if (video_is_unregistered(vdev)) + return -ENODEV; + return vdev->fops->get_unmapped_area(filp, addr, len, pgoff, flags); +} +#endif + static int v4l2_mmap(struct file *filp, struct vm_area_struct *vm) { struct video_device *vdev = video_devdata(filp); @@ -250,6 +267,7 @@ static const struct file_operations v4l2_unlocked_fops = { .read = v4l2_read, .write = v4l2_write, .open = v4l2_open, + .get_unmapped_area = v4l2_get_unmapped_area, .mmap = v4l2_mmap, .unlocked_ioctl = v4l2_unlocked_ioctl, #ifdef CONFIG_COMPAT @@ -265,6 +283,7 @@ static const struct file_operations v4l2_fops = { .read = v4l2_read, .write = v4l2_write, .open = v4l2_open, + .get_unmapped_area = v4l2_get_unmapped_area, .mmap = v4l2_mmap, .ioctl = v4l2_ioctl, #ifdef CONFIG_COMPAT diff --git a/include/media/v4l2-dev.h b/include/media/v4l2-dev.h index e36faab8459b..2058dd45e915 100644 --- a/include/media/v4l2-dev.h +++ b/include/media/v4l2-dev.h @@ -40,6 +40,8 @@ struct v4l2_file_operations { unsigned int (*poll) (struct file *, struct poll_table_struct *); long (*ioctl) (struct file *, unsigned int, unsigned long); long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long); + unsigned long (*get_unmapped_area) (struct file *, unsigned long, + unsigned long, unsigned long, unsigned long); int (*mmap) (struct file *, struct vm_area_struct *); int (*open) (struct file *); int (*release) (struct file *); -- cgit v1.2.3 From fbc0ae205c5dfb1049a36f0a98cc9211a3a090bb Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Thu, 26 Mar 2009 17:44:38 -0300 Subject: V4L/DVB (11243): cx88: Missing failure checks The ioremap one was reported in October 2007 (Bug 9146), the kmalloc one was blindingly obvious while looking at the ioremap one The bug suggests some other configuration for lots of I/O memory (32MB per device is ioremapped) but I'll leave that to the real maintainers Signed-off-by: Alan Cox Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx88/cx88-cards.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'drivers/media/video') diff --git a/drivers/media/video/cx88/cx88-cards.c b/drivers/media/video/cx88/cx88-cards.c index b9def8cbcdab..348f6ef08b2a 100644 --- a/drivers/media/video/cx88/cx88-cards.c +++ b/drivers/media/video/cx88/cx88-cards.c @@ -3127,6 +3127,8 @@ struct cx88_core *cx88_core_create(struct pci_dev *pci, int nr) int i; core = kzalloc(sizeof(*core), GFP_KERNEL); + if (core == NULL) + return NULL; atomic_inc(&core->refcount); core->pci_bus = pci->bus->number; @@ -3157,6 +3159,11 @@ struct cx88_core *cx88_core_create(struct pci_dev *pci, int nr) pci_resource_len(pci, 0)); core->bmmio = (u8 __iomem *)core->lmmio; + if (core->lmmio == NULL) { + kfree(core); + return NULL; + } + /* board config */ core->boardnr = UNSET; if (card[core->nr] < ARRAY_SIZE(cx88_boards)) -- cgit v1.2.3 From 06630aec92d6a71658ac1538e2a65af5cfc5f2af Mon Sep 17 00:00:00 2001 From: Janne Grunau Date: Fri, 27 Mar 2009 20:01:40 -0300 Subject: V4L/DVB (11245): hdpvr: add struct v4l2_device Signed-off-by: Janne Grunau Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/hdpvr/hdpvr-core.c | 9 +++++++++ drivers/media/video/hdpvr/hdpvr.h | 4 ++++ 2 files changed, 13 insertions(+) (limited to 'drivers/media/video') diff --git a/drivers/media/video/hdpvr/hdpvr-core.c b/drivers/media/video/hdpvr/hdpvr-core.c index 547833eb6cec..3b19a259dc4e 100644 --- a/drivers/media/video/hdpvr/hdpvr-core.c +++ b/drivers/media/video/hdpvr/hdpvr-core.c @@ -278,6 +278,13 @@ static int hdpvr_probe(struct usb_interface *interface, err("Out of memory"); goto error; } + + /* register v4l2_device early so it can be used for printks */ + if (v4l2_device_register(&interface->dev, &dev->v4l2_dev)) { + err("v4l2_device_register failed"); + goto error; + } + mutex_init(&dev->io_mutex); mutex_init(&dev->i2c_mutex); mutex_init(&dev->usbc_mutex); @@ -387,6 +394,7 @@ static void hdpvr_disconnect(struct usb_interface *interface) /* prevent more I/O from starting and stop any ongoing */ mutex_lock(&dev->io_mutex); dev->status = STATUS_DISCONNECTED; + v4l2_device_disconnect(&dev->v4l2_dev); video_unregister_device(dev->video_dev); wake_up_interruptible(&dev->wait_data); wake_up_interruptible(&dev->wait_buffer); @@ -413,6 +421,7 @@ static void hdpvr_disconnect(struct usb_interface *interface) printk(KERN_INFO "Hauppauge HD PVR: device /dev/video%d disconnected\n", minor); + v4l2_device_unregister(&dev->v4l2_dev); kfree(dev->usbc_buf); kfree(dev); } diff --git a/drivers/media/video/hdpvr/hdpvr.h b/drivers/media/video/hdpvr/hdpvr.h index 3af415d81df7..1edd8759121e 100644 --- a/drivers/media/video/hdpvr/hdpvr.h +++ b/drivers/media/video/hdpvr/hdpvr.h @@ -15,6 +15,8 @@ #include #include +#include + #define HDPVR_MAJOR_VERSION 0 #define HDPVR_MINOR_VERSION 2 #define HDPVR_RELEASE 0 @@ -65,6 +67,8 @@ struct hdpvr_device { struct video_device *video_dev; /* the usb device for this device */ struct usb_device *udev; + /* v4l2-device unused */ + struct v4l2_device v4l2_dev; /* the max packet size of the bulk endpoint */ size_t bulk_in_size; -- cgit v1.2.3 From 9ef77adfb9ac170bcaf449530cf129c48547fd55 Mon Sep 17 00:00:00 2001 From: Janne Grunau Date: Fri, 27 Mar 2009 20:09:40 -0300 Subject: V4L/DVB (11246): hdpvr: convert printing macros to v4l2_* with struct v4l2_device it gives us a nice and unique prefix per device Signed-off-by: Janne Grunau Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/hdpvr/hdpvr-control.c | 22 +++++------ drivers/media/video/hdpvr/hdpvr-core.c | 56 +++++++++++++++------------- drivers/media/video/hdpvr/hdpvr-video.c | 61 +++++++++++++++++-------------- 3 files changed, 75 insertions(+), 64 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/hdpvr/hdpvr-control.c b/drivers/media/video/hdpvr/hdpvr-control.c index 51de74aebfcb..06791749d1a0 100644 --- a/drivers/media/video/hdpvr/hdpvr-control.c +++ b/drivers/media/video/hdpvr/hdpvr-control.c @@ -40,9 +40,9 @@ int hdpvr_config_call(struct hdpvr_device *dev, uint value, u8 valbuf) dev->usbc_buf, 1, 10000); mutex_unlock(&dev->usbc_mutex); - dev_dbg(&dev->udev->dev, - "config call request for value 0x%x returned %d\n", value, - ret); + v4l2_dbg(MSG_INFO, hdpvr_debug, &dev->v4l2_dev, + "config call request for value 0x%x returned %d\n", value, + ret); return ret < 0 ? ret : 0; } @@ -57,7 +57,7 @@ struct hdpvr_video_info *get_video_info(struct hdpvr_device *dev) vidinf = kzalloc(sizeof(struct hdpvr_video_info), GFP_KERNEL); if (!vidinf) { - dev_err(&dev->udev->dev, "out of memory"); + v4l2_err(&dev->v4l2_dev, "out of memory\n"); goto err; } @@ -78,8 +78,8 @@ struct hdpvr_video_info *get_video_info(struct hdpvr_device *dev) if (hdpvr_debug & MSG_INFO) { hex_dump_to_buffer(dev->usbc_buf, 5, 16, 1, print_buf, sizeof(print_buf), 0); - dev_dbg(&dev->udev->dev, "get video info returned: %d, %s\n", - ret, print_buf); + v4l2_dbg(MSG_INFO, hdpvr_debug, &dev->v4l2_dev, + "get video info returned: %d, %s\n", ret, print_buf); } #endif mutex_unlock(&dev->usbc_mutex); @@ -111,9 +111,9 @@ int get_input_lines_info(struct hdpvr_device *dev) if (hdpvr_debug & MSG_INFO) { hex_dump_to_buffer(dev->usbc_buf, 3, 16, 1, print_buf, sizeof(print_buf), 0); - dev_dbg(&dev->udev->dev, - "get input lines info returned: %d, %s\n", ret, - print_buf); + v4l2_dbg(MSG_INFO, hdpvr_debug, &dev->v4l2_dev, + "get input lines info returned: %d, %s\n", ret, + print_buf); } #endif lines = dev->usbc_buf[1] << 8 | dev->usbc_buf[0]; @@ -155,8 +155,8 @@ int hdpvr_set_audio(struct hdpvr_device *dev, u8 input, dev->usbc_buf[1] = 1; else { mutex_unlock(&dev->usbc_mutex); - dev_err(&dev->udev->dev, "invalid audio codec %d\n", - codec); + v4l2_err(&dev->v4l2_dev, "invalid audio codec %d\n", + codec); ret = -EINVAL; goto error; } diff --git a/drivers/media/video/hdpvr/hdpvr-core.c b/drivers/media/video/hdpvr/hdpvr-core.c index 3b19a259dc4e..188bd5aea258 100644 --- a/drivers/media/video/hdpvr/hdpvr-core.c +++ b/drivers/media/video/hdpvr/hdpvr-core.c @@ -125,7 +125,7 @@ static int device_authorization(struct hdpvr_device *dev) size_t buf_size = 46; char *print_buf = kzalloc(5*buf_size+1, GFP_KERNEL); if (!print_buf) { - dev_err(&dev->udev->dev, "Out of memory"); + v4l2_err(&dev->v4l2_dev, "Out of memory\n"); goto error; } #endif @@ -138,17 +138,17 @@ static int device_authorization(struct hdpvr_device *dev) dev->usbc_buf, 46, 10000); if (ret != 46) { - dev_err(&dev->udev->dev, - "unexpected answer of status request, len %d", ret); + v4l2_err(&dev->v4l2_dev, + "unexpected answer of status request, len %d\n", ret); goto error; } #ifdef HDPVR_DEBUG else { hex_dump_to_buffer(dev->usbc_buf, 46, 16, 1, print_buf, sizeof(print_buf), 0); - dev_dbg(&dev->udev->dev, - "Status request returned, len %d: %s\n", - ret, print_buf); + v4l2_dbg(MSG_INFO, hdpvr_debug, &dev->v4l2_dev, + "Status request returned, len %d: %s\n", + ret, print_buf); } #endif if (dev->usbc_buf[1] == HDPVR_FIRMWARE_VERSION) { @@ -156,11 +156,11 @@ static int device_authorization(struct hdpvr_device *dev) } else if (dev->usbc_buf[1] == HDPVR_FIRMWARE_VERSION_AC3) { dev->flags |= HDPVR_FLAG_AC3_CAP; } else if (dev->usbc_buf[1] > HDPVR_FIRMWARE_VERSION_AC3) { - dev_notice(&dev->udev->dev, "untested firmware version 0x%x, " - "the driver might not work\n", dev->usbc_buf[1]); + v4l2_info(&dev->v4l2_dev, "untested firmware version 0x%x, " + "the driver might not work\n", dev->usbc_buf[1]); dev->flags |= HDPVR_FLAG_AC3_CAP; } else { - dev_err(&dev->udev->dev, "unknown firmware version 0x%x\n", + v4l2_err(&dev->v4l2_dev, "unknown firmware version 0x%x\n", dev->usbc_buf[1]); ret = -EINVAL; goto error; @@ -169,12 +169,14 @@ static int device_authorization(struct hdpvr_device *dev) response = dev->usbc_buf+38; #ifdef HDPVR_DEBUG hex_dump_to_buffer(response, 8, 16, 1, print_buf, sizeof(print_buf), 0); - dev_dbg(&dev->udev->dev, "challenge: %s\n", print_buf); + v4l2_dbg(MSG_INFO, hdpvr_debug, &dev->v4l2_dev, "challenge: %s\n", + print_buf); #endif challenge(response); #ifdef HDPVR_DEBUG hex_dump_to_buffer(response, 8, 16, 1, print_buf, sizeof(print_buf), 0); - dev_dbg(&dev->udev->dev, " response: %s\n", print_buf); + v4l2_dbg(MSG_INFO, hdpvr_debug, &dev->v4l2_dev, " response: %s\n", + print_buf); #endif msleep(100); @@ -184,7 +186,8 @@ static int device_authorization(struct hdpvr_device *dev) 0x0000, 0x0000, response, 8, 10000); - dev_dbg(&dev->udev->dev, "magic request returned %d\n", ret); + v4l2_dbg(MSG_INFO, hdpvr_debug, &dev->v4l2_dev, + "magic request returned %d\n", ret); mutex_unlock(&dev->usbc_mutex); retval = ret != 8; @@ -214,12 +217,13 @@ static int hdpvr_device_init(struct hdpvr_device *dev) CTRL_LOW_PASS_FILTER_VALUE, CTRL_DEFAULT_INDEX, buf, 4, 1000); - dev_dbg(&dev->udev->dev, "control request returned %d\n", ret); + v4l2_dbg(MSG_INFO, hdpvr_debug, &dev->v4l2_dev, + "control request returned %d\n", ret); mutex_unlock(&dev->usbc_mutex); vidinf = get_video_info(dev); if (!vidinf) - dev_dbg(&dev->udev->dev, + v4l2_dbg(MSG_INFO, hdpvr_debug, &dev->v4l2_dev, "no valid video signal or device init failed\n"); else kfree(vidinf); @@ -231,7 +235,8 @@ static int hdpvr_device_init(struct hdpvr_device *dev) usb_sndctrlpipe(dev->udev, 0), 0xd4, 0x38, 0, 0, buf, 1, 1000); - dev_dbg(&dev->udev->dev, "control request returned %d\n", ret); + v4l2_dbg(MSG_INFO, hdpvr_debug, &dev->v4l2_dev, + "control request returned %d\n", ret); /* boost analog audio */ buf[0] = boost_audio; @@ -239,7 +244,8 @@ static int hdpvr_device_init(struct hdpvr_device *dev) usb_sndctrlpipe(dev->udev, 0), 0xd5, 0x38, 0, 0, buf, 1, 1000); - dev_dbg(&dev->udev->dev, "control request returned %d\n", ret); + v4l2_dbg(MSG_INFO, hdpvr_debug, &dev->v4l2_dev, + "control request returned %d\n", ret); mutex_unlock(&dev->usbc_mutex); dev->status = STATUS_IDLE; @@ -290,7 +296,7 @@ static int hdpvr_probe(struct usb_interface *interface, mutex_init(&dev->usbc_mutex); dev->usbc_buf = kmalloc(64, GFP_KERNEL); if (!dev->usbc_buf) { - dev_err(&dev->udev->dev, "Out of memory"); + v4l2_err(&dev->v4l2_dev, "Out of memory\n"); goto error; } @@ -332,26 +338,27 @@ static int hdpvr_probe(struct usb_interface *interface, } if (!dev->bulk_in_endpointAddr) { - err("Could not find bulk-in endpoint"); + v4l2_err(&dev->v4l2_dev, "Could not find bulk-in endpoint\n"); goto error; } /* init the device */ if (hdpvr_device_init(dev)) { - err("device init failed"); + v4l2_err(&dev->v4l2_dev, "device init failed\n"); goto error; } mutex_lock(&dev->io_mutex); if (hdpvr_alloc_buffers(dev, NUM_BUFFERS)) { - err("allocating transfer buffers failed"); + v4l2_err(&dev->v4l2_dev, + "allocating transfer buffers failed\n"); goto error; } mutex_unlock(&dev->io_mutex); if (hdpvr_register_videodev(dev, &interface->dev, video_nr[atomic_inc_return(&dev_nr)])) { - err("registering videodev failed"); + v4l2_err(&dev->v4l2_dev, "registering videodev failed\n"); goto error; } @@ -359,7 +366,7 @@ static int hdpvr_probe(struct usb_interface *interface, /* until i2c is working properly */ retval = 0; /* hdpvr_register_i2c_adapter(dev); */ if (retval < 0) { - err("registering i2c adapter failed"); + v4l2_err(&dev->v4l2_dev, "registering i2c adapter failed\n"); goto error; } #endif /* CONFIG_I2C */ @@ -368,7 +375,7 @@ static int hdpvr_probe(struct usb_interface *interface, usb_set_intfdata(interface, dev); /* let the user know what node this device is now attached to */ - v4l2_info(dev->video_dev, "device now attached to /dev/video%d\n", + v4l2_info(&dev->v4l2_dev, "device now attached to /dev/video%d\n", dev->video_dev->minor); return 0; @@ -418,8 +425,7 @@ static void hdpvr_disconnect(struct usb_interface *interface) atomic_dec(&dev_nr); - printk(KERN_INFO "Hauppauge HD PVR: device /dev/video%d disconnected\n", - minor); + v4l2_info(&dev->v4l2_dev, "device /dev/video%d disconnected\n", minor); v4l2_device_unregister(&dev->v4l2_dev); kfree(dev->usbc_buf); diff --git a/drivers/media/video/hdpvr/hdpvr-video.c b/drivers/media/video/hdpvr/hdpvr-video.c index 2fe57303c0b5..f6e1bcefddb7 100644 --- a/drivers/media/video/hdpvr/hdpvr-video.c +++ b/drivers/media/video/hdpvr/hdpvr-video.c @@ -28,11 +28,12 @@ #define BULK_URB_TIMEOUT 1250 /* 1.25 seconds */ -#define print_buffer_status() v4l2_dbg(MSG_BUFFER, hdpvr_debug, dev->video_dev,\ - "%s:%d buffer stat: %d free, %d proc\n",\ - __func__, __LINE__, \ - list_size(&dev->free_buff_list), \ - list_size(&dev->rec_buff_list)) +#define print_buffer_status() { \ + v4l2_dbg(MSG_BUFFER, hdpvr_debug, &dev->v4l2_dev, \ + "%s:%d buffer stat: %d free, %d proc\n", \ + __func__, __LINE__, \ + list_size(&dev->free_buff_list), \ + list_size(&dev->rec_buff_list)); } struct hdpvr_fh { struct hdpvr_device *dev; @@ -123,21 +124,21 @@ int hdpvr_alloc_buffers(struct hdpvr_device *dev, uint count) struct hdpvr_buffer *buf; struct urb *urb; - v4l2_dbg(MSG_INFO, hdpvr_debug, dev->video_dev, + v4l2_dbg(MSG_INFO, hdpvr_debug, &dev->v4l2_dev, "allocating %u buffers\n", count); for (i = 0; i < count; i++) { buf = kzalloc(sizeof(struct hdpvr_buffer), GFP_KERNEL); if (!buf) { - err("cannot allocate buffer"); + v4l2_err(&dev->v4l2_dev, "cannot allocate buffer\n"); goto exit; } buf->dev = dev; urb = usb_alloc_urb(0, GFP_KERNEL); if (!urb) { - err("cannot allocate urb"); + v4l2_err(&dev->v4l2_dev, "cannot allocate urb\n"); goto exit; } buf->urb = urb; @@ -145,7 +146,8 @@ int hdpvr_alloc_buffers(struct hdpvr_device *dev, uint count) mem = usb_buffer_alloc(dev->udev, dev->bulk_in_size, GFP_KERNEL, &urb->transfer_dma); if (!mem) { - err("cannot allocate usb transfer buffer"); + v4l2_err(&dev->v4l2_dev, + "cannot allocate usb transfer buffer\n"); goto exit; } @@ -178,7 +180,8 @@ static int hdpvr_submit_buffers(struct hdpvr_device *dev) buf = list_entry(dev->free_buff_list.next, struct hdpvr_buffer, buff_list); if (buf->status != BUFSTAT_AVAILABLE) { - err("buffer not marked as availbale"); + v4l2_err(&dev->v4l2_dev, + "buffer not marked as availbale\n"); ret = -EFAULT; goto err; } @@ -188,7 +191,9 @@ static int hdpvr_submit_buffers(struct hdpvr_device *dev) urb->actual_length = 0; ret = usb_submit_urb(urb, GFP_KERNEL); if (ret) { - err("usb_submit_urb in %s returned %d", __func__, ret); + v4l2_err(&dev->v4l2_dev, + "usb_submit_urb in %s returned %d\n", + __func__, ret); if (++err_count > 2) break; continue; @@ -228,7 +233,7 @@ static void hdpvr_transmit_buffers(struct work_struct *work) while (dev->status == STATUS_STREAMING) { if (hdpvr_submit_buffers(dev)) { - v4l2_err(dev->video_dev, "couldn't submit buffers\n"); + v4l2_err(&dev->v4l2_dev, "couldn't submit buffers\n"); goto error; } if (wait_event_interruptible(dev->wait_buffer, @@ -237,11 +242,11 @@ static void hdpvr_transmit_buffers(struct work_struct *work) goto error; } - v4l2_dbg(MSG_INFO, hdpvr_debug, dev->video_dev, + v4l2_dbg(MSG_INFO, hdpvr_debug, &dev->v4l2_dev, "transmit worker exited\n"); return; error: - v4l2_dbg(MSG_INFO, hdpvr_debug, dev->video_dev, + v4l2_dbg(MSG_INFO, hdpvr_debug, &dev->v4l2_dev, "transmit buffers errored\n"); dev->status = STATUS_ERROR; } @@ -260,7 +265,7 @@ static int hdpvr_start_streaming(struct hdpvr_device *dev) vidinf = get_video_info(dev); if (vidinf) { - v4l2_dbg(MSG_BUFFER, hdpvr_debug, dev->video_dev, + v4l2_dbg(MSG_BUFFER, hdpvr_debug, &dev->v4l2_dev, "video signal: %dx%d@%dhz\n", vidinf->width, vidinf->height, vidinf->fps); kfree(vidinf); @@ -269,7 +274,7 @@ static int hdpvr_start_streaming(struct hdpvr_device *dev) ret = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, 0), 0xb8, 0x38, 0x1, 0, NULL, 0, 8000); - v4l2_dbg(MSG_BUFFER, hdpvr_debug, dev->video_dev, + v4l2_dbg(MSG_BUFFER, hdpvr_debug, &dev->v4l2_dev, "encoder start control request returned %d\n", ret); hdpvr_config_call(dev, CTRL_START_STREAMING_VALUE, 0x00); @@ -277,14 +282,14 @@ static int hdpvr_start_streaming(struct hdpvr_device *dev) INIT_WORK(&dev->worker, hdpvr_transmit_buffers); queue_work(dev->workqueue, &dev->worker); - v4l2_dbg(MSG_BUFFER, hdpvr_debug, dev->video_dev, + v4l2_dbg(MSG_BUFFER, hdpvr_debug, &dev->v4l2_dev, "streaming started\n"); dev->status = STATUS_STREAMING; return 0; } msleep(250); - v4l2_dbg(MSG_INFO, hdpvr_debug, dev->video_dev, + v4l2_dbg(MSG_INFO, hdpvr_debug, &dev->v4l2_dev, "no video signal at input %d\n", dev->options.video_input); return -EAGAIN; } @@ -330,14 +335,14 @@ static int hdpvr_open(struct file *file) dev = (struct hdpvr_device *)video_get_drvdata(video_devdata(file)); if (!dev) { - err("open failing with with ENODEV"); + v4l2_err(&dev->v4l2_dev, "open failing with with ENODEV\n"); retval = -ENODEV; goto err; } fh = kzalloc(sizeof(struct hdpvr_fh), GFP_KERNEL); if (!fh) { - err("Out of memory?"); + v4l2_err(&dev->v4l2_dev, "Out of memory\n"); goto err; } /* lock the device to allow correctly handling errors @@ -396,8 +401,8 @@ static ssize_t hdpvr_read(struct file *file, char __user *buffer, size_t count, mutex_lock(&dev->io_mutex); if (dev->status == STATUS_IDLE) { if (hdpvr_start_streaming(dev)) { - v4l2_dbg(MSG_INFO, hdpvr_debug, dev->video_dev, - "start_streaming failed"); + v4l2_dbg(MSG_INFO, hdpvr_debug, &dev->v4l2_dev, + "start_streaming failed\n"); ret = -EIO; msleep(200); dev->status = STATUS_IDLE; @@ -445,7 +450,7 @@ static ssize_t hdpvr_read(struct file *file, char __user *buffer, size_t count, if (copy_to_user(buffer, urb->transfer_buffer + buf->pos, cnt)) { - err("read: copy_to_user failed"); + v4l2_err(&dev->v4l2_dev, "read: copy_to_user failed\n"); if (!ret) ret = -EFAULT; goto err; @@ -493,8 +498,8 @@ static unsigned int hdpvr_poll(struct file *filp, poll_table *wait) if (dev->status == STATUS_IDLE) { if (hdpvr_start_streaming(dev)) { - v4l2_dbg(MSG_BUFFER, hdpvr_debug, dev->video_dev, - "start_streaming failed"); + v4l2_dbg(MSG_BUFFER, hdpvr_debug, &dev->v4l2_dev, + "start_streaming failed\n"); dev->status = STATUS_IDLE; } @@ -1130,7 +1135,7 @@ static int vidioc_encoder_cmd(struct file *filp, void *priv, res = hdpvr_stop_streaming(dev); break; default: - v4l2_dbg(MSG_INFO, hdpvr_debug, dev->video_dev, + v4l2_dbg(MSG_INFO, hdpvr_debug, &dev->v4l2_dev, "Unsupported encoder cmd %d\n", a->cmd); res = -EINVAL; } @@ -1197,7 +1202,7 @@ int hdpvr_register_videodev(struct hdpvr_device *dev, struct device *parent, /* setup and register video device */ dev->video_dev = video_device_alloc(); if (!dev->video_dev) { - err("video_device_alloc() failed"); + v4l2_err(&dev->v4l2_dev, "video_device_alloc() failed\n"); goto error; } @@ -1207,7 +1212,7 @@ int hdpvr_register_videodev(struct hdpvr_device *dev, struct device *parent, video_set_drvdata(dev->video_dev, dev); if (video_register_device(dev->video_dev, VFL_TYPE_GRABBER, devnum)) { - err("V4L2 device registration failed"); + v4l2_err(&dev->v4l2_dev, "video_device registration failed\n"); goto error; } -- cgit v1.2.3 From 7d771ff0dc3371923db929d9f88932acec3fc8e8 Mon Sep 17 00:00:00 2001 From: Janne Grunau Date: Fri, 27 Mar 2009 20:21:17 -0300 Subject: V4L/DVB (11247): hdpvr: empty internal device buffer after stopping streaming Makes the next capturing starting faster and more reliable. Signed-off-by: Janne Grunau Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/hdpvr/hdpvr-video.c | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) (limited to 'drivers/media/video') diff --git a/drivers/media/video/hdpvr/hdpvr-video.c b/drivers/media/video/hdpvr/hdpvr-video.c index f6e1bcefddb7..3e6ffee8dfed 100644 --- a/drivers/media/video/hdpvr/hdpvr-video.c +++ b/drivers/media/video/hdpvr/hdpvr-video.c @@ -298,11 +298,20 @@ static int hdpvr_start_streaming(struct hdpvr_device *dev) /* function expects dev->io_mutex to be hold by caller */ static int hdpvr_stop_streaming(struct hdpvr_device *dev) { + uint actual_length, c = 0; + u8 *buf; + if (dev->status == STATUS_IDLE) return 0; else if (dev->status != STATUS_STREAMING) return -EAGAIN; + buf = kmalloc(dev->bulk_in_size, GFP_KERNEL); + if (!buf) + v4l2_err(&dev->v4l2_dev, "failed to allocate temporary buffer " + "for emptying the internal device buffer. " + "Next capture start will be slow\n"); + dev->status = STATUS_SHUTTING_DOWN; hdpvr_config_call(dev, CTRL_STOP_STREAMING_VALUE, 0x00); mutex_unlock(&dev->io_mutex); @@ -316,6 +325,23 @@ static int hdpvr_stop_streaming(struct hdpvr_device *dev) /* kill the still outstanding urbs */ hdpvr_cancel_queue(dev); + /* emptying the device buffer beforeshutting it down */ + while (buf && ++c < 500 && + !usb_bulk_msg(dev->udev, + usb_rcvbulkpipe(dev->udev, + dev->bulk_in_endpointAddr), + buf, dev->bulk_in_size, &actual_length, + BULK_URB_TIMEOUT)) { + /* wait */ + msleep(5); + v4l2_dbg(MSG_BUFFER, hdpvr_debug, &dev->v4l2_dev, + "%2d: got %d bytes\n", c, actual_length); + } + kfree(buf); + v4l2_dbg(MSG_BUFFER, hdpvr_debug, &dev->v4l2_dev, + "used %d urbs to empty device buffers\n", c-1); + msleep(10); + dev->status = STATUS_IDLE; return 0; -- cgit v1.2.3 From e7ddcd98a179c441d54fe84d221cea4e5852b235 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Sat, 28 Mar 2009 15:35:26 -0300 Subject: V4L/DVB (11251): tuner: prevent invalid initialization of t->config in set_type Drivers that don't set "config" directly in the set_type function will end up with an invalid configuration value. Check that the value is sane, otherwise initialize to 0. Thanks to James Edward Geiger & Steven Toth for reporting this bug. Cc: Steven Toth Cc: James Edward Geiger Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/tuner-core.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/tuner-core.c b/drivers/media/video/tuner-core.c index 2a957e2beabf..421475e0ea59 100644 --- a/drivers/media/video/tuner-core.c +++ b/drivers/media/video/tuner-core.c @@ -364,7 +364,8 @@ static void set_type(struct i2c_client *c, unsigned int type, } t->type = type; - t->config = new_config; + /* prevent invalid config values */ + t->config = ((new_config >= 0) && (new_config < 256)) ? new_config : 0; if (tuner_callback != NULL) { tuner_dbg("defining GPIO callback\n"); t->fe.callback = tuner_callback; -- cgit v1.2.3 From 195784b8efd53c1034c6b6d5c8d8d4d25b91d505 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sat, 28 Mar 2009 09:27:02 -0300 Subject: V4L/DVB (11253): saa7134: fix RTD Embedded Technologies VFG7350 support. This card has the saa6752hs on 7-bit address 0x21 instead of 0x20. Add support in the card definition struct to select which address to use and update the definitions accordingly. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/saa7134/saa7134-cards.c | 8 ++++++++ drivers/media/video/saa7134/saa7134-core.c | 5 +++-- drivers/media/video/saa7134/saa7134-empress.c | 3 +-- drivers/media/video/saa7134/saa7134.h | 1 + 4 files changed, 13 insertions(+), 4 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/saa7134/saa7134-cards.c b/drivers/media/video/saa7134/saa7134-cards.c index 265a52ff8c33..3a038133b260 100644 --- a/drivers/media/video/saa7134/saa7134-cards.c +++ b/drivers/media/video/saa7134/saa7134-cards.c @@ -273,6 +273,7 @@ struct saa7134_board saa7134_boards[] = { .radio_type = UNSET, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, + .empress_addr = 0x20, .inputs = {{ .name = name_comp1, @@ -409,6 +410,7 @@ struct saa7134_board saa7134_boards[] = { .radio_type = UNSET, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, + .empress_addr = 0x20, .tda9887_conf = TDA9887_PRESENT, .gpiomask = 0x820000, .inputs = {{ @@ -819,6 +821,7 @@ struct saa7134_board saa7134_boards[] = { .radio_type = UNSET, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, + .empress_addr = 0x20, .inputs = {{ .name = name_comp1, .vmux = 4, @@ -978,6 +981,7 @@ struct saa7134_board saa7134_boards[] = { .radio_type = UNSET, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, + .empress_addr = 0x20, .inputs = {{ .name = name_comp1, .vmux = 1, @@ -2365,6 +2369,7 @@ struct saa7134_board saa7134_boards[] = { .radio_type = UNSET, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, + .empress_addr = 0x21, .inputs = {{ .name = "Composite 0", .vmux = 0, @@ -4133,6 +4138,7 @@ struct saa7134_board saa7134_boards[] = { .radio_type = UNSET, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, + .empress_addr = 0x20, .tda9887_conf = TDA9887_PRESENT, .inputs = { { .name = name_tv, @@ -4169,6 +4175,7 @@ struct saa7134_board saa7134_boards[] = { .radio_type = UNSET, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, + .empress_addr = 0x20, .tda9887_conf = TDA9887_PRESENT, .inputs = { { .name = name_tv, @@ -4206,6 +4213,7 @@ struct saa7134_board saa7134_boards[] = { .radio_type = UNSET, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, + .empress_addr = 0x20, .tda9887_conf = TDA9887_PRESENT, .inputs = { { .name = name_tv, diff --git a/drivers/media/video/saa7134/saa7134-core.c b/drivers/media/video/saa7134/saa7134-core.c index 321f0d724485..4c24c9c7bb5b 100644 --- a/drivers/media/video/saa7134/saa7134-core.c +++ b/drivers/media/video/saa7134/saa7134-core.c @@ -982,8 +982,9 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev, /* load i2c helpers */ if (card_is_empress(dev)) { struct v4l2_subdev *sd = - v4l2_i2c_new_subdev(&dev->i2c_adap, "saa6752hs", - "saa6752hs", 0x20); + v4l2_i2c_new_subdev(&dev->i2c_adap, + "saa6752hs", "saa6752hs", + saa7134_boards[dev->board].empress_addr); if (sd) sd->grp_id = GRP_EMPRESS; diff --git a/drivers/media/video/saa7134/saa7134-empress.c b/drivers/media/video/saa7134/saa7134-empress.c index c6cfe0fe7e3d..9db3472667e5 100644 --- a/drivers/media/video/saa7134/saa7134-empress.c +++ b/drivers/media/video/saa7134/saa7134-empress.c @@ -416,8 +416,7 @@ static int empress_g_chip_ident(struct file *file, void *fh, if (chip->match.type == V4L2_CHIP_MATCH_I2C_DRIVER && !strcmp(chip->match.name, "saa6752hs")) return saa_call_empress(dev, core, g_chip_ident, chip); - if (chip->match.type == V4L2_CHIP_MATCH_I2C_ADDR && - chip->match.addr == 0x20) + if (chip->match.type == V4L2_CHIP_MATCH_I2C_ADDR) return saa_call_empress(dev, core, g_chip_ident, chip); return -EINVAL; } diff --git a/drivers/media/video/saa7134/saa7134.h b/drivers/media/video/saa7134/saa7134.h index d1498e55bef3..11396687b69c 100644 --- a/drivers/media/video/saa7134/saa7134.h +++ b/drivers/media/video/saa7134/saa7134.h @@ -332,6 +332,7 @@ struct saa7134_board { unsigned int radio_type; unsigned char tuner_addr; unsigned char radio_addr; + unsigned char empress_addr; unsigned int tda9887_conf; unsigned int tuner_config; -- cgit v1.2.3 From 5fed935c4ea98923f4ddbffa29134be5f30e4b2c Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sat, 28 Mar 2009 09:32:42 -0300 Subject: V4L/DVB (11254): cs53l32a: remove legacy support. All drivers that use this device have been converted to v4l2_subdev, so there is no more need to support autoprobing on kernels >= 2.6.22. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cs53l32a.c | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/cs53l32a.c b/drivers/media/video/cs53l32a.c index 2f33abd2e01c..5aeb066857a7 100644 --- a/drivers/media/video/cs53l32a.c +++ b/drivers/media/video/cs53l32a.c @@ -29,7 +29,7 @@ #include #include #include -#include +#include MODULE_DESCRIPTION("i2c device driver for cs53l32a Audio ADC"); MODULE_AUTHOR("Martin Vaughan"); @@ -41,9 +41,6 @@ module_param(debug, bool, 0644); MODULE_PARM_DESC(debug, "Debugging messages, 0=Off (default), 1=On"); -static unsigned short normal_i2c[] = { 0x22 >> 1, I2C_CLIENT_END }; - -I2C_CLIENT_INSMOD; /* ----------------------------------------------------------------------- */ @@ -122,11 +119,6 @@ static int cs53l32a_log_status(struct v4l2_subdev *sd) return 0; } -static int cs53l32a_command(struct i2c_client *client, unsigned cmd, void *arg) -{ - return v4l2_subdev_command(i2c_get_clientdata(client), cmd, arg); -} - /* ----------------------------------------------------------------------- */ static const struct v4l2_subdev_core_ops cs53l32a_core_ops = { @@ -218,7 +210,6 @@ MODULE_DEVICE_TABLE(i2c, cs53l32a_id); static struct v4l2_i2c_driver_data v4l2_i2c_data = { .name = "cs53l32a", - .command = cs53l32a_command, .remove = cs53l32a_remove, .probe = cs53l32a_probe, .id_table = cs53l32a_id, -- cgit v1.2.3 From 3fd8ab30c1fe9118a13f4b55172067ee04ef7a67 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sat, 28 Mar 2009 09:38:29 -0300 Subject: V4L/DVB (11256): dabusb: fix compile warning. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/dabusb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/dabusb.c b/drivers/media/video/dabusb.c index 384da45807a0..ba3709bec3f0 100644 --- a/drivers/media/video/dabusb.c +++ b/drivers/media/video/dabusb.c @@ -675,7 +675,6 @@ static int dabusb_release (struct inode *inode, struct file *file) static long dabusb_ioctl (struct file *file, unsigned int cmd, unsigned long arg) { - lock_kernel(); pdabusb_t s = (pdabusb_t) file->private_data; pbulk_transfer_t pbulk; int ret = 0; @@ -683,6 +682,7 @@ static long dabusb_ioctl (struct file *file, unsigned int cmd, unsigned long arg dbg("dabusb_ioctl"); + lock_kernel(); if (s->remove_pending) { unlock_kernel(); return -EIO; -- cgit v1.2.3 From 34796bc009565ea72643087b7d69c9fa748bce9b Mon Sep 17 00:00:00 2001 From: Trent Piepho Date: Sat, 28 Mar 2009 22:25:35 -0300 Subject: V4L/DVB (11260): v4l2-ioctl: Check format for S_PARM and G_PARM Return EINVAL if VIDIOC_S/G_PARM is called for a buffer type that the driver doesn't define a ->vidioc_try_fmt_XXX() method for. Several other ioctls, like QUERYBUF, QBUF, and DQBUF, etc. do this too. It saves each driver from having to check if the buffer type is one that it supports. Signed-off-by: Trent Piepho Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/v4l2-ioctl.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'drivers/media/video') diff --git a/drivers/media/video/v4l2-ioctl.c b/drivers/media/video/v4l2-ioctl.c index 54ba6b0b951f..f41c6f506f42 100644 --- a/drivers/media/video/v4l2-ioctl.c +++ b/drivers/media/video/v4l2-ioctl.c @@ -1551,6 +1551,9 @@ static long __video_do_ioctl(struct file *file, struct v4l2_streamparm *p = arg; if (ops->vidioc_g_parm) { + ret = check_fmt(ops, p->type); + if (ret) + break; ret = ops->vidioc_g_parm(file, fh, p); } else { if (p->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) @@ -1570,6 +1573,10 @@ static long __video_do_ioctl(struct file *file, if (!ops->vidioc_s_parm) break; + ret = check_fmt(ops, p->type); + if (ret) + break; + dbgarg(cmd, "type=%d\n", p->type); ret = ops->vidioc_s_parm(file, fh, p); break; -- cgit v1.2.3 From 601bc2984508e8b70a604167229f4f687eae63bb Mon Sep 17 00:00:00 2001 From: Trent Piepho Date: Sat, 28 Mar 2009 22:25:35 -0300 Subject: V4L/DVB (11262): bttv: Remove buffer type check from vidioc_g_parm The v4l2-ioctl core only allows buffer types for which the corresponding ->vidioc_try_fmt_xxx() methods are defined to be used with vidioc_(q|dq|query)bufs(), vidioc_reqbufs() and now vidioc_(s|g)_parm. The driver was only allowing VIDEO_CAPTURE buffers for g_parm, but since the driver defines ->vidioc_try_fmt_vid_overlay() and ->vidioc_try_fmt_vbi_cap() it will now allow VIDEO_OVERLAY and VBI_CAPTURE buffers as well. This should be fine as the driver only fills in the frame rate field, which is just as valid for video overlay and vbi capture as it is for video capture. Signed-off-by: Trent Piepho Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/bt8xx/bttv-driver.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/bt8xx/bttv-driver.c b/drivers/media/video/bt8xx/bttv-driver.c index 3079d925e4cf..1dc79b82cf42 100644 --- a/drivers/media/video/bt8xx/bttv-driver.c +++ b/drivers/media/video/bt8xx/bttv-driver.c @@ -2928,8 +2928,6 @@ static int bttv_g_parm(struct file *file, void *f, struct bttv_fh *fh = f; struct bttv *btv = fh->btv; - if (parm->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - return -EINVAL; v4l2_video_std_frame_period(bttv_tvnorms[btv->tvnorm].v4l2_id, &parm->parm.capture.timeperframe); return 0; -- cgit v1.2.3 From 5a27578667b3bd00cab909296824498bdbd732d5 Mon Sep 17 00:00:00 2001 From: Trent Piepho Date: Sat, 28 Mar 2009 22:25:35 -0300 Subject: V4L/DVB (11263): gspca: Stop setting buffer type, and avoid memset in querycap The v4l2-ioctl core checks the buffer type now by only allowing buffer types for which the corresponding ->vidioc_try_fmt_xxx() methods are defined. This driver only defines ->vidioc_try_fmt_vid_cap() so only VIDEO_CAPTURE buffers are allowed to be used with vidioc_g_parm. Also, ->vidioc_enum_fmt_vid_cap() is only called for VIDEO_CAPTURE buffers. There is no need to set the buffer type since it must already be the correct value. The struct which ->vidioc_querycap() is supposed to fill in is already zeroed so it's not necessary to call memset on it. Cc: Jean-Francois Moine Signed-off-by: Trent Piepho Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/gspca.c | 4 ---- 1 file changed, 4 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/gspca/gspca.c b/drivers/media/video/gspca/gspca.c index 66e91d896eda..a75c1ca2db41 100644 --- a/drivers/media/video/gspca/gspca.c +++ b/drivers/media/video/gspca/gspca.c @@ -765,7 +765,6 @@ static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv, fmtdesc->pixelformat = fmt_tb[index]; if (gspca_is_compressed(fmt_tb[index])) fmtdesc->flags = V4L2_FMT_FLAG_COMPRESSED; - fmtdesc->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; fmtdesc->description[0] = fmtdesc->pixelformat & 0xff; fmtdesc->description[1] = (fmtdesc->pixelformat >> 8) & 0xff; fmtdesc->description[2] = (fmtdesc->pixelformat >> 16) & 0xff; @@ -962,8 +961,6 @@ static int vidioc_querycap(struct file *file, void *priv, struct gspca_dev *gspca_dev = priv; int ret; - memset(cap, 0, sizeof *cap); - /* protect the access to the usb device */ if (mutex_lock_interruptible(&gspca_dev->usb_lock)) return -ERESTARTSYS; @@ -1341,7 +1338,6 @@ static int vidioc_g_parm(struct file *filp, void *priv, { struct gspca_dev *gspca_dev = priv; - parm->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; parm->parm.capture.readbuffers = gspca_dev->nbufread; if (gspca_dev->sd_desc->get_streamparm) { -- cgit v1.2.3 From 020b882b1d34e8787658a15e00f2ea0d4651605b Mon Sep 17 00:00:00 2001 From: Trent Piepho Date: Sat, 28 Mar 2009 22:25:36 -0300 Subject: V4L/DVB (11264): omap24xxcam: Remove buffer type check from vidioc_s/g_parm The v4l2-ioctl core now only allows buffer types for which the corresponding ->vidioc_try_fmt_xxx() methods are defined to be used in vidioc_(g|s)_parm. This driver only defines ->vidioc_try_fmt_vid_cap() so only VIDEO_CAPTURE buffers are allowed to be used with vidioc_s_parm() and vidioc_g_parm(). Cc: Sakari Ailus Signed-off-by: Trent Piepho Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/omap24xxcam.c | 6 ------ 1 file changed, 6 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/omap24xxcam.c b/drivers/media/video/omap24xxcam.c index 2cea7fee9b51..5fc4ac0d88f0 100644 --- a/drivers/media/video/omap24xxcam.c +++ b/drivers/media/video/omap24xxcam.c @@ -1285,9 +1285,6 @@ static int vidioc_g_parm(struct file *file, void *fh, struct omap24xxcam_device *cam = ofh->cam; int rval; - if (a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - return -EINVAL; - mutex_lock(&cam->mutex); rval = vidioc_int_g_parm(cam->sdev, a); mutex_unlock(&cam->mutex); @@ -1303,9 +1300,6 @@ static int vidioc_s_parm(struct file *file, void *fh, struct v4l2_streamparm old_streamparm; int rval; - if (a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - return -EINVAL; - mutex_lock(&cam->mutex); if (cam->streaming) { rval = -EBUSY; -- cgit v1.2.3 From 2509e1cb3360961113117f25ae482c430f3bd03d Mon Sep 17 00:00:00 2001 From: Trent Piepho Date: Sat, 28 Mar 2009 22:25:36 -0300 Subject: V4L/DVB (11265): stkwebcam: Remove buffer type check from g_parm and q/dq/reqbufs The v4l2-ioctl core only allows buffer types for which the corresponding ->vidioc_try_fmt_xxx() methods are defined to be used with vidioc_(q|dq|query)bufs(), vidioc_reqbufs() and now vidioc_(s|g)_parm. This driver only defines ->vidioc_try_fmt_vid_cap() so only VIDEO_CAPTURE buffers are allowed to be used with vidioc_g_parm(), vidioc_qbuf(), vidioc_dqbuf(), and vidioc_reqbufs(). Cc: Jaime Velasco Juan Signed-off-by: Trent Piepho Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/stk-webcam.c | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/stk-webcam.c b/drivers/media/video/stk-webcam.c index 6b7f0da9b515..1a6d39cbd6f3 100644 --- a/drivers/media/video/stk-webcam.c +++ b/drivers/media/video/stk-webcam.c @@ -1112,8 +1112,6 @@ static int stk_vidioc_reqbufs(struct file *filp, if (dev == NULL) return -ENODEV; - if (rb->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - return -EINVAL; if (rb->memory != V4L2_MEMORY_MMAP) return -EINVAL; if (is_streaming(dev) @@ -1152,8 +1150,6 @@ static int stk_vidioc_qbuf(struct file *filp, struct stk_camera *dev = priv; struct stk_sio_buffer *sbuf; unsigned long flags; - if (buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - return -EINVAL; if (buf->memory != V4L2_MEMORY_MMAP) return -EINVAL; @@ -1180,8 +1176,7 @@ static int stk_vidioc_dqbuf(struct file *filp, unsigned long flags; int ret; - if (buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE - || !is_streaming(dev)) + if (!is_streaming(dev)) return -EINVAL; if (filp->f_flags & O_NONBLOCK && list_empty(&dev->sio_full)) @@ -1240,9 +1235,6 @@ static int stk_vidioc_streamoff(struct file *filp, static int stk_vidioc_g_parm(struct file *filp, void *priv, struct v4l2_streamparm *sp) { - if (sp->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - return -EINVAL; - /*FIXME This is not correct */ sp->parm.capture.timeperframe.numerator = 1; sp->parm.capture.timeperframe.denominator = 30; -- cgit v1.2.3 From 4f5a7444baaabfa93cfd5d7c8f7e021ea5eaa861 Mon Sep 17 00:00:00 2001 From: Trent Piepho Date: Sat, 28 Mar 2009 22:25:36 -0300 Subject: V4L/DVB (11266): vino: Remove code for things already done by video_ioctl2 The v4l2-ioctl core only allows buffer types for which the corresponding ->vidioc_try_fmt_xxx() methods are defined to be used in vidioc_(g|s)_parm, vidioc_(q|dq|query)buf, and vidioc_reqbufs. Remove buffer type checking from vino_g_parm(), vino_s_parm(), vino_reqbufs(), vino_querybuf(), vino_qbuf(), and vino_dqbuf(). This reduced the indent level of the code so a few lines can be wrapped better. Also fixed the C++ type comments. The v4l2-ioctl core also provides structs that have been pre-zeroed for all fields that driver is supposed to fill in, so remove zeroing code from vino_enum_fmt_vid_cap(). Also, the format index is unsigned so it's not necessary to check if it's less than zero. Signed-off-by: Trent Piepho Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/vino.c | 290 ++++++++++++++++++--------------------------- 1 file changed, 114 insertions(+), 176 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/vino.c b/drivers/media/video/vino.c index 675067f92d96..8da4dd1e0e94 100644 --- a/drivers/media/video/vino.c +++ b/drivers/media/video/vino.c @@ -3102,22 +3102,14 @@ out: static int vino_enum_fmt_vid_cap(struct file *file, void *__fh, struct v4l2_fmtdesc *fd) { - enum v4l2_buf_type type = fd->type; - int index = fd->index; + dprintk("format index = %d\n", fd->index); - dprintk("format index = %d\n", index); - - if ((fd->index < 0) || - (fd->index >= VINO_DATA_FMT_COUNT)) + if (fd->index >= VINO_DATA_FMT_COUNT) return -EINVAL; - dprintk("format name = %s\n", - vino_data_formats[index].description); - - memset(fd, 0, sizeof(struct v4l2_fmtdesc)); - fd->index = index; - fd->type = type; - fd->pixelformat = vino_data_formats[index].pixelformat; - strcpy(fd->description, vino_data_formats[index].description); + dprintk("format name = %s\n", vino_data_formats[fd->index].description); + + fd->pixelformat = vino_data_formats[fd->index].pixelformat; + strcpy(fd->description, vino_data_formats[fd->index].description); return 0; } @@ -3327,28 +3319,18 @@ static int vino_g_parm(struct file *file, void *__fh, { struct vino_channel_settings *vcs = video_drvdata(file); unsigned long flags; + struct v4l2_captureparm *cp = &sp->parm.capture; - switch (sp->type) { - case V4L2_BUF_TYPE_VIDEO_CAPTURE: { - struct v4l2_captureparm *cp = &sp->parm.capture; - memset(cp, 0, sizeof(struct v4l2_captureparm)); + cp->capability = V4L2_CAP_TIMEPERFRAME; + cp->timeperframe.numerator = 1; - cp->capability = V4L2_CAP_TIMEPERFRAME; - cp->timeperframe.numerator = 1; + spin_lock_irqsave(&vino_drvdata->input_lock, flags); - spin_lock_irqsave(&vino_drvdata->input_lock, flags); + cp->timeperframe.denominator = vcs->fps; - cp->timeperframe.denominator = vcs->fps; + spin_unlock_irqrestore(&vino_drvdata->input_lock, flags); - spin_unlock_irqrestore(&vino_drvdata->input_lock, flags); - - // TODO: cp->readbuffers = xxx; - break; - } - case V4L2_BUF_TYPE_VIDEO_OVERLAY: - default: - return -EINVAL; - } + /* TODO: cp->readbuffers = xxx; */ return 0; } @@ -3358,32 +3340,21 @@ static int vino_s_parm(struct file *file, void *__fh, { struct vino_channel_settings *vcs = video_drvdata(file); unsigned long flags; + struct v4l2_captureparm *cp = &sp->parm.capture; - switch (sp->type) { - case V4L2_BUF_TYPE_VIDEO_CAPTURE: { - struct v4l2_captureparm *cp = &sp->parm.capture; - - spin_lock_irqsave(&vino_drvdata->input_lock, flags); - - if ((cp->timeperframe.numerator == 0) || - (cp->timeperframe.denominator == 0)) { - /* reset framerate */ - vino_set_default_framerate(vcs); - } else { - vino_set_framerate(vcs, cp->timeperframe.denominator / - cp->timeperframe.numerator); - } - - spin_unlock_irqrestore(&vino_drvdata->input_lock, flags); + spin_lock_irqsave(&vino_drvdata->input_lock, flags); - // TODO: set buffers according to cp->readbuffers - break; - } - case V4L2_BUF_TYPE_VIDEO_OVERLAY: - default: - return -EINVAL; + if ((cp->timeperframe.numerator == 0) || + (cp->timeperframe.denominator == 0)) { + /* reset framerate */ + vino_set_default_framerate(vcs); + } else { + vino_set_framerate(vcs, cp->timeperframe.denominator / + cp->timeperframe.numerator); } + spin_unlock_irqrestore(&vino_drvdata->input_lock, flags); + return 0; } @@ -3391,42 +3362,35 @@ static int vino_reqbufs(struct file *file, void *__fh, struct v4l2_requestbuffers *rb) { struct vino_channel_settings *vcs = video_drvdata(file); + if (vcs->reading) return -EBUSY; - switch (rb->type) { - case V4L2_BUF_TYPE_VIDEO_CAPTURE: { - // TODO: check queue type - if (rb->memory != V4L2_MEMORY_MMAP) { - dprintk("type not mmap\n"); - return -EINVAL; - } + /* TODO: check queue type */ + if (rb->memory != V4L2_MEMORY_MMAP) { + dprintk("type not mmap\n"); + return -EINVAL; + } - dprintk("count = %d\n", rb->count); - if (rb->count > 0) { - if (vino_is_capturing(vcs)) { - dprintk("busy, capturing\n"); - return -EBUSY; - } + dprintk("count = %d\n", rb->count); + if (rb->count > 0) { + if (vino_is_capturing(vcs)) { + dprintk("busy, capturing\n"); + return -EBUSY; + } - if (vino_queue_has_mapped_buffers(&vcs->fb_queue)) { - dprintk("busy, buffers still mapped\n"); - return -EBUSY; - } else { - vcs->streaming = 0; - vino_queue_free(&vcs->fb_queue); - vino_queue_init(&vcs->fb_queue, &rb->count); - } + if (vino_queue_has_mapped_buffers(&vcs->fb_queue)) { + dprintk("busy, buffers still mapped\n"); + return -EBUSY; } else { vcs->streaming = 0; - vino_capture_stop(vcs); vino_queue_free(&vcs->fb_queue); + vino_queue_init(&vcs->fb_queue, &rb->count); } - break; - } - case V4L2_BUF_TYPE_VIDEO_OVERLAY: - default: - return -EINVAL; + } else { + vcs->streaming = 0; + vino_capture_stop(vcs); + vino_queue_free(&vcs->fb_queue); } return 0; @@ -3474,35 +3438,27 @@ static int vino_querybuf(struct file *file, void *__fh, struct v4l2_buffer *b) { struct vino_channel_settings *vcs = video_drvdata(file); + struct vino_framebuffer *fb; + if (vcs->reading) return -EBUSY; - switch (b->type) { - case V4L2_BUF_TYPE_VIDEO_CAPTURE: { - struct vino_framebuffer *fb; - - // TODO: check queue type - if (b->index >= vino_queue_get_length(&vcs->fb_queue)) { - dprintk("invalid index = %d\n", - b->index); - return -EINVAL; - } - - fb = vino_queue_get_buffer(&vcs->fb_queue, - b->index); - if (fb == NULL) { - dprintk("vino_queue_get_buffer() failed"); - return -EINVAL; - } - - vino_v4l2_get_buffer_status(vcs, fb, b); - break; + /* TODO: check queue type */ + if (b->index >= vino_queue_get_length(&vcs->fb_queue)) { + dprintk("invalid index = %d\n", + b->index); + return -EINVAL; } - case V4L2_BUF_TYPE_VIDEO_OVERLAY: - default: + + fb = vino_queue_get_buffer(&vcs->fb_queue, + b->index); + if (fb == NULL) { + dprintk("vino_queue_get_buffer() failed"); return -EINVAL; } + vino_v4l2_get_buffer_status(vcs, fb, b); + return 0; } @@ -3510,36 +3466,28 @@ static int vino_qbuf(struct file *file, void *__fh, struct v4l2_buffer *b) { struct vino_channel_settings *vcs = video_drvdata(file); + struct vino_framebuffer *fb; + int ret; + if (vcs->reading) return -EBUSY; - switch (b->type) { - case V4L2_BUF_TYPE_VIDEO_CAPTURE: { - struct vino_framebuffer *fb; - int ret; - - // TODO: check queue type - if (b->memory != V4L2_MEMORY_MMAP) { - dprintk("type not mmap\n"); - return -EINVAL; - } + /* TODO: check queue type */ + if (b->memory != V4L2_MEMORY_MMAP) { + dprintk("type not mmap\n"); + return -EINVAL; + } - fb = vino_capture_enqueue(vcs, b->index); - if (fb == NULL) - return -EINVAL; + fb = vino_capture_enqueue(vcs, b->index); + if (fb == NULL) + return -EINVAL; - vino_v4l2_get_buffer_status(vcs, fb, b); + vino_v4l2_get_buffer_status(vcs, fb, b); - if (vcs->streaming) { - ret = vino_capture_next(vcs, 1); - if (ret) - return ret; - } - break; - } - case V4L2_BUF_TYPE_VIDEO_OVERLAY: - default: - return -EINVAL; + if (vcs->streaming) { + ret = vino_capture_next(vcs, 1); + if (ret) + return ret; } return 0; @@ -3550,73 +3498,63 @@ static int vino_dqbuf(struct file *file, void *__fh, { struct vino_channel_settings *vcs = video_drvdata(file); unsigned int nonblocking = file->f_flags & O_NONBLOCK; + struct vino_framebuffer *fb; + unsigned int incoming, outgoing; + int err; + if (vcs->reading) return -EBUSY; - switch (b->type) { - case V4L2_BUF_TYPE_VIDEO_CAPTURE: { - struct vino_framebuffer *fb; - unsigned int incoming, outgoing; - int err; + /* TODO: check queue type */ + + err = vino_queue_get_incoming(&vcs->fb_queue, &incoming); + if (err) { + dprintk("vino_queue_get_incoming() failed\n"); + return -EINVAL; + } + err = vino_queue_get_outgoing(&vcs->fb_queue, &outgoing); + if (err) { + dprintk("vino_queue_get_outgoing() failed\n"); + return -EINVAL; + } - // TODO: check queue type + dprintk("incoming = %d, outgoing = %d\n", incoming, outgoing); - err = vino_queue_get_incoming(&vcs->fb_queue, &incoming); - if (err) { - dprintk("vino_queue_get_incoming() failed\n"); + if (outgoing == 0) { + if (incoming == 0) { + dprintk("no incoming or outgoing buffers\n"); return -EINVAL; } - err = vino_queue_get_outgoing(&vcs->fb_queue, &outgoing); - if (err) { - dprintk("vino_queue_get_outgoing() failed\n"); - return -EINVAL; + if (nonblocking) { + dprintk("non-blocking I/O was selected and " + "there are no buffers to dequeue\n"); + return -EAGAIN; } - dprintk("incoming = %d, outgoing = %d\n", incoming, outgoing); - - if (outgoing == 0) { - if (incoming == 0) { - dprintk("no incoming or outgoing buffers\n"); - return -EINVAL; - } - if (nonblocking) { - dprintk("non-blocking I/O was selected and " - "there are no buffers to dequeue\n"); - return -EAGAIN; - } - + err = vino_wait_for_frame(vcs); + if (err) { err = vino_wait_for_frame(vcs); if (err) { - err = vino_wait_for_frame(vcs); - if (err) { - /* interrupted or - * no frames captured because - * of frame skipping */ - // vino_capture_failed(vcs); - return -EIO; - } + /* interrupted or no frames captured because of + * frame skipping */ + /* vino_capture_failed(vcs); */ + return -EIO; } } + } - fb = vino_queue_remove(&vcs->fb_queue, &b->index); - if (fb == NULL) { - dprintk("vino_queue_remove() failed\n"); - return -EINVAL; - } - - err = vino_check_buffer(vcs, fb); + fb = vino_queue_remove(&vcs->fb_queue, &b->index); + if (fb == NULL) { + dprintk("vino_queue_remove() failed\n"); + return -EINVAL; + } - vino_v4l2_get_buffer_status(vcs, fb, b); + err = vino_check_buffer(vcs, fb); - if (err) - return -EIO; + vino_v4l2_get_buffer_status(vcs, fb, b); - break; - } - case V4L2_BUF_TYPE_VIDEO_OVERLAY: - default: - return -EINVAL; - } + if (err) + return -EIO; return 0; } -- cgit v1.2.3 From e33ee31ac39620c2f91bd8c057982f94a31df958 Mon Sep 17 00:00:00 2001 From: Trent Piepho Date: Sat, 28 Mar 2009 22:25:36 -0300 Subject: V4L/DVB (11267): cafe_ccic: Remove buffer type check from XXXbuf The v4l2-ioctl core only allows buffer types for which the corresponding ->vidioc_try_fmt_xxx() methods are defined to be used with vidioc_(q|dq|query)bufs() and vidioc_reqbufs(). This driver only defines ->vidioc_try_fmt_vid_cap() so only VIDEO_CAPTURE buffers are allowed to be used with cafe_vidioc_reqbufs(), cafe_vidioc_querybuf(), cafe_vidioc_qbuf(), and cafe_vidioc_dqbuf(). The ->vidioc_(s|g|try|enum)_fmt_vid_cap() methods are only called on VIDEO_CAPTURE buffers. Thus, there is no need to check or set the buffer's 'type' field since it must already be set to VIDEO_CAPTURE. So the check in cafe_vidioc_enum_fmt_vid_cap() can be removed. The 'index' field of v4l2_buffer is unsigned so the checks for it being less than zero can be removed too. Signed-off-by: Trent Piepho Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cafe_ccic.c | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/cafe_ccic.c b/drivers/media/video/cafe_ccic.c index 1c79369447f4..7abe94d9fb4c 100644 --- a/drivers/media/video/cafe_ccic.c +++ b/drivers/media/video/cafe_ccic.c @@ -1151,8 +1151,6 @@ static int cafe_vidioc_reqbufs(struct file *filp, void *priv, * Make sure it's something we can do. User pointers could be * implemented without great pain, but that's not been done yet. */ - if (req->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - return -EINVAL; if (req->memory != V4L2_MEMORY_MMAP) return -EINVAL; /* @@ -1216,9 +1214,7 @@ static int cafe_vidioc_querybuf(struct file *filp, void *priv, int ret = -EINVAL; mutex_lock(&cam->s_mutex); - if (buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - goto out; - if (buf->index < 0 || buf->index >= cam->n_sbufs) + if (buf->index >= cam->n_sbufs) goto out; *buf = cam->sb_bufs[buf->index].v4lbuf; ret = 0; @@ -1236,9 +1232,7 @@ static int cafe_vidioc_qbuf(struct file *filp, void *priv, unsigned long flags; mutex_lock(&cam->s_mutex); - if (buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - goto out; - if (buf->index < 0 || buf->index >= cam->n_sbufs) + if (buf->index >= cam->n_sbufs) goto out; sbuf = cam->sb_bufs + buf->index; if (sbuf->v4lbuf.flags & V4L2_BUF_FLAG_QUEUED) { @@ -1269,8 +1263,6 @@ static int cafe_vidioc_dqbuf(struct file *filp, void *priv, unsigned long flags; mutex_lock(&cam->s_mutex); - if (buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - goto out_unlock; if (cam->state != S_STREAMING) goto out_unlock; if (list_empty(&cam->sb_full) && filp->f_flags & O_NONBLOCK) { @@ -1503,8 +1495,6 @@ static int cafe_vidioc_enum_fmt_vid_cap(struct file *filp, struct cafe_camera *cam = priv; int ret; - if (fmt->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - return -EINVAL; mutex_lock(&cam->s_mutex); ret = sensor_call(cam, video, enum_fmt, fmt); mutex_unlock(&cam->s_mutex); -- cgit v1.2.3 From f29816bc317704a33b15269b9e2201de3c9d6a79 Mon Sep 17 00:00:00 2001 From: Trent Piepho Date: Sat, 28 Mar 2009 22:25:36 -0300 Subject: V4L/DVB (11268): cx23885-417: Don't need to zero ioctl parameter fields The v4l2 core code in v4l2_ioctl will zero out the structure the driver is supposed to fill in for read-only ioctls. For read/write ioctls, all the fields which aren't supplied from userspace will be zeroed out. Zeroing code is removed from enum_input, g_tuner, g_frequency, querycap, enum_fmt_vid_cap, g_fmt_vid_cap, and try_fmt_vid_cap. The ->vidioc_(s|g|try|enum)_fmt_vid_cap() methods are only called on VIDEO_CAPTURE buffers. Thus, there is no need to check or set the buffer's 'type' field since it must already be set to VIDEO_CAPTURE. There also appeared to be a copy and paste error in vidioc_try_fmt_vid_cap() that would set f->fmt.pix.sizeimage to zero. Note that the s_fmt_vid_cap method doesn't appear to actually do anything. Whatever parameters were requested are just silently ignored. Was this intentional? Who knows, as the commit log entry for the driver just says, "Add generic cx23417 hardware encoder support." There are no docs. A comment like "this driver totally ignores the v4l2 spec w.r.t. VIDIOC_S_FMT because ..." would have gone a long way. Cc: Steven Toth Signed-off-by: Trent Piepho Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx23885/cx23885-417.c | 27 ++++----------------------- 1 file changed, 4 insertions(+), 23 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/cx23885/cx23885-417.c b/drivers/media/video/cx23885/cx23885-417.c index bfe25841dbf4..b02944d38932 100644 --- a/drivers/media/video/cx23885/cx23885-417.c +++ b/drivers/media/video/cx23885/cx23885-417.c @@ -1198,21 +1198,16 @@ static int vidioc_enum_input(struct file *file, void *priv, struct cx23885_fh *fh = file->private_data; struct cx23885_dev *dev = fh->dev; struct cx23885_input *input; - unsigned int n; + int n; - n = i->index; - - if (n >= 4) + if (i->index >= 4) return -EINVAL; - input = &cx23885_boards[dev->board].input[n]; + input = &cx23885_boards[dev->board].input[i->index]; if (input->type == 0) return -EINVAL; - memset(i, 0, sizeof(*i)); - i->index = n; - /* FIXME * strcpy(i->name, input->name); */ strcpy(i->name, "unset"); @@ -1255,7 +1250,6 @@ static int vidioc_g_tuner(struct file *file, void *priv, return -EINVAL; if (0 != t->index) return -EINVAL; - memset(t, 0, sizeof(*t)); strcpy(t->name, "Television"); cx23885_call_i2c_clients(&dev->i2c_bus[2], VIDIOC_G_TUNER, t); cx23885_call_i2c_clients(&dev->i2c_bus[1], VIDIOC_G_TUNER, t); @@ -1286,7 +1280,6 @@ static int vidioc_g_frequency(struct file *file, void *priv, struct cx23885_fh *fh = file->private_data; struct cx23885_dev *dev = fh->dev; - memset(f, 0, sizeof(*f)); if (UNSET == dev->tuner_type) return -EINVAL; f->type = V4L2_TUNER_ANALOG_TV; @@ -1346,7 +1339,6 @@ static int vidioc_querycap(struct file *file, void *priv, struct cx23885_dev *dev = fh->dev; struct cx23885_tsport *tsport = &dev->ts1; - memset(cap, 0, sizeof(*cap)); strcpy(cap->driver, dev->name); strlcpy(cap->card, cx23885_boards[tsport->dev->board].name, sizeof(cap->card)); @@ -1366,16 +1358,10 @@ static int vidioc_querycap(struct file *file, void *priv, static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv, struct v4l2_fmtdesc *f) { - int index; - - index = f->index; - if (index != 0) + if (f->index != 0) return -EINVAL; - memset(f, 0, sizeof(*f)); - f->index = index; strlcpy(f->description, "MPEG", sizeof(f->description)); - f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; f->pixelformat = V4L2_PIX_FMT_MPEG; return 0; @@ -1387,8 +1373,6 @@ static int vidioc_g_fmt_vid_cap(struct file *file, void *priv, struct cx23885_fh *fh = file->private_data; struct cx23885_dev *dev = fh->dev; - memset(f, 0, sizeof(*f)); - f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG; f->fmt.pix.bytesperline = 0; f->fmt.pix.sizeimage = @@ -1408,12 +1392,10 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv, struct cx23885_fh *fh = file->private_data; struct cx23885_dev *dev = fh->dev; - f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG; f->fmt.pix.bytesperline = 0; f->fmt.pix.sizeimage = dev->ts1.ts_packet_size * dev->ts1.ts_packet_count; - f->fmt.pix.sizeimage = f->fmt.pix.colorspace = 0; dprintk(1, "VIDIOC_TRY_FMT: w: %d, h: %d, f: %d\n", dev->ts1.width, dev->ts1.height, fh->mpegq.field); @@ -1426,7 +1408,6 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, struct cx23885_fh *fh = file->private_data; struct cx23885_dev *dev = fh->dev; - f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG; f->fmt.pix.bytesperline = 0; f->fmt.pix.sizeimage = -- cgit v1.2.3 From 185cda966633fc18b9df09b6d84d5ec2db4a57ff Mon Sep 17 00:00:00 2001 From: Trent Piepho Date: Sat, 28 Mar 2009 22:25:36 -0300 Subject: V4L/DVB (11269): cx88-blackbird: Stop setting buffer type in XXX_fmt_vid_cap The ->vidioc_(s|g|try|enum)_fmt_vid_cap() methods are only called on VIDEO_CAPTURE buffers. Thus, there is no need to check or set the 'type' field since it must already be set to VIDEO_CAPTURE. Signed-off-by: Trent Piepho Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx88/cx88-blackbird.c | 4 ---- 1 file changed, 4 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/cx88/cx88-blackbird.c b/drivers/media/video/cx88/cx88-blackbird.c index 7f5b8bfd08ac..484df549345c 100644 --- a/drivers/media/video/cx88/cx88-blackbird.c +++ b/drivers/media/video/cx88/cx88-blackbird.c @@ -746,7 +746,6 @@ static int vidioc_enum_fmt_vid_cap (struct file *file, void *priv, return -EINVAL; strlcpy(f->description, "MPEG", sizeof(f->description)); - f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; f->pixelformat = V4L2_PIX_FMT_MPEG; return 0; } @@ -757,7 +756,6 @@ static int vidioc_g_fmt_vid_cap (struct file *file, void *priv, struct cx8802_fh *fh = priv; struct cx8802_dev *dev = fh->dev; - f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG; f->fmt.pix.bytesperline = 0; f->fmt.pix.sizeimage = dev->ts_packet_size * dev->ts_packet_count; /* 188 * 4 * 1024; */ @@ -776,7 +774,6 @@ static int vidioc_try_fmt_vid_cap (struct file *file, void *priv, struct cx8802_fh *fh = priv; struct cx8802_dev *dev = fh->dev; - f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG; f->fmt.pix.bytesperline = 0; f->fmt.pix.sizeimage = dev->ts_packet_size * dev->ts_packet_count; /* 188 * 4 * 1024; */; @@ -793,7 +790,6 @@ static int vidioc_s_fmt_vid_cap (struct file *file, void *priv, struct cx8802_dev *dev = fh->dev; struct cx88_core *core = dev->core; - f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG; f->fmt.pix.bytesperline = 0; f->fmt.pix.sizeimage = dev->ts_packet_size * dev->ts_packet_count; /* 188 * 4 * 1024; */; -- cgit v1.2.3 From 6174523c5948f8a36f778f0abdfc648a5d73bf46 Mon Sep 17 00:00:00 2001 From: Trent Piepho Date: Sat, 28 Mar 2009 22:25:36 -0300 Subject: V4L/DVB (11270): meye: Remove buffer type checks from XXX_fmt_vid_cap, XXXbuf The ->vidioc_(s|g|try|enum)_fmt_vid_cap() methods are only called on VIDEO_CAPTURE buffers. Thus, there is no need to check or set the buffer's 'type' field since it must already be set to VIDEO_CAPTURE. The v4l2-ioctl core only allows buffer types for which the corresponding ->vidioc_try_fmt_xxx() methods are defined to be used with vidioc_(q|dq|query)bufs() and vidioc_reqbufs(). Since this driver only defines ->vidioc_try_fmt_vid_cap() the checks can be removed from vidioc_reqbufs(), vidioc_querybuf(), vidioc_qbuf(), and vidioc_dqbuf(). Also, the buffer index is unsigned so it's not necessary to check if it is less than zero. Signed-off-by: Trent Piepho Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/meye.c | 29 +++-------------------------- 1 file changed, 3 insertions(+), 26 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/meye.c b/drivers/media/video/meye.c index d9d73d888aa0..2ad11f0999c6 100644 --- a/drivers/media/video/meye.c +++ b/drivers/media/video/meye.c @@ -1256,18 +1256,13 @@ static int vidioc_enum_fmt_vid_cap(struct file *file, void *fh, if (f->index > 1) return -EINVAL; - if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - return -EINVAL; - if (f->index == 0) { /* standard YUV 422 capture */ - f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; f->flags = 0; strcpy(f->description, "YUV422"); f->pixelformat = V4L2_PIX_FMT_YUYV; } else { /* compressed MJPEG capture */ - f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; f->flags = V4L2_FMT_FLAG_COMPRESSED; strcpy(f->description, "MJPEG"); f->pixelformat = V4L2_PIX_FMT_MJPEG; @@ -1279,9 +1274,6 @@ static int vidioc_enum_fmt_vid_cap(struct file *file, void *fh, static int vidioc_try_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *f) { - if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - return -EINVAL; - if (f->fmt.pix.pixelformat != V4L2_PIX_FMT_YUYV && f->fmt.pix.pixelformat != V4L2_PIX_FMT_MJPEG) return -EINVAL; @@ -1312,9 +1304,6 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *fh, static int vidioc_g_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *f) { - if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - return -EINVAL; - switch (meye.mchip_mode) { case MCHIP_HIC_MODE_CONT_OUT: default: @@ -1338,9 +1327,6 @@ static int vidioc_g_fmt_vid_cap(struct file *file, void *fh, static int vidioc_s_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *f) { - if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - return -EINVAL; - if (f->fmt.pix.pixelformat != V4L2_PIX_FMT_YUYV && f->fmt.pix.pixelformat != V4L2_PIX_FMT_MJPEG) return -EINVAL; @@ -1386,9 +1372,6 @@ static int vidioc_reqbufs(struct file *file, void *fh, { int i; - if (req->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - return -EINVAL; - if (req->memory != V4L2_MEMORY_MMAP) return -EINVAL; @@ -1429,9 +1412,9 @@ static int vidioc_reqbufs(struct file *file, void *fh, static int vidioc_querybuf(struct file *file, void *fh, struct v4l2_buffer *buf) { - int index = buf->index; + unsigned int index = buf->index; - if (index < 0 || index >= gbuffers) + if (index >= gbuffers) return -EINVAL; buf->bytesused = meye.grab_buffer[index].size; @@ -1455,13 +1438,10 @@ static int vidioc_querybuf(struct file *file, void *fh, struct v4l2_buffer *buf) static int vidioc_qbuf(struct file *file, void *fh, struct v4l2_buffer *buf) { - if (buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - return -EINVAL; - if (buf->memory != V4L2_MEMORY_MMAP) return -EINVAL; - if (buf->index < 0 || buf->index >= gbuffers) + if (buf->index >= gbuffers) return -EINVAL; if (meye.grab_buffer[buf->index].state != MEYE_BUF_UNUSED) @@ -1481,9 +1461,6 @@ static int vidioc_dqbuf(struct file *file, void *fh, struct v4l2_buffer *buf) { int reqnr; - if (buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - return -EINVAL; - if (buf->memory != V4L2_MEMORY_MMAP) return -EINVAL; -- cgit v1.2.3 From 975f5766be048fb65eae6dbf423db129cd641124 Mon Sep 17 00:00:00 2001 From: Trent Piepho Date: Sat, 28 Mar 2009 22:25:36 -0300 Subject: V4L/DVB (11271): usbvision: Remove buffer type checks from enum_fmt_vid_cap, XXXbuf The v4l2-ioctl core only allows buffer types for which the corresponding ->vidioc_try_fmt_xxx() methods are defined to be used with vidioc_(q|dq|query)buf() and vidioc_reqbufs(). Since this driver only defines ->vidioc_try_fmt_vid_cap() the checks can be removed from vidioc_reqbufs(), vidioc_qbuf(), and vidioc_dqbuf(). The ->vidioc_(s|g|try|enum)_fmt_vid_cap() methods are only called on VIDEO_CAPTURE buffers. Thus, there is no need to check or set the buffer's 'type' field since it must already be set to VIDEO_CAPTURE. So setting the buffer type in vidioc_enum_fmt_vid_cap() can be removed. Signed-off-by: Trent Piepho Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/usbvision/usbvision-video.c | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/usbvision/usbvision-video.c b/drivers/media/video/usbvision/usbvision-video.c index 74a7652dee43..fa62a2fd7b22 100644 --- a/drivers/media/video/usbvision/usbvision-video.c +++ b/drivers/media/video/usbvision/usbvision-video.c @@ -757,8 +757,7 @@ static int vidioc_reqbufs (struct file *file, /* Check input validity: the user must do a VIDEO CAPTURE and MMAP method. */ - if((vr->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) || - (vr->memory != V4L2_MEMORY_MMAP)) + if (vr->memory != V4L2_MEMORY_MMAP) return -EINVAL; if(usbvision->streaming == Stream_On) { @@ -816,9 +815,6 @@ static int vidioc_qbuf (struct file *file, void *priv, struct v4l2_buffer *vb) unsigned long lock_flags; /* FIXME : works only on VIDEO_CAPTURE MODE, MMAP. */ - if(vb->type != V4L2_CAP_VIDEO_CAPTURE) { - return -EINVAL; - } if(vb->index>=usbvision->num_frames) { return -EINVAL; } @@ -853,9 +849,6 @@ static int vidioc_dqbuf (struct file *file, void *priv, struct v4l2_buffer *vb) struct usbvision_frame *f; unsigned long lock_flags; - if (vb->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - return -EINVAL; - if (list_empty(&(usbvision->outqueue))) { if (usbvision->streaming == Stream_Idle) return -EINVAL; @@ -921,7 +914,6 @@ static int vidioc_enum_fmt_vid_cap (struct file *file, void *priv, if(vfd->index>=USBVISION_SUPPORTED_PALETTES-1) { return -EINVAL; } - vfd->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; strcpy(vfd->description,usbvision_v4l2_format[vfd->index].desc); vfd->pixelformat = usbvision_v4l2_format[vfd->index].format; return 0; -- cgit v1.2.3 From 8f84a775c2ad8a0d95f944f6397248b9c0c25e50 Mon Sep 17 00:00:00 2001 From: Trent Piepho Date: Sat, 28 Mar 2009 22:25:36 -0300 Subject: V4L/DVB (11272): zr364xx: Remove code for things already done by video_ioctl2 The ->vidioc_(s|g|try|enum)_fmt_vid_cap() methods are only called on VIDEO_CAPTURE buffers. Thus, there is no need to check or set the buffer's 'type' field since it must already be set to VIDEO_CAPTURE. Checking the buffer type can be removed from zr364xx_vidioc_(s|g|try|enum)_fmt_vid_cap(). The v4l2 core code in v4l2_ioctl will zero out the structure the driver is supposed to fill in for read-only ioctls. For read/write ioctls, all the fields which aren't supplied from userspace will be zeroed out. Zeroing code can be removed from zr364xx_vidioc_querycap(), zr364xx_vidioc_enum_input(), zr364xx_vidioc_enum_fmt_vid_cap(), and zr364xx_vidioc_g_fmt_vid_cap(). Cc: Antoine Jacquet Signed-off-by: Trent Piepho Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/zr364xx.c | 16 ---------------- 1 file changed, 16 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/zr364xx.c b/drivers/media/video/zr364xx.c index f2f8cdd71c46..221409fe1682 100644 --- a/drivers/media/video/zr364xx.c +++ b/drivers/media/video/zr364xx.c @@ -426,7 +426,6 @@ static ssize_t zr364xx_read(struct file *file, char __user *buf, size_t cnt, static int zr364xx_vidioc_querycap(struct file *file, void *priv, struct v4l2_capability *cap) { - memset(cap, 0, sizeof(*cap)); strcpy(cap->driver, DRIVER_DESC); cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE; return 0; @@ -437,8 +436,6 @@ static int zr364xx_vidioc_enum_input(struct file *file, void *priv, { if (i->index != 0) return -EINVAL; - memset(i, 0, sizeof(*i)); - i->index = 0; strcpy(i->name, DRIVER_DESC " Camera"); i->type = V4L2_INPUT_TYPE_CAMERA; return 0; @@ -530,11 +527,6 @@ static int zr364xx_vidioc_enum_fmt_vid_cap(struct file *file, { if (f->index > 0) return -EINVAL; - if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - return -EINVAL; - memset(f, 0, sizeof(*f)); - f->index = 0; - f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; f->flags = V4L2_FMT_FLAG_COMPRESSED; strcpy(f->description, "JPEG"); f->pixelformat = V4L2_PIX_FMT_JPEG; @@ -551,8 +543,6 @@ static int zr364xx_vidioc_try_fmt_vid_cap(struct file *file, void *priv, return -ENODEV; cam = video_get_drvdata(vdev); - if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - return -EINVAL; if (f->fmt.pix.pixelformat != V4L2_PIX_FMT_JPEG) return -EINVAL; if (f->fmt.pix.field != V4L2_FIELD_ANY && @@ -578,10 +568,6 @@ static int zr364xx_vidioc_g_fmt_vid_cap(struct file *file, void *priv, return -ENODEV; cam = video_get_drvdata(vdev); - if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - return -EINVAL; - memset(&f->fmt.pix, 0, sizeof(struct v4l2_pix_format)); - f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; f->fmt.pix.pixelformat = V4L2_PIX_FMT_JPEG; f->fmt.pix.field = V4L2_FIELD_NONE; f->fmt.pix.width = cam->width; @@ -603,8 +589,6 @@ static int zr364xx_vidioc_s_fmt_vid_cap(struct file *file, void *priv, return -ENODEV; cam = video_get_drvdata(vdev); - if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - return -EINVAL; if (f->fmt.pix.pixelformat != V4L2_PIX_FMT_JPEG) return -EINVAL; if (f->fmt.pix.field != V4L2_FIELD_ANY && -- cgit v1.2.3 From 5fa7b9f3c0f249a4faed6c3e534917199249ead8 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 18 Mar 2009 13:59:34 -0300 Subject: V4L/DVB (11275): tvaudio: fix mute and s/g_tuner handling The mute control depends on CHIP_HAS_INPUTSEL, so test for that first. The s/g_tuner code should check whether getmode/setmode is set at the beginning instead of filling in the struct and discovering at the end that this chip doesn't implement audiomodes after all (i.e. is a simple muxer chip). Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/tvaudio.c | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/tvaudio.c b/drivers/media/video/tvaudio.c index e8ab28532d94..faa9e3dd782f 100644 --- a/drivers/media/video/tvaudio.c +++ b/drivers/media/video/tvaudio.c @@ -1511,6 +1511,8 @@ static int tvaudio_g_ctrl(struct v4l2_subdev *sd, switch (ctrl->id) { case V4L2_CID_AUDIO_MUTE: + if (!(desc->flags & CHIP_HAS_INPUTSEL)) + break; ctrl->value=chip->muted; return 0; case V4L2_CID_AUDIO_VOLUME: @@ -1552,6 +1554,9 @@ static int tvaudio_s_ctrl(struct v4l2_subdev *sd, switch (ctrl->id) { case V4L2_CID_AUDIO_MUTE: + if (!(desc->flags & CHIP_HAS_INPUTSEL)) + break; + if (ctrl->value < 0 || ctrl->value >= 2) return -ERANGE; chip->muted = ctrl->value; @@ -1636,7 +1641,9 @@ static int tvaudio_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qc) switch (qc->id) { case V4L2_CID_AUDIO_MUTE: - return v4l2_ctrl_query_fill(qc, 0, 1, 1, 0); + if (desc->flags & CHIP_HAS_INPUTSEL) + return v4l2_ctrl_query_fill(qc, 0, 1, 1, 0); + break; case V4L2_CID_AUDIO_VOLUME: if (desc->flags & CHIP_HAS_VOLUME) return v4l2_ctrl_query_fill(qc, 0, 65535, 65535 / 100, 58880); @@ -1661,7 +1668,9 @@ static int tvaudio_s_routing(struct v4l2_subdev *sd, const struct v4l2_routing * struct CHIPSTATE *chip = to_state(sd); struct CHIPDESC *desc = chip->desc; - if (!(desc->flags & CHIP_HAS_INPUTSEL) || rt->input >= 4) + if (!(desc->flags & CHIP_HAS_INPUTSEL)) + return 0; + if (rt->input >= 4) return -EINVAL; /* There are four inputs: tuner, radio, extern and intern. */ chip->input = rt->input; @@ -1678,8 +1687,11 @@ static int tvaudio_s_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt) struct CHIPDESC *desc = chip->desc; int mode = 0; + if (!desc->setmode) + return 0; if (chip->radio) return 0; + switch (vt->audmode) { case V4L2_TUNER_MODE_MONO: case V4L2_TUNER_MODE_STEREO: @@ -1695,7 +1707,7 @@ static int tvaudio_s_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt) } chip->audmode = vt->audmode; - if (desc->setmode && mode) { + if (mode) { chip->watch_stereo = 0; /* del_timer(&chip->wt); */ chip->mode = mode; @@ -1710,15 +1722,17 @@ static int tvaudio_g_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt) struct CHIPDESC *desc = chip->desc; int mode = V4L2_TUNER_MODE_MONO; + if (!desc->getmode) + return 0; if (chip->radio) return 0; + vt->audmode = chip->audmode; vt->rxsubchans = 0; vt->capability = V4L2_TUNER_CAP_STEREO | V4L2_TUNER_CAP_LANG1 | V4L2_TUNER_CAP_LANG2; - if (desc->getmode) - mode = desc->getmode(chip); + mode = desc->getmode(chip); if (mode & V4L2_TUNER_MODE_MONO) vt->rxsubchans |= V4L2_TUNER_SUB_MONO; -- cgit v1.2.3 From 411674fd189abe5910ea4caf08b7eac5c4a4d967 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 18 Mar 2009 14:02:36 -0300 Subject: V4L/DVB (11276): tvaudio: add tda9875 support. This change allows bttv to use tvaudio for this device. Since this device has the same i2c address as the tda9874 we need to support both in the same tvaudio driver. This makes it possible for tvaudio to detect which chip is used. Originally the tda9875 was only available in the dedicated tda9875 driver, but that makes life very hard for bttv since loading tvaudio might misdetect a tda9875 as a tda9874. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/tvaudio.c | 132 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 132 insertions(+) (limited to 'drivers/media/video') diff --git a/drivers/media/video/tvaudio.c b/drivers/media/video/tvaudio.c index faa9e3dd782f..8333efab8685 100644 --- a/drivers/media/video/tvaudio.c +++ b/drivers/media/video/tvaudio.c @@ -1047,6 +1047,116 @@ static int tda9874a_initialize(struct CHIPSTATE *chip) return 0; } +/* ---------------------------------------------------------------------- */ +/* audio chip description - defines+functions for tda9875 */ +/* The TDA9875 is made by Philips Semiconductor + * http://www.semiconductors.philips.com + * TDA9875: I2C-bus controlled DSP audio processor, FM demodulator + * + */ + +/* subaddresses for TDA9875 */ +#define TDA9875_MUT 0x12 /*General mute (value --> 0b11001100*/ +#define TDA9875_CFG 0x01 /* Config register (value --> 0b00000000 */ +#define TDA9875_DACOS 0x13 /*DAC i/o select (ADC) 0b0000100*/ +#define TDA9875_LOSR 0x16 /*Line output select regirter 0b0100 0001*/ + +#define TDA9875_CH1V 0x0c /*Channel 1 volume (mute)*/ +#define TDA9875_CH2V 0x0d /*Channel 2 volume (mute)*/ +#define TDA9875_SC1 0x14 /*SCART 1 in (mono)*/ +#define TDA9875_SC2 0x15 /*SCART 2 in (mono)*/ + +#define TDA9875_ADCIS 0x17 /*ADC input select (mono) 0b0110 000*/ +#define TDA9875_AER 0x19 /*Audio effect (AVL+Pseudo) 0b0000 0110*/ +#define TDA9875_MCS 0x18 /*Main channel select (DAC) 0b0000100*/ +#define TDA9875_MVL 0x1a /* Main volume gauche */ +#define TDA9875_MVR 0x1b /* Main volume droite */ +#define TDA9875_MBA 0x1d /* Main Basse */ +#define TDA9875_MTR 0x1e /* Main treble */ +#define TDA9875_ACS 0x1f /* Auxilary channel select (FM) 0b0000000*/ +#define TDA9875_AVL 0x20 /* Auxilary volume gauche */ +#define TDA9875_AVR 0x21 /* Auxilary volume droite */ +#define TDA9875_ABA 0x22 /* Auxilary Basse */ +#define TDA9875_ATR 0x23 /* Auxilary treble */ + +#define TDA9875_MSR 0x02 /* Monitor select register */ +#define TDA9875_C1MSB 0x03 /* Carrier 1 (FM) frequency register MSB */ +#define TDA9875_C1MIB 0x04 /* Carrier 1 (FM) frequency register (16-8]b */ +#define TDA9875_C1LSB 0x05 /* Carrier 1 (FM) frequency register LSB */ +#define TDA9875_C2MSB 0x06 /* Carrier 2 (nicam) frequency register MSB */ +#define TDA9875_C2MIB 0x07 /* Carrier 2 (nicam) frequency register (16-8]b */ +#define TDA9875_C2LSB 0x08 /* Carrier 2 (nicam) frequency register LSB */ +#define TDA9875_DCR 0x09 /* Demodulateur configuration regirter*/ +#define TDA9875_DEEM 0x0a /* FM de-emphasis regirter*/ +#define TDA9875_FMAT 0x0b /* FM Matrix regirter*/ + +/* values */ +#define TDA9875_MUTE_ON 0xff /* general mute */ +#define TDA9875_MUTE_OFF 0xcc /* general no mute */ + +static int tda9875_initialize(struct CHIPSTATE *chip) +{ + chip_write(chip, TDA9875_CFG, 0xd0); /*reg de config 0 (reset)*/ + chip_write(chip, TDA9875_MSR, 0x03); /* Monitor 0b00000XXX*/ + chip_write(chip, TDA9875_C1MSB, 0x00); /*Car1(FM) MSB XMHz*/ + chip_write(chip, TDA9875_C1MIB, 0x00); /*Car1(FM) MIB XMHz*/ + chip_write(chip, TDA9875_C1LSB, 0x00); /*Car1(FM) LSB XMHz*/ + chip_write(chip, TDA9875_C2MSB, 0x00); /*Car2(NICAM) MSB XMHz*/ + chip_write(chip, TDA9875_C2MIB, 0x00); /*Car2(NICAM) MIB XMHz*/ + chip_write(chip, TDA9875_C2LSB, 0x00); /*Car2(NICAM) LSB XMHz*/ + chip_write(chip, TDA9875_DCR, 0x00); /*Demod config 0x00*/ + chip_write(chip, TDA9875_DEEM, 0x44); /*DE-Emph 0b0100 0100*/ + chip_write(chip, TDA9875_FMAT, 0x00); /*FM Matrix reg 0x00*/ + chip_write(chip, TDA9875_SC1, 0x00); /* SCART 1 (SC1)*/ + chip_write(chip, TDA9875_SC2, 0x01); /* SCART 2 (sc2)*/ + + chip_write(chip, TDA9875_CH1V, 0x10); /* Channel volume 1 mute*/ + chip_write(chip, TDA9875_CH2V, 0x10); /* Channel volume 2 mute */ + chip_write(chip, TDA9875_DACOS, 0x02); /* sig DAC i/o(in:nicam)*/ + chip_write(chip, TDA9875_ADCIS, 0x6f); /* sig ADC input(in:mono)*/ + chip_write(chip, TDA9875_LOSR, 0x00); /* line out (in:mono)*/ + chip_write(chip, TDA9875_AER, 0x00); /*06 Effect (AVL+PSEUDO) */ + chip_write(chip, TDA9875_MCS, 0x44); /* Main ch select (DAC) */ + chip_write(chip, TDA9875_MVL, 0x03); /* Vol Main left 10dB */ + chip_write(chip, TDA9875_MVR, 0x03); /* Vol Main right 10dB*/ + chip_write(chip, TDA9875_MBA, 0x00); /* Main Bass Main 0dB*/ + chip_write(chip, TDA9875_MTR, 0x00); /* Main Treble Main 0dB*/ + chip_write(chip, TDA9875_ACS, 0x44); /* Aux chan select (dac)*/ + chip_write(chip, TDA9875_AVL, 0x00); /* Vol Aux left 0dB*/ + chip_write(chip, TDA9875_AVR, 0x00); /* Vol Aux right 0dB*/ + chip_write(chip, TDA9875_ABA, 0x00); /* Aux Bass Main 0dB*/ + chip_write(chip, TDA9875_ATR, 0x00); /* Aux Aigus Main 0dB*/ + + chip_write(chip, TDA9875_MUT, 0xcc); /* General mute */ + return 0; +} + +static int tda9875_volume(int val) { return (unsigned char)(val / 602 - 84); } +static int tda9875_bass(int val) { return (unsigned char)(max(-12, val / 2115 - 15)); } +static int tda9875_treble(int val) { return (unsigned char)(val / 2622 - 12); } + +/* ----------------------------------------------------------------------- */ + + +/* *********************** * + * i2c interface functions * + * *********************** */ + +static int tda9875_checkit(struct CHIPSTATE *chip) +{ + struct v4l2_subdev *sd = &chip->sd; + int dic, rev; + + dic = chip_read2(chip, 254); + rev = chip_read2(chip, 255); + + if (dic == 0 || dic == 2) { /* tda9875 and tda9875A */ + v4l2_info(sd, "found tda9875%s rev. %d.\n", + dic == 0 ? "" : "A", rev); + return 1; + } + return 0; +} /* ---------------------------------------------------------------------- */ /* audio chip descriptions - defines+functions for tea6420 */ @@ -1280,6 +1390,7 @@ static int tda9850 = 1; static int tda9855 = 1; static int tda9873 = 1; static int tda9874a = 1; +static int tda9875 = 1; static int tea6300; /* default 0 - address clash with msp34xx */ static int tea6320; /* default 0 - address clash with msp34xx */ static int tea6420 = 1; @@ -1292,6 +1403,7 @@ module_param(tda9850, int, 0444); module_param(tda9855, int, 0444); module_param(tda9873, int, 0444); module_param(tda9874a, int, 0444); +module_param(tda9875, int, 0444); module_param(tea6300, int, 0444); module_param(tea6320, int, 0444); module_param(tea6420, int, 0444); @@ -1348,6 +1460,26 @@ static struct CHIPDESC chiplist[] = { .getmode = tda9874a_getmode, .setmode = tda9874a_setmode, }, + { + .name = "tda9875", + .insmodopt = &tda9875, + .addr_lo = I2C_ADDR_TDA9875 >> 1, + .addr_hi = I2C_ADDR_TDA9875 >> 1, + .flags = CHIP_HAS_VOLUME | CHIP_HAS_BASSTREBLE, + + /* callbacks */ + .initialize = tda9875_initialize, + .checkit = tda9875_checkit, + .volfunc = tda9875_volume, + .bassfunc = tda9875_bass, + .treblefunc = tda9875_treble, + .leftreg = TDA9875_MVL, + .rightreg = TDA9875_MVR, + .bassreg = TDA9875_MBA, + .treblereg = TDA9875_MTR, + .leftinit = 58880, + .rightinit = 58880, + }, { .name = "tda9850", .insmodopt = &tda9850, -- cgit v1.2.3 From e4129a9ccea54e8f4fbc408476120059809a4627 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Thu, 19 Mar 2009 16:53:32 -0300 Subject: V4L/DVB (11277): tvaudio: always call init_timer to prevent rmmod crash. In the tvaudio_remove function del_timer_sync(&chip->wt) is called. However, chip->wt isn't always initialized depending on the type of audio chip. Since del_timer_sync hangs when given an uninitialized timer we should always initialize it. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/tvaudio.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/tvaudio.c b/drivers/media/video/tvaudio.c index 8333efab8685..226bf3565ac9 100644 --- a/drivers/media/video/tvaudio.c +++ b/drivers/media/video/tvaudio.c @@ -2050,6 +2050,7 @@ static int tvaudio_probe(struct i2c_client *client, const struct i2c_device_id * } chip->thread = NULL; + init_timer(&chip->wt); if (desc->flags & CHIP_NEED_CHECKMODE) { if (!desc->getmode || !desc->setmode) { /* This shouldn't be happen. Warn user, but keep working @@ -2059,7 +2060,6 @@ static int tvaudio_probe(struct i2c_client *client, const struct i2c_device_id * return 0; } /* start async thread */ - init_timer(&chip->wt); chip->wt.function = chip_thread_wake; chip->wt.data = (unsigned long)chip; chip->thread = kthread_run(chip_thread, chip, client->name); -- cgit v1.2.3 From 859f0277a6c3ba59b0a5a1eb183f8f6ce661a95d Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sat, 28 Mar 2009 08:29:00 -0300 Subject: V4L/DVB (11278): bttv: convert to v4l2_subdev since i2c autoprobing will disappear. Since i2c autoprobing will disappear bttv needs to be converted to use v4l2_subdev instead. Without autoprobing the autoload module option has become obsolete. A warning is generated if it is set, but it is otherwise ignored. Since the bttv card definitions are of questionable value a new option was introduced to allow the user to control which audio module is selected: msp3400, tda7432 or tvaudio (or none at all). By default bttv will use the card definitions and fallback on tvaudio as the last resort. If no audio device was found a warning is printed. The saa6588 RDS device is now also explicitly probed since it is no longer possible to autoprobe it. A new saa6588 module option was added to override the card definition since I suspect more cards have this device than one would guess from the card definitions. Note that the probe addresses of the i2c modules are hardcoded in this driver. Once all v4l drivers are converted to v4l2_subdev this will be cleaned up. Such data belongs in an i2c driver header. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/bt8xx/bttv-cards.c | 179 +++++++++++++++++++++++++++----- drivers/media/video/bt8xx/bttv-driver.c | 41 ++++---- drivers/media/video/bt8xx/bttv-i2c.c | 53 ---------- drivers/media/video/bt8xx/bttv.h | 7 +- drivers/media/video/bt8xx/bttvp.h | 5 +- 5 files changed, 180 insertions(+), 105 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/bt8xx/bttv-cards.c b/drivers/media/video/bt8xx/bttv-cards.c index 1536ab5a4a8d..b9c3ba51fb86 100644 --- a/drivers/media/video/bt8xx/bttv-cards.c +++ b/drivers/media/video/bt8xx/bttv-cards.c @@ -96,12 +96,10 @@ static unsigned int pll[BTTV_MAX] = { [ 0 ... (BTTV_MAX-1) ] = UNSET }; static unsigned int tuner[BTTV_MAX] = { [ 0 ... (BTTV_MAX-1) ] = UNSET }; static unsigned int svhs[BTTV_MAX] = { [ 0 ... (BTTV_MAX-1) ] = UNSET }; static unsigned int remote[BTTV_MAX] = { [ 0 ... (BTTV_MAX-1) ] = UNSET }; +static unsigned int audiodev[BTTV_MAX]; +static unsigned int saa6588[BTTV_MAX]; static struct bttv *master[BTTV_MAX] = { [ 0 ... (BTTV_MAX-1) ] = NULL }; -#ifdef MODULE -static unsigned int autoload = 1; -#else -static unsigned int autoload; -#endif +static unsigned int autoload = UNSET; static unsigned int gpiomask = UNSET; static unsigned int audioall = UNSET; static unsigned int audiomux[5] = { [ 0 ... 4 ] = UNSET }; @@ -120,6 +118,7 @@ module_param_array(pll, int, NULL, 0444); module_param_array(tuner, int, NULL, 0444); module_param_array(svhs, int, NULL, 0444); module_param_array(remote, int, NULL, 0444); +module_param_array(audiodev, int, NULL, 0444); module_param_array(audiomux, int, NULL, 0444); MODULE_PARM_DESC(triton1,"set ETBF pci config bit " @@ -130,7 +129,14 @@ MODULE_PARM_DESC(latency,"pci latency timer"); MODULE_PARM_DESC(card,"specify TV/grabber card model, see CARDLIST file for a list"); MODULE_PARM_DESC(pll,"specify installed crystal (0=none, 28=28 MHz, 35=35 MHz)"); MODULE_PARM_DESC(tuner,"specify installed tuner type"); -MODULE_PARM_DESC(autoload,"automatically load i2c modules like tuner.o, default is 1 (yes)"); +MODULE_PARM_DESC(autoload, "obsolete option, please do not use anymore"); +MODULE_PARM_DESC(audiodev, "specify audio device:\n" + "\t\t-1 = no audio\n" + "\t\t 0 = autodetect (default)\n" + "\t\t 1 = msp3400\n" + "\t\t 2 = tda7432\n" + "\t\t 3 = tvaudio"); +MODULE_PARM_DESC(saa6588, "if 1, then load the saa6588 RDS module, default (0) is to use the card definition."); MODULE_PARM_DESC(no_overlay,"allow override overlay default (0 disables, 1 enables)" " [some VIA/SIS chipsets are known to have problem with overlay]"); @@ -3318,6 +3324,17 @@ void __devinit bttv_init_card1(struct bttv *btv) /* initialization part two -- after registering i2c bus */ void __devinit bttv_init_card2(struct bttv *btv) { + static const unsigned short tvaudio_addrs[] = { + I2C_ADDR_TDA8425 >> 1, + I2C_ADDR_TEA6300 >> 1, + I2C_ADDR_TEA6420 >> 1, + I2C_ADDR_TDA9840 >> 1, + I2C_ADDR_TDA985x_L >> 1, + I2C_ADDR_TDA985x_H >> 1, + I2C_ADDR_TDA9874 >> 1, + I2C_ADDR_PIC16C54 >> 1, + I2C_CLIENT_END + }; int addr=ADDR_UNSET; btv->tuner_type = UNSET; @@ -3481,6 +3498,12 @@ void __devinit bttv_init_card2(struct bttv *btv) printk(KERN_INFO "bttv%d: tuner type=%d\n", btv->c.nr, btv->tuner_type); + if (autoload != UNSET) { + printk(KERN_WARNING "bttv%d: the autoload option is obsolete.\n", btv->c.nr); + printk(KERN_WARNING "bttv%d: use option msp3400, tda7432 or tvaudio to\n", btv->c.nr); + printk(KERN_WARNING "bttv%d: override which audio module should be used.\n", btv->c.nr); + } + if (UNSET == btv->tuner_type) btv->tuner_type = TUNER_ABSENT; @@ -3488,8 +3511,13 @@ void __devinit bttv_init_card2(struct bttv *btv) struct tuner_setup tun_setup; /* Load tuner module before issuing tuner config call! */ - if (autoload) - request_module("tuner"); + if (bttv_tvcards[btv->c.type].has_radio) + v4l2_i2c_new_probed_subdev(&btv->c.i2c_adap, + "tuner", "tuner", v4l2_i2c_tuner_addrs(ADDRS_RADIO)); + v4l2_i2c_new_probed_subdev(&btv->c.i2c_adap, "tuner", + "tuner", v4l2_i2c_tuner_addrs(ADDRS_DEMOD)); + v4l2_i2c_new_probed_subdev(&btv->c.i2c_adap, "tuner", + "tuner", v4l2_i2c_tuner_addrs(ADDRS_TV_WITH_DEMOD)); tun_setup.mode_mask = T_ANALOG_TV | T_DIGITAL_TV; tun_setup.type = btv->tuner_type; @@ -3498,7 +3526,7 @@ void __devinit bttv_init_card2(struct bttv *btv) if (bttv_tvcards[btv->c.type].has_radio) tun_setup.mode_mask |= T_RADIO; - bttv_call_i2c_clients(btv, TUNER_SET_TYPE_ADDR, &tun_setup); + bttv_call_all(btv, tuner, s_type_addr, &tun_setup); } if (btv->tda9887_conf) { @@ -3507,7 +3535,7 @@ void __devinit bttv_init_card2(struct bttv *btv) tda9887_cfg.tuner = TUNER_TDA9887; tda9887_cfg.priv = &btv->tda9887_conf; - bttv_call_i2c_clients(btv, TUNER_SET_CONFIG, &tda9887_cfg); + bttv_call_all(btv, tuner, s_config, &tda9887_cfg); } btv->dig = bttv_tvcards[btv->c.type].has_dig_in ? @@ -3530,31 +3558,127 @@ void __devinit bttv_init_card2(struct bttv *btv) if (bttv_tvcards[btv->c.type].audio_mode_gpio) btv->audio_mode_gpio=bttv_tvcards[btv->c.type].audio_mode_gpio; - if (!autoload) - return; - if (btv->tuner_type == TUNER_ABSENT) return; /* no tuner or related drivers to load */ + if (btv->has_saa6588 || saa6588[btv->c.nr]) { + /* Probe for RDS receiver chip */ + static const unsigned short addrs[] = { + 0x20 >> 1, + 0x22 >> 1, + I2C_CLIENT_END + }; + struct v4l2_subdev *sd; + + sd = v4l2_i2c_new_probed_subdev(&btv->c.i2c_adap, + "saa6588", "saa6588", addrs); + btv->has_saa6588 = (sd != NULL); + } + /* try to detect audio/fader chips */ - if (!bttv_tvcards[btv->c.type].no_msp34xx && - bttv_I2CRead(btv, I2C_ADDR_MSP3400, "MSP34xx") >=0) - request_module("msp3400"); - if (bttv_tvcards[btv->c.type].msp34xx_alt && - bttv_I2CRead(btv, I2C_ADDR_MSP3400_ALT, "MSP34xx (alternate address)") >=0) - request_module("msp3400"); + /* First check if the user specified the audio chip via a module + option. */ + + switch (audiodev[btv->c.nr]) { + case -1: + return; /* do not load any audio module */ + + case 0: /* autodetect */ + break; + + case 1: { + /* The user specified that we should probe for msp3400 */ + static const unsigned short addrs[] = { + I2C_ADDR_MSP3400 >> 1, + I2C_ADDR_MSP3400_ALT >> 1, + I2C_CLIENT_END + }; + + btv->sd_msp34xx = v4l2_i2c_new_probed_subdev(&btv->c.i2c_adap, + "msp3400", "msp3400", addrs); + if (btv->sd_msp34xx) + return; + goto no_audio; + } + + case 2: { + /* The user specified that we should probe for tda7432 */ + static const unsigned short addrs[] = { + I2C_ADDR_TDA7432 >> 1, + I2C_CLIENT_END + }; + + if (v4l2_i2c_new_probed_subdev(&btv->c.i2c_adap, + "tda7432", "tda7432", addrs)) + return; + goto no_audio; + } - if (!bttv_tvcards[btv->c.type].no_tda9875 && - bttv_I2CRead(btv, I2C_ADDR_TDA9875, "TDA9875") >=0) - request_module("tda9875"); + case 3: { + /* The user specified that we should probe for tvaudio */ + btv->sd_tvaudio = v4l2_i2c_new_probed_subdev(&btv->c.i2c_adap, + "tvaudio", "tvaudio", tvaudio_addrs); + if (btv->sd_tvaudio) + return; + goto no_audio; + } - if (!bttv_tvcards[btv->c.type].no_tda7432 && - bttv_I2CRead(btv, I2C_ADDR_TDA7432, "TDA7432") >=0) - request_module("tda7432"); + default: + printk(KERN_WARNING "bttv%d: unknown audiodev value!\n", + btv->c.nr); + return; + } + + /* There were no overrides, so now we try to discover this through the + card definition */ + + /* probe for msp3400 first: this driver can detect whether or not + it really is a msp3400, so it will return NULL when the device + found is really something else (e.g. a tea6300). */ + if (!bttv_tvcards[btv->c.type].no_msp34xx) { + static const unsigned short addrs[] = { + I2C_ADDR_MSP3400 >> 1, + I2C_CLIENT_END + }; + + btv->sd_msp34xx = v4l2_i2c_new_probed_subdev(&btv->c.i2c_adap, + "msp3400", "msp3400", addrs); + } else if (bttv_tvcards[btv->c.type].msp34xx_alt) { + static const unsigned short addrs[] = { + I2C_ADDR_MSP3400_ALT >> 1, + I2C_CLIENT_END + }; + + btv->sd_msp34xx = v4l2_i2c_new_probed_subdev(&btv->c.i2c_adap, + "msp3400", "msp3400", addrs); + } + + /* If we found a msp34xx, then we're done. */ + if (btv->sd_msp34xx) + return; + + /* it might also be a tda7432. */ + if (!bttv_tvcards[btv->c.type].no_tda7432) { + static const unsigned short addrs[] = { + I2C_ADDR_TDA7432 >> 1, + I2C_CLIENT_END + }; + + if (v4l2_i2c_new_probed_subdev(&btv->c.i2c_adap, + "tda7432", "tda7432", addrs)) + return; + } + + /* Now see if we can find one of the tvaudio devices. */ + btv->sd_tvaudio = v4l2_i2c_new_probed_subdev(&btv->c.i2c_adap, + "tvaudio", "tvaudio", tvaudio_addrs); + if (btv->sd_tvaudio) + return; - if (bttv_tvcards[btv->c.type].needs_tvaudio) - request_module("tvaudio"); +no_audio: + printk(KERN_WARNING "bttv%d: audio absent, no audio device found!\n", + btv->c.nr); } @@ -3626,6 +3750,7 @@ static int terratec_active_radio_upgrade(struct bttv *btv) printk("bttv%d: Terratec Active Radio Upgrade found.\n", btv->c.nr); btv->has_radio = 1; + btv->has_saa6588 = 1; btv->has_matchbox = 1; } else { btv->has_radio = 0; diff --git a/drivers/media/video/bt8xx/bttv-driver.c b/drivers/media/video/bt8xx/bttv-driver.c index 1dc79b82cf42..7a8ca0d8356f 100644 --- a/drivers/media/video/bt8xx/bttv-driver.c +++ b/drivers/media/video/bt8xx/bttv-driver.c @@ -1163,7 +1163,6 @@ audio_mux(struct bttv *btv, int input, int mute) { int gpio_val, signal; struct v4l2_control ctrl; - struct i2c_client *c; gpio_inout(bttv_tvcards[btv->c.type].gpiomask, bttv_tvcards[btv->c.type].gpiomask); @@ -1197,9 +1196,8 @@ audio_mux(struct bttv *btv, int input, int mute) ctrl.id = V4L2_CID_AUDIO_MUTE; ctrl.value = btv->mute; - bttv_call_i2c_clients(btv, VIDIOC_S_CTRL, &ctrl); - c = btv->i2c_msp34xx_client; - if (c) { + bttv_call_all(btv, core, s_ctrl, &ctrl); + if (btv->sd_msp34xx) { struct v4l2_routing route; /* Note: the inputs tuner/radio/extern/intern are translated @@ -1238,15 +1236,14 @@ audio_mux(struct bttv *btv, int input, int mute) break; } route.output = MSP_OUTPUT_DEFAULT; - c->driver->command(c, VIDIOC_INT_S_AUDIO_ROUTING, &route); + v4l2_subdev_call(btv->sd_msp34xx, audio, s_routing, &route); } - c = btv->i2c_tvaudio_client; - if (c) { + if (btv->sd_tvaudio) { struct v4l2_routing route; route.input = input; route.output = 0; - c->driver->command(c, VIDIOC_INT_S_AUDIO_ROUTING, &route); + v4l2_subdev_call(btv->sd_tvaudio, audio, s_routing, &route); } return 0; } @@ -1332,7 +1329,7 @@ set_tvnorm(struct bttv *btv, unsigned int norm) break; } id = tvnorm->v4l2_id; - bttv_call_i2c_clients(btv, VIDIOC_S_STD, &id); + bttv_call_all(btv, tuner, s_std, id); return 0; } @@ -1476,7 +1473,7 @@ static int bttv_g_ctrl(struct file *file, void *priv, case V4L2_CID_AUDIO_BALANCE: case V4L2_CID_AUDIO_BASS: case V4L2_CID_AUDIO_TREBLE: - bttv_call_i2c_clients(btv, VIDIOC_G_CTRL, c); + bttv_call_all(btv, core, g_ctrl, c); break; case V4L2_CID_PRIVATE_CHROMA_AGC: @@ -1550,12 +1547,12 @@ static int bttv_s_ctrl(struct file *file, void *f, if (btv->volume_gpio) btv->volume_gpio(btv, c->value); - bttv_call_i2c_clients(btv, VIDIOC_S_CTRL, c); + bttv_call_all(btv, core, s_ctrl, c); break; case V4L2_CID_AUDIO_BALANCE: case V4L2_CID_AUDIO_BASS: case V4L2_CID_AUDIO_TREBLE: - bttv_call_i2c_clients(btv, VIDIOC_S_CTRL, c); + bttv_call_all(btv, core, s_ctrl, c); break; case V4L2_CID_PRIVATE_CHROMA_AGC: @@ -1973,7 +1970,7 @@ static int bttv_s_tuner(struct file *file, void *priv, return -EINVAL; mutex_lock(&btv->lock); - bttv_call_i2c_clients(btv, VIDIOC_S_TUNER, t); + bttv_call_all(btv, tuner, s_tuner, t); if (btv->audio_mode_gpio) btv->audio_mode_gpio(btv, t, 1); @@ -2018,7 +2015,7 @@ static int bttv_s_frequency(struct file *file, void *priv, return -EINVAL; mutex_lock(&btv->lock); btv->freq = f->frequency; - bttv_call_i2c_clients(btv, VIDIOC_S_FREQUENCY, f); + bttv_call_all(btv, tuner, s_frequency, f); if (btv->has_matchbox && btv->radio_user) tea5757_set_freq(btv, btv->freq); mutex_unlock(&btv->lock); @@ -2032,7 +2029,7 @@ static int bttv_log_status(struct file *file, void *f) printk(KERN_INFO "bttv%d: ======== START STATUS CARD #%d ========\n", btv->c.nr, btv->c.nr); - bttv_call_i2c_clients(btv, VIDIOC_LOG_STATUS, NULL); + bttv_call_all(btv, core, log_status); printk(KERN_INFO "bttv%d: ======== END STATUS CARD #%d ========\n", btv->c.nr, btv->c.nr); return 0; @@ -2946,7 +2943,7 @@ static int bttv_g_tuner(struct file *file, void *priv, mutex_lock(&btv->lock); t->rxsubchans = V4L2_TUNER_SUB_MONO; - bttv_call_i2c_clients(btv, VIDIOC_G_TUNER, t); + bttv_call_all(btv, tuner, g_tuner, t); strcpy(t->name, "Television"); t->capability = V4L2_TUNER_CAP_NORM; t->type = V4L2_TUNER_ANALOG_TV; @@ -3437,7 +3434,7 @@ static int radio_open(struct file *file) btv->radio_user++; - bttv_call_i2c_clients(btv,AUDC_SET_RADIO,NULL); + bttv_call_all(btv, tuner, s_radio); audio_input(btv,TVAUDIO_INPUT_RADIO); mutex_unlock(&btv->lock); @@ -3457,7 +3454,7 @@ static int radio_release(struct file *file) btv->radio_user--; - bttv_call_i2c_clients(btv, RDS_CMD_CLOSE, &cmd); + bttv_call_all(btv, core, ioctl, RDS_CMD_CLOSE, &cmd); return 0; } @@ -3490,7 +3487,7 @@ static int radio_g_tuner(struct file *file, void *priv, struct v4l2_tuner *t) strcpy(t->name, "Radio"); t->type = V4L2_TUNER_RADIO; - bttv_call_i2c_clients(btv, VIDIOC_G_TUNER, t); + bttv_call_all(btv, tuner, g_tuner, t); if (btv->audio_mode_gpio) btv->audio_mode_gpio(btv, t, 0); @@ -3532,7 +3529,7 @@ static int radio_s_tuner(struct file *file, void *priv, if (0 != t->index) return -EINVAL; - bttv_call_i2c_clients(btv, VIDIOC_G_TUNER, t); + bttv_call_all(btv, tuner, g_tuner, t); return 0; } @@ -3593,7 +3590,7 @@ static ssize_t radio_read(struct file *file, char __user *data, cmd.instance = file; cmd.result = -ENODEV; - bttv_call_i2c_clients(btv, RDS_CMD_READ, &cmd); + bttv_call_all(btv, core, ioctl, RDS_CMD_READ, &cmd); return cmd.result; } @@ -3606,7 +3603,7 @@ static unsigned int radio_poll(struct file *file, poll_table *wait) cmd.instance = file; cmd.event_list = wait; cmd.result = -ENODEV; - bttv_call_i2c_clients(btv, RDS_CMD_POLL, &cmd); + bttv_call_all(btv, core, ioctl, RDS_CMD_POLL, &cmd); return cmd.result; } diff --git a/drivers/media/video/bt8xx/bttv-i2c.c b/drivers/media/video/bt8xx/bttv-i2c.c index 9b66c5b09321..a99d92fac3dc 100644 --- a/drivers/media/video/bt8xx/bttv-i2c.c +++ b/drivers/media/video/bt8xx/bttv-i2c.c @@ -36,8 +36,6 @@ #include #include -static int attach_inform(struct i2c_client *client); - static int i2c_debug; static int i2c_hw; static int i2c_scan; @@ -266,51 +264,6 @@ static const struct i2c_algorithm bttv_algo = { /* ----------------------------------------------------------------------- */ /* I2C functions - common stuff */ -static int attach_inform(struct i2c_client *client) -{ - struct v4l2_device *v4l2_dev = i2c_get_adapdata(client->adapter); - struct bttv *btv = to_bttv(v4l2_dev); - int addr=ADDR_UNSET; - - - if (ADDR_UNSET != bttv_tvcards[btv->c.type].tuner_addr) - addr = bttv_tvcards[btv->c.type].tuner_addr; - - - if (bttv_debug) - printk(KERN_DEBUG "bttv%d: %s i2c attach [addr=0x%x,client=%s]\n", - btv->c.nr, client->driver->driver.name, client->addr, - client->name); - if (!client->driver->command) - return 0; - - if (client->driver->id == I2C_DRIVERID_MSP3400) - btv->i2c_msp34xx_client = client; - if (client->driver->id == I2C_DRIVERID_TVAUDIO) - btv->i2c_tvaudio_client = client; - if (btv->tuner_type != TUNER_ABSENT) { - struct tuner_setup tun_setup; - - if (addr == ADDR_UNSET || addr == client->addr) { - tun_setup.mode_mask = T_ANALOG_TV | T_DIGITAL_TV | T_RADIO; - tun_setup.type = btv->tuner_type; - tun_setup.addr = addr; - bttv_call_i2c_clients(btv, TUNER_SET_TYPE_ADDR, &tun_setup); - } - - } - - return 0; -} - -void bttv_call_i2c_clients(struct bttv *btv, unsigned int cmd, void *arg) -{ - if (0 != btv->i2c_rc) - return; - i2c_clients_command(&btv->c.i2c_adap, cmd, arg); -} - - /* read I2C */ int bttv_I2CRead(struct bttv *btv, unsigned char addr, char *probe_for) { @@ -417,8 +370,6 @@ int __devinit init_bttv_i2c(struct bttv *btv) btv->c.i2c_adap.algo_data = &btv->i2c_algo; } btv->c.i2c_adap.owner = THIS_MODULE; - btv->c.i2c_adap.class = I2C_CLASS_TV_ANALOG; - btv->c.i2c_adap.client_register = attach_inform; btv->c.i2c_adap.dev.parent = &btv->c.pci->dev; snprintf(btv->c.i2c_adap.name, sizeof(btv->c.i2c_adap.name), @@ -428,10 +379,6 @@ int __devinit init_bttv_i2c(struct bttv *btv) i2c_set_adapdata(&btv->c.i2c_adap, &btv->c.v4l2_dev); btv->i2c_client.adapter = &btv->c.i2c_adap; - if (bttv_tvcards[btv->c.type].no_video) - btv->c.i2c_adap.class &= ~I2C_CLASS_TV_ANALOG; - if (bttv_tvcards[btv->c.type].has_dvb) - btv->c.i2c_adap.class |= I2C_CLASS_TV_DIGITAL; if (btv->use_i2c_hw) { btv->i2c_rc = i2c_add_adapter(&btv->c.i2c_adap); diff --git a/drivers/media/video/bt8xx/bttv.h b/drivers/media/video/bt8xx/bttv.h index fac5f86356d2..3d36daf206f3 100644 --- a/drivers/media/video/bt8xx/bttv.h +++ b/drivers/media/video/bt8xx/bttv.h @@ -240,6 +240,9 @@ struct tvcard { unsigned int no_tda7432:1; unsigned int needs_tvaudio:1; unsigned int msp34xx_alt:1; + /* Note: currently no card definition needs to mark the presence + of a RDS saa6588 chip. If this is ever needed, then add a new + 'has_saa6588' bit here. */ unsigned int no_video:1; /* video pci function is unused */ unsigned int has_dvb:1; @@ -355,7 +358,9 @@ void bttv_gpio_bits(struct bttv_core *core, u32 mask, u32 bits); /* ---------------------------------------------------------- */ /* i2c */ -extern void bttv_call_i2c_clients(struct bttv *btv, unsigned int cmd, void *arg); +#define bttv_call_all(btv, o, f, args...) \ + v4l2_device_call_all(&btv->c.v4l2_dev, 0, o, f, ##args) + extern int bttv_I2CRead(struct bttv *btv, unsigned char addr, char *probe_for); extern int bttv_I2CWrite(struct bttv *btv, unsigned char addr, unsigned char b1, unsigned char b2, int both); diff --git a/drivers/media/video/bt8xx/bttvp.h b/drivers/media/video/bt8xx/bttvp.h index 5755b407c0a2..96498489199d 100644 --- a/drivers/media/video/bt8xx/bttvp.h +++ b/drivers/media/video/bt8xx/bttvp.h @@ -329,6 +329,7 @@ struct bttv { unsigned int tuner_type; /* tuner chip type */ unsigned int tda9887_conf; unsigned int svhs, dig; + unsigned int has_saa6588:1; struct bttv_pll_info pll; int triton1; int gpioirq; @@ -352,8 +353,8 @@ struct bttv { int i2c_state, i2c_rc; int i2c_done; wait_queue_head_t i2c_queue; - struct i2c_client *i2c_msp34xx_client; - struct i2c_client *i2c_tvaudio_client; + struct v4l2_subdev *sd_msp34xx; + struct v4l2_subdev *sd_tvaudio; /* video4linux (1) */ struct video_device *video_dev; -- cgit v1.2.3 From 893cce04b77e3e520e2b3ce4ae629f57dc6ce7f7 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sat, 28 Mar 2009 08:55:11 -0300 Subject: V4L/DVB (11279): bttv: tda9875 is no longer used by bttv, so remove from bt8xx/Kconfig. Since tda9875 support was merged into tvaudio the bttv driver no longer needs tda9875 as helper driver. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/bt8xx/Kconfig | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/bt8xx/Kconfig b/drivers/media/video/bt8xx/Kconfig index ce71e8e7b835..94c9df8b1158 100644 --- a/drivers/media/video/bt8xx/Kconfig +++ b/drivers/media/video/bt8xx/Kconfig @@ -10,7 +10,6 @@ config VIDEO_BT848 select VIDEO_MSP3400 if VIDEO_HELPER_CHIPS_AUTO select VIDEO_TVAUDIO if VIDEO_HELPER_CHIPS_AUTO select VIDEO_TDA7432 if VIDEO_HELPER_CHIPS_AUTO - select VIDEO_TDA9875 if VIDEO_HELPER_CHIPS_AUTO ---help--- Support for BT848 based frame grabber/overlay boards. This includes the Miro, Hauppauge and STB boards. Please read the material in -- cgit v1.2.3 From ffe84b7a31bb39a26d74ff5a9ee921cd2c23e29c Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sun, 29 Mar 2009 06:17:31 -0300 Subject: V4L/DVB (11281): bttv: move saa6588 config to the helper chip config saa6588 can also be used by other drivers than just bttv. Move it to a new RDS decoders category and add it as helper chip to bttv. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/Kconfig | 26 ++++++++++++++------------ drivers/media/video/bt8xx/Kconfig | 1 + 2 files changed, 15 insertions(+), 12 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig index 3f85b9e63754..76bad5819592 100644 --- a/drivers/media/video/Kconfig +++ b/drivers/media/video/Kconfig @@ -249,6 +249,20 @@ config VIDEO_VP27SMPX To compile this driver as a module, choose M here: the module will be called vp27smpx. +comment "RDS decoders" + +config VIDEO_SAA6588 + tristate "SAA6588 Radio Chip RDS decoder support" + depends on VIDEO_V4L2 && I2C + + help + Support for this Radio Data System (RDS) decoder. This allows + seeing radio station identification transmitted using this + standard. + + To compile this driver as a module, choose M here: the + module will be called saa6588. + comment "Video decoders" config VIDEO_BT819 @@ -467,18 +481,6 @@ config VIDEO_VIVI source "drivers/media/video/bt8xx/Kconfig" -config VIDEO_SAA6588 - tristate "SAA6588 Radio Chip RDS decoder support on BT848 cards" - depends on I2C && VIDEO_BT848 - - help - Support for Radio Data System (RDS) decoder. This allows seeing - radio station identification transmitted using this standard. - Currently, it works only with bt8x8 chips. - - To compile this driver as a module, choose M here: the - module will be called saa6588. - config VIDEO_PMS tristate "Mediavision Pro Movie Studio Video For Linux" depends on ISA && VIDEO_V4L1 diff --git a/drivers/media/video/bt8xx/Kconfig b/drivers/media/video/bt8xx/Kconfig index 94c9df8b1158..3077c45015f5 100644 --- a/drivers/media/video/bt8xx/Kconfig +++ b/drivers/media/video/bt8xx/Kconfig @@ -10,6 +10,7 @@ config VIDEO_BT848 select VIDEO_MSP3400 if VIDEO_HELPER_CHIPS_AUTO select VIDEO_TVAUDIO if VIDEO_HELPER_CHIPS_AUTO select VIDEO_TDA7432 if VIDEO_HELPER_CHIPS_AUTO + select VIDEO_SAA6588 if VIDEO_HELPER_CHIPS_AUTO ---help--- Support for BT848 based frame grabber/overlay boards. This includes the Miro, Hauppauge and STB boards. Please read the material in -- cgit v1.2.3 From 2983baf8d6c1a564b6bbcc3e142f2e9408d9cbbe Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sun, 29 Mar 2009 06:26:27 -0300 Subject: V4L/DVB (11282): saa7134: add RDS support. The Terratec Cinergy 600 TV MK3 supports the RDS decoder saa6588. Add support to saa7134 for such devices. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/saa7134/Kconfig | 1 + drivers/media/video/saa7134/saa7134-cards.c | 1 + drivers/media/video/saa7134/saa7134-core.c | 11 +++++++++ drivers/media/video/saa7134/saa7134-video.c | 37 +++++++++++++++++++++++++++++ drivers/media/video/saa7134/saa7134.h | 1 + 5 files changed, 51 insertions(+) (limited to 'drivers/media/video') diff --git a/drivers/media/video/saa7134/Kconfig b/drivers/media/video/saa7134/Kconfig index a2089acb0309..0ba68987bfce 100644 --- a/drivers/media/video/saa7134/Kconfig +++ b/drivers/media/video/saa7134/Kconfig @@ -6,6 +6,7 @@ config VIDEO_SAA7134 select VIDEO_TUNER select VIDEO_TVEEPROM select CRC32 + select VIDEO_SAA6588 if VIDEO_HELPER_CHIPS_AUTO ---help--- This is a video4linux driver for Philips SAA713x based TV cards. diff --git a/drivers/media/video/saa7134/saa7134-cards.c b/drivers/media/video/saa7134/saa7134-cards.c index 3a038133b260..a790a7246a63 100644 --- a/drivers/media/video/saa7134/saa7134-cards.c +++ b/drivers/media/video/saa7134/saa7134-cards.c @@ -1704,6 +1704,7 @@ struct saa7134_board saa7134_boards[] = { .radio_type = UNSET, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, + .rds_addr = 0x10, .tda9887_conf = TDA9887_PRESENT, .inputs = {{ .name = name_tv, diff --git a/drivers/media/video/saa7134/saa7134-core.c b/drivers/media/video/saa7134/saa7134-core.c index 4c24c9c7bb5b..dafa0d88bed0 100644 --- a/drivers/media/video/saa7134/saa7134-core.c +++ b/drivers/media/video/saa7134/saa7134-core.c @@ -990,6 +990,17 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev, sd->grp_id = GRP_EMPRESS; } + if (saa7134_boards[dev->board].rds_addr) { + unsigned short addrs[2] = { 0, I2C_CLIENT_END }; + struct v4l2_subdev *sd; + + addrs[0] = saa7134_boards[dev->board].rds_addr; + sd = v4l2_i2c_new_probed_subdev(&dev->i2c_adap, "saa6588", + "saa6588", addrs); + if (sd) + printk(KERN_INFO "%s: found RDS decoder\n", dev->name); + } + request_submodules(dev); v4l2_prio_init(&dev->prio); diff --git a/drivers/media/video/saa7134/saa7134-video.c b/drivers/media/video/saa7134/saa7134-video.c index 6a4ae89a81a9..404f70eeb355 100644 --- a/drivers/media/video/saa7134/saa7134-video.c +++ b/drivers/media/video/saa7134/saa7134-video.c @@ -30,6 +30,7 @@ #include "saa7134-reg.h" #include "saa7134.h" #include +#include /* ------------------------------------------------------------------ */ @@ -1462,6 +1463,7 @@ static int video_release(struct file *file) { struct saa7134_fh *fh = file->private_data; struct saa7134_dev *dev = fh->dev; + struct rds_command cmd; unsigned long flags; /* turn off overlay */ @@ -1495,6 +1497,8 @@ static int video_release(struct file *file) saa_andorb(SAA7134_OFMT_DATA_B, 0x1f, 0); saa_call_all(dev, core, s_standby, 0); + if (fh->radio) + saa_call_all(dev, core, ioctl, RDS_CMD_CLOSE, &cmd); /* free stuff */ videobuf_mmap_free(&fh->cap); @@ -1515,6 +1519,37 @@ static int video_mmap(struct file *file, struct vm_area_struct * vma) return videobuf_mmap_mapper(saa7134_queue(fh), vma); } +static ssize_t radio_read(struct file *file, char __user *data, + size_t count, loff_t *ppos) +{ + struct saa7134_fh *fh = file->private_data; + struct saa7134_dev *dev = fh->dev; + struct rds_command cmd; + + cmd.block_count = count/3; + cmd.buffer = data; + cmd.instance = file; + cmd.result = -ENODEV; + + saa_call_all(dev, core, ioctl, RDS_CMD_READ, &cmd); + + return cmd.result; +} + +static unsigned int radio_poll(struct file *file, poll_table *wait) +{ + struct saa7134_fh *fh = file->private_data; + struct saa7134_dev *dev = fh->dev; + struct rds_command cmd; + + cmd.instance = file; + cmd.event_list = wait; + cmd.result = -ENODEV; + saa_call_all(dev, core, ioctl, RDS_CMD_POLL, &cmd); + + return cmd.result; +} + /* ------------------------------------------------------------------ */ static int saa7134_try_get_set_fmt_vbi_cap(struct file *file, void *priv, @@ -2439,8 +2474,10 @@ static const struct v4l2_ioctl_ops video_ioctl_ops = { static const struct v4l2_file_operations radio_fops = { .owner = THIS_MODULE, .open = video_open, + .read = radio_read, .release = video_release, .ioctl = video_ioctl2, + .poll = radio_poll, }; static const struct v4l2_ioctl_ops radio_ioctl_ops = { diff --git a/drivers/media/video/saa7134/saa7134.h b/drivers/media/video/saa7134/saa7134.h index 11396687b69c..a2dd326de5b9 100644 --- a/drivers/media/video/saa7134/saa7134.h +++ b/drivers/media/video/saa7134/saa7134.h @@ -333,6 +333,7 @@ struct saa7134_board { unsigned char tuner_addr; unsigned char radio_addr; unsigned char empress_addr; + unsigned char rds_addr; unsigned int tda9887_conf; unsigned int tuner_config; -- cgit v1.2.3 From aef822074b88397968560b650a9f4bdbf973e2b3 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sun, 29 Mar 2009 06:29:30 -0300 Subject: V4L/DVB (11283): saa6588: remove legacy code. saa6588 is now only used through v4l2_subdev, so we can remove the old legacy code. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/saa6588.c | 16 +--------------- 1 file changed, 1 insertion(+), 15 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/saa6588.c b/drivers/media/video/saa6588.c index 2ce758c1ebb1..c25e81af5ce0 100644 --- a/drivers/media/video/saa6588.c +++ b/drivers/media/video/saa6588.c @@ -34,16 +34,8 @@ #include #include #include -#include +#include -/* Addresses to scan */ -static unsigned short normal_i2c[] = { - 0x20 >> 1, - 0x22 >> 1, - I2C_CLIENT_END, -}; - -I2C_CLIENT_INSMOD; /* insmod options */ static unsigned int debug; @@ -431,11 +423,6 @@ static int saa6588_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ide return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_SAA6588, 0); } -static int saa6588_command(struct i2c_client *client, unsigned cmd, void *arg) -{ - return v4l2_subdev_command(i2c_get_clientdata(client), cmd, arg); -} - /* ----------------------------------------------------------------------- */ static const struct v4l2_subdev_core_ops saa6588_core_ops = { @@ -511,7 +498,6 @@ MODULE_DEVICE_TABLE(i2c, saa6588_id); static struct v4l2_i2c_driver_data v4l2_i2c_data = { .name = "saa6588", - .command = saa6588_command, .probe = saa6588_probe, .remove = saa6588_remove, .id_table = saa6588_id, -- cgit v1.2.3 From 0ce566da77767bc7dd6e4016a6544c9e814d2ed3 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Fri, 27 Mar 2009 10:46:49 -0300 Subject: V4L/DVB (11292): uvcvideo: Add support for Syntek cameras found in JAOtech Smart Terminals Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/uvc/uvc_driver.c | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'drivers/media/video') diff --git a/drivers/media/video/uvc/uvc_driver.c b/drivers/media/video/uvc/uvc_driver.c index 22e2783ac555..399412d7f020 100644 --- a/drivers/media/video/uvc/uvc_driver.c +++ b/drivers/media/video/uvc/uvc_driver.c @@ -1915,6 +1915,15 @@ static struct usb_device_id uvc_ids[] = { .bInterfaceSubClass = 1, .bInterfaceProtocol = 0, .driver_info = UVC_QUIRK_STREAM_NO_FID }, + /* Syntek (JAOtech Smart Terminal) */ + { .match_flags = USB_DEVICE_ID_MATCH_DEVICE + | USB_DEVICE_ID_MATCH_INT_INFO, + .idVendor = 0x174f, + .idProduct = 0x8a34, + .bInterfaceClass = USB_CLASS_VIDEO, + .bInterfaceSubClass = 1, + .bInterfaceProtocol = 0, + .driver_info = UVC_QUIRK_STREAM_NO_FID }, /* Lenovo Thinkpad SL500 */ { .match_flags = USB_DEVICE_ID_MATCH_DEVICE | USB_DEVICE_ID_MATCH_INT_INFO, -- cgit v1.2.3 From 8bbd90ce80d39d372857235f00c7abb208bd9e4f Mon Sep 17 00:00:00 2001 From: Márton Németh Date: Fri, 27 Mar 2009 11:13:57 -0300 Subject: V4L/DVB (11293): uvcvideo: Add zero fill for VIDIOC_ENUM_FMT MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When enumerating formats with VIDIOC_ENUM_FMT the uvcvideo driver does not fill the reserved fields of the struct v4l2_fmtdesc with zeros as required by V4L2 API revision 0.24 [1]. Add the missing initializations. The patch was tested with v4l-test 0.10 [2] with CNF7129 webcam found on EeePC 901. References: [1] V4L2 API specification, revision 0.24 http://v4l2spec.bytesex.org/spec/r8367.htm [2] v4l-test: Test environment for Video For Linux Two API http://v4l-test.sourceforge.net/ Signed-off-by: Márton Németh Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/uvc/uvc_v4l2.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers/media/video') diff --git a/drivers/media/video/uvc/uvc_v4l2.c b/drivers/media/video/uvc/uvc_v4l2.c index 30781b82b6b5..2a80caa54fb4 100644 --- a/drivers/media/video/uvc/uvc_v4l2.c +++ b/drivers/media/video/uvc/uvc_v4l2.c @@ -673,11 +673,17 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg) { struct v4l2_fmtdesc *fmt = arg; struct uvc_format *format; + enum v4l2_buf_type type = fmt->type; + __u32 index = fmt->index; if (fmt->type != video->streaming->type || fmt->index >= video->streaming->nformats) return -EINVAL; + memset(fmt, 0, sizeof(*fmt)); + fmt->index = index; + fmt->type = type; + format = &video->streaming->format[fmt->index]; fmt->flags = 0; if (format->flags & UVC_FMT_FLAG_COMPRESSED) -- cgit v1.2.3 From c0714f6cc6a7850062db41d5b2b8b90e5682ae41 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 13 Mar 2009 08:02:43 -0300 Subject: V4L/DVB (11295): cx23885: convert to v4l2_device. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx23885/cx23885-core.c | 17 +++++++++++------ drivers/media/video/cx23885/cx23885-i2c.c | 9 +++++---- drivers/media/video/cx23885/cx23885-video.c | 4 ++-- drivers/media/video/cx23885/cx23885.h | 8 +++++++- 4 files changed, 25 insertions(+), 13 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/cx23885/cx23885-core.c b/drivers/media/video/cx23885/cx23885-core.c index d19d453cf62a..548279225d73 100644 --- a/drivers/media/video/cx23885/cx23885-core.c +++ b/drivers/media/video/cx23885/cx23885-core.c @@ -1739,16 +1739,20 @@ static int __devinit cx23885_initdev(struct pci_dev *pci_dev, if (NULL == dev) return -ENOMEM; + err = v4l2_device_register(&pci_dev->dev, &dev->v4l2_dev); + if (err < 0) + goto fail_free; + /* pci init */ dev->pci = pci_dev; if (pci_enable_device(pci_dev)) { err = -EIO; - goto fail_free; + goto fail_unreg; } if (cx23885_dev_setup(dev) < 0) { err = -EINVAL; - goto fail_free; + goto fail_unreg; } /* print pci info */ @@ -1775,8 +1779,6 @@ static int __devinit cx23885_initdev(struct pci_dev *pci_dev, goto fail_irq; } - pci_set_drvdata(pci_dev, dev); - switch (dev->board) { case CX23885_BOARD_NETUP_DUAL_DVBS2_CI: cx_set(PCI_INT_MSK, 0x01800000); /* for NetUP */ @@ -1787,6 +1789,8 @@ static int __devinit cx23885_initdev(struct pci_dev *pci_dev, fail_irq: cx23885_dev_unregister(dev); +fail_unreg: + v4l2_device_unregister(&dev->v4l2_dev); fail_free: kfree(dev); return err; @@ -1794,7 +1798,8 @@ fail_free: static void __devexit cx23885_finidev(struct pci_dev *pci_dev) { - struct cx23885_dev *dev = pci_get_drvdata(pci_dev); + struct v4l2_device *v4l2_dev = pci_get_drvdata(pci_dev); + struct cx23885_dev *dev = to_cx23885(v4l2_dev); cx23885_shutdown(dev); @@ -1802,13 +1807,13 @@ static void __devexit cx23885_finidev(struct pci_dev *pci_dev) /* unregister stuff */ free_irq(pci_dev->irq, dev); - pci_set_drvdata(pci_dev, NULL); mutex_lock(&devlist); list_del(&dev->devlist); mutex_unlock(&devlist); cx23885_dev_unregister(dev); + v4l2_device_unregister(v4l2_dev); kfree(dev); } diff --git a/drivers/media/video/cx23885/cx23885-i2c.c b/drivers/media/video/cx23885/cx23885-i2c.c index bb7f71a1fcbe..969b7ebbc827 100644 --- a/drivers/media/video/cx23885/cx23885-i2c.c +++ b/drivers/media/video/cx23885/cx23885-i2c.c @@ -270,8 +270,8 @@ static int i2c_xfer(struct i2c_adapter *i2c_adap, static int attach_inform(struct i2c_client *client) { - struct cx23885_i2c *bus = i2c_get_adapdata(client->adapter); - struct cx23885_dev *dev = bus->dev; + struct v4l2_device *v4l2_dev = i2c_get_adapdata(client->adapter); + struct cx23885_dev *dev = to_cx23885(v4l2_dev); struct tuner_setup tun_setup; dprintk(1, "%s i2c attach [addr=0x%x,client=%s]\n", @@ -310,7 +310,8 @@ static int attach_inform(struct i2c_client *client) static int detach_inform(struct i2c_client *client) { - struct cx23885_dev *dev = i2c_get_adapdata(client->adapter); + struct v4l2_device *v4l2_dev = i2c_get_adapdata(client->adapter); + struct cx23885_dev *dev = to_cx23885(v4l2_dev); dprintk(1, "i2c detach [client=%s]\n", client->name); @@ -402,7 +403,7 @@ int cx23885_i2c_register(struct cx23885_i2c *bus) bus->i2c_algo.data = bus; bus->i2c_adap.algo_data = bus; - i2c_set_adapdata(&bus->i2c_adap, bus); + i2c_set_adapdata(&bus->i2c_adap, &dev->v4l2_dev); i2c_add_adapter(&bus->i2c_adap); bus->i2c_client.adapter = &bus->i2c_adap; diff --git a/drivers/media/video/cx23885/cx23885-video.c b/drivers/media/video/cx23885/cx23885-video.c index 726602935353..1596f4ff3dfe 100644 --- a/drivers/media/video/cx23885/cx23885-video.c +++ b/drivers/media/video/cx23885/cx23885-video.c @@ -320,8 +320,8 @@ static struct video_device *cx23885_vdev_init(struct cx23885_dev *dev, if (NULL == vfd) return NULL; *vfd = *template; - vfd->minor = -1; - vfd->parent = &pci->dev; + vfd->minor = -1; + vfd->v4l2_dev = &dev->v4l2_dev; vfd->release = video_device_release; snprintf(vfd->name, sizeof(vfd->name), "%s %s (%s)", dev->name, type, cx23885_boards[dev->board].name); diff --git a/drivers/media/video/cx23885/cx23885.h b/drivers/media/video/cx23885/cx23885.h index 779fc35b18d6..ba57643f1198 100644 --- a/drivers/media/video/cx23885/cx23885.h +++ b/drivers/media/video/cx23885/cx23885.h @@ -24,7 +24,7 @@ #include #include -#include +#include #include #include #include @@ -277,6 +277,7 @@ struct cx23885_tsport { struct cx23885_dev { struct list_head devlist; atomic_t refcount; + struct v4l2_device v4l2_dev; /* pci stuff */ struct pci_dev *pci; @@ -342,6 +343,11 @@ struct cx23885_dev { }; +static inline struct cx23885_dev *to_cx23885(struct v4l2_device *v4l2_dev) +{ + return container_of(v4l2_dev, struct cx23885_dev, v4l2_dev); +} + extern struct list_head cx23885_devlist; #define SRAM_CH01 0 /* Video A */ -- cgit v1.2.3 From d35ed62704bc1d44dd4746a242e8c09f2a48fc40 Mon Sep 17 00:00:00 2001 From: Steven Toth Date: Sat, 28 Mar 2009 13:58:28 -0300 Subject: V4L/DVB (11296): cx23885: bugfix error message if firmware is not found If the firmware failed to be found the error message indicated the incorrect filename. Signed-off-by: Steven Toth Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx23885/cx23885-417.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/cx23885/cx23885-417.c b/drivers/media/video/cx23885/cx23885-417.c index b02944d38932..9e57c33b5496 100644 --- a/drivers/media/video/cx23885/cx23885-417.c +++ b/drivers/media/video/cx23885/cx23885-417.c @@ -896,7 +896,7 @@ static int cx23885_load_firmware(struct cx23885_dev *dev) if (retval != 0) { printk(KERN_ERR "ERROR: Hotplug firmware request failed (%s).\n", - CX2341X_FIRM_ENC_FILENAME); + CX23885_FIRM_IMAGE_NAME); printk(KERN_ERR "Please fix your hotplug setup, the board will " "not work without firmware loaded!\n"); return -1; -- cgit v1.2.3 From 0d5a19f15837de69f864b2a43a93f119224d778c Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sun, 29 Mar 2009 06:53:29 -0300 Subject: V4L/DVB (11297): cx23885: convert to v4l2_subdev. Convert this driver to v4l2_subdev. Note that currently the only card with analog support in this driver is the HVR-1800. The analog tuner support in this driver is limited to what is needed for this board. When analog support is added for other cards, then the tuner load code will probably have to be expanded to take care of those boards. For example, there is currently no support for either radio tuners or tda9887 demods. I'd like to thank Steven Toth for testing this on his HVR-1800. Tested-by: Steven Toth Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx23885/cx23885-417.c | 20 +++------ drivers/media/video/cx23885/cx23885-cards.c | 4 +- drivers/media/video/cx23885/cx23885-core.c | 2 +- drivers/media/video/cx23885/cx23885-dvb.c | 2 +- drivers/media/video/cx23885/cx23885-i2c.c | 67 ++--------------------------- drivers/media/video/cx23885/cx23885-video.c | 41 ++++++++++++------ drivers/media/video/cx23885/cx23885.h | 6 ++- 7 files changed, 47 insertions(+), 95 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/cx23885/cx23885-417.c b/drivers/media/video/cx23885/cx23885-417.c index 9e57c33b5496..6f5df90af93e 100644 --- a/drivers/media/video/cx23885/cx23885-417.c +++ b/drivers/media/video/cx23885/cx23885-417.c @@ -1251,8 +1251,7 @@ static int vidioc_g_tuner(struct file *file, void *priv, if (0 != t->index) return -EINVAL; strcpy(t->name, "Television"); - cx23885_call_i2c_clients(&dev->i2c_bus[2], VIDIOC_G_TUNER, t); - cx23885_call_i2c_clients(&dev->i2c_bus[1], VIDIOC_G_TUNER, t); + call_all(dev, tuner, g_tuner, t); dprintk(1, "VIDIOC_G_TUNER: tuner type %d\n", t->type); @@ -1269,7 +1268,7 @@ static int vidioc_s_tuner(struct file *file, void *priv, return -EINVAL; /* Update the A/V core */ - cx23885_call_i2c_clients(&dev->i2c_bus[2], VIDIOC_S_TUNER, t); + call_all(dev, tuner, s_tuner, t); return 0; } @@ -1285,8 +1284,7 @@ static int vidioc_g_frequency(struct file *file, void *priv, f->type = V4L2_TUNER_ANALOG_TV; f->frequency = dev->freq; - /* Assumption that tuner is always on bus 1 */ - cx23885_call_i2c_clients(&dev->i2c_bus[1], VIDIOC_G_FREQUENCY, f); + call_all(dev, tuner, g_frequency, f); return 0; } @@ -1313,8 +1311,7 @@ static int vidioc_s_frequency(struct file *file, void *priv, return -EINVAL; dev->freq = f->frequency; - /* Assumption that tuner is always on bus 1 */ - cx23885_call_i2c_clients(&dev->i2c_bus[1], VIDIOC_S_FREQUENCY, f); + call_all(dev, tuner, s_frequency, f); cx23885_initialize_codec(dev); @@ -1328,7 +1325,7 @@ static int vidioc_s_ctrl(struct file *file, void *priv, struct cx23885_dev *dev = fh->dev; /* Update the A/V core */ - cx23885_call_i2c_clients(&dev->i2c_bus[2], VIDIOC_S_CTRL, ctl); + call_all(dev, core, s_ctrl, ctl); return 0; } @@ -1524,12 +1521,7 @@ static int vidioc_log_status(struct file *file, void *priv) printk(KERN_INFO "%s/2: ============ START LOG STATUS ============\n", dev->name); - cx23885_call_i2c_clients(&dev->i2c_bus[0], VIDIOC_LOG_STATUS, - NULL); - cx23885_call_i2c_clients(&dev->i2c_bus[1], VIDIOC_LOG_STATUS, - NULL); - cx23885_call_i2c_clients(&dev->i2c_bus[2], VIDIOC_LOG_STATUS, - NULL); + call_all(dev, core, log_status); cx2341x_log_status(&dev->mpeg_params, name); printk(KERN_INFO "%s/2: ============= END LOG STATUS =============\n", diff --git a/drivers/media/video/cx23885/cx23885-cards.c b/drivers/media/video/cx23885/cx23885-cards.c index 08cd793cd151..5e4b7e790d94 100644 --- a/drivers/media/video/cx23885/cx23885-cards.c +++ b/drivers/media/video/cx23885/cx23885-cards.c @@ -739,7 +739,9 @@ void cx23885_card_setup(struct cx23885_dev *dev) case CX23885_BOARD_LEADTEK_WINFAST_PXDVR3200_H: case CX23885_BOARD_COMPRO_VIDEOMATE_E650F: case CX23885_BOARD_NETUP_DUAL_DVBS2_CI: - request_module("cx25840"); + dev->sd_cx25840 = v4l2_i2c_new_subdev(&dev->i2c_bus[2].i2c_adap, + "cx25840", "cx25840", 0x88 >> 1); + v4l2_subdev_call(dev->sd_cx25840, core, init, 0); break; } diff --git a/drivers/media/video/cx23885/cx23885-core.c b/drivers/media/video/cx23885/cx23885-core.c index 548279225d73..dc7fff22cfdd 100644 --- a/drivers/media/video/cx23885/cx23885-core.c +++ b/drivers/media/video/cx23885/cx23885-core.c @@ -875,7 +875,7 @@ static int cx23885_dev_setup(struct cx23885_dev *dev) cx23885_i2c_register(&dev->i2c_bus[1]); cx23885_i2c_register(&dev->i2c_bus[2]); cx23885_card_setup(dev); - cx23885_call_i2c_clients(&dev->i2c_bus[0], TUNER_SET_STANDBY, NULL); + call_all(dev, core, s_standby, 0); cx23885_ir_init(dev); if (cx23885_boards[dev->board].porta == CX23885_ANALOG_VIDEO) { diff --git a/drivers/media/video/cx23885/cx23885-dvb.c b/drivers/media/video/cx23885/cx23885-dvb.c index 8d731fffad58..d43c74396767 100644 --- a/drivers/media/video/cx23885/cx23885-dvb.c +++ b/drivers/media/video/cx23885/cx23885-dvb.c @@ -673,7 +673,7 @@ static int dvb_register(struct cx23885_tsport *port) fe0->dvb.frontend->callback = cx23885_tuner_callback; /* Put the analog decoder in standby to keep it quiet */ - cx23885_call_i2c_clients(i2c_bus, TUNER_SET_STANDBY, NULL); + call_all(dev, core, s_standby, 0); if (fe0->dvb.frontend->ops.analog_ops.standby) fe0->dvb.frontend->ops.analog_ops.standby(fe0->dvb.frontend); diff --git a/drivers/media/video/cx23885/cx23885-i2c.c b/drivers/media/video/cx23885/cx23885-i2c.c index 969b7ebbc827..3421bd12056a 100644 --- a/drivers/media/video/cx23885/cx23885-i2c.c +++ b/drivers/media/video/cx23885/cx23885-i2c.c @@ -268,65 +268,6 @@ static int i2c_xfer(struct i2c_adapter *i2c_adap, return retval; } -static int attach_inform(struct i2c_client *client) -{ - struct v4l2_device *v4l2_dev = i2c_get_adapdata(client->adapter); - struct cx23885_dev *dev = to_cx23885(v4l2_dev); - struct tuner_setup tun_setup; - - dprintk(1, "%s i2c attach [addr=0x%x,client=%s]\n", - client->driver->driver.name, client->addr, client->name); - - if (!client->driver->command) - return 0; - - if (dev->tuner_type != UNSET) { - - dprintk(1, "%s (tuner) i2c attach [addr=0x%x,client=%s]\n", - client->driver->driver.name, client->addr, - client->name); - - if ((dev->tuner_addr == ADDR_UNSET) || - (dev->tuner_addr == client->addr)) { - - dprintk(1, "%s (tuner || addr UNSET)\n", - client->driver->driver.name); - - dprintk(1, "%s i2c attach [addr=0x%x,client=%s]\n", - client->driver->driver.name, - client->addr, client->name); - - tun_setup.mode_mask = T_ANALOG_TV; - tun_setup.type = dev->tuner_type; - tun_setup.addr = dev->tuner_addr; - - client->driver->command(client, TUNER_SET_TYPE_ADDR, - &tun_setup); - } - } - - return 0; -} - -static int detach_inform(struct i2c_client *client) -{ - struct v4l2_device *v4l2_dev = i2c_get_adapdata(client->adapter); - struct cx23885_dev *dev = to_cx23885(v4l2_dev); - - dprintk(1, "i2c detach [client=%s]\n", client->name); - - return 0; -} - -void cx23885_call_i2c_clients(struct cx23885_i2c *bus, - unsigned int cmd, void *arg) -{ - if (bus->i2c_rc != 0) - return; - - i2c_clients_command(&bus->i2c_adap, cmd, arg); -} - static u32 cx23885_functionality(struct i2c_adapter *adap) { return I2C_FUNC_SMBUS_EMUL | I2C_FUNC_I2C; @@ -344,9 +285,6 @@ static struct i2c_adapter cx23885_i2c_adap_template = { .owner = THIS_MODULE, .id = I2C_HW_B_CX23885, .algo = &cx23885_i2c_algo_template, - .class = I2C_CLASS_TV_ANALOG, - .client_register = attach_inform, - .client_unregister = detach_inform, }; static struct i2c_client cx23885_i2c_client_template = { @@ -410,8 +348,11 @@ int cx23885_i2c_register(struct cx23885_i2c *bus) if (0 == bus->i2c_rc) { dprintk(1, "%s: i2c bus %d registered\n", dev->name, bus->nr); - if (i2c_scan) + if (i2c_scan) { + printk(KERN_INFO "%s: scan bus %d:\n", + dev->name, bus->nr); do_i2c_scan(dev->name, &bus->i2c_client); + } } else printk(KERN_WARNING "%s: i2c bus %d register FAILED\n", dev->name, bus->nr); diff --git a/drivers/media/video/cx23885/cx23885-video.c b/drivers/media/video/cx23885/cx23885-video.c index 1596f4ff3dfe..f0ac62c5dc83 100644 --- a/drivers/media/video/cx23885/cx23885-video.c +++ b/drivers/media/video/cx23885/cx23885-video.c @@ -299,11 +299,7 @@ static int cx23885_set_tvnorm(struct cx23885_dev *dev, v4l2_std_id norm) dev->tvnorm = norm; - /* Tell the analog tuner/demods */ - cx23885_call_i2c_clients(&dev->i2c_bus[1], VIDIOC_S_STD, &norm); - - /* Tell the internal A/V decoder */ - cx23885_call_i2c_clients(&dev->i2c_bus[2], VIDIOC_S_STD, &norm); + call_all(dev, tuner, s_std, norm); return 0; } @@ -410,8 +406,7 @@ static int cx23885_video_mux(struct cx23885_dev *dev, unsigned int input) route.input = INPUT(input)->vmux; /* Tell the internal A/V decoder */ - cx23885_call_i2c_clients(&dev->i2c_bus[2], - VIDIOC_INT_S_VIDEO_ROUTING, &route); + v4l2_subdev_call(dev->sd_cx25840, video, s_routing, &route); return 0; } @@ -887,7 +882,7 @@ static int cx23885_get_control(struct cx23885_dev *dev, struct v4l2_control *ctl) { dprintk(1, "%s() calling cx25840(VIDIOC_G_CTRL)\n", __func__); - cx23885_call_i2c_clients(&dev->i2c_bus[2], VIDIOC_G_CTRL, ctl); + call_all(dev, core, g_ctrl, ctl); return 0; } @@ -1001,7 +996,7 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, fh->vidq.field = f->fmt.pix.field; dprintk(2, "%s() width=%d height=%d field=%d\n", __func__, fh->width, fh->height, fh->vidq.field); - cx23885_call_i2c_clients(&dev->i2c_bus[2], VIDIOC_S_FMT, f); + call_all(dev, video, s_fmt, f); return 0; } @@ -1281,7 +1276,7 @@ static int vidioc_g_frequency(struct file *file, void *priv, f->type = fh->radio ? V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV; f->frequency = dev->freq; - cx23885_call_i2c_clients(&dev->i2c_bus[1], VIDIOC_G_FREQUENCY, f); + call_all(dev, tuner, g_frequency, f); return 0; } @@ -1296,7 +1291,7 @@ static int cx23885_set_freq(struct cx23885_dev *dev, struct v4l2_frequency *f) mutex_lock(&dev->lock); dev->freq = f->frequency; - cx23885_call_i2c_clients(&dev->i2c_bus[1], VIDIOC_S_FREQUENCY, f); + call_all(dev, tuner, s_frequency, f); /* When changing channels it is required to reset TVAUDIO */ msleep(10); @@ -1330,7 +1325,7 @@ static int vidioc_g_register(struct file *file, void *fh, if (!v4l2_chip_match_host(®->match)) return -EINVAL; - cx23885_call_i2c_clients(&dev->i2c_bus[2], VIDIOC_DBG_G_REGISTER, reg); + call_all(dev, core, g_register, reg); return 0; } @@ -1343,7 +1338,7 @@ static int vidioc_s_register(struct file *file, void *fh, if (!v4l2_chip_match_host(®->match)) return -EINVAL; - cx23885_call_i2c_clients(&dev->i2c_bus[2], VIDIOC_DBG_S_REGISTER, reg); + call_all(dev, core, s_register, reg); return 0; } @@ -1524,6 +1519,26 @@ int cx23885_video_register(struct cx23885_dev *dev) /* Don't enable VBI yet */ cx_set(PCI_INT_MSK, 1); + if (TUNER_ABSENT != dev->tuner_type) { + struct v4l2_subdev *sd = NULL; + + if (dev->tuner_addr) + sd = v4l2_i2c_new_subdev(&dev->i2c_bus[1].i2c_adap, + "tuner", "tuner", dev->tuner_addr); + else + sd = v4l2_i2c_new_probed_subdev(&dev->i2c_bus[1].i2c_adap, + "tuner", "tuner", v4l2_i2c_tuner_addrs(ADDRS_TV)); + if (sd) { + struct tuner_setup tun_setup; + + tun_setup.mode_mask = T_ANALOG_TV; + tun_setup.type = dev->tuner_type; + tun_setup.addr = v4l2_i2c_subdev_addr(sd); + + v4l2_subdev_call(sd, tuner, s_type_addr, &tun_setup); + } + } + /* register v4l devices */ dev->video_dev = cx23885_vdev_init(dev, dev->pci, diff --git a/drivers/media/video/cx23885/cx23885.h b/drivers/media/video/cx23885/cx23885.h index ba57643f1198..02d980a29962 100644 --- a/drivers/media/video/cx23885/cx23885.h +++ b/drivers/media/video/cx23885/cx23885.h @@ -323,6 +323,7 @@ struct cx23885_dev { unsigned int radio_type; unsigned char radio_addr; unsigned int has_radio; + struct v4l2_subdev *sd_cx25840; /* V4l */ u32 freq; @@ -348,6 +349,9 @@ static inline struct cx23885_dev *to_cx23885(struct v4l2_device *v4l2_dev) return container_of(v4l2_dev, struct cx23885_dev, v4l2_dev); } +#define call_all(dev, o, f, args...) \ + v4l2_device_call_all(&dev->v4l2_dev, 0, o, f, ##args) + extern struct list_head cx23885_devlist; #define SRAM_CH01 0 /* Video A */ @@ -464,8 +468,6 @@ extern struct videobuf_queue_ops cx23885_vbi_qops; /* cx23885-i2c.c */ extern int cx23885_i2c_register(struct cx23885_i2c *bus); extern int cx23885_i2c_unregister(struct cx23885_i2c *bus); -extern void cx23885_call_i2c_clients(struct cx23885_i2c *bus, unsigned int cmd, - void *arg); extern void cx23885_av_clk(struct cx23885_dev *dev, int enable); /* ----------------------------------------------------------- */ -- cgit v1.2.3 From b6198ade556add7a6f1dd1d38dd489b0484cab2d Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sun, 29 Mar 2009 08:55:46 -0300 Subject: V4L/DVB (11298): cx25840: remove legacy code for old-style i2c API All drivers that use cx25840 are now converted to v4l2_subdev, so I can remove the support for the old-style i2c API. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx25840/cx25840-core.c | 20 +------------------- 1 file changed, 1 insertion(+), 19 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/cx25840/cx25840-core.c b/drivers/media/video/cx25840/cx25840-core.c index 4a5d5ef9dfc7..a9b8e520ae57 100644 --- a/drivers/media/video/cx25840/cx25840-core.c +++ b/drivers/media/video/cx25840/cx25840-core.c @@ -39,7 +39,7 @@ #include #include #include -#include +#include #include #include "cx25840-core.h" @@ -48,15 +48,12 @@ MODULE_DESCRIPTION("Conexant CX25840 audio/video decoder driver"); MODULE_AUTHOR("Ulf Eklund, Chris Kennedy, Hans Verkuil, Tyler Trafford"); MODULE_LICENSE("GPL"); -static unsigned short normal_i2c[] = { 0x88 >> 1, I2C_CLIENT_END }; - static int cx25840_debug; module_param_named(debug,cx25840_debug, int, 0644); MODULE_PARM_DESC(debug, "Debugging messages [0=Off (default) 1=On]"); -I2C_CLIENT_INSMOD; /* ----------------------------------------------------------------------- */ @@ -1393,19 +1390,6 @@ static int cx25840_log_status(struct v4l2_subdev *sd) return 0; } -static int cx25840_command(struct i2c_client *client, unsigned cmd, void *arg) -{ - /* ignore this command */ - if (cmd == TUNER_SET_TYPE_ADDR || cmd == TUNER_SET_CONFIG) - return 0; - - /* Old-style drivers rely on initialization on first use, so - call the init whenever a command is issued to this driver. - New-style drivers using v4l2_subdev should call init explicitly. */ - cx25840_init(i2c_get_clientdata(client), 0); - return v4l2_subdev_command(i2c_get_clientdata(client), cmd, arg); -} - /* ----------------------------------------------------------------------- */ static const struct v4l2_subdev_core_ops cx25840_core_ops = { @@ -1541,8 +1525,6 @@ MODULE_DEVICE_TABLE(i2c, cx25840_id); static struct v4l2_i2c_driver_data v4l2_i2c_data = { .name = "cx25840", - .driverid = I2C_DRIVERID_CX25840, - .command = cx25840_command, .probe = cx25840_probe, .remove = cx25840_remove, .id_table = cx25840_id, -- cgit v1.2.3 From b8341e1d2acadf3935fb299a325f569a1c20daa6 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sun, 29 Mar 2009 08:26:01 -0300 Subject: V4L/DVB (11300): cx88: convert to v4l2_subdev. Convert cx88 to use v4l2_subdev since the old i2c autoprobing mechanism will be removed. Added code to explicitly load tvaudio where needed. Also fix the rtc-isl1208 support: since that driver no longer supports autoprobing it has to be loaded using the new i2c API. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx88/cx88-blackbird.c | 4 +-- drivers/media/video/cx88/cx88-cards.c | 40 ++++++++++++++++++++++++------ drivers/media/video/cx88/cx88-core.c | 7 ++++-- drivers/media/video/cx88/cx88-dvb.c | 2 +- drivers/media/video/cx88/cx88-i2c.c | 41 ------------------------------- drivers/media/video/cx88/cx88-video.c | 40 +++++++++++++++++++++--------- drivers/media/video/cx88/cx88.h | 14 +++++++++-- 7 files changed, 80 insertions(+), 68 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/cx88/cx88-blackbird.c b/drivers/media/video/cx88/cx88-blackbird.c index 484df549345c..44eacfb0d0d6 100644 --- a/drivers/media/video/cx88/cx88-blackbird.c +++ b/drivers/media/video/cx88/cx88-blackbird.c @@ -915,7 +915,7 @@ static int vidioc_log_status (struct file *file, void *priv) snprintf(name, sizeof(name), "%s/2", core->name); printk("%s/2: ============ START LOG STATUS ============\n", core->name); - cx88_call_i2c_clients(core, VIDIOC_LOG_STATUS, NULL); + call_all(core, core, log_status); cx2341x_log_status(&dev->params, name); printk("%s/2: ============= END LOG STATUS =============\n", core->name); @@ -970,7 +970,7 @@ static int vidioc_g_frequency (struct file *file, void *priv, f->type = V4L2_TUNER_ANALOG_TV; f->frequency = core->freq; - cx88_call_i2c_clients(core,VIDIOC_G_FREQUENCY,f); + call_all(core, tuner, g_frequency, f); return 0; } diff --git a/drivers/media/video/cx88/cx88-cards.c b/drivers/media/video/cx88/cx88-cards.c index 348f6ef08b2a..c226fff49f23 100644 --- a/drivers/media/video/cx88/cx88-cards.c +++ b/drivers/media/video/cx88/cx88-cards.c @@ -732,6 +732,8 @@ static const struct cx88_board cx88_boards[] = { .radio_type = UNSET, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, + /* Some variants use a tda9874 and so need the tvaudio module. */ + .audio_chip = V4L2_IDENT_TVAUDIO, .input = {{ .type = CX88_VMUX_TELEVISION, .vmux = 0, @@ -2985,7 +2987,7 @@ static void cx88_card_setup(struct cx88_core *core) tea5767_cfg.tuner = TUNER_TEA5767; tea5767_cfg.priv = &ctl; - cx88_call_i2c_clients(core, TUNER_SET_CONFIG, &tea5767_cfg); + call_all(core, tuner, s_config, &tea5767_cfg); break; } case CX88_BOARD_TEVII_S420: @@ -3010,7 +3012,7 @@ static void cx88_card_setup(struct cx88_core *core) tun_setup.type = core->board.radio_type; tun_setup.addr = core->board.radio_addr; tun_setup.tuner_callback = cx88_tuner_callback; - cx88_call_i2c_clients(core, TUNER_SET_TYPE_ADDR, &tun_setup); + call_all(core, tuner, s_type_addr, &tun_setup); mode_mask &= ~T_RADIO; } @@ -3020,7 +3022,7 @@ static void cx88_card_setup(struct cx88_core *core) tun_setup.addr = core->board.tuner_addr; tun_setup.tuner_callback = cx88_tuner_callback; - cx88_call_i2c_clients(core, TUNER_SET_TYPE_ADDR, &tun_setup); + call_all(core, tuner, s_type_addr, &tun_setup); } if (core->board.tda9887_conf) { @@ -3029,7 +3031,7 @@ static void cx88_card_setup(struct cx88_core *core) tda9887_cfg.tuner = TUNER_TDA9887; tda9887_cfg.priv = &core->board.tda9887_conf; - cx88_call_i2c_clients(core, TUNER_SET_CONFIG, &tda9887_cfg); + call_all(core, tuner, s_config, &tda9887_cfg); } if (core->board.tuner_type == TUNER_XC2028) { @@ -3045,9 +3047,9 @@ static void cx88_card_setup(struct cx88_core *core) xc2028_cfg.priv = &ctl; info_printk(core, "Asking xc2028/3028 to load firmware %s\n", ctl.fname); - cx88_call_i2c_clients(core, TUNER_SET_CONFIG, &xc2028_cfg); + call_all(core, tuner, s_config, &xc2028_cfg); } - cx88_call_i2c_clients (core, TUNER_SET_STANDBY, NULL); + call_all(core, core, s_standby, 0); } /* ------------------------------------------------------------------ */ @@ -3202,8 +3204,30 @@ struct cx88_core *cx88_core_create(struct pci_dev *pci, int nr) cx88_i2c_init(core, pci); /* load tuner module, if needed */ - if (TUNER_ABSENT != core->board.tuner_type) - request_module("tuner"); + if (TUNER_ABSENT != core->board.tuner_type) { + int has_demod = (core->board.tda9887_conf & TDA9887_PRESENT); + + /* I don't trust the radio_type as is stored in the card + definitions, so we just probe for it. + The radio_type is sometimes missing, or set to UNSET but + later code configures a tea5767. + */ + v4l2_i2c_new_probed_subdev(&core->i2c_adap, "tuner", "tuner", + v4l2_i2c_tuner_addrs(ADDRS_RADIO)); + if (has_demod) + v4l2_i2c_new_probed_subdev(&core->i2c_adap, "tuner", + "tuner", v4l2_i2c_tuner_addrs(ADDRS_DEMOD)); + if (core->board.tuner_addr == ADDR_UNSET) { + enum v4l2_i2c_tuner_type type = + has_demod ? ADDRS_TV_WITH_DEMOD : ADDRS_TV; + + v4l2_i2c_new_probed_subdev(&core->i2c_adap, "tuner", + "tuner", v4l2_i2c_tuner_addrs(type)); + } else { + v4l2_i2c_new_subdev(&core->i2c_adap, + "tuner", "tuner", core->board.tuner_addr); + } + } cx88_card_setup(core); cx88_ir_init(core, pci); diff --git a/drivers/media/video/cx88/cx88-core.c b/drivers/media/video/cx88/cx88-core.c index 17c7dad42617..f2fb9f30bfc1 100644 --- a/drivers/media/video/cx88/cx88-core.c +++ b/drivers/media/video/cx88/cx88-core.c @@ -991,7 +991,7 @@ int cx88_set_tvnorm(struct cx88_core *core, v4l2_std_id norm) set_tvaudio(core); // tell i2c chips - cx88_call_i2c_clients(core,VIDIOC_S_STD,&norm); + call_all(core, tuner, s_std, norm); // done return 0; @@ -1059,8 +1059,11 @@ void cx88_core_put(struct cx88_core *core, struct pci_dev *pci) mutex_lock(&devlist); cx88_ir_fini(core); - if (0 == core->i2c_rc) + if (0 == core->i2c_rc) { + if (core->i2c_rtc) + i2c_unregister_device(core->i2c_rtc); i2c_del_adapter(&core->i2c_adap); + } list_del(&core->devlist); iounmap(core->lmmio); cx88_devcount--; diff --git a/drivers/media/video/cx88/cx88-dvb.c b/drivers/media/video/cx88/cx88-dvb.c index 08346fa05cd7..4ff4d9fe0355 100644 --- a/drivers/media/video/cx88/cx88-dvb.c +++ b/drivers/media/video/cx88/cx88-dvb.c @@ -1168,7 +1168,7 @@ static int dvb_register(struct cx8802_dev *dev) fe1->dvb.frontend->ops.ts_bus_ctrl = cx88_dvb_bus_ctrl; /* Put the analog decoder in standby to keep it quiet */ - cx88_call_i2c_clients(core, TUNER_SET_STANDBY, NULL); + call_all(core, core, s_standby, 0); /* register everything */ return videobuf_dvb_register_bus(&dev->frontends, THIS_MODULE, dev, diff --git a/drivers/media/video/cx88/cx88-i2c.c b/drivers/media/video/cx88/cx88-i2c.c index 4a17a7579323..996b4ed5a4fc 100644 --- a/drivers/media/video/cx88/cx88-i2c.c +++ b/drivers/media/video/cx88/cx88-i2c.c @@ -97,39 +97,6 @@ static int cx8800_bit_getsda(void *data) /* ----------------------------------------------------------------------- */ -static int attach_inform(struct i2c_client *client) -{ - struct v4l2_device *v4l2_dev = i2c_get_adapdata(client->adapter); - struct cx88_core *core = to_core(v4l2_dev); - - dprintk(1, "%s i2c attach [addr=0x%x,client=%s]\n", - client->driver->driver.name, client->addr, client->name); - return 0; -} - -static int detach_inform(struct i2c_client *client) -{ - struct v4l2_device *v4l2_dev = i2c_get_adapdata(client->adapter); - struct cx88_core *core = to_core(v4l2_dev); - - dprintk(1, "i2c detach [client=%s]\n", client->name); - return 0; -} - -void cx88_call_i2c_clients(struct cx88_core *core, unsigned int cmd, void *arg) -{ - if (0 != core->i2c_rc) - return; - - if (core->gate_ctrl) - core->gate_ctrl(core, 1); - - i2c_clients_command(&core->i2c_adap, cmd, arg); - - if (core->gate_ctrl) - core->gate_ctrl(core, 0); -} - static const struct i2c_algo_bit_data cx8800_i2c_algo_template = { .setsda = cx8800_bit_setsda, .setscl = cx8800_bit_setscl, @@ -175,17 +142,11 @@ int cx88_i2c_init(struct cx88_core *core, struct pci_dev *pci) memcpy(&core->i2c_algo, &cx8800_i2c_algo_template, sizeof(core->i2c_algo)); - if (core->board.tuner_type != TUNER_ABSENT) - core->i2c_adap.class |= I2C_CLASS_TV_ANALOG; - if (core->board.mpeg & CX88_MPEG_DVB) - core->i2c_adap.class |= I2C_CLASS_TV_DIGITAL; core->i2c_adap.dev.parent = &pci->dev; strlcpy(core->i2c_adap.name,core->name,sizeof(core->i2c_adap.name)); core->i2c_adap.owner = THIS_MODULE; core->i2c_adap.id = I2C_HW_B_CX2388x; - core->i2c_adap.client_register = attach_inform; - core->i2c_adap.client_unregister = detach_inform; core->i2c_algo.udelay = i2c_udelay; core->i2c_algo.data = core; i2c_set_adapdata(&core->i2c_adap, &core->v4l2_dev); @@ -224,8 +185,6 @@ int cx88_i2c_init(struct cx88_core *core, struct pci_dev *pci) /* ----------------------------------------------------------------------- */ -EXPORT_SYMBOL(cx88_call_i2c_clients); - /* * Local variables: * c-basic-offset: 8 diff --git a/drivers/media/video/cx88/cx88-video.c b/drivers/media/video/cx88/cx88-video.c index 5b0fbc602f3e..434237af5184 100644 --- a/drivers/media/video/cx88/cx88-video.c +++ b/drivers/media/video/cx88/cx88-video.c @@ -431,8 +431,7 @@ int cx88_video_mux(struct cx88_core *core, unsigned int input) struct v4l2_routing route; route.input = INPUT(input).audioroute; - cx88_call_i2c_clients(core, - VIDIOC_INT_S_AUDIO_ROUTING, &route); + call_all(core, audio, s_routing, &route); } /* cx2388's C-ADC is connected to the tuner only. When used with S-Video, that ADC is busy dealing with @@ -827,8 +826,7 @@ static int video_open(struct file *file) struct v4l2_routing route; route.input = core->board.radio.audioroute; - cx88_call_i2c_clients(core, - VIDIOC_INT_S_AUDIO_ROUTING, &route); + call_all(core, audio, s_routing, &route); } /* "I2S ADC mode" */ core->tvaudio = WW_I2SADC; @@ -839,7 +837,7 @@ static int video_open(struct file *file) cx88_set_tvaudio(core); cx88_set_stereo(core,V4L2_TUNER_MODE_STEREO,1); } - cx88_call_i2c_clients(core,AUDC_SET_RADIO,NULL); + call_all(core, tuner, s_radio); } unlock_kernel(); @@ -933,7 +931,7 @@ static int video_release(struct file *file) kfree(fh); if(atomic_dec_and_test(&dev->core->users)) - cx88_call_i2c_clients (dev->core, TUNER_SET_STANDBY, NULL); + call_all(dev->core, core, s_standby, 0); return 0; } @@ -1395,7 +1393,7 @@ static int vidioc_g_frequency (struct file *file, void *priv, f->type = fh->radio ? V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV; f->frequency = core->freq; - cx88_call_i2c_clients(core,VIDIOC_G_FREQUENCY,f); + call_all(core, tuner, g_frequency, f); return 0; } @@ -1411,7 +1409,7 @@ int cx88_set_freq (struct cx88_core *core, mutex_lock(&core->lock); core->freq = f->frequency; cx88_newstation(core); - cx88_call_i2c_clients(core,VIDIOC_S_FREQUENCY,f); + call_all(core, tuner, s_frequency, f); /* When changing channels it is required to reset TVAUDIO */ msleep (10); @@ -1493,7 +1491,7 @@ static int radio_g_tuner (struct file *file, void *priv, strcpy(t->name, "Radio"); t->type = V4L2_TUNER_RADIO; - cx88_call_i2c_clients(core,VIDIOC_G_TUNER,t); + call_all(core, tuner, g_tuner, t); return 0; } @@ -1527,7 +1525,7 @@ static int radio_s_tuner (struct file *file, void *priv, if (0 != t->index) return -EINVAL; - cx88_call_i2c_clients(core,VIDIOC_S_TUNER,t); + call_all(core, tuner, s_tuner, t); return 0; } @@ -1884,12 +1882,30 @@ static int __devinit cx8800_initdev(struct pci_dev *pci_dev, /* load and configure helper modules */ if (core->board.audio_chip == V4L2_IDENT_WM8775) - request_module("wm8775"); + v4l2_i2c_new_subdev(&core->i2c_adap, + "wm8775", "wm8775", 0x36 >> 1); + + if (core->board.audio_chip == V4L2_IDENT_TVAUDIO) { + /* This probes for a tda9874 as is used on some + Pixelview Ultra boards. */ + static const unsigned short i2c_addr[] = { + 0xb0 >> 1, I2C_CLIENT_END + }; + + v4l2_i2c_new_probed_subdev(&core->i2c_adap, + "tvaudio", "tvaudio", i2c_addr); + } switch (core->boardnr) { case CX88_BOARD_DVICO_FUSIONHDTV_5_GOLD: - case CX88_BOARD_DVICO_FUSIONHDTV_7_GOLD: + case CX88_BOARD_DVICO_FUSIONHDTV_7_GOLD: { + static struct i2c_board_info rtc_info = { + I2C_BOARD_INFO("isl1208", 0x6f) + }; + request_module("rtc-isl1208"); + core->i2c_rtc = i2c_new_device(&core->i2c_adap, &rtc_info); + } /* break intentionally omitted */ case CX88_BOARD_DVICO_FUSIONHDTV_5_PCI_NANO: request_module("ir-kbd-i2c"); diff --git a/drivers/media/video/cx88/cx88.h b/drivers/media/video/cx88/cx88.h index 890018c48cd8..9a43fdf20fae 100644 --- a/drivers/media/video/cx88/cx88.h +++ b/drivers/media/video/cx88/cx88.h @@ -328,6 +328,7 @@ struct cx88_core { /* config info -- analog */ struct v4l2_device v4l2_dev; + struct i2c_client *i2c_rtc; unsigned int boardnr; struct cx88_board board; @@ -371,6 +372,17 @@ static inline struct cx88_core *to_core(struct v4l2_device *v4l2_dev) return container_of(v4l2_dev, struct cx88_core, v4l2_dev); } +#define call_all(core, o, f, args...) \ + do { \ + if (!core->i2c_rc) { \ + if (core->gate_ctrl) \ + core->gate_ctrl(core, 1); \ + v4l2_device_call_all(&core->v4l2_dev, 0, o, f, ##args); \ + if (core->gate_ctrl) \ + core->gate_ctrl(core, 0); \ + } \ + } while (0) + struct cx8800_dev; struct cx8802_dev; @@ -616,8 +628,6 @@ extern struct videobuf_queue_ops cx8800_vbi_qops; /* cx88-i2c.c */ extern int cx88_i2c_init(struct cx88_core *core, struct pci_dev *pci); -extern void cx88_call_i2c_clients(struct cx88_core *core, - unsigned int cmd, void *arg); /* ----------------------------------------------------------- */ -- cgit v1.2.3 From 4705e8c8508e4278a174855815b0fcd26fbc7e00 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sun, 29 Mar 2009 08:50:31 -0300 Subject: V4L/DVB (11301): wm8775: remove legacy code for old-style i2c API All drivers that use wm8775 are now converted to v4l2_subdev, so I can remove the support for the old-style i2c API. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/wm8775.c | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/wm8775.c b/drivers/media/video/wm8775.c index 53fcd42843e0..eddf11abe1d9 100644 --- a/drivers/media/video/wm8775.c +++ b/drivers/media/video/wm8775.c @@ -34,15 +34,12 @@ #include #include #include -#include +#include MODULE_DESCRIPTION("wm8775 driver"); MODULE_AUTHOR("Ulf Eklund, Hans Verkuil"); MODULE_LICENSE("GPL"); -static unsigned short normal_i2c[] = { 0x36 >> 1, I2C_CLIENT_END }; - -I2C_CLIENT_INSMOD; /* ----------------------------------------------------------------------- */ @@ -161,11 +158,6 @@ static int wm8775_s_frequency(struct v4l2_subdev *sd, struct v4l2_frequency *fre return 0; } -static int wm8775_command(struct i2c_client *client, unsigned cmd, void *arg) -{ - return v4l2_subdev_command(i2c_get_clientdata(client), cmd, arg); -} - /* ----------------------------------------------------------------------- */ static const struct v4l2_subdev_core_ops wm8775_core_ops = { @@ -268,8 +260,6 @@ MODULE_DEVICE_TABLE(i2c, wm8775_id); static struct v4l2_i2c_driver_data v4l2_i2c_data = { .name = "wm8775", - .driverid = I2C_DRIVERID_WM8775, - .command = wm8775_command, .probe = wm8775_probe, .remove = wm8775_remove, .id_table = wm8775_id, -- cgit v1.2.3 From a61389134c7c69a63ce779e40f6a052f7b3a17fd Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sun, 29 Mar 2009 09:04:29 -0300 Subject: V4L/DVB (11302): tda9875: remove legacy code for old-style i2c API tda9875 is no longer used with the old-style i2c API, so I can remove the support for that. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/tda9875.c | 15 +-------------- 1 file changed, 1 insertion(+), 14 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/tda9875.c b/drivers/media/video/tda9875.c index e71b2bd46612..24e2b7d2ae58 100644 --- a/drivers/media/video/tda9875.c +++ b/drivers/media/video/tda9875.c @@ -28,20 +28,13 @@ #include #include #include -#include +#include #include static int debug; /* insmod parameter */ module_param(debug, int, S_IRUGO | S_IWUSR); MODULE_LICENSE("GPL"); -/* Addresses to scan */ -static unsigned short normal_i2c[] = { - I2C_ADDR_TDA9875 >> 1, - I2C_CLIENT_END -}; - -I2C_CLIENT_INSMOD; /* This is a superset of the TDA9875 */ struct tda9875 { @@ -321,11 +314,6 @@ static int tda9875_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qc) return -EINVAL; } -static int tda9875_command(struct i2c_client *client, unsigned cmd, void *arg) -{ - return v4l2_subdev_command(i2c_get_clientdata(client), cmd, arg); -} - /* ----------------------------------------------------------------------- */ static const struct v4l2_subdev_core_ops tda9875_core_ops = { @@ -402,7 +390,6 @@ MODULE_DEVICE_TABLE(i2c, tda9875_id); static struct v4l2_i2c_driver_data v4l2_i2c_data = { .name = "tda9875", - .command = tda9875_command, .probe = tda9875_probe, .remove = tda9875_remove, .id_table = tda9875_id, -- cgit v1.2.3 From 267ea2a9dc53eba8a314db74c169223d7c775145 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sun, 29 Mar 2009 09:06:00 -0300 Subject: V4L/DVB (11303): tda7432: remove legacy code for old-style i2c API tda7432 is no longer used with the old-style i2c API, so I can remove the support for that. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/tda7432.c | 15 +-------------- 1 file changed, 1 insertion(+), 14 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/tda7432.c b/drivers/media/video/tda7432.c index 976ce207cfcb..005f8a468031 100644 --- a/drivers/media/video/tda7432.c +++ b/drivers/media/video/tda7432.c @@ -50,7 +50,7 @@ #include #include #include -#include +#include #ifndef VIDEO_AUDIO_BALANCE # define VIDEO_AUDIO_BALANCE 32 @@ -69,13 +69,6 @@ MODULE_PARM_DESC(maxvol,"Set maximium volume to +20db (0), default is 0db(1)"); module_param(maxvol, int, S_IRUGO | S_IWUSR); -/* Address to scan (I2C address of this chip) */ -static unsigned short normal_i2c[] = { - I2C_ADDR_TDA7432 >> 1, - I2C_CLIENT_END, -}; - -I2C_CLIENT_INSMOD; /* Structure of address and subaddresses for the tda7432 */ @@ -433,11 +426,6 @@ static int tda7432_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qc) return -EINVAL; } -static int tda7432_command(struct i2c_client *client, unsigned cmd, void *arg) -{ - return v4l2_subdev_command(i2c_get_clientdata(client), cmd, arg); -} - /* ----------------------------------------------------------------------- */ static const struct v4l2_subdev_core_ops tda7432_core_ops = { @@ -500,7 +488,6 @@ MODULE_DEVICE_TABLE(i2c, tda7432_id); static struct v4l2_i2c_driver_data v4l2_i2c_data = { .name = "tda7432", - .command = tda7432_command, .probe = tda7432_probe, .remove = tda7432_remove, .id_table = tda7432_id, -- cgit v1.2.3 From a0d1251da012594381165e36590312009693bf49 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sun, 29 Mar 2009 09:19:09 -0300 Subject: V4L/DVB (11304): v4l2: remove v4l2_subdev_command calls where they are no longer needed. Several i2c drivers still used v4l2_subdev_command, even though they were converted to v4l2_subdev. Remove those unused .command callbacks. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cs5345.c | 7 ------- drivers/media/video/m52790.c | 6 ------ drivers/media/video/ovcamchip/ovcamchip_core.c | 6 ------ drivers/media/video/saa717x.c | 7 ------- drivers/media/video/tlv320aic23b.c | 6 ------ drivers/media/video/upd64031a.c | 6 ------ drivers/media/video/upd64083.c | 6 ------ drivers/media/video/vp27smpx.c | 6 ------ drivers/media/video/wm8739.c | 6 ------ 9 files changed, 56 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/cs5345.c b/drivers/media/video/cs5345.c index 87e91072627a..9714059ee949 100644 --- a/drivers/media/video/cs5345.c +++ b/drivers/media/video/cs5345.c @@ -141,11 +141,6 @@ static int cs5345_log_status(struct v4l2_subdev *sd) return 0; } -static int cs5345_command(struct i2c_client *client, unsigned cmd, void *arg) -{ - return v4l2_subdev_command(i2c_get_clientdata(client), cmd, arg); -} - /* ----------------------------------------------------------------------- */ static const struct v4l2_subdev_core_ops cs5345_core_ops = { @@ -214,8 +209,6 @@ MODULE_DEVICE_TABLE(i2c, cs5345_id); static struct v4l2_i2c_driver_data v4l2_i2c_data = { .name = "cs5345", - .driverid = I2C_DRIVERID_CS5345, - .command = cs5345_command, .probe = cs5345_probe, .remove = cs5345_remove, .id_table = cs5345_id, diff --git a/drivers/media/video/m52790.c b/drivers/media/video/m52790.c index 41988072b973..1f340fefc49d 100644 --- a/drivers/media/video/m52790.c +++ b/drivers/media/video/m52790.c @@ -132,11 +132,6 @@ static int m52790_log_status(struct v4l2_subdev *sd) return 0; } -static int m52790_command(struct i2c_client *client, unsigned cmd, void *arg) -{ - return v4l2_subdev_command(i2c_get_clientdata(client), cmd, arg); -} - /* ----------------------------------------------------------------------- */ static const struct v4l2_subdev_core_ops m52790_core_ops = { @@ -210,7 +205,6 @@ MODULE_DEVICE_TABLE(i2c, m52790_id); static struct v4l2_i2c_driver_data v4l2_i2c_data = { .name = "m52790", - .command = m52790_command, .probe = m52790_probe, .remove = m52790_remove, .id_table = m52790_id, diff --git a/drivers/media/video/ovcamchip/ovcamchip_core.c b/drivers/media/video/ovcamchip/ovcamchip_core.c index 21ec1dd2e1e5..d573d8428998 100644 --- a/drivers/media/video/ovcamchip/ovcamchip_core.c +++ b/drivers/media/video/ovcamchip/ovcamchip_core.c @@ -322,11 +322,6 @@ static long ovcamchip_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg) } } -static int ovcamchip_command(struct i2c_client *client, unsigned cmd, void *arg) -{ - return v4l2_subdev_command(i2c_get_clientdata(client), cmd, arg); -} - /* ----------------------------------------------------------------------- */ static const struct v4l2_subdev_core_ops ovcamchip_core_ops = { @@ -394,7 +389,6 @@ MODULE_DEVICE_TABLE(i2c, ovcamchip_id); static struct v4l2_i2c_driver_data v4l2_i2c_data = { .name = "ovcamchip", - .command = ovcamchip_command, .probe = ovcamchip_probe, .remove = ovcamchip_remove, .id_table = ovcamchip_id, diff --git a/drivers/media/video/saa717x.c b/drivers/media/video/saa717x.c index 5ad7a77699de..25bf2303a6b5 100644 --- a/drivers/media/video/saa717x.c +++ b/drivers/media/video/saa717x.c @@ -1380,11 +1380,6 @@ static int saa717x_g_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt) return 0; } -static int saa717x_command(struct i2c_client *client, unsigned cmd, void *arg) -{ - return v4l2_subdev_command(i2c_get_clientdata(client), cmd, arg); -} - /* ----------------------------------------------------------------------- */ static const struct v4l2_subdev_core_ops saa717x_core_ops = { @@ -1528,9 +1523,7 @@ MODULE_DEVICE_TABLE(i2c, saa717x_id); static struct v4l2_i2c_driver_data v4l2_i2c_data = { .name = "saa717x", - .command = saa717x_command, .probe = saa717x_probe, .remove = saa717x_remove, - .legacy_class = I2C_CLASS_TV_ANALOG | I2C_CLASS_TV_DIGITAL, .id_table = saa717x_id, }; diff --git a/drivers/media/video/tlv320aic23b.c b/drivers/media/video/tlv320aic23b.c index b8cc7d39a90a..07789c64814c 100644 --- a/drivers/media/video/tlv320aic23b.c +++ b/drivers/media/video/tlv320aic23b.c @@ -118,11 +118,6 @@ static int tlv320aic23b_log_status(struct v4l2_subdev *sd) return 0; } -static int tlv320aic23b_command(struct i2c_client *client, unsigned cmd, void *arg) -{ - return v4l2_subdev_command(i2c_get_clientdata(client), cmd, arg); -} - /* ----------------------------------------------------------------------- */ static const struct v4l2_subdev_core_ops tlv320aic23b_core_ops = { @@ -205,7 +200,6 @@ MODULE_DEVICE_TABLE(i2c, tlv320aic23b_id); static struct v4l2_i2c_driver_data v4l2_i2c_data = { .name = "tlv320aic23b", - .command = tlv320aic23b_command, .probe = tlv320aic23b_probe, .remove = tlv320aic23b_remove, .id_table = tlv320aic23b_id, diff --git a/drivers/media/video/upd64031a.c b/drivers/media/video/upd64031a.c index 5b2c4399027c..c0ac651bb358 100644 --- a/drivers/media/video/upd64031a.c +++ b/drivers/media/video/upd64031a.c @@ -187,11 +187,6 @@ static int upd64031a_s_register(struct v4l2_subdev *sd, struct v4l2_dbg_register } #endif -static int upd64031a_command(struct i2c_client *client, unsigned cmd, void *arg) -{ - return v4l2_subdev_command(i2c_get_clientdata(client), cmd, arg); -} - /* ----------------------------------------------------------------------- */ static const struct v4l2_subdev_core_ops upd64031a_core_ops = { @@ -267,7 +262,6 @@ MODULE_DEVICE_TABLE(i2c, upd64031a_id); static struct v4l2_i2c_driver_data v4l2_i2c_data = { .name = "upd64031a", - .command = upd64031a_command, .probe = upd64031a_probe, .remove = upd64031a_remove, .id_table = upd64031a_id, diff --git a/drivers/media/video/upd64083.c b/drivers/media/video/upd64083.c index acd66c172efe..410c915d51fa 100644 --- a/drivers/media/video/upd64083.c +++ b/drivers/media/video/upd64083.c @@ -164,11 +164,6 @@ static int upd64083_log_status(struct v4l2_subdev *sd) return 0; } -static int upd64083_command(struct i2c_client *client, unsigned cmd, void *arg) -{ - return v4l2_subdev_command(i2c_get_clientdata(client), cmd, arg); -} - /* ----------------------------------------------------------------------- */ static const struct v4l2_subdev_core_ops upd64083_core_ops = { @@ -239,7 +234,6 @@ MODULE_DEVICE_TABLE(i2c, upd64083_id); static struct v4l2_i2c_driver_data v4l2_i2c_data = { .name = "upd64083", - .command = upd64083_command, .probe = upd64083_probe, .remove = upd64083_remove, .id_table = upd64083_id, diff --git a/drivers/media/video/vp27smpx.c b/drivers/media/video/vp27smpx.c index 9a590a91d7de..42e23a4fa607 100644 --- a/drivers/media/video/vp27smpx.c +++ b/drivers/media/video/vp27smpx.c @@ -129,11 +129,6 @@ static int vp27smpx_log_status(struct v4l2_subdev *sd) return 0; } -static int vp27smpx_command(struct i2c_client *client, unsigned cmd, void *arg) -{ - return v4l2_subdev_command(i2c_get_clientdata(client), cmd, arg); -} - /* ----------------------------------------------------------------------- */ static const struct v4l2_subdev_core_ops vp27smpx_core_ops = { @@ -206,7 +201,6 @@ MODULE_DEVICE_TABLE(i2c, vp27smpx_id); static struct v4l2_i2c_driver_data v4l2_i2c_data = { .name = "vp27smpx", - .command = vp27smpx_command, .probe = vp27smpx_probe, .remove = vp27smpx_remove, .id_table = vp27smpx_id, diff --git a/drivers/media/video/wm8739.c b/drivers/media/video/wm8739.c index 18535c4a0549..b572ce288e14 100644 --- a/drivers/media/video/wm8739.c +++ b/drivers/media/video/wm8739.c @@ -252,11 +252,6 @@ static int wm8739_log_status(struct v4l2_subdev *sd) return 0; } -static int wm8739_command(struct i2c_client *client, unsigned cmd, void *arg) -{ - return v4l2_subdev_command(i2c_get_clientdata(client), cmd, arg); -} - /* ----------------------------------------------------------------------- */ static const struct v4l2_subdev_core_ops wm8739_core_ops = { @@ -343,7 +338,6 @@ MODULE_DEVICE_TABLE(i2c, wm8739_id); static struct v4l2_i2c_driver_data v4l2_i2c_data = { .name = "wm8739", - .command = wm8739_command, .probe = wm8739_probe, .remove = wm8739_remove, .id_table = wm8739_id, -- cgit v1.2.3 From 43d5eab7d632de5bde582d41b5d0eac01b52bb3a Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sun, 29 Mar 2009 17:47:30 -0300 Subject: V4L/DVB (11305): cx88: prevent probing rtc and ir devices tuner-core.c contains a hack for cx88 board to prevent probing of certain addresses: /* HACK: Ignore 0x6b and 0x6f on cx88 boards. * FusionHDTV5 RT Gold has an ir receiver at 0x6b * and an RTC at 0x6f which can get corrupted if probed. */ With the new i2c API this hack no longer works. So instead change the list of tuner probe addresses in the cx88 driver itself, which is much more clean. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx88/cx88-cards.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/cx88/cx88-cards.c b/drivers/media/video/cx88/cx88-cards.c index c226fff49f23..0363971a23a8 100644 --- a/drivers/media/video/cx88/cx88-cards.c +++ b/drivers/media/video/cx88/cx88-cards.c @@ -3205,6 +3205,15 @@ struct cx88_core *cx88_core_create(struct pci_dev *pci, int nr) /* load tuner module, if needed */ if (TUNER_ABSENT != core->board.tuner_type) { + /* Ignore 0x6b and 0x6f on cx88 boards. + * FusionHDTV5 RT Gold has an ir receiver at 0x6b + * and an RTC at 0x6f which can get corrupted if probed. */ + static const unsigned short tv_addrs[] = { + 0x42, 0x43, 0x4a, 0x4b, /* tda8290 */ + 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, + 0x68, 0x69, 0x6a, 0x6c, 0x6d, 0x6e, + I2C_CLIENT_END + }; int has_demod = (core->board.tda9887_conf & TDA9887_PRESENT); /* I don't trust the radio_type as is stored in the card @@ -3218,11 +3227,8 @@ struct cx88_core *cx88_core_create(struct pci_dev *pci, int nr) v4l2_i2c_new_probed_subdev(&core->i2c_adap, "tuner", "tuner", v4l2_i2c_tuner_addrs(ADDRS_DEMOD)); if (core->board.tuner_addr == ADDR_UNSET) { - enum v4l2_i2c_tuner_type type = - has_demod ? ADDRS_TV_WITH_DEMOD : ADDRS_TV; - v4l2_i2c_new_probed_subdev(&core->i2c_adap, "tuner", - "tuner", v4l2_i2c_tuner_addrs(type)); + "tuner", has_demod ? tv_addrs + 4 : tv_addrs); } else { v4l2_i2c_new_subdev(&core->i2c_adap, "tuner", "tuner", core->board.tuner_addr); -- cgit v1.2.3 From 2c26976d726838878eb8dd1bc91f84df38a05143 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 30 Mar 2009 08:18:10 -0300 Subject: V4L/DVB (11308): msp3400: use the V4L2 header since no V4L1 code is there Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/msp3400-driver.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/msp3400-driver.c b/drivers/media/video/msp3400-driver.c index 204513ee3364..9e8e06cfe5c6 100644 --- a/drivers/media/video/msp3400-driver.c +++ b/drivers/media/video/msp3400-driver.c @@ -53,7 +53,7 @@ #include #include #include -#include +#include #include #include #include -- cgit v1.2.3 From df1d5ed8a81565b78d45fbdffb6561c75c75ec0d Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Mon, 30 Mar 2009 06:26:40 -0300 Subject: V4L/DVB (11309): cx25840: cleanup: remove intermediate 'ioctl' step The audio and vbi functions where still called through an ioctl-like interface, even though this is no longer needed with v4l2-subdev. Just change each 'case' into a proper function and call that directly. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx25840/cx25840-audio.c | 121 ++++++----- drivers/media/video/cx25840/cx25840-core.c | 24 +-- drivers/media/video/cx25840/cx25840-core.h | 8 +- drivers/media/video/cx25840/cx25840-vbi.c | 314 +++++++++++++--------------- 4 files changed, 219 insertions(+), 248 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/cx25840/cx25840-audio.c b/drivers/media/video/cx25840/cx25840-audio.c index d199d80ea0a3..93d74bee292a 100644 --- a/drivers/media/video/cx25840/cx25840-audio.c +++ b/drivers/media/video/cx25840/cx25840-audio.c @@ -363,75 +363,74 @@ static void set_mute(struct i2c_client *client, int mute) } } -int cx25840_audio(struct i2c_client *client, unsigned int cmd, void *arg) +int cx25840_s_clock_freq(struct v4l2_subdev *sd, u32 freq) { - struct cx25840_state *state = to_state(i2c_get_clientdata(client)); - struct v4l2_control *ctrl = arg; + struct i2c_client *client = v4l2_get_subdevdata(sd); + struct cx25840_state *state = to_state(sd); int retval; - switch (cmd) { - case VIDIOC_INT_AUDIO_CLOCK_FREQ: - if (!state->is_cx25836) - cx25840_and_or(client, 0x810, ~0x1, 1); - if (state->aud_input != CX25840_AUDIO_SERIAL) { - cx25840_and_or(client, 0x803, ~0x10, 0); - cx25840_write(client, 0x8d3, 0x1f); - } - retval = set_audclk_freq(client, *(u32 *)arg); - if (state->aud_input != CX25840_AUDIO_SERIAL) { - cx25840_and_or(client, 0x803, ~0x10, 0x10); - } - if (!state->is_cx25836) - cx25840_and_or(client, 0x810, ~0x1, 0); - return retval; - - case VIDIOC_G_CTRL: - switch (ctrl->id) { - case V4L2_CID_AUDIO_VOLUME: - ctrl->value = get_volume(client); - break; - case V4L2_CID_AUDIO_BASS: - ctrl->value = get_bass(client); - break; - case V4L2_CID_AUDIO_TREBLE: - ctrl->value = get_treble(client); - break; - case V4L2_CID_AUDIO_BALANCE: - ctrl->value = get_balance(client); - break; - case V4L2_CID_AUDIO_MUTE: - ctrl->value = get_mute(client); - break; - default: - return -EINVAL; - } - break; + if (!state->is_cx25836) + cx25840_and_or(client, 0x810, ~0x1, 1); + if (state->aud_input != CX25840_AUDIO_SERIAL) { + cx25840_and_or(client, 0x803, ~0x10, 0); + cx25840_write(client, 0x8d3, 0x1f); + } + retval = set_audclk_freq(client, freq); + if (state->aud_input != CX25840_AUDIO_SERIAL) + cx25840_and_or(client, 0x803, ~0x10, 0x10); + if (!state->is_cx25836) + cx25840_and_or(client, 0x810, ~0x1, 0); + return retval; +} - case VIDIOC_S_CTRL: - switch (ctrl->id) { - case V4L2_CID_AUDIO_VOLUME: - set_volume(client, ctrl->value); - break; - case V4L2_CID_AUDIO_BASS: - set_bass(client, ctrl->value); - break; - case V4L2_CID_AUDIO_TREBLE: - set_treble(client, ctrl->value); - break; - case V4L2_CID_AUDIO_BALANCE: - set_balance(client, ctrl->value); - break; - case V4L2_CID_AUDIO_MUTE: - set_mute(client, ctrl->value); - break; - default: - return -EINVAL; - } - break; +int cx25840_audio_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) +{ + struct i2c_client *client = v4l2_get_subdevdata(sd); + switch (ctrl->id) { + case V4L2_CID_AUDIO_VOLUME: + ctrl->value = get_volume(client); + break; + case V4L2_CID_AUDIO_BASS: + ctrl->value = get_bass(client); + break; + case V4L2_CID_AUDIO_TREBLE: + ctrl->value = get_treble(client); + break; + case V4L2_CID_AUDIO_BALANCE: + ctrl->value = get_balance(client); + break; + case V4L2_CID_AUDIO_MUTE: + ctrl->value = get_mute(client); + break; default: return -EINVAL; } + return 0; +} +int cx25840_audio_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) +{ + struct i2c_client *client = v4l2_get_subdevdata(sd); + + switch (ctrl->id) { + case V4L2_CID_AUDIO_VOLUME: + set_volume(client, ctrl->value); + break; + case V4L2_CID_AUDIO_BASS: + set_bass(client, ctrl->value); + break; + case V4L2_CID_AUDIO_TREBLE: + set_treble(client, ctrl->value); + break; + case V4L2_CID_AUDIO_BALANCE: + set_balance(client, ctrl->value); + break; + case V4L2_CID_AUDIO_MUTE: + set_mute(client, ctrl->value); + break; + default: + return -EINVAL; + } return 0; } diff --git a/drivers/media/video/cx25840/cx25840-core.c b/drivers/media/video/cx25840/cx25840-core.c index a9b8e520ae57..ec67aea0cdb8 100644 --- a/drivers/media/video/cx25840/cx25840-core.c +++ b/drivers/media/video/cx25840/cx25840-core.c @@ -775,7 +775,7 @@ static int cx25840_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) case V4L2_CID_AUDIO_MUTE: if (state->is_cx25836) return -EINVAL; - return cx25840_audio(client, VIDIOC_S_CTRL, ctrl); + return cx25840_audio_s_ctrl(sd, ctrl); default: return -EINVAL; @@ -812,7 +812,7 @@ static int cx25840_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) case V4L2_CID_AUDIO_MUTE: if (state->is_cx25836) return -EINVAL; - return cx25840_audio(client, VIDIOC_G_CTRL, ctrl); + return cx25840_audio_g_ctrl(sd, ctrl); default: return -EINVAL; } @@ -828,7 +828,7 @@ static int cx25840_g_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt) switch (fmt->type) { case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE: - return cx25840_vbi(client, VIDIOC_G_FMT, fmt); + return cx25840_vbi_g_fmt(sd, fmt); default: return -EINVAL; } @@ -890,10 +890,10 @@ static int cx25840_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt) break; case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE: - return cx25840_vbi(client, VIDIOC_S_FMT, fmt); + return cx25840_vbi_s_fmt(sd, fmt); case V4L2_BUF_TYPE_VBI_CAPTURE: - return cx25840_vbi(client, VIDIOC_S_FMT, fmt); + return cx25840_vbi_s_fmt(sd, fmt); default: return -EINVAL; @@ -1153,20 +1153,6 @@ static int cx25840_s_register(struct v4l2_subdev *sd, struct v4l2_dbg_register * } #endif -static int cx25840_decode_vbi_line(struct v4l2_subdev *sd, struct v4l2_decode_vbi_line *vbi) -{ - struct i2c_client *client = v4l2_get_subdevdata(sd); - - return cx25840_vbi(client, VIDIOC_INT_DECODE_VBI_LINE, vbi); -} - -static int cx25840_s_clock_freq(struct v4l2_subdev *sd, u32 freq) -{ - struct i2c_client *client = v4l2_get_subdevdata(sd); - - return cx25840_audio(client, VIDIOC_INT_AUDIO_CLOCK_FREQ, &freq); -} - static int cx25840_s_stream(struct v4l2_subdev *sd, int enable) { struct cx25840_state *state = to_state(sd); diff --git a/drivers/media/video/cx25840/cx25840-core.h b/drivers/media/video/cx25840/cx25840-core.h index be0558277ca3..9ad0eb86ecfd 100644 --- a/drivers/media/video/cx25840/cx25840-core.h +++ b/drivers/media/video/cx25840/cx25840-core.h @@ -75,11 +75,15 @@ int cx25840_loadfw(struct i2c_client *client); /* ----------------------------------------------------------------------- */ /* cx25850-audio.c */ -int cx25840_audio(struct i2c_client *client, unsigned int cmd, void *arg); void cx25840_audio_set_path(struct i2c_client *client); +int cx25840_s_clock_freq(struct v4l2_subdev *sd, u32 freq); +int cx25840_audio_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl); +int cx25840_audio_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl); /* ----------------------------------------------------------------------- */ /* cx25850-vbi.c */ -int cx25840_vbi(struct i2c_client *client, unsigned int cmd, void *arg); +int cx25840_vbi_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt); +int cx25840_vbi_g_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt); +int cx25840_decode_vbi_line(struct v4l2_subdev *sd, struct v4l2_decode_vbi_line *vbi); #endif diff --git a/drivers/media/video/cx25840/cx25840-vbi.c b/drivers/media/video/cx25840/cx25840-vbi.c index 03f09b288eb8..35f6592f6c47 100644 --- a/drivers/media/video/cx25840/cx25840-vbi.c +++ b/drivers/media/video/cx25840/cx25840-vbi.c @@ -82,199 +82,181 @@ static int decode_vps(u8 * dst, u8 * p) return err & 0xf0; } -int cx25840_vbi(struct i2c_client *client, unsigned int cmd, void *arg) +int cx25840_vbi_g_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt) { - struct cx25840_state *state = to_state(i2c_get_clientdata(client)); - struct v4l2_format *fmt; + struct i2c_client *client = v4l2_get_subdevdata(sd); + struct cx25840_state *state = to_state(sd); struct v4l2_sliced_vbi_format *svbi; + static const u16 lcr2vbi[] = { + 0, V4L2_SLICED_TELETEXT_B, 0, /* 1 */ + 0, V4L2_SLICED_WSS_625, 0, /* 4 */ + V4L2_SLICED_CAPTION_525, /* 6 */ + 0, 0, V4L2_SLICED_VPS, 0, 0, /* 9 */ + 0, 0, 0, 0 + }; + int is_pal = !(state->std & V4L2_STD_525_60); + int i; - switch (cmd) { - case VIDIOC_G_FMT: - { - static u16 lcr2vbi[] = { - 0, V4L2_SLICED_TELETEXT_B, 0, /* 1 */ - 0, V4L2_SLICED_WSS_625, 0, /* 4 */ - V4L2_SLICED_CAPTION_525, /* 6 */ - 0, 0, V4L2_SLICED_VPS, 0, 0, /* 9 */ - 0, 0, 0, 0 - }; - int is_pal = !(state->std & V4L2_STD_525_60); - int i; - - fmt = arg; - if (fmt->type != V4L2_BUF_TYPE_SLICED_VBI_CAPTURE) - return -EINVAL; - svbi = &fmt->fmt.sliced; - memset(svbi, 0, sizeof(*svbi)); - /* we're done if raw VBI is active */ - if ((cx25840_read(client, 0x404) & 0x10) == 0) - break; + if (fmt->type != V4L2_BUF_TYPE_SLICED_VBI_CAPTURE) + return -EINVAL; + svbi = &fmt->fmt.sliced; + memset(svbi, 0, sizeof(*svbi)); + /* we're done if raw VBI is active */ + if ((cx25840_read(client, 0x404) & 0x10) == 0) + return 0; - if (is_pal) { - for (i = 7; i <= 23; i++) { - u8 v = cx25840_read(client, 0x424 + i - 7); + if (is_pal) { + for (i = 7; i <= 23; i++) { + u8 v = cx25840_read(client, 0x424 + i - 7); - svbi->service_lines[0][i] = lcr2vbi[v >> 4]; - svbi->service_lines[1][i] = lcr2vbi[v & 0xf]; - svbi->service_set |= - svbi->service_lines[0][i] | svbi->service_lines[1][i]; - } + svbi->service_lines[0][i] = lcr2vbi[v >> 4]; + svbi->service_lines[1][i] = lcr2vbi[v & 0xf]; + svbi->service_set |= svbi->service_lines[0][i] | + svbi->service_lines[1][i]; } - else { - for (i = 10; i <= 21; i++) { - u8 v = cx25840_read(client, 0x424 + i - 10); - - svbi->service_lines[0][i] = lcr2vbi[v >> 4]; - svbi->service_lines[1][i] = lcr2vbi[v & 0xf]; - svbi->service_set |= - svbi->service_lines[0][i] | svbi->service_lines[1][i]; - } + } else { + for (i = 10; i <= 21; i++) { + u8 v = cx25840_read(client, 0x424 + i - 10); + + svbi->service_lines[0][i] = lcr2vbi[v >> 4]; + svbi->service_lines[1][i] = lcr2vbi[v & 0xf]; + svbi->service_set |= svbi->service_lines[0][i] | + svbi->service_lines[1][i]; } - break; } + return 0; +} - case VIDIOC_S_FMT: - { - int is_pal = !(state->std & V4L2_STD_525_60); - int vbi_offset = is_pal ? 1 : 0; - int i, x; - u8 lcr[24]; - - fmt = arg; - if (fmt->type != V4L2_BUF_TYPE_SLICED_VBI_CAPTURE && - fmt->type != V4L2_BUF_TYPE_VBI_CAPTURE) - return -EINVAL; - svbi = &fmt->fmt.sliced; - if (fmt->type == V4L2_BUF_TYPE_VBI_CAPTURE) { - /* raw VBI */ - memset(svbi, 0, sizeof(*svbi)); - - /* Setup standard */ - cx25840_std_setup(client); - - /* VBI Offset */ - cx25840_write(client, 0x47f, vbi_offset); - cx25840_write(client, 0x404, 0x2e); - break; - } - - for (x = 0; x <= 23; x++) - lcr[x] = 0x00; +int cx25840_vbi_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt) +{ + struct i2c_client *client = v4l2_get_subdevdata(sd); + struct cx25840_state *state = to_state(sd); + struct v4l2_sliced_vbi_format *svbi; + int is_pal = !(state->std & V4L2_STD_525_60); + int vbi_offset = is_pal ? 1 : 0; + int i, x; + u8 lcr[24]; + + if (fmt->type != V4L2_BUF_TYPE_SLICED_VBI_CAPTURE && + fmt->type != V4L2_BUF_TYPE_VBI_CAPTURE) + return -EINVAL; + svbi = &fmt->fmt.sliced; + if (fmt->type == V4L2_BUF_TYPE_VBI_CAPTURE) { + /* raw VBI */ + memset(svbi, 0, sizeof(*svbi)); /* Setup standard */ cx25840_std_setup(client); - /* Sliced VBI */ - cx25840_write(client, 0x404, 0x32); /* Ancillary data */ - cx25840_write(client, 0x406, 0x13); + /* VBI Offset */ cx25840_write(client, 0x47f, vbi_offset); + cx25840_write(client, 0x404, 0x2e); + return 0; + } - if (is_pal) { - for (i = 0; i <= 6; i++) - svbi->service_lines[0][i] = - svbi->service_lines[1][i] = 0; - } else { - for (i = 0; i <= 9; i++) - svbi->service_lines[0][i] = - svbi->service_lines[1][i] = 0; - - for (i = 22; i <= 23; i++) - svbi->service_lines[0][i] = - svbi->service_lines[1][i] = 0; - } - - for (i = 7; i <= 23; i++) { - for (x = 0; x <= 1; x++) { - switch (svbi->service_lines[1-x][i]) { - case V4L2_SLICED_TELETEXT_B: - lcr[i] |= 1 << (4 * x); - break; - case V4L2_SLICED_WSS_625: - lcr[i] |= 4 << (4 * x); - break; - case V4L2_SLICED_CAPTION_525: - lcr[i] |= 6 << (4 * x); - break; - case V4L2_SLICED_VPS: - lcr[i] |= 9 << (4 * x); - break; - } - } - } + for (x = 0; x <= 23; x++) + lcr[x] = 0x00; + + /* Setup standard */ + cx25840_std_setup(client); + + /* Sliced VBI */ + cx25840_write(client, 0x404, 0x32); /* Ancillary data */ + cx25840_write(client, 0x406, 0x13); + cx25840_write(client, 0x47f, vbi_offset); + + if (is_pal) { + for (i = 0; i <= 6; i++) + svbi->service_lines[0][i] = + svbi->service_lines[1][i] = 0; + } else { + for (i = 0; i <= 9; i++) + svbi->service_lines[0][i] = + svbi->service_lines[1][i] = 0; + + for (i = 22; i <= 23; i++) + svbi->service_lines[0][i] = + svbi->service_lines[1][i] = 0; + } - if (is_pal) { - for (x = 1, i = 0x424; i <= 0x434; i++, x++) { - cx25840_write(client, i, lcr[6 + x]); - } - } - else { - for (x = 1, i = 0x424; i <= 0x430; i++, x++) { - cx25840_write(client, i, lcr[9 + x]); - } - for (i = 0x431; i <= 0x434; i++) { - cx25840_write(client, i, 0); + for (i = 7; i <= 23; i++) { + for (x = 0; x <= 1; x++) { + switch (svbi->service_lines[1-x][i]) { + case V4L2_SLICED_TELETEXT_B: + lcr[i] |= 1 << (4 * x); + break; + case V4L2_SLICED_WSS_625: + lcr[i] |= 4 << (4 * x); + break; + case V4L2_SLICED_CAPTION_525: + lcr[i] |= 6 << (4 * x); + break; + case V4L2_SLICED_VPS: + lcr[i] |= 9 << (4 * x); + break; } } + } - cx25840_write(client, 0x43c, 0x16); - - if (is_pal) { - cx25840_write(client, 0x474, 0x2a); - } else { - cx25840_write(client, 0x474, 0x22); - } - break; + if (is_pal) { + for (x = 1, i = 0x424; i <= 0x434; i++, x++) + cx25840_write(client, i, lcr[6 + x]); + } else { + for (x = 1, i = 0x424; i <= 0x430; i++, x++) + cx25840_write(client, i, lcr[9 + x]); + for (i = 0x431; i <= 0x434; i++) + cx25840_write(client, i, 0); } - case VIDIOC_INT_DECODE_VBI_LINE: - { - struct v4l2_decode_vbi_line *vbi = arg; - u8 *p = vbi->p; - int id1, id2, l, err = 0; + cx25840_write(client, 0x43c, 0x16); + cx25840_write(client, 0x474, is_pal ? 0x2a : 0x22); + return 0; +} - if (p[0] || p[1] != 0xff || p[2] != 0xff || - (p[3] != 0x55 && p[3] != 0x91)) { - vbi->line = vbi->type = 0; - break; - } +int cx25840_decode_vbi_line(struct v4l2_subdev *sd, struct v4l2_decode_vbi_line *vbi) +{ + struct cx25840_state *state = to_state(sd); + u8 *p = vbi->p; + int id1, id2, l, err = 0; + + if (p[0] || p[1] != 0xff || p[2] != 0xff || + (p[3] != 0x55 && p[3] != 0x91)) { + vbi->line = vbi->type = 0; + return 0; + } - p += 4; - id1 = p[-1]; - id2 = p[0] & 0xf; - l = p[2] & 0x3f; - l += state->vbi_line_offset; - p += 4; + p += 4; + id1 = p[-1]; + id2 = p[0] & 0xf; + l = p[2] & 0x3f; + l += state->vbi_line_offset; + p += 4; - switch (id2) { - case 1: - id2 = V4L2_SLICED_TELETEXT_B; - break; - case 4: - id2 = V4L2_SLICED_WSS_625; - break; - case 6: - id2 = V4L2_SLICED_CAPTION_525; - err = !odd_parity(p[0]) || !odd_parity(p[1]); - break; - case 9: - id2 = V4L2_SLICED_VPS; - if (decode_vps(p, p) != 0) { - err = 1; - } - break; - default: - id2 = 0; + switch (id2) { + case 1: + id2 = V4L2_SLICED_TELETEXT_B; + break; + case 4: + id2 = V4L2_SLICED_WSS_625; + break; + case 6: + id2 = V4L2_SLICED_CAPTION_525; + err = !odd_parity(p[0]) || !odd_parity(p[1]); + break; + case 9: + id2 = V4L2_SLICED_VPS; + if (decode_vps(p, p) != 0) err = 1; - break; - } - - vbi->type = err ? 0 : id2; - vbi->line = err ? 0 : l; - vbi->is_second_field = err ? 0 : (id1 == 0x55); - vbi->p = p; break; - } + default: + id2 = 0; + err = 1; + break; } + vbi->type = err ? 0 : id2; + vbi->line = err ? 0 : l; + vbi->is_second_field = err ? 0 : (id1 == 0x55); + vbi->p = p; return 0; } -- cgit v1.2.3 From 41c129a87014bb83efb3e0224bb44cfc54659f8f Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Mon, 30 Mar 2009 06:43:13 -0300 Subject: V4L/DVB (11310): cx18: remove intermediate 'ioctl' step The audio and vbi parts still used an 'ioctl'-like interface. Replace this with normal functions. Cc: Andy Walls Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx18/cx18-av-audio.c | 120 ++++++------ drivers/media/video/cx18/cx18-av-core.c | 29 +-- drivers/media/video/cx18/cx18-av-core.h | 9 +- drivers/media/video/cx18/cx18-av-vbi.c | 325 +++++++++++++++---------------- 4 files changed, 228 insertions(+), 255 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/cx18/cx18-av-audio.c b/drivers/media/video/cx18/cx18-av-audio.c index a2f0ad570434..9e30983f2ff6 100644 --- a/drivers/media/video/cx18/cx18-av-audio.c +++ b/drivers/media/video/cx18/cx18-av-audio.c @@ -464,82 +464,76 @@ static void set_mute(struct cx18 *cx, int mute) } } -int cx18_av_audio(struct cx18 *cx, unsigned int cmd, void *arg) +int cx18_av_s_clock_freq(struct v4l2_subdev *sd, u32 freq) { + struct cx18 *cx = v4l2_get_subdevdata(sd); struct cx18_av_state *state = &cx->av_state; - struct v4l2_control *ctrl = arg; int retval; + u8 v; - switch (cmd) { - case VIDIOC_INT_AUDIO_CLOCK_FREQ: - { - u8 v; - if (state->aud_input > CX18_AV_AUDIO_SERIAL2) { - v = cx18_av_read(cx, 0x803) & ~0x10; - cx18_av_write_expect(cx, 0x803, v, v, 0x1f); - cx18_av_write(cx, 0x8d3, 0x1f); - } - v = cx18_av_read(cx, 0x810) | 0x1; - cx18_av_write_expect(cx, 0x810, v, v, 0x0f); + if (state->aud_input > CX18_AV_AUDIO_SERIAL2) { + v = cx18_av_read(cx, 0x803) & ~0x10; + cx18_av_write_expect(cx, 0x803, v, v, 0x1f); + cx18_av_write(cx, 0x8d3, 0x1f); + } + v = cx18_av_read(cx, 0x810) | 0x1; + cx18_av_write_expect(cx, 0x810, v, v, 0x0f); - retval = set_audclk_freq(cx, *(u32 *)arg); + retval = set_audclk_freq(cx, freq); - v = cx18_av_read(cx, 0x810) & ~0x1; - cx18_av_write_expect(cx, 0x810, v, v, 0x0f); - if (state->aud_input > CX18_AV_AUDIO_SERIAL2) { - v = cx18_av_read(cx, 0x803) | 0x10; - cx18_av_write_expect(cx, 0x803, v, v, 0x1f); - } - return retval; + v = cx18_av_read(cx, 0x810) & ~0x1; + cx18_av_write_expect(cx, 0x810, v, v, 0x0f); + if (state->aud_input > CX18_AV_AUDIO_SERIAL2) { + v = cx18_av_read(cx, 0x803) | 0x10; + cx18_av_write_expect(cx, 0x803, v, v, 0x1f); } + return retval; +} - case VIDIOC_G_CTRL: - switch (ctrl->id) { - case V4L2_CID_AUDIO_VOLUME: - ctrl->value = get_volume(cx); - break; - case V4L2_CID_AUDIO_BASS: - ctrl->value = get_bass(cx); - break; - case V4L2_CID_AUDIO_TREBLE: - ctrl->value = get_treble(cx); - break; - case V4L2_CID_AUDIO_BALANCE: - ctrl->value = get_balance(cx); - break; - case V4L2_CID_AUDIO_MUTE: - ctrl->value = get_mute(cx); - break; - default: - return -EINVAL; - } +int cx18_av_audio_g_ctrl(struct cx18 *cx, struct v4l2_control *ctrl) +{ + switch (ctrl->id) { + case V4L2_CID_AUDIO_VOLUME: + ctrl->value = get_volume(cx); break; - - case VIDIOC_S_CTRL: - switch (ctrl->id) { - case V4L2_CID_AUDIO_VOLUME: - set_volume(cx, ctrl->value); - break; - case V4L2_CID_AUDIO_BASS: - set_bass(cx, ctrl->value); - break; - case V4L2_CID_AUDIO_TREBLE: - set_treble(cx, ctrl->value); - break; - case V4L2_CID_AUDIO_BALANCE: - set_balance(cx, ctrl->value); - break; - case V4L2_CID_AUDIO_MUTE: - set_mute(cx, ctrl->value); - break; - default: - return -EINVAL; - } + case V4L2_CID_AUDIO_BASS: + ctrl->value = get_bass(cx); + break; + case V4L2_CID_AUDIO_TREBLE: + ctrl->value = get_treble(cx); + break; + case V4L2_CID_AUDIO_BALANCE: + ctrl->value = get_balance(cx); + break; + case V4L2_CID_AUDIO_MUTE: + ctrl->value = get_mute(cx); break; - default: return -EINVAL; } + return 0; +} +int cx18_av_audio_s_ctrl(struct cx18 *cx, struct v4l2_control *ctrl) +{ + switch (ctrl->id) { + case V4L2_CID_AUDIO_VOLUME: + set_volume(cx, ctrl->value); + break; + case V4L2_CID_AUDIO_BASS: + set_bass(cx, ctrl->value); + break; + case V4L2_CID_AUDIO_TREBLE: + set_treble(cx, ctrl->value); + break; + case V4L2_CID_AUDIO_BALANCE: + set_balance(cx, ctrl->value); + break; + case V4L2_CID_AUDIO_MUTE: + set_mute(cx, ctrl->value); + break; + default: + return -EINVAL; + } return 0; } diff --git a/drivers/media/video/cx18/cx18-av-core.c b/drivers/media/video/cx18/cx18-av-core.c index 21f4be8393b7..f4dd9d78eb3d 100644 --- a/drivers/media/video/cx18/cx18-av-core.c +++ b/drivers/media/video/cx18/cx18-av-core.c @@ -413,19 +413,6 @@ void cx18_av_std_setup(struct cx18 *cx) cx18_av_write(cx, 0x47f, state->slicer_line_delay); } -static int cx18_av_decode_vbi_line(struct v4l2_subdev *sd, - struct v4l2_decode_vbi_line *vbi_line) -{ - struct cx18 *cx = v4l2_get_subdevdata(sd); - return cx18_av_vbi(cx, VIDIOC_INT_DECODE_VBI_LINE, vbi_line); -} - -static int cx18_av_s_clock_freq(struct v4l2_subdev *sd, u32 freq) -{ - struct cx18 *cx = v4l2_get_subdevdata(sd); - return cx18_av_audio(cx, VIDIOC_INT_AUDIO_CLOCK_FREQ, &freq); -} - static void input_change(struct cx18 *cx) { struct cx18_av_state *state = &cx->av_state; @@ -772,7 +759,7 @@ static int cx18_av_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) case V4L2_CID_AUDIO_TREBLE: case V4L2_CID_AUDIO_BALANCE: case V4L2_CID_AUDIO_MUTE: - return cx18_av_audio(cx, VIDIOC_S_CTRL, ctrl); + return cx18_av_audio_s_ctrl(cx, ctrl); default: return -EINVAL; @@ -802,7 +789,7 @@ static int cx18_av_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) case V4L2_CID_AUDIO_TREBLE: case V4L2_CID_AUDIO_BALANCE: case V4L2_CID_AUDIO_MUTE: - return cx18_av_audio(cx, VIDIOC_G_CTRL, ctrl); + return cx18_av_audio_g_ctrl(cx, ctrl); default: return -EINVAL; } @@ -845,13 +832,7 @@ static int cx18_av_g_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt) { struct cx18 *cx = v4l2_get_subdevdata(sd); - switch (fmt->type) { - case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE: - return cx18_av_vbi(cx, VIDIOC_G_FMT, fmt); - default: - return -EINVAL; - } - return 0; + return cx18_av_vbi_g_fmt(cx, fmt); } static int cx18_av_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt) @@ -925,10 +906,10 @@ static int cx18_av_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt) break; case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE: - return cx18_av_vbi(cx, VIDIOC_S_FMT, fmt); + return cx18_av_vbi_s_fmt(cx, fmt); case V4L2_BUF_TYPE_VBI_CAPTURE: - return cx18_av_vbi(cx, VIDIOC_S_FMT, fmt); + return cx18_av_vbi_s_fmt(cx, fmt); default: return -EINVAL; diff --git a/drivers/media/video/cx18/cx18-av-core.h b/drivers/media/video/cx18/cx18-av-core.h index 2687a2c91ddd..c458120e8c90 100644 --- a/drivers/media/video/cx18/cx18-av-core.h +++ b/drivers/media/video/cx18/cx18-av-core.h @@ -355,11 +355,16 @@ int cx18_av_loadfw(struct cx18 *cx); /* ----------------------------------------------------------------------- */ /* cx18_av-audio.c */ -int cx18_av_audio(struct cx18 *cx, unsigned int cmd, void *arg); +int cx18_av_audio_g_ctrl(struct cx18 *cx, struct v4l2_control *ctrl); +int cx18_av_audio_s_ctrl(struct cx18 *cx, struct v4l2_control *ctrl); +int cx18_av_s_clock_freq(struct v4l2_subdev *sd, u32 freq); void cx18_av_audio_set_path(struct cx18 *cx); /* ----------------------------------------------------------------------- */ /* cx18_av-vbi.c */ -int cx18_av_vbi(struct cx18 *cx, unsigned int cmd, void *arg); +int cx18_av_decode_vbi_line(struct v4l2_subdev *sd, + struct v4l2_decode_vbi_line *vbi); +int cx18_av_vbi_g_fmt(struct cx18 *cx, struct v4l2_format *fmt); +int cx18_av_vbi_s_fmt(struct cx18 *cx, struct v4l2_format *fmt); #endif diff --git a/drivers/media/video/cx18/cx18-av-vbi.c b/drivers/media/video/cx18/cx18-av-vbi.c index 27699839b80d..23b31670bf1d 100644 --- a/drivers/media/video/cx18/cx18-av-vbi.c +++ b/drivers/media/video/cx18/cx18-av-vbi.c @@ -129,196 +129,189 @@ static int decode_vps(u8 *dst, u8 *p) return err & 0xf0; } -int cx18_av_vbi(struct cx18 *cx, unsigned int cmd, void *arg) +int cx18_av_vbi_g_fmt(struct cx18 *cx, struct v4l2_format *fmt) { struct cx18_av_state *state = &cx->av_state; - struct v4l2_format *fmt; struct v4l2_sliced_vbi_format *svbi; + static const u16 lcr2vbi[] = { + 0, V4L2_SLICED_TELETEXT_B, 0, /* 1 */ + 0, V4L2_SLICED_WSS_625, 0, /* 4 */ + V4L2_SLICED_CAPTION_525, /* 6 */ + 0, 0, V4L2_SLICED_VPS, 0, 0, /* 9 */ + 0, 0, 0, 0 + }; + int is_pal = !(state->std & V4L2_STD_525_60); + int i; - switch (cmd) { - case VIDIOC_G_FMT: - { - static u16 lcr2vbi[] = { - 0, V4L2_SLICED_TELETEXT_B, 0, /* 1 */ - 0, V4L2_SLICED_WSS_625, 0, /* 4 */ - V4L2_SLICED_CAPTION_525, /* 6 */ - 0, 0, V4L2_SLICED_VPS, 0, 0, /* 9 */ - 0, 0, 0, 0 - }; - int is_pal = !(state->std & V4L2_STD_525_60); - int i; - - fmt = arg; - if (fmt->type != V4L2_BUF_TYPE_SLICED_VBI_CAPTURE) - return -EINVAL; - svbi = &fmt->fmt.sliced; - memset(svbi, 0, sizeof(*svbi)); - /* we're done if raw VBI is active */ - if ((cx18_av_read(cx, 0x404) & 0x10) == 0) - break; - - if (is_pal) { - for (i = 7; i <= 23; i++) { - u8 v = cx18_av_read(cx, 0x424 + i - 7); - - svbi->service_lines[0][i] = lcr2vbi[v >> 4]; - svbi->service_lines[1][i] = lcr2vbi[v & 0xf]; - svbi->service_set |= svbi->service_lines[0][i] | - svbi->service_lines[1][i]; - } - } else { - for (i = 10; i <= 21; i++) { - u8 v = cx18_av_read(cx, 0x424 + i - 10); - - svbi->service_lines[0][i] = lcr2vbi[v >> 4]; - svbi->service_lines[1][i] = lcr2vbi[v & 0xf]; - svbi->service_set |= svbi->service_lines[0][i] | - svbi->service_lines[1][i]; - } - } - break; - } + if (fmt->type != V4L2_BUF_TYPE_SLICED_VBI_CAPTURE) + return -EINVAL; + svbi = &fmt->fmt.sliced; + memset(svbi, 0, sizeof(*svbi)); + /* we're done if raw VBI is active */ + if ((cx18_av_read(cx, 0x404) & 0x10) == 0) + return 0; + + if (is_pal) { + for (i = 7; i <= 23; i++) { + u8 v = cx18_av_read(cx, 0x424 + i - 7); - case VIDIOC_S_FMT: - { - int is_pal = !(state->std & V4L2_STD_525_60); - int i, x; - u8 lcr[24]; - - fmt = arg; - if (fmt->type != V4L2_BUF_TYPE_SLICED_VBI_CAPTURE && - fmt->type != V4L2_BUF_TYPE_VBI_CAPTURE) - return -EINVAL; - svbi = &fmt->fmt.sliced; - if (fmt->type == V4L2_BUF_TYPE_VBI_CAPTURE) { - /* raw VBI */ - memset(svbi, 0, sizeof(*svbi)); - - /* Setup standard */ - cx18_av_std_setup(cx); - - /* VBI Offset */ - cx18_av_write(cx, 0x47f, state->slicer_line_delay); - cx18_av_write(cx, 0x404, 0x2e); - break; + svbi->service_lines[0][i] = lcr2vbi[v >> 4]; + svbi->service_lines[1][i] = lcr2vbi[v & 0xf]; + svbi->service_set |= svbi->service_lines[0][i] | + svbi->service_lines[1][i]; } + } else { + for (i = 10; i <= 21; i++) { + u8 v = cx18_av_read(cx, 0x424 + i - 10); + + svbi->service_lines[0][i] = lcr2vbi[v >> 4]; + svbi->service_lines[1][i] = lcr2vbi[v & 0xf]; + svbi->service_set |= svbi->service_lines[0][i] | + svbi->service_lines[1][i]; + } + } + return 0; +} - for (x = 0; x <= 23; x++) - lcr[x] = 0x00; +int cx18_av_vbi_s_fmt(struct cx18 *cx, struct v4l2_format *fmt) +{ + struct cx18_av_state *state = &cx->av_state; + struct v4l2_sliced_vbi_format *svbi; + int is_pal = !(state->std & V4L2_STD_525_60); + int i, x; + u8 lcr[24]; + + if (fmt->type != V4L2_BUF_TYPE_SLICED_VBI_CAPTURE && + fmt->type != V4L2_BUF_TYPE_VBI_CAPTURE) + return -EINVAL; + svbi = &fmt->fmt.sliced; + if (fmt->type == V4L2_BUF_TYPE_VBI_CAPTURE) { + /* raw VBI */ + memset(svbi, 0, sizeof(*svbi)); /* Setup standard */ cx18_av_std_setup(cx); - /* Sliced VBI */ - cx18_av_write(cx, 0x404, 0x32); /* Ancillary data */ - cx18_av_write(cx, 0x406, 0x13); + /* VBI Offset */ cx18_av_write(cx, 0x47f, state->slicer_line_delay); + cx18_av_write(cx, 0x404, 0x2e); + return 0; + } - /* Force impossible lines to 0 */ - if (is_pal) { - for (i = 0; i <= 6; i++) - svbi->service_lines[0][i] = - svbi->service_lines[1][i] = 0; - } else { - for (i = 0; i <= 9; i++) - svbi->service_lines[0][i] = - svbi->service_lines[1][i] = 0; - - for (i = 22; i <= 23; i++) - svbi->service_lines[0][i] = - svbi->service_lines[1][i] = 0; - } + for (x = 0; x <= 23; x++) + lcr[x] = 0x00; + + /* Setup standard */ + cx18_av_std_setup(cx); + + /* Sliced VBI */ + cx18_av_write(cx, 0x404, 0x32); /* Ancillary data */ + cx18_av_write(cx, 0x406, 0x13); + cx18_av_write(cx, 0x47f, state->slicer_line_delay); + + /* Force impossible lines to 0 */ + if (is_pal) { + for (i = 0; i <= 6; i++) + svbi->service_lines[0][i] = + svbi->service_lines[1][i] = 0; + } else { + for (i = 0; i <= 9; i++) + svbi->service_lines[0][i] = + svbi->service_lines[1][i] = 0; + + for (i = 22; i <= 23; i++) + svbi->service_lines[0][i] = + svbi->service_lines[1][i] = 0; + } - /* Build register values for requested service lines */ - for (i = 7; i <= 23; i++) { - for (x = 0; x <= 1; x++) { - switch (svbi->service_lines[1-x][i]) { - case V4L2_SLICED_TELETEXT_B: - lcr[i] |= 1 << (4 * x); - break; - case V4L2_SLICED_WSS_625: - lcr[i] |= 4 << (4 * x); - break; - case V4L2_SLICED_CAPTION_525: - lcr[i] |= 6 << (4 * x); - break; - case V4L2_SLICED_VPS: - lcr[i] |= 9 << (4 * x); - break; - } + /* Build register values for requested service lines */ + for (i = 7; i <= 23; i++) { + for (x = 0; x <= 1; x++) { + switch (svbi->service_lines[1-x][i]) { + case V4L2_SLICED_TELETEXT_B: + lcr[i] |= 1 << (4 * x); + break; + case V4L2_SLICED_WSS_625: + lcr[i] |= 4 << (4 * x); + break; + case V4L2_SLICED_CAPTION_525: + lcr[i] |= 6 << (4 * x); + break; + case V4L2_SLICED_VPS: + lcr[i] |= 9 << (4 * x); + break; } } + } - if (is_pal) { - for (x = 1, i = 0x424; i <= 0x434; i++, x++) - cx18_av_write(cx, i, lcr[6 + x]); - } else { - for (x = 1, i = 0x424; i <= 0x430; i++, x++) - cx18_av_write(cx, i, lcr[9 + x]); - for (i = 0x431; i <= 0x434; i++) - cx18_av_write(cx, i, 0); - } + if (is_pal) { + for (x = 1, i = 0x424; i <= 0x434; i++, x++) + cx18_av_write(cx, i, lcr[6 + x]); + } else { + for (x = 1, i = 0x424; i <= 0x430; i++, x++) + cx18_av_write(cx, i, lcr[9 + x]); + for (i = 0x431; i <= 0x434; i++) + cx18_av_write(cx, i, 0); + } - cx18_av_write(cx, 0x43c, 0x16); - /* FIXME - should match vblank set in cx18_av_std_setup() */ - cx18_av_write(cx, 0x474, is_pal ? 0x2a : 26); - break; + cx18_av_write(cx, 0x43c, 0x16); + /* FIXME - should match vblank set in cx18_av_std_setup() */ + cx18_av_write(cx, 0x474, is_pal ? 0x2a : 26); + return 0; +} + +int cx18_av_decode_vbi_line(struct v4l2_subdev *sd, + struct v4l2_decode_vbi_line *vbi) +{ + struct cx18 *cx = v4l2_get_subdevdata(sd); + struct cx18_av_state *state = &cx->av_state; + struct vbi_anc_data *anc = (struct vbi_anc_data *)vbi->p; + u8 *p; + int did, sdid, l, err = 0; + + /* + * Check for the ancillary data header for sliced VBI + */ + if (anc->preamble[0] || + anc->preamble[1] != 0xff || anc->preamble[2] != 0xff || + (anc->did != sliced_vbi_did[0] && + anc->did != sliced_vbi_did[1])) { + vbi->line = vbi->type = 0; + return 0; } - case VIDIOC_INT_DECODE_VBI_LINE: - { - struct v4l2_decode_vbi_line *vbi = arg; - u8 *p; - struct vbi_anc_data *anc = (struct vbi_anc_data *) vbi->p; - int did, sdid, l, err = 0; - - /* - * Check for the ancillary data header for sliced VBI - */ - if (anc->preamble[0] || - anc->preamble[1] != 0xff || anc->preamble[2] != 0xff || - (anc->did != sliced_vbi_did[0] && - anc->did != sliced_vbi_did[1])) { - vbi->line = vbi->type = 0; - break; - } + did = anc->did; + sdid = anc->sdid & 0xf; + l = anc->idid[0] & 0x3f; + l += state->slicer_line_offset; + p = anc->payload; - did = anc->did; - sdid = anc->sdid & 0xf; - l = anc->idid[0] & 0x3f; - l += state->slicer_line_offset; - p = anc->payload; - - /* Decode the SDID set by the slicer */ - switch (sdid) { - case 1: - sdid = V4L2_SLICED_TELETEXT_B; - break; - case 4: - sdid = V4L2_SLICED_WSS_625; - break; - case 6: - sdid = V4L2_SLICED_CAPTION_525; - err = !odd_parity(p[0]) || !odd_parity(p[1]); - break; - case 9: - sdid = V4L2_SLICED_VPS; - if (decode_vps(p, p) != 0) - err = 1; - break; - default: - sdid = 0; + /* Decode the SDID set by the slicer */ + switch (sdid) { + case 1: + sdid = V4L2_SLICED_TELETEXT_B; + break; + case 4: + sdid = V4L2_SLICED_WSS_625; + break; + case 6: + sdid = V4L2_SLICED_CAPTION_525; + err = !odd_parity(p[0]) || !odd_parity(p[1]); + break; + case 9: + sdid = V4L2_SLICED_VPS; + if (decode_vps(p, p) != 0) err = 1; - break; - } - - vbi->type = err ? 0 : sdid; - vbi->line = err ? 0 : l; - vbi->is_second_field = err ? 0 : (did == sliced_vbi_did[1]); - vbi->p = p; break; - } + default: + sdid = 0; + err = 1; + break; } + vbi->type = err ? 0 : sdid; + vbi->line = err ? 0 : l; + vbi->is_second_field = err ? 0 : (did == sliced_vbi_did[1]); + vbi->p = p; return 0; } -- cgit v1.2.3 From bccfa449ae5bd4cc5b52160d25fbdb1fe8a27932 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Mon, 30 Mar 2009 06:55:27 -0300 Subject: V4L/DVB (11311): v4l: replace 'ioctl' references in v4l i2c drivers Replace 'VIDIOC_' references in v4l i2c drivers by their new v4l2_subdev callback names. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/ks0127.c | 23 ++++++++++++----------- drivers/media/video/saa7115.c | 4 ++-- drivers/media/video/tuner-core.c | 17 +++++++---------- drivers/media/video/tvp5150.c | 8 ++++---- drivers/media/video/vpx3220.c | 8 ++++---- 5 files changed, 29 insertions(+), 31 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/ks0127.c b/drivers/media/video/ks0127.c index 4b3a116f2f59..841024b6bcdf 100644 --- a/drivers/media/video/ks0127.c +++ b/drivers/media/video/ks0127.c @@ -421,7 +421,7 @@ static int ks0127_s_routing(struct v4l2_subdev *sd, const struct v4l2_routing *r case KS_INPUT_COMPOSITE_5: case KS_INPUT_COMPOSITE_6: v4l2_dbg(1, debug, sd, - "VIDIOC_S_INPUT %d: Composite\n", route->input); + "s_routing %d: Composite\n", route->input); /* autodetect 50/60 Hz */ ks0127_and_or(sd, KS_CMDA, 0xfc, 0x00); /* VSE=0 */ @@ -455,7 +455,7 @@ static int ks0127_s_routing(struct v4l2_subdev *sd, const struct v4l2_routing *r case KS_INPUT_SVIDEO_2: case KS_INPUT_SVIDEO_3: v4l2_dbg(1, debug, sd, - "VIDIOC_S_INPUT %d: S-Video\n", route->input); + "s_routing %d: S-Video\n", route->input); /* autodetect 50/60 Hz */ ks0127_and_or(sd, KS_CMDA, 0xfc, 0x00); /* VSE=0 */ @@ -486,7 +486,7 @@ static int ks0127_s_routing(struct v4l2_subdev *sd, const struct v4l2_routing *r break; case KS_INPUT_YUV656: - v4l2_dbg(1, debug, sd, "VIDIOC_S_INPUT 15: YUV656\n"); + v4l2_dbg(1, debug, sd, "s_routing 15: YUV656\n"); if (ks->norm & V4L2_STD_525_60) /* force 60 Hz */ ks0127_and_or(sd, KS_CMDA, 0xfc, 0x03); @@ -531,7 +531,7 @@ static int ks0127_s_routing(struct v4l2_subdev *sd, const struct v4l2_routing *r default: v4l2_dbg(1, debug, sd, - "VIDIOC_INT_S_VIDEO_ROUTING: Unknown input %d\n", route->input); + "s_routing: Unknown input %d\n", route->input); break; } @@ -551,23 +551,23 @@ static int ks0127_s_std(struct v4l2_subdev *sd, v4l2_std_id std) ks->norm = std; if (std & V4L2_STD_NTSC) { v4l2_dbg(1, debug, sd, - "VIDIOC_S_STD: NTSC_M\n"); + "s_std: NTSC_M\n"); ks0127_and_or(sd, KS_CHROMA, 0x9f, 0x20); } else if (std & V4L2_STD_PAL_N) { v4l2_dbg(1, debug, sd, - "KS0127_SET_NORM: NTSC_N (fixme)\n"); + "s_std: NTSC_N (fixme)\n"); ks0127_and_or(sd, KS_CHROMA, 0x9f, 0x40); } else if (std & V4L2_STD_PAL) { v4l2_dbg(1, debug, sd, - "VIDIOC_S_STD: PAL_N\n"); + "s_std: PAL_N\n"); ks0127_and_or(sd, KS_CHROMA, 0x9f, 0x20); } else if (std & V4L2_STD_PAL_M) { v4l2_dbg(1, debug, sd, - "KS0127_SET_NORM: PAL_M (fixme)\n"); + "s_std: PAL_M (fixme)\n"); ks0127_and_or(sd, KS_CHROMA, 0x9f, 0x40); } else if (std & V4L2_STD_SECAM) { v4l2_dbg(1, debug, sd, - "KS0127_SET_NORM: SECAM\n"); + "s_std: SECAM\n"); /* set to secam autodetection */ ks0127_and_or(sd, KS_CHROMA, 0xdf, 0x20); @@ -579,7 +579,7 @@ static int ks0127_s_std(struct v4l2_subdev *sd, v4l2_std_id std) /* force to secam mode */ ks0127_and_or(sd, KS_DEMOD, 0xf0, 0x0f); } else { - v4l2_dbg(1, debug, sd, "VIDIOC_S_STD: Unknown norm %llx\n", + v4l2_dbg(1, debug, sd, "s_std: Unknown norm %llx\n", (unsigned long long)std); } return 0; @@ -608,7 +608,6 @@ static int ks0127_status(struct v4l2_subdev *sd, u32 *pstatus, v4l2_std_id *pstd u8 status; v4l2_std_id std = V4L2_STD_ALL; - v4l2_dbg(1, debug, sd, "VIDIOC_QUERYSTD/VIDIOC_INT_G_INPUT_STATUS\n"); status = ks0127_read(sd, KS_STAT); if (!(status & 0x20)) /* NOVID not set */ stat = 0; @@ -627,11 +626,13 @@ static int ks0127_status(struct v4l2_subdev *sd, u32 *pstatus, v4l2_std_id *pstd static int ks0127_querystd(struct v4l2_subdev *sd, v4l2_std_id *std) { + v4l2_dbg(1, debug, sd, "querystd\n"); return ks0127_status(sd, NULL, std); } static int ks0127_g_input_status(struct v4l2_subdev *sd, u32 *status) { + v4l2_dbg(1, debug, sd, "g_input_status\n"); return ks0127_status(sd, status, NULL); } diff --git a/drivers/media/video/saa7115.c b/drivers/media/video/saa7115.c index 591f7f98aa33..cebf159f52cf 100644 --- a/drivers/media/video/saa7115.c +++ b/drivers/media/video/saa7115.c @@ -931,8 +931,8 @@ static void saa711x_set_v4lstd(struct v4l2_subdev *sd, v4l2_std_id std) /* Prevent unnecessary standard changes. During a standard change the I-Port is temporarily disabled. Any devices reading from that port can get confused. - Note that VIDIOC_S_STD is also used to switch from - radio to TV mode, so if a VIDIOC_S_STD is broadcast to + Note that s_std is also used to switch from + radio to TV mode, so if a s_std is broadcast to all I2C devices then you do not want to have an unwanted side-effect here. */ if (std == state->std) diff --git a/drivers/media/video/tuner-core.c b/drivers/media/video/tuner-core.c index 421475e0ea59..bbf1f488a164 100644 --- a/drivers/media/video/tuner-core.c +++ b/drivers/media/video/tuner-core.c @@ -778,8 +778,7 @@ static int tuner_s_radio(struct v4l2_subdev *sd) struct tuner *t = to_tuner(sd); struct i2c_client *client = v4l2_get_subdevdata(sd); - if (set_mode(client, t, V4L2_TUNER_RADIO, "AUDC_SET_RADIO") - == -EINVAL) + if (set_mode(client, t, V4L2_TUNER_RADIO, "s_radio") == -EINVAL) return 0; if (t->radio_freq) set_freq(client, t->radio_freq); @@ -793,7 +792,7 @@ static int tuner_s_standby(struct v4l2_subdev *sd, u32 standby) tuner_dbg("Putting tuner to sleep\n"); - if (check_mode(t, "TUNER_SET_STANDBY") == -EINVAL) + if (check_mode(t, "s_standby") == -EINVAL) return 0; t->mode = T_STANDBY; if (analog_ops->standby) @@ -952,8 +951,7 @@ static int tuner_s_std(struct v4l2_subdev *sd, v4l2_std_id std) struct tuner *t = to_tuner(sd); struct i2c_client *client = v4l2_get_subdevdata(sd); - if (set_mode(client, t, V4L2_TUNER_ANALOG_TV, "VIDIOC_S_STD") - == -EINVAL) + if (set_mode(client, t, V4L2_TUNER_ANALOG_TV, "s_std") == -EINVAL) return 0; switch_v4l2(); @@ -970,8 +968,7 @@ static int tuner_s_frequency(struct v4l2_subdev *sd, struct v4l2_frequency *f) struct tuner *t = to_tuner(sd); struct i2c_client *client = v4l2_get_subdevdata(sd); - if (set_mode(client, t, f->type, "VIDIOC_S_FREQUENCY") - == -EINVAL) + if (set_mode(client, t, f->type, "s_frequency") == -EINVAL) return 0; switch_v4l2(); set_freq(client, f->frequency); @@ -984,7 +981,7 @@ static int tuner_g_frequency(struct v4l2_subdev *sd, struct v4l2_frequency *f) struct tuner *t = to_tuner(sd); struct dvb_tuner_ops *fe_tuner_ops = &t->fe.ops.tuner_ops; - if (check_mode(t, "VIDIOC_G_FREQUENCY") == -EINVAL) + if (check_mode(t, "g_frequency") == -EINVAL) return 0; switch_v4l2(); f->type = t->mode; @@ -1008,7 +1005,7 @@ static int tuner_g_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt) struct analog_demod_ops *analog_ops = &t->fe.ops.analog_ops; struct dvb_tuner_ops *fe_tuner_ops = &t->fe.ops.tuner_ops; - if (check_mode(t, "VIDIOC_G_TUNER") == -EINVAL) + if (check_mode(t, "g_tuner") == -EINVAL) return 0; switch_v4l2(); @@ -1057,7 +1054,7 @@ static int tuner_s_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt) struct tuner *t = to_tuner(sd); struct i2c_client *client = v4l2_get_subdevdata(sd); - if (check_mode(t, "VIDIOC_S_TUNER") == -EINVAL) + if (check_mode(t, "s_tuner") == -EINVAL) return 0; switch_v4l2(); diff --git a/drivers/media/video/tvp5150.c b/drivers/media/video/tvp5150.c index 9ee55f26c4f9..3a5a95f134b4 100644 --- a/drivers/media/video/tvp5150.c +++ b/drivers/media/video/tvp5150.c @@ -631,7 +631,7 @@ static int tvp5150_g_sliced_vbi_cap(struct v4l2_subdev *sd, const struct i2c_vbi_ram_value *regs = vbi_ram_default; int line; - v4l2_dbg(1, debug, sd, "VIDIOC_G_SLICED_VBI_CAP\n"); + v4l2_dbg(1, debug, sd, "g_sliced_vbi_cap\n"); memset(cap, 0, sizeof *cap); while (regs->reg != (u16)-1 ) { @@ -830,7 +830,7 @@ static int tvp5150_reset(struct v4l2_subdev *sd, u32 val) static int tvp5150_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) { - v4l2_dbg(1, debug, sd, "VIDIOC_G_CTRL called\n"); + v4l2_dbg(1, debug, sd, "g_ctrl called\n"); switch (ctrl->id) { case V4L2_CID_BRIGHTNESS: @@ -860,7 +860,7 @@ static int tvp5150_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) if (ctrl->value < tvp5150_qctrl[i].minimum || ctrl->value > tvp5150_qctrl[i].maximum) return -ERANGE; - v4l2_dbg(1, debug, sd, "VIDIOC_S_CTRL: id=%d, value=%d\n", + v4l2_dbg(1, debug, sd, "s_ctrl: id=%d, value=%d\n", ctrl->id, ctrl->value); break; } @@ -1014,7 +1014,7 @@ static int tvp5150_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qc) { int i; - v4l2_dbg(1, debug, sd, "VIDIOC_QUERYCTRL called\n"); + v4l2_dbg(1, debug, sd, "queryctrl called\n"); for (i = 0; i < ARRAY_SIZE(tvp5150_qctrl); i++) if (qc->id && qc->id == tvp5150_qctrl[i].id) { diff --git a/drivers/media/video/vpx3220.c b/drivers/media/video/vpx3220.c index 0cc23539f74d..2fa7e8bb5746 100644 --- a/drivers/media/video/vpx3220.c +++ b/drivers/media/video/vpx3220.c @@ -296,8 +296,6 @@ static int vpx3220_status(struct v4l2_subdev *sd, u32 *pstatus, v4l2_std_id *pst int res = V4L2_IN_ST_NO_SIGNAL, status; v4l2_std_id std = 0; - v4l2_dbg(1, debug, sd, "VIDIOC_QUERYSTD/VIDIOC_INT_G_INPUT_STATUS\n"); - status = vpx3220_fp_read(sd, 0x0f3); v4l2_dbg(1, debug, sd, "status: 0x%04x\n", status); @@ -336,11 +334,13 @@ static int vpx3220_status(struct v4l2_subdev *sd, u32 *pstatus, v4l2_std_id *pst static int vpx3220_querystd(struct v4l2_subdev *sd, v4l2_std_id *std) { + v4l2_dbg(1, debug, sd, "querystd\n"); return vpx3220_status(sd, NULL, std); } static int vpx3220_g_input_status(struct v4l2_subdev *sd, u32 *status) { + v4l2_dbg(1, debug, sd, "g_input_status\n"); return vpx3220_status(sd, status, NULL); } @@ -354,7 +354,7 @@ static int vpx3220_s_std(struct v4l2_subdev *sd, v4l2_std_id std) choosen video norm */ temp_input = vpx3220_fp_read(sd, 0xf2); - v4l2_dbg(1, debug, sd, "VIDIOC_S_STD %llx\n", (unsigned long long)std); + v4l2_dbg(1, debug, sd, "s_std %llx\n", (unsigned long long)std); if (std & V4L2_STD_NTSC) { vpx3220_write_fp_block(sd, init_ntsc, sizeof(init_ntsc) >> 1); v4l2_dbg(1, debug, sd, "norm switched to NTSC\n"); @@ -410,7 +410,7 @@ static int vpx3220_s_routing(struct v4l2_subdev *sd, const struct v4l2_routing * static int vpx3220_s_stream(struct v4l2_subdev *sd, int enable) { - v4l2_dbg(1, debug, sd, "VIDIOC_STREAM%s\n", enable ? "ON" : "OFF"); + v4l2_dbg(1, debug, sd, "s_stream %s\n", enable ? "on" : "off"); vpx3220_write(sd, 0xf2, (enable ? 0x1b : 0x00)); return 0; -- cgit v1.2.3 From 5eb35fd06397e42b49ff4d37587fa1bfbd136014 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Mon, 30 Mar 2009 07:04:07 -0300 Subject: V4L/DVB (11312): tuner: remove V4L1 code from this driver. No i2c modules are called with the V4L1 API anymore, so this can be removed. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/tuner-core.c | 129 --------------------------------------- 1 file changed, 129 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/tuner-core.c b/drivers/media/video/tuner-core.c index bbf1f488a164..72d41032742d 100644 --- a/drivers/media/video/tuner-core.c +++ b/drivers/media/video/tuner-core.c @@ -800,132 +800,6 @@ static int tuner_s_standby(struct v4l2_subdev *sd, u32 standby) return 0; } -#ifdef CONFIG_VIDEO_ALLOW_V4L1 -static long tuner_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg) -{ - struct tuner *t = to_tuner(sd); - struct i2c_client *client = v4l2_get_subdevdata(sd); - struct analog_demod_ops *analog_ops = &t->fe.ops.analog_ops; - struct dvb_tuner_ops *fe_tuner_ops = &t->fe.ops.tuner_ops; - - switch (cmd) { - case VIDIOCSAUDIO: - if (check_mode(t, "VIDIOCSAUDIO") == -EINVAL) - return 0; - if (check_v4l2(t) == -EINVAL) - return 0; - - /* Should be implemented, since bttv calls it */ - tuner_dbg("VIDIOCSAUDIO not implemented.\n"); - break; - case VIDIOCSCHAN: - { - static const v4l2_std_id map[] = { - [VIDEO_MODE_PAL] = V4L2_STD_PAL, - [VIDEO_MODE_NTSC] = V4L2_STD_NTSC_M, - [VIDEO_MODE_SECAM] = V4L2_STD_SECAM, - [4 /* bttv */ ] = V4L2_STD_PAL_M, - [5 /* bttv */ ] = V4L2_STD_PAL_N, - [6 /* bttv */ ] = V4L2_STD_NTSC_M_JP, - }; - struct video_channel *vc = arg; - - if (check_v4l2(t) == -EINVAL) - return 0; - - if (set_mode(client,t,V4L2_TUNER_ANALOG_TV, "VIDIOCSCHAN")==-EINVAL) - return 0; - - if (vc->norm < ARRAY_SIZE(map)) - t->std = map[vc->norm]; - tuner_fixup_std(t); - if (t->tv_freq) - set_tv_freq(client, t->tv_freq); - return 0; - } - case VIDIOCSFREQ: - { - unsigned long *v = arg; - - if (check_mode(t, "VIDIOCSFREQ") == -EINVAL) - return 0; - if (check_v4l2(t) == -EINVAL) - return 0; - - set_freq(client, *v); - return 0; - } - case VIDIOCGTUNER: - { - struct video_tuner *vt = arg; - - if (check_mode(t, "VIDIOCGTUNER") == -EINVAL) - return 0; - if (check_v4l2(t) == -EINVAL) - return 0; - - if (V4L2_TUNER_RADIO == t->mode) { - if (fe_tuner_ops->get_status) { - u32 tuner_status; - - fe_tuner_ops->get_status(&t->fe, &tuner_status); - if (tuner_status & TUNER_STATUS_STEREO) - vt->flags |= VIDEO_TUNER_STEREO_ON; - else - vt->flags &= ~VIDEO_TUNER_STEREO_ON; - } else { - if (analog_ops->is_stereo) { - if (analog_ops->is_stereo(&t->fe)) - vt->flags |= - VIDEO_TUNER_STEREO_ON; - else - vt->flags &= - ~VIDEO_TUNER_STEREO_ON; - } - } - if (analog_ops->has_signal) - vt->signal = - analog_ops->has_signal(&t->fe); - - vt->flags |= VIDEO_TUNER_LOW; /* Allow freqs at 62.5 Hz */ - - vt->rangelow = radio_range[0] * 16000; - vt->rangehigh = radio_range[1] * 16000; - - } else { - vt->rangelow = tv_range[0] * 16; - vt->rangehigh = tv_range[1] * 16; - } - - return 0; - } - case VIDIOCGAUDIO: - { - struct video_audio *va = arg; - - if (check_mode(t, "VIDIOCGAUDIO") == -EINVAL) - return 0; - if (check_v4l2(t) == -EINVAL) - return 0; - - if (V4L2_TUNER_RADIO == t->mode) { - if (fe_tuner_ops->get_status) { - u32 tuner_status; - - fe_tuner_ops->get_status(&t->fe, &tuner_status); - va->mode = (tuner_status & TUNER_STATUS_STEREO) - ? VIDEO_SOUND_STEREO : VIDEO_SOUND_MONO; - } else if (analog_ops->is_stereo) - va->mode = analog_ops->is_stereo(&t->fe) - ? VIDEO_SOUND_STEREO : VIDEO_SOUND_MONO; - } - return 0; - } - } - return -ENOIOCTLCMD; -} -#endif - static int tuner_s_config(struct v4l2_subdev *sd, const struct v4l2_priv_tun_config *cfg) { struct tuner *t = to_tuner(sd); @@ -1111,9 +985,6 @@ static int tuner_resume(struct i2c_client *c) static const struct v4l2_subdev_core_ops tuner_core_ops = { .log_status = tuner_log_status, .s_standby = tuner_s_standby, -#ifdef CONFIG_VIDEO_ALLOW_V4L1 - .ioctl = tuner_ioctl, -#endif }; static const struct v4l2_subdev_tuner_ops tuner_tuner_ops = { -- cgit v1.2.3 From 7c4673335b5f0508a47763840d7f2403fa6d2773 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Mon, 30 Mar 2009 07:16:08 -0300 Subject: V4L/DVB (11315): cx25840: fix 'unused variable' warning. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx25840/cx25840-core.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers/media/video') diff --git a/drivers/media/video/cx25840/cx25840-core.c b/drivers/media/video/cx25840/cx25840-core.c index ec67aea0cdb8..737ee4ea8830 100644 --- a/drivers/media/video/cx25840/cx25840-core.c +++ b/drivers/media/video/cx25840/cx25840-core.c @@ -824,8 +824,6 @@ static int cx25840_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) static int cx25840_g_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt) { - struct i2c_client *client = v4l2_get_subdevdata(sd); - switch (fmt->type) { case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE: return cx25840_vbi_g_fmt(sd, fmt); -- cgit v1.2.3 From fd3a019534e0a9ada11bcc357a8faa9251029cbb Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Mon, 30 Mar 2009 08:03:02 -0300 Subject: V4L/DVB (11316): saa7191: tuner ops wasn't set. The tuner ops pointer wasn't set, so s_std never worked here. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/saa7191.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/media/video') diff --git a/drivers/media/video/saa7191.c b/drivers/media/video/saa7191.c index 2e6fce5b51fd..3f523aeec56e 100644 --- a/drivers/media/video/saa7191.c +++ b/drivers/media/video/saa7191.c @@ -597,6 +597,7 @@ static const struct v4l2_subdev_video_ops saa7191_video_ops = { static const struct v4l2_subdev_ops saa7191_ops = { .core = &saa7191_core_ops, .video = &saa7191_video_ops, + .tuner = &saa7191_tuner_ops, }; static int saa7191_probe(struct i2c_client *client, -- cgit v1.2.3