summaryrefslogtreecommitdiff
path: root/linux
diff options
context:
space:
mode:
Diffstat (limited to 'linux')
-rwxr-xr-xlinux/Documentation/dvb/get_dvb_firmware2
-rw-r--r--linux/Documentation/video4linux/CARDLIST.cx886
-rw-r--r--linux/Documentation/video4linux/CARDLIST.em28xx2
-rw-r--r--linux/Documentation/video4linux/CARDLIST.saa71342
-rw-r--r--linux/Documentation/video4linux/CARDLIST.tuner1
-rw-r--r--linux/Documentation/video4linux/cx18.txt2
-rw-r--r--linux/Documentation/video4linux/gspca.txt5
-rw-r--r--linux/arch/arm/mach-mx3/clock.c19
-rw-r--r--linux/arch/arm/mach-pxa/devices.c9
-rw-r--r--linux/arch/arm/mach-pxa/pcm990-baseboard.c2
-rw-r--r--linux/arch/arm/plat-mxc/include/mach/memory.h8
-rw-r--r--linux/arch/sh/boards/board-ap325rxa.c15
-rw-r--r--linux/arch/sh/boards/mach-migor/setup.c19
-rw-r--r--linux/drivers/media/common/ir-keymaps.c23
-rw-r--r--linux/drivers/media/common/tuners/tuner-simple.c57
-rw-r--r--linux/drivers/media/common/tuners/tuner-types.c29
-rw-r--r--linux/drivers/media/dvb/b2c2/flexcop-fe-tuner.c196
-rw-r--r--linux/drivers/media/dvb/bt8xx/bt878.c8
-rw-r--r--linux/drivers/media/dvb/dm1105/dm1105.c121
-rw-r--r--linux/drivers/media/dvb/dvb-core/dvb_net.c65
-rw-r--r--linux/drivers/media/dvb/dvb-usb/Kconfig3
-rw-r--r--linux/drivers/media/dvb/dvb-usb/af9015.c2
-rw-r--r--linux/drivers/media/dvb/dvb-usb/dw2102.c328
-rw-r--r--linux/drivers/media/dvb/dvb-usb/dw2102.h1
-rw-r--r--linux/drivers/media/dvb/frontends/au8522_dig.c98
-rw-r--r--linux/drivers/media/dvb/frontends/lgs8gxx.c10
-rw-r--r--linux/drivers/media/dvb/frontends/lnbp21.c2
-rw-r--r--linux/drivers/media/dvb/frontends/stv0900.h7
-rw-r--r--linux/drivers/media/dvb/frontends/stv0900_core.c100
-rw-r--r--linux/drivers/media/dvb/frontends/stv0900_priv.h2
-rw-r--r--linux/drivers/media/dvb/frontends/tda10048.c1
-rw-r--r--linux/drivers/media/dvb/siano/smscoreapi.c4
-rw-r--r--linux/drivers/media/radio/dsbr100.c109
-rw-r--r--linux/drivers/media/radio/radio-tea5764.c4
-rw-r--r--linux/drivers/media/video/Kconfig10
-rw-r--r--linux/drivers/media/video/Makefile70
-rw-r--r--linux/drivers/media/video/bt8xx/bttv-driver.c11
-rw-r--r--linux/drivers/media/video/cx18/cx18-cards.c63
-rw-r--r--linux/drivers/media/video/cx18/cx18-controls.c2
-rw-r--r--linux/drivers/media/video/cx18/cx18-driver.c3
-rw-r--r--linux/drivers/media/video/cx18/cx18-driver.h5
-rw-r--r--linux/drivers/media/video/cx18/cx18-dvb.c53
-rw-r--r--linux/drivers/media/video/cx231xx/cx231xx-avcore.c2
-rw-r--r--linux/drivers/media/video/cx2341x.c2
-rw-r--r--linux/drivers/media/video/cx23885/cx23885-dvb.c33
-rw-r--r--linux/drivers/media/video/cx23885/cx23885-video.c14
-rw-r--r--linux/drivers/media/video/cx88/cx88-alsa.c7
-rw-r--r--linux/drivers/media/video/cx88/cx88-cards.c94
-rw-r--r--linux/drivers/media/video/cx88/cx88-video.c14
-rw-r--r--linux/drivers/media/video/em28xx/em28xx-cards.c128
-rw-r--r--linux/drivers/media/video/em28xx/em28xx-core.c21
-rw-r--r--linux/drivers/media/video/em28xx/em28xx-dvb.c15
-rw-r--r--linux/drivers/media/video/em28xx/em28xx.h2
-rw-r--r--linux/drivers/media/video/gspca/gspca.c120
-rw-r--r--linux/drivers/media/video/gspca/m5602/m5602_ov9650.c37
-rw-r--r--linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.c6
-rw-r--r--linux/drivers/media/video/gspca/ov519.c1436
-rw-r--r--linux/drivers/media/video/gspca/ov534.c4
-rw-r--r--linux/drivers/media/video/gspca/sonixj.c183
-rw-r--r--linux/drivers/media/video/gspca/spca505.c14
-rw-r--r--linux/drivers/media/video/gspca/stv06xx/Makefile3
-rw-r--r--linux/drivers/media/video/gspca/stv06xx/stv06xx.c55
-rw-r--r--linux/drivers/media/video/gspca/stv06xx/stv06xx.h12
-rw-r--r--linux/drivers/media/video/gspca/stv06xx/stv06xx_hdcs.c10
-rw-r--r--linux/drivers/media/video/gspca/stv06xx/stv06xx_sensor.h3
-rw-r--r--linux/drivers/media/video/gspca/stv06xx/stv06xx_st6422.c453
-rw-r--r--linux/drivers/media/video/gspca/stv06xx/stv06xx_st6422.h59
-rw-r--r--linux/drivers/media/video/hdpvr/hdpvr-video.c2
-rw-r--r--linux/drivers/media/video/ivtv/ivtv-controls.c2
-rw-r--r--linux/drivers/media/video/ivtv/ivtv-driver.c2
-rw-r--r--linux/drivers/media/video/ivtv/ivtv-i2c.c2
-rw-r--r--linux/drivers/media/video/ivtv/ivtv-queue.c3
-rw-r--r--linux/drivers/media/video/mx3_camera.c6
-rw-r--r--linux/drivers/media/video/ov511.c47
-rw-r--r--linux/drivers/media/video/ov511.h3
-rw-r--r--linux/drivers/media/video/pvrusb2/pvrusb2-audio.c14
-rw-r--r--linux/drivers/media/video/pvrusb2/pvrusb2-cs53l32a.c24
-rw-r--r--linux/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.c37
-rw-r--r--linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c60
-rw-r--r--linux/drivers/media/video/pvrusb2/pvrusb2-video-v4l.c35
-rw-r--r--linux/drivers/media/video/pwc/pwc-if.c6
-rw-r--r--linux/drivers/media/video/pxa_camera.c18
-rw-r--r--linux/drivers/media/video/saa7134/Makefile3
-rw-r--r--linux/drivers/media/video/saa7134/saa7134-cards.c8
-rw-r--r--linux/drivers/media/video/saa7134/saa7134-core.c17
-rw-r--r--linux/drivers/media/video/saa7134/saa7134-empress.c11
-rw-r--r--linux/drivers/media/video/saa7134/saa7134-ts.c120
-rw-r--r--linux/drivers/media/video/saa7134/saa7134-video.c1
-rw-r--r--linux/drivers/media/video/saa7134/saa7134.h12
-rw-r--r--linux/drivers/media/video/se401.c882
-rw-r--r--linux/drivers/media/video/se401.h7
-rw-r--r--linux/drivers/media/video/soc_camera.c2
-rw-r--r--linux/drivers/media/video/tcm825x.c4
-rw-r--r--linux/drivers/media/video/tveeprom.c4
-rw-r--r--linux/drivers/media/video/tvp514x.c2
-rw-r--r--linux/drivers/media/video/usbvideo/Kconfig5
-rw-r--r--linux/drivers/media/video/usbvideo/konicawc.c4
-rw-r--r--linux/drivers/media/video/usbvideo/quickcam_messenger.c4
-rw-r--r--linux/drivers/media/video/usbvision/usbvision-core.c14
-rw-r--r--linux/drivers/media/video/usbvision/usbvision-video.c2
-rw-r--r--linux/drivers/media/video/uvc/uvc_ctrl.c35
-rw-r--r--linux/drivers/media/video/uvc/uvc_driver.c25
-rw-r--r--linux/drivers/media/video/uvc/uvc_queue.c14
-rw-r--r--linux/drivers/media/video/uvc/uvc_v4l2.c17
-rw-r--r--linux/drivers/media/video/uvc/uvcvideo.h2
-rw-r--r--linux/drivers/media/video/v4l2-common.c9
-rw-r--r--linux/drivers/media/video/v4l2-ioctl.c17
-rw-r--r--linux/drivers/media/video/videobuf-core.c1
-rw-r--r--linux/drivers/media/video/videobuf-dma-sg.c2
-rw-r--r--linux/drivers/media/video/vino.c6
-rw-r--r--linux/drivers/media/video/zoran/zoran_card.c2
-rw-r--r--linux/drivers/media/video/zr364xx.c6
-rw-r--r--linux/include/linux/mmc/sdio_ids.h10
-rw-r--r--linux/include/linux/videodev2.h7
-rw-r--r--linux/include/media/ir-common.h2
-rw-r--r--linux/include/media/tuner.h1
-rw-r--r--linux/include/media/v4l2-i2c-drv.h5
-rw-r--r--linux/sound/pci/bt87x.c8
118 files changed, 4408 insertions, 1330 deletions
diff --git a/linux/Documentation/dvb/get_dvb_firmware b/linux/Documentation/dvb/get_dvb_firmware
index 815a57840..a52adfc9a 100755
--- a/linux/Documentation/dvb/get_dvb_firmware
+++ b/linux/Documentation/dvb/get_dvb_firmware
@@ -317,7 +317,7 @@ sub nxt2002 {
sub nxt2004 {
my $sourcefile = "AVerTVHD_MCE_A180_Drv_v1.2.2.16.zip";
- my $url = "http://www.aver.com/support/Drivers/$sourcefile";
+ my $url = "http://www.avermedia-usa.com/support/Drivers/$sourcefile";
my $hash = "111cb885b1e009188346d72acfed024c";
my $outfile = "dvb-fe-nxt2004.fw";
my $tmpdir = tempdir(DIR => "/tmp", CLEANUP => 1);
diff --git a/linux/Documentation/video4linux/CARDLIST.cx88 b/linux/Documentation/video4linux/CARDLIST.cx88
index 89093f531..0736518b2 100644
--- a/linux/Documentation/video4linux/CARDLIST.cx88
+++ b/linux/Documentation/video4linux/CARDLIST.cx88
@@ -6,8 +6,8 @@
5 -> Leadtek Winfast 2000XP Expert [107d:6611,107d:6613]
6 -> AverTV Studio 303 (M126) [1461:000b]
7 -> MSI TV-@nywhere Master [1462:8606]
- 8 -> Leadtek Winfast DV2000 [107d:6620]
- 9 -> Leadtek PVR 2000 [107d:663b,107d:663c,107d:6632]
+ 8 -> Leadtek Winfast DV2000 [107d:6620,107d:6621]
+ 9 -> Leadtek PVR 2000 [107d:663b,107d:663c,107d:6632,107d:6630,107d:6638,107d:6631,107d:6637,107d:663d]
10 -> IODATA GV-VCP3/PCI [10fc:d003]
11 -> Prolink PlayTV PVR
12 -> ASUS PVR-416 [1043:4823,1461:c111]
@@ -59,7 +59,7 @@
58 -> Pinnacle PCTV HD 800i [11bd:0051]
59 -> DViCO FusionHDTV 5 PCI nano [18ac:d530]
60 -> Pinnacle Hybrid PCTV [12ab:1788]
- 61 -> Winfast TV2000 XP Global [107d:6f18]
+ 61 -> Leadtek TV2000 XP Global [107d:6f18,107d:6618]
62 -> PowerColor RA330 [14f1:ea3d]
63 -> Geniatech X8000-MT DVBT [14f1:8852]
64 -> DViCO FusionHDTV DVB-T PRO [18ac:db30]
diff --git a/linux/Documentation/video4linux/CARDLIST.em28xx b/linux/Documentation/video4linux/CARDLIST.em28xx
index b03a68586..873630e7e 100644
--- a/linux/Documentation/video4linux/CARDLIST.em28xx
+++ b/linux/Documentation/video4linux/CARDLIST.em28xx
@@ -64,3 +64,5 @@
66 -> Empire dual TV (em2880)
67 -> Terratec Grabby (em2860) [0ccd:0096]
68 -> Terratec AV350 (em2860) [0ccd:0084]
+ 69 -> KWorld ATSC 315U HDTV TV Box (em2882) [eb1a:a313]
+ 70 -> Evga inDtube (em2882)
diff --git a/linux/Documentation/video4linux/CARDLIST.saa7134 b/linux/Documentation/video4linux/CARDLIST.saa7134
index e56934e50..15562427e 100644
--- a/linux/Documentation/video4linux/CARDLIST.saa7134
+++ b/linux/Documentation/video4linux/CARDLIST.saa7134
@@ -143,7 +143,7 @@
142 -> Beholder BeholdTV H6 [5ace:6290]
143 -> Beholder BeholdTV M63 [5ace:6191]
144 -> Beholder BeholdTV M6 Extra [5ace:6193]
-145 -> AVerMedia MiniPCI DVB-T Hybrid M103 [1461:f636]
+145 -> AVerMedia MiniPCI DVB-T Hybrid M103 [1461:f636,1461:f736]
146 -> ASUSTeK P7131 Analog
147 -> Asus Tiger 3in1 [1043:4878]
148 -> Encore ENLTV-FM v5.3 [1a7f:2008]
diff --git a/linux/Documentation/video4linux/CARDLIST.tuner b/linux/Documentation/video4linux/CARDLIST.tuner
index 22c1c5597..be6784407 100644
--- a/linux/Documentation/video4linux/CARDLIST.tuner
+++ b/linux/Documentation/video4linux/CARDLIST.tuner
@@ -77,3 +77,4 @@ tuner=76 - Xceive 5000 tuner
tuner=77 - TCL tuner MF02GIP-5N-E
tuner=78 - Philips FMD1216MEX MK3 Hybrid Tuner
tuner=79 - Philips PAL/SECAM multi (FM1216 MK5)
+tuner=80 - Philips FQ1216LME MK3 PAL/SECAM w/active loopthrough
diff --git a/linux/Documentation/video4linux/cx18.txt b/linux/Documentation/video4linux/cx18.txt
index 914cb7e73..4652c0f5d 100644
--- a/linux/Documentation/video4linux/cx18.txt
+++ b/linux/Documentation/video4linux/cx18.txt
@@ -11,7 +11,7 @@ encoder chip:
2) Some people have problems getting the i2c bus to work.
The symptom is that the eeprom cannot be read and the card is
unusable. This is probably fixed, but if you have problems
- then post to the video4linux or ivtv-users mailinglist.
+ then post to the video4linux or ivtv-users mailing list.
3) VBI (raw or sliced) has not yet been implemented.
diff --git a/linux/Documentation/video4linux/gspca.txt b/linux/Documentation/video4linux/gspca.txt
index 1bb103fe9..2bcf78896 100644
--- a/linux/Documentation/video4linux/gspca.txt
+++ b/linux/Documentation/video4linux/gspca.txt
@@ -163,10 +163,11 @@ sunplus 055f:c650 Mustek MDC5500Z
zc3xx 055f:d003 Mustek WCam300A
zc3xx 055f:d004 Mustek WCam300 AN
conex 0572:0041 Creative Notebook cx11646
-ov519 05a9:0519 OmniVision
+ov519 05a9:0519 OV519 Microphone
ov519 05a9:0530 OmniVision
-ov519 05a9:4519 OmniVision
+ov519 05a9:4519 Webcam Classic
ov519 05a9:8519 OmniVision
+ov519 05a9:a518 D-Link DSB-C310 Webcam
sunplus 05da:1018 Digital Dream Enigma 1.3
stk014 05e1:0893 Syntek DV4000
spca561 060b:a001 Maxell Compact Pc PM3
diff --git a/linux/arch/arm/mach-mx3/clock.c b/linux/arch/arm/mach-mx3/clock.c
index 9957a1153..8b1423972 100644
--- a/linux/arch/arm/mach-mx3/clock.c
+++ b/linux/arch/arm/mach-mx3/clock.c
@@ -483,7 +483,7 @@ DEFINE_CLOCK(i2c3_clk, 2, MXC_CCM_CGR0, 30, NULL, NULL, &perclk_clk);
DEFINE_CLOCK(mpeg4_clk, 0, MXC_CCM_CGR1, 0, NULL, NULL, &ahb_clk);
DEFINE_CLOCK(mstick1_clk, 0, MXC_CCM_CGR1, 2, mstick1_get_rate, NULL, &usb_pll_clk);
DEFINE_CLOCK(mstick2_clk, 1, MXC_CCM_CGR1, 4, mstick2_get_rate, NULL, &usb_pll_clk);
-DEFINE_CLOCK1(csi_clk, 0, MXC_CCM_CGR1, 6, csi, NULL, &ahb_clk);
+DEFINE_CLOCK1(csi_clk, 0, MXC_CCM_CGR1, 6, csi, NULL, &serial_pll_clk);
DEFINE_CLOCK(rtc_clk, 0, MXC_CCM_CGR1, 8, NULL, NULL, &ipg_clk);
DEFINE_CLOCK(wdog_clk, 0, MXC_CCM_CGR1, 10, NULL, NULL, &ipg_clk);
DEFINE_CLOCK(pwm_clk, 0, MXC_CCM_CGR1, 12, NULL, NULL, &perclk_clk);
@@ -516,7 +516,7 @@ DEFINE_CLOCK(ipg_clk, 0, NULL, 0, ipg_get_rate, NULL, &ahb_clk);
.clk = &c, \
},
-static struct clk_lookup lookups[] __initdata = {
+static struct clk_lookup lookups[] = {
_REGISTER_CLOCK(NULL, "emi", emi_clk)
_REGISTER_CLOCK(NULL, "cspi", cspi1_clk)
_REGISTER_CLOCK(NULL, "cspi", cspi2_clk)
@@ -566,13 +566,18 @@ int __init mx31_clocks_init(unsigned long fref)
u32 reg;
int i;
- mxc_set_cpu_type(MXC_CPU_MX31);
-
ckih_rate = fref;
for (i = 0; i < ARRAY_SIZE(lookups); i++)
clkdev_add(&lookups[i]);
+ /* change the csi_clk parent if necessary */
+ reg = __raw_readl(MXC_CCM_CCMR);
+ if (!(reg & MXC_CCM_CCMR_CSCS))
+ if (clk_set_parent(&csi_clk, &usb_pll_clk))
+ pr_err("%s: error changing csi_clk parent\n", __func__);
+
+
/* Turn off all possible clocks */
__raw_writel((3 << 4), MXC_CCM_CGR0);
__raw_writel(0, MXC_CCM_CGR1);
@@ -581,6 +586,12 @@ int __init mx31_clocks_init(unsigned long fref)
MX32, but still required to be set */
MXC_CCM_CGR2);
+ /*
+ * Before turning off usb_pll make sure ipg_per_clk is generated
+ * by ipg_clk and not usb_pll.
+ */
+ __raw_writel(__raw_readl(MXC_CCM_CCMR) | (1 << 24), MXC_CCM_CCMR);
+
usb_pll_disable(&usb_pll_clk);
pr_info("Clock input source is %ld\n", clk_get_rate(&ckih_clk));
diff --git a/linux/arch/arm/mach-pxa/devices.c b/linux/arch/arm/mach-pxa/devices.c
index 5ec10735b..d19f5096a 100644
--- a/linux/arch/arm/mach-pxa/devices.c
+++ b/linux/arch/arm/mach-pxa/devices.c
@@ -39,7 +39,7 @@
#include <mach/pxafb.h>
#include <mach/mmc.h>
#include <mach/irda.h>
-#include <mach/i2c.h>
+#include <plat/i2c.h>
#include <mach/ohci.h>
#include <mach/pxa27x_keypad.h>
#include <mach/pxa2xx_spi.h>
@@ -104,7 +104,10 @@ void __init pxa_set_mci_info(struct pxamci_platform_data *info)
}
-static struct pxa2xx_udc_mach_info pxa_udc_info;
+static struct pxa2xx_udc_mach_info pxa_udc_info = {
+ .gpio_pullup = -1,
+ .gpio_vbus = -1,
+};
void __init pxa_set_udc_info(struct pxa2xx_udc_mach_info *info)
{
@@ -319,7 +322,7 @@ static struct resource pxa3xx_resources_i2c_power[] = {
};
struct platform_device pxa3xx_device_i2c_power = {
- .name = "pxa2xx-i2c",
+ .name = "pxa3xx-pwri2c",
.id = 1,
.resource = pxa3xx_resources_i2c_power,
.num_resources = ARRAY_SIZE(pxa3xx_resources_i2c_power),
diff --git a/linux/arch/arm/mach-pxa/pcm990-baseboard.c b/linux/arch/arm/mach-pxa/pcm990-baseboard.c
index 9ce1ef2e5..01791d74e 100644
--- a/linux/arch/arm/mach-pxa/pcm990-baseboard.c
+++ b/linux/arch/arm/mach-pxa/pcm990-baseboard.c
@@ -28,7 +28,7 @@
#include <media/soc_camera.h>
#include <asm/gpio.h>
-#include <mach/i2c.h>
+#include <plat/i2c.h>
#include <mach/camera.h>
#include <asm/mach/map.h>
#include <mach/pxa27x.h>
diff --git a/linux/arch/arm/plat-mxc/include/mach/memory.h b/linux/arch/arm/plat-mxc/include/mach/memory.h
index eca37d09f..6065e0017 100644
--- a/linux/arch/arm/plat-mxc/include/mach/memory.h
+++ b/linux/arch/arm/plat-mxc/include/mach/memory.h
@@ -32,4 +32,12 @@
#define CONSISTENT_DMA_SIZE SZ_4M
#endif /* CONFIG_MX1_VIDEO */
+#if defined(CONFIG_MX3_VIDEO)
+/*
+ * Increase size of DMA-consistent memory region.
+ * This is required for mx3 camera driver to capture at least two QXGA frames.
+ */
+#define CONSISTENT_DMA_SIZE SZ_8M
+#endif /* CONFIG_MX3_VIDEO */
+
#endif /* __ASM_ARCH_MXC_MEMORY_H__ */
diff --git a/linux/arch/sh/boards/board-ap325rxa.c b/linux/arch/sh/boards/board-ap325rxa.c
index 39e46919d..1c4d83ef2 100644
--- a/linux/arch/sh/boards/board-ap325rxa.c
+++ b/linux/arch/sh/boards/board-ap325rxa.c
@@ -263,6 +263,9 @@ static int camera_probe(void)
struct i2c_msg msg;
int ret;
+ if (!a)
+ return -ENODEV;
+
camera_power(1);
msg.addr = 0x6e;
msg.buf = camera_ncm03j_magic;
@@ -532,6 +535,18 @@ static int __init ap325rxa_devices_setup(void)
}
device_initcall(ap325rxa_devices_setup);
+/* Return the board specific boot mode pin configuration */
+static int ap325rxa_mode_pins(void)
+{
+ /* MD0=0, MD1=0, MD2=0: Clock Mode 0
+ * MD3=0: 16-bit Area0 Bus Width
+ * MD5=1: Little Endian
+ * TSTMD=1, MD8=1: Test Mode Disabled
+ */
+ return MODE_PIN5 | MODE_PIN8;
+}
+
static struct sh_machine_vector mv_ap325rxa __initmv = {
.mv_name = "AP-325RXA",
+ .mv_mode_pins = ap325rxa_mode_pins,
};
diff --git a/linux/arch/sh/boards/mach-migor/setup.c b/linux/arch/sh/boards/mach-migor/setup.c
index 1ee1de0bc..6ed401cd3 100644
--- a/linux/arch/sh/boards/mach-migor/setup.c
+++ b/linux/arch/sh/boards/mach-migor/setup.c
@@ -584,3 +584,22 @@ static int __init migor_devices_setup(void)
return platform_add_devices(migor_devices, ARRAY_SIZE(migor_devices));
}
__initcall(migor_devices_setup);
+
+/* Return the board specific boot mode pin configuration */
+static int migor_mode_pins(void)
+{
+ /* MD0=1, MD1=1, MD2=0: Clock Mode 3
+ * MD3=0: 16-bit Area0 Bus Width
+ * MD5=1: Little Endian
+ * TSTMD=1, MD8=0: Test Mode Disabled
+ */
+ return MODE_PIN0 | MODE_PIN1 | MODE_PIN5;
+}
+
+/*
+ * The Machine Vector
+ */
+static struct sh_machine_vector mv_migor __initmv = {
+ .mv_name = "Migo-R",
+ .mv_mode_pins = migor_mode_pins,
+};
diff --git a/linux/drivers/media/common/ir-keymaps.c b/linux/drivers/media/common/ir-keymaps.c
index d5fd71968..56fa64b4c 100644
--- a/linux/drivers/media/common/ir-keymaps.c
+++ b/linux/drivers/media/common/ir-keymaps.c
@@ -2800,3 +2800,26 @@ IR_KEYTAB_TYPE ir_codes_dm1105_nec[IR_KEYTAB_SIZE] = {
[0x1b] = KEY_B, /*recall*/
};
EXPORT_SYMBOL_GPL(ir_codes_dm1105_nec);
+
+/* EVGA inDtube
+ Devin Heitmueller <devin.heitmueller@gmail.com>
+ */
+IR_KEYTAB_TYPE ir_codes_evga_indtube[IR_KEYTAB_SIZE] = {
+ [0x12] = KEY_POWER,
+ [0x02] = KEY_MODE, /* TV */
+ [0x14] = KEY_MUTE,
+ [0x1a] = KEY_CHANNELUP,
+ [0x16] = KEY_TV2, /* PIP */
+ [0x1d] = KEY_VOLUMEUP,
+ [0x05] = KEY_CHANNELDOWN,
+ [0x0f] = KEY_PLAYPAUSE,
+ [0x19] = KEY_VOLUMEDOWN,
+ [0x1c] = KEY_REWIND,
+ [0x0d] = KEY_RECORD,
+ [0x18] = KEY_FORWARD,
+ [0x1e] = KEY_PREVIOUS,
+ [0x1b] = KEY_STOP,
+ [0x1f] = KEY_NEXT,
+ [0x13] = KEY_CAMERA,
+};
+EXPORT_SYMBOL_GPL(ir_codes_evga_indtube);
diff --git a/linux/drivers/media/common/tuners/tuner-simple.c b/linux/drivers/media/common/tuners/tuner-simple.c
index 233476df9..2ac1c8edb 100644
--- a/linux/drivers/media/common/tuners/tuner-simple.c
+++ b/linux/drivers/media/common/tuners/tuner-simple.c
@@ -423,6 +423,24 @@ static int simple_std_setup(struct dvb_frontend *fe,
return 0;
}
+static int simple_set_aux_byte(struct dvb_frontend *fe, u8 config, u8 aux)
+{
+ struct tuner_simple_priv *priv = fe->tuner_priv;
+ int rc;
+ u8 buffer[2];
+
+ buffer[0] = (config & ~0x38) | 0x18;
+ buffer[1] = aux;
+
+ tuner_dbg("setting aux byte: 0x%02x 0x%02x\n", buffer[0], buffer[1]);
+
+ rc = tuner_i2c_xfer_send(&priv->i2c_props, buffer, 2);
+ if (2 != rc)
+ tuner_warn("i2c i/o error: rc == %d (should be 2)\n", rc);
+
+ return rc == 2 ? 0 : rc;
+}
+
static int simple_post_tune(struct dvb_frontend *fe, u8 *buffer,
u16 div, u8 config, u8 cb)
{
@@ -431,30 +449,10 @@ static int simple_post_tune(struct dvb_frontend *fe, u8 *buffer,
switch (priv->type) {
case TUNER_LG_TDVS_H06XF:
- /* Set the Auxiliary Byte. */
-#if 0
- buffer[2] &= ~0x20;
- buffer[2] |= 0x18;
- buffer[3] = 0x20;
- tuner_dbg("tv 0x%02x 0x%02x 0x%02x 0x%02x\n",
- buffer[0], buffer[1], buffer[2], buffer[3]);
-
- rc = tuner_i2c_xfer_send(&priv->i2c_props, buffer, 4);
- if (4 != rc)
- tuner_warn("i2c i/o error: rc == %d "
- "(should be 4)\n", rc);
-#else
- buffer[0] = buffer[2];
- buffer[0] &= ~0x20;
- buffer[0] |= 0x18;
- buffer[1] = 0x20;
- tuner_dbg("tv 0x%02x 0x%02x\n", buffer[0], buffer[1]);
-
- rc = tuner_i2c_xfer_send(&priv->i2c_props, buffer, 2);
- if (2 != rc)
- tuner_warn("i2c i/o error: rc == %d "
- "(should be 2)\n", rc);
-#endif
+ simple_set_aux_byte(fe, config, 0x20);
+ break;
+ case TUNER_PHILIPS_FQ1216LME_MK3:
+ simple_set_aux_byte(fe, config, 0x60); /* External AGC */
break;
case TUNER_MICROTUNE_4042FI5:
{
@@ -526,6 +524,11 @@ static int simple_radio_bandswitch(struct dvb_frontend *fe, u8 *buffer)
case TUNER_THOMSON_DTT761X:
buffer[3] = 0x39;
break;
+ case TUNER_PHILIPS_FQ1216LME_MK3:
+ tuner_err("This tuner doesn't have FM\n");
+ /* Set the low band for sanity, since it covers 88-108 MHz */
+ buffer[3] = 0x01;
+ break;
case TUNER_MICROTUNE_4049FM5:
default:
buffer[3] = 0xa4;
@@ -698,12 +701,12 @@ static int simple_set_radio_freq(struct dvb_frontend *fe,
return 0;
}
- /* Bandswitch byte */
- simple_radio_bandswitch(fe, &buffer[0]);
-
buffer[2] = (t_params->ranges[0].config & ~TUNER_RATIO_MASK) |
TUNER_RATIO_SELECT_50; /* 50 kHz step */
+ /* Bandswitch byte */
+ simple_radio_bandswitch(fe, &buffer[0]);
+
/* Convert from 1/16 kHz V4L steps to 1/20 MHz (=50 kHz) PLL steps
freq * (1 Mhz / 16000 V4L steps) * (20 PLL steps / 1 MHz) =
freq * (1/800) */
diff --git a/linux/drivers/media/common/tuners/tuner-types.c b/linux/drivers/media/common/tuners/tuner-types.c
index 43afd30b0..e57d7cb2f 100644
--- a/linux/drivers/media/common/tuners/tuner-types.c
+++ b/linux/drivers/media/common/tuners/tuner-types.c
@@ -1280,6 +1280,28 @@ static struct tuner_params tuner_tcl_mf02gip_5n_params[] = {
},
};
+/* 80-89 */
+/* --------- TUNER_PHILIPS_FQ1216LME_MK3 -- active loopthrough, no FM ------- */
+
+static struct tuner_params tuner_fq1216lme_mk3_params[] = {
+ {
+ .type = TUNER_PARAM_TYPE_PAL,
+ .ranges = tuner_fm1216me_mk3_pal_ranges,
+ .count = ARRAY_SIZE(tuner_fm1216me_mk3_pal_ranges),
+ .cb_first_if_lower_freq = 1, /* not specified, but safe to do */
+ .has_tda9887 = 1, /* TDA9886 */
+ .port1_active = 1,
+ .port2_active = 1,
+ .port2_invert_for_secam_lc = 1,
+ .default_top_low = 4,
+ .default_top_mid = 4,
+ .default_top_high = 4,
+ .default_top_secam_low = 4,
+ .default_top_secam_mid = 4,
+ .default_top_secam_high = 4,
+ },
+};
+
/* --------------------------------------------------------------------- */
struct tunertype tuners[] = {
@@ -1725,6 +1747,13 @@ struct tunertype tuners[] = {
.params = tuner_fm1216mk5_params,
.count = ARRAY_SIZE(tuner_fm1216mk5_params),
},
+
+ /* 80-89 */
+ [TUNER_PHILIPS_FQ1216LME_MK3] = { /* PAL/SECAM, Loop-thru, no FM */
+ .name = "Philips FQ1216LME MK3 PAL/SECAM w/active loopthrough",
+ .params = tuner_fq1216lme_mk3_params,
+ .count = ARRAY_SIZE(tuner_fq1216lme_mk3_params),
+ },
};
EXPORT_SYMBOL(tuners);
diff --git a/linux/drivers/media/dvb/b2c2/flexcop-fe-tuner.c b/linux/drivers/media/dvb/b2c2/flexcop-fe-tuner.c
index 3f485bf13..efb4a6c2b 100644
--- a/linux/drivers/media/dvb/b2c2/flexcop-fe-tuner.c
+++ b/linux/drivers/media/dvb/b2c2/flexcop-fe-tuner.c
@@ -175,23 +175,23 @@ static int skystar23_samsung_tbdu18132_tuner_set_params(struct dvb_frontend *fe,
return 0;
}
-static void skystar2_rev23_attach(struct flexcop_device *fc,
+static int skystar2_rev23_attach(struct flexcop_device *fc,
struct i2c_adapter *i2c)
{
- fc->fe = dvb_attach(mt312_attach,
- &skystar23_samsung_tbdu18132_config, i2c);
+ fc->fe = dvb_attach(mt312_attach, &skystar23_samsung_tbdu18132_config, i2c);
if (fc->fe != NULL) {
struct dvb_frontend_ops *ops = &fc->fe->ops;
- ops->tuner_ops.set_params \
- = skystar23_samsung_tbdu18132_tuner_set_params;
+ ops->tuner_ops.set_params =
+ skystar23_samsung_tbdu18132_tuner_set_params;
ops->diseqc_send_master_cmd = flexcop_diseqc_send_master_cmd;
ops->diseqc_send_burst = flexcop_diseqc_send_burst;
ops->set_tone = flexcop_set_tone;
ops->set_voltage = flexcop_set_voltage;
fc->fe_sleep = ops->sleep;
ops->sleep = flexcop_sleep;
- fc->dev_type = FC_SKY_REV23;
+ return 1;
}
+ return 0;
}
#endif
@@ -307,7 +307,7 @@ static struct stv0299_config samsung_tbmu24112_config = {
.set_symbol_rate = samsung_tbmu24112_set_symbol_rate,
};
-static void skystar2_rev26_attach(struct flexcop_device *fc,
+static int skystar2_rev26_attach(struct flexcop_device *fc,
struct i2c_adapter *i2c)
{
fc->fe = dvb_attach(stv0299_attach, &samsung_tbmu24112_config, i2c);
@@ -317,7 +317,9 @@ static void skystar2_rev26_attach(struct flexcop_device *fc,
ops->set_voltage = flexcop_set_voltage;
fc->fe_sleep = ops->sleep;
ops->sleep = flexcop_sleep;
+ return 1;
}
+ return 0;
}
#endif
@@ -334,43 +336,54 @@ static struct itd1000_config skystar2_rev2_7_itd1000_config = {
.i2c_address = 0x61,
};
-static void skystar2_rev27_attach(struct flexcop_device *fc,
+static int skystar2_rev27_attach(struct flexcop_device *fc,
struct i2c_adapter *i2c)
{
+ flexcop_ibi_value r108;
+ struct i2c_adapter *i2c_tuner;
+
/* enable no_base_addr - no repeated start when reading */
fc->fc_i2c_adap[0].no_base_addr = 1;
- fc->fe = dvb_attach(s5h1420_attach,
- &skystar2_rev2_7_s5h1420_config, i2c);
- if (fc->fe != NULL) {
- flexcop_ibi_value r108;
- struct i2c_adapter *i2c_tuner \
- = s5h1420_get_tuner_i2c_adapter(fc->fe);
- struct dvb_frontend_ops *ops = &fc->fe->ops;
+ fc->fe = dvb_attach(s5h1420_attach, &skystar2_rev2_7_s5h1420_config,
+ i2c);
+ if (!fc->fe)
+ goto fail;
- fc->fe_sleep = ops->sleep;
- ops->sleep = flexcop_sleep;
-
- /* enable no_base_addr - no repeated start when reading */
- fc->fc_i2c_adap[2].no_base_addr = 1;
- if (dvb_attach(isl6421_attach, fc->fe,
- &fc->fc_i2c_adap[2].i2c_adap, 0x08, 1, 1) == NULL)
- err("ISL6421 could NOT be attached");
- else
- info("ISL6421 successfully attached");
-
- /* the ITD1000 requires a lower i2c clock - is it a problem ? */
- r108.raw = 0x00000506;
- fc->write_ibi_reg(fc, tw_sm_c_108, r108);
- if (i2c_tuner) {
- if (dvb_attach(itd1000_attach, fc->fe, i2c_tuner,
- &skystar2_rev2_7_itd1000_config) == NULL)
- err("ITD1000 could NOT be attached");
- else
- info("ITD1000 successfully attached");
- }
- } else
- fc->fc_i2c_adap[0].no_base_addr = 0;
- /* for the next devices we need it again */
+ i2c_tuner = s5h1420_get_tuner_i2c_adapter(fc->fe);
+ if (!i2c_tuner)
+ goto fail;
+
+ fc->fe_sleep = fc->fe->ops.sleep;
+ fc->fe->ops.sleep = flexcop_sleep;
+
+ /* enable no_base_addr - no repeated start when reading */
+ fc->fc_i2c_adap[2].no_base_addr = 1;
+ if (!dvb_attach(isl6421_attach, fc->fe, &fc->fc_i2c_adap[2].i2c_adap,
+ 0x08, 1, 1)) {
+ err("ISL6421 could NOT be attached");
+ goto fail_isl;
+ }
+ info("ISL6421 successfully attached");
+
+ /* the ITD1000 requires a lower i2c clock - is it a problem ? */
+ r108.raw = 0x00000506;
+ fc->write_ibi_reg(fc, tw_sm_c_108, r108);
+ if (!dvb_attach(itd1000_attach, fc->fe, i2c_tuner,
+ &skystar2_rev2_7_itd1000_config)) {
+ err("ITD1000 could NOT be attached");
+ /* Should i2c clock be restored? */
+ goto fail_isl;
+ }
+ info("ITD1000 successfully attached");
+
+ return 1;
+
+fail_isl:
+ fc->fc_i2c_adap[2].no_base_addr = 0;
+fail:
+ /* for the next devices we need it again */
+ fc->fc_i2c_adap[0].no_base_addr = 0;
+ return 0;
}
#endif
@@ -387,32 +400,38 @@ static const struct cx24113_config skystar2_rev2_8_cx24113_config = {
.xtal_khz = 10111,
};
-static void skystar2_rev28_attach(struct flexcop_device *fc,
+static int skystar2_rev28_attach(struct flexcop_device *fc,
struct i2c_adapter *i2c)
{
- fc->fe = dvb_attach(cx24123_attach,
- &skystar2_rev2_8_cx24123_config, i2c);
- if (fc->fe != NULL) {
- struct i2c_adapter *i2c_tuner \
- = cx24123_get_tuner_i2c_adapter(fc->fe);
- if (i2c_tuner != NULL) {
- if (dvb_attach(cx24113_attach, fc->fe,
- &skystar2_rev2_8_cx24113_config,
- i2c_tuner) == NULL)
- err("CX24113 could NOT be attached");
- else
- info("CX24113 successfully attached");
- }
+ struct i2c_adapter *i2c_tuner;
+
+ fc->fe = dvb_attach(cx24123_attach, &skystar2_rev2_8_cx24123_config,
+ i2c);
+ if (!fc->fe)
+ return 0;
+
+ i2c_tuner = cx24123_get_tuner_i2c_adapter(fc->fe);;
+ if (!i2c_tuner)
+ return 0;
- fc->fc_i2c_adap[2].no_base_addr = 1;
- if (dvb_attach(isl6421_attach, fc->fe,
- &fc->fc_i2c_adap[2].i2c_adap, 0x08, 0, 0) == NULL)
- err("ISL6421 could NOT be attached");
- else
- info("ISL6421 successfully attached");
+ if (!dvb_attach(cx24113_attach, fc->fe, &skystar2_rev2_8_cx24113_config,
+ i2c_tuner)) {
+ err("CX24113 could NOT be attached");
+ return 0;
+ }
+ info("CX24113 successfully attached");
+
+ fc->fc_i2c_adap[2].no_base_addr = 1;
+ if (!dvb_attach(isl6421_attach, fc->fe, &fc->fc_i2c_adap[2].i2c_adap,
+ 0x08, 0, 0)) {
+ err("ISL6421 could NOT be attached");
+ fc->fc_i2c_adap[2].no_base_addr = 0;
+ return 0;
+ }
+ info("ISL6421 successfully attached");
/* TODO on i2c_adap[1] addr 0x11 (EEPROM) there seems to be an
* IR-receiver (PIC16F818) - but the card has no input for that ??? */
- }
+ return 1;
}
#endif
@@ -466,12 +485,15 @@ static struct mt352_config samsung_tdtc9251dh0_config = {
.demod_init = samsung_tdtc9251dh0_demod_init,
};
-static void airstar_dvbt_attach(struct flexcop_device *fc,
+static int airstar_dvbt_attach(struct flexcop_device *fc,
struct i2c_adapter *i2c)
{
fc->fe = dvb_attach(mt352_attach, &samsung_tdtc9251dh0_config, i2c);
- if (fc->fe != NULL)
+ if (fc->fe != NULL) {
fc->fe->ops.tuner_ops.calc_regs = samsung_tdtc9251dh0_calc_regs;
+ return 1;
+ }
+ return 0;
}
#endif
@@ -489,10 +511,11 @@ static struct bcm3510_config air2pc_atsc_first_gen_config = {
.request_firmware = flexcop_fe_request_firmware,
};
-static void airstar_atsc1_attach(struct flexcop_device *fc,
+static int airstar_atsc1_attach(struct flexcop_device *fc,
struct i2c_adapter *i2c)
{
fc->fe = dvb_attach(bcm3510_attach, &air2pc_atsc_first_gen_config, i2c);
+ return fc->fe != NULL;
}
#endif
@@ -502,13 +525,15 @@ static struct nxt200x_config samsung_tbmv_config = {
.demod_address = 0x0a,
};
-static void airstar_atsc2_attach(struct flexcop_device *fc,
+static int airstar_atsc2_attach(struct flexcop_device *fc,
struct i2c_adapter *i2c)
{
fc->fe = dvb_attach(nxt200x_attach, &samsung_tbmv_config, i2c);
- if (fc->fe != NULL)
- dvb_attach(dvb_pll_attach, fc->fe, 0x61, NULL,
- DVB_PLL_SAMSUNG_TBMV);
+ if (!fc->fe)
+ return 0;
+
+ return !!dvb_attach(dvb_pll_attach, fc->fe, 0x61, NULL,
+ DVB_PLL_SAMSUNG_TBMV);
}
#endif
@@ -521,14 +546,15 @@ static struct lgdt330x_config air2pc_atsc_hd5000_config = {
.clock_polarity_flip = 1,
};
-static void airstar_atsc3_attach(struct flexcop_device *fc,
+static int airstar_atsc3_attach(struct flexcop_device *fc,
struct i2c_adapter *i2c)
{
fc->fe = dvb_attach(lgdt330x_attach, &air2pc_atsc_hd5000_config, i2c);
- if (fc->fe != NULL) {
- dvb_attach(simple_tuner_attach, fc->fe, i2c, 0x61,
- TUNER_LG_TDVS_H06XF);
- }
+ if (!fc->fe)
+ return 0;
+
+ return !!dvb_attach(simple_tuner_attach, fc->fe, i2c, 0x61,
+ TUNER_LG_TDVS_H06XF);
}
#endif
@@ -659,22 +685,24 @@ static struct stv0297_config alps_tdee4_stv0297_config = {
.inittab = alps_tdee4_stv0297_inittab,
};
-static void cablestar2_attach(struct flexcop_device *fc,
+static int cablestar2_attach(struct flexcop_device *fc,
struct i2c_adapter *i2c)
{
fc->fc_i2c_adap[0].no_base_addr = 1;
fc->fe = dvb_attach(stv0297_attach, &alps_tdee4_stv0297_config, i2c);
- if (fc->fe != NULL)
- fc->fe->ops.tuner_ops.set_params \
- = alps_tdee4_stv0297_tuner_set_params;
- else
+ if (!fc->fe) {
+ /* Reset for next frontend to try */
fc->fc_i2c_adap[0].no_base_addr = 0;
+ return 0;
+ }
+ fc->fe->ops.tuner_ops.set_params = alps_tdee4_stv0297_tuner_set_params;
+ return 1;
}
#endif
static struct {
flexcop_device_type_t type;
- void (*attach)(struct flexcop_device *, struct i2c_adapter *);
+ int (*attach)(struct flexcop_device *, struct i2c_adapter *);
} flexcop_frontends[] = {
#if defined(CONFIG_DVB_S5H1420_MODULE)
{ FC_SKY_REV27, skystar2_rev27_attach },
@@ -713,9 +741,13 @@ int flexcop_frontend_init(struct flexcop_device *fc)
/* type needs to be set before, because of some workarounds
* done based on the probed card type */
fc->dev_type = flexcop_frontends[i].type;
- flexcop_frontends[i].attach(fc, &fc->fc_i2c_adap[0].i2c_adap);
- if (fc->fe != NULL)
+ if (flexcop_frontends[i].attach(fc, &fc->fc_i2c_adap[0].i2c_adap))
goto fe_found;
+ /* Clean up partially attached frontend */
+ if (fc->fe) {
+ dvb_frontend_detach(fc->fe);
+ fc->fe = NULL;
+ }
}
fc->dev_type = FC_UNK;
err("no frontend driver found for this B2C2/FlexCop adapter");
@@ -724,10 +756,8 @@ int flexcop_frontend_init(struct flexcop_device *fc)
fe_found:
info("found '%s' .", fc->fe->ops.info.name);
if (dvb_register_frontend(&fc->dvb_adapter, fc->fe)) {
- struct dvb_frontend_ops *ops = &fc->fe->ops;
err("frontend registration failed!");
- if (ops->release != NULL)
- ops->release(fc->fe);
+ dvb_frontend_detach(fc->fe);
fc->fe = NULL;
return -EINVAL;
}
diff --git a/linux/drivers/media/dvb/bt8xx/bt878.c b/linux/drivers/media/dvb/bt8xx/bt878.c
index 57f0f84b6..456cd8756 100644
--- a/linux/drivers/media/dvb/bt8xx/bt878.c
+++ b/linux/drivers/media/dvb/bt8xx/bt878.c
@@ -512,12 +512,6 @@ static int __devinit bt878_probe(struct pci_dev *dev,
pci_set_master(dev);
pci_set_drvdata(dev, bt);
-/* if(init_bt878(btv) < 0) {
- bt878_remove(dev);
- return -EIO;
- }
-*/
-
if ((result = bt878_mem_alloc(bt))) {
printk(KERN_ERR "bt878: failed to allocate memory!\n");
goto fail2;
@@ -583,7 +577,7 @@ static struct pci_driver bt878_pci_driver = {
.name = "bt878",
.id_table = bt878_pci_tbl,
.probe = bt878_probe,
- .remove = bt878_remove,
+ .remove = __devexit_p(bt878_remove),
};
static int bt878_pci_driver_registered;
diff --git a/linux/drivers/media/dvb/dm1105/dm1105.c b/linux/drivers/media/dvb/dm1105/dm1105.c
index ca1048fd4..17edeb66b 100644
--- a/linux/drivers/media/dvb/dm1105/dm1105.c
+++ b/linux/drivers/media/dvb/dm1105/dm1105.c
@@ -51,6 +51,9 @@
#ifndef PCI_VENDOR_ID_TRIGEM
#define PCI_VENDOR_ID_TRIGEM 0x109f
#endif
+#ifndef PCI_VENDOR_ID_AXESS
+#define PCI_VENDOR_ID_AXESS 0x195d
+#endif
#ifndef PCI_DEVICE_ID_DM1105
#define PCI_DEVICE_ID_DM1105 0x036f
#endif
@@ -60,6 +63,9 @@
#ifndef PCI_DEVICE_ID_DW2004
#define PCI_DEVICE_ID_DW2004 0x2004
#endif
+#ifndef PCI_DEVICE_ID_DM05
+#define PCI_DEVICE_ID_DM05 0x1105
+#endif
/* ----------------------------------------------- */
/* sdmc dm1105 registers */
@@ -150,6 +156,11 @@
#define DM1105_LNB_13V 0x00010100
#define DM1105_LNB_18V 0x00000100
+/* GPIO's for LNB power control for Axess DM05 */
+#define DM05_LNB_MASK 0x00000000
+#define DM05_LNB_13V 0x00020000
+#define DM05_LNB_18V 0x00030000
+
static int ir_debug;
module_param(ir_debug, int, 0644);
MODULE_PARM_DESC(ir_debug, "enable debugging information for IR decoding");
@@ -188,6 +199,8 @@ struct dm1105dvb {
/* irq */
struct work_struct work;
+ struct workqueue_struct *wq;
+ char wqn[16];
/* dma */
dma_addr_t dma_addr;
@@ -316,15 +329,25 @@ static inline struct dm1105dvb *frontend_to_dm1105dvb(struct dvb_frontend *fe)
static int dm1105dvb_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage)
{
struct dm1105dvb *dm1105dvb = frontend_to_dm1105dvb(fe);
+ u32 lnb_mask, lnb_13v, lnb_18v;
- if (voltage == SEC_VOLTAGE_18) {
- outl(DM1105_LNB_MASK, dm_io_mem(DM1105_GPIOCTR));
- outl(DM1105_LNB_18V, dm_io_mem(DM1105_GPIOVAL));
- } else {
- /*LNB ON-13V by default!*/
- outl(DM1105_LNB_MASK, dm_io_mem(DM1105_GPIOCTR));
- outl(DM1105_LNB_13V, dm_io_mem(DM1105_GPIOVAL));
- }
+ switch (dm1105dvb->pdev->subsystem_device) {
+ case PCI_DEVICE_ID_DM05:
+ lnb_mask = DM05_LNB_MASK;
+ lnb_13v = DM05_LNB_13V;
+ lnb_18v = DM05_LNB_18V;
+ break;
+ default:
+ lnb_mask = DM1105_LNB_MASK;
+ lnb_13v = DM1105_LNB_13V;
+ lnb_18v = DM1105_LNB_18V;
+ }
+
+ outl(lnb_mask, dm_io_mem(DM1105_GPIOCTR));
+ if (voltage == SEC_VOLTAGE_18)
+ outl(lnb_18v , dm_io_mem(DM1105_GPIOVAL));
+ else
+ outl(lnb_13v, dm_io_mem(DM1105_GPIOVAL));
return 0;
}
@@ -463,7 +486,7 @@ static irqreturn_t dm1105dvb_irq(int irq, void *dev_id)
case (INTSTS_TSIRQ | INTSTS_IR):
dm1105dvb->nextwrp = inl(dm_io_mem(DM1105_WRP)) -
inl(dm_io_mem(DM1105_STADR));
- schedule_work(&dm1105dvb->work);
+ queue_work(dm1105dvb->wq, &dm1105dvb->work);
break;
case INTSTS_IR:
dm1105dvb->ir.ir_command = inl(dm_io_mem(DM1105_IRCODE));
@@ -599,46 +622,44 @@ static int __devinit frontend_init(struct dm1105dvb *dm1105dvb)
int ret;
switch (dm1105dvb->pdev->subsystem_device) {
- case PCI_DEVICE_ID_DW2002:
+ case PCI_DEVICE_ID_DW2004:
dm1105dvb->fe = dvb_attach(
- stv0299_attach, &sharp_z0194a_config,
+ cx24116_attach, &serit_sp2633_config,
&dm1105dvb->i2c_adap);
+ if (dm1105dvb->fe)
+ dm1105dvb->fe->ops.set_voltage = dm1105dvb_set_voltage;
+ break;
+ default:
+ dm1105dvb->fe = dvb_attach(
+ stv0299_attach, &sharp_z0194a_config,
+ &dm1105dvb->i2c_adap);
if (dm1105dvb->fe) {
dm1105dvb->fe->ops.set_voltage =
dm1105dvb_set_voltage;
dvb_attach(dvb_pll_attach, dm1105dvb->fe, 0x60,
&dm1105dvb->i2c_adap, DVB_PLL_OPERA1);
+ break;
}
- if (!dm1105dvb->fe) {
- dm1105dvb->fe = dvb_attach(
- stv0288_attach, &earda_config,
- &dm1105dvb->i2c_adap);
- if (dm1105dvb->fe) {
- dm1105dvb->fe->ops.set_voltage =
- dm1105dvb_set_voltage;
- dvb_attach(stb6000_attach, dm1105dvb->fe, 0x61,
- &dm1105dvb->i2c_adap);
- }
+ dm1105dvb->fe = dvb_attach(
+ stv0288_attach, &earda_config,
+ &dm1105dvb->i2c_adap);
+ if (dm1105dvb->fe) {
+ dm1105dvb->fe->ops.set_voltage =
+ dm1105dvb_set_voltage;
+ dvb_attach(stb6000_attach, dm1105dvb->fe, 0x61,
+ &dm1105dvb->i2c_adap);
+ break;
}
- if (!dm1105dvb->fe) {
- dm1105dvb->fe = dvb_attach(
- si21xx_attach, &serit_config,
- &dm1105dvb->i2c_adap);
- if (dm1105dvb->fe)
- dm1105dvb->fe->ops.set_voltage =
- dm1105dvb_set_voltage;
- }
- break;
- case PCI_DEVICE_ID_DW2004:
dm1105dvb->fe = dvb_attach(
- cx24116_attach, &serit_sp2633_config,
+ si21xx_attach, &serit_config,
&dm1105dvb->i2c_adap);
if (dm1105dvb->fe)
- dm1105dvb->fe->ops.set_voltage = dm1105dvb_set_voltage;
- break;
+ dm1105dvb->fe->ops.set_voltage =
+ dm1105dvb_set_voltage;
+
}
if (!dm1105dvb->fe) {
@@ -662,10 +683,17 @@ static void __devinit dm1105dvb_read_mac(struct dm1105dvb *dm1105dvb, u8 *mac)
static u8 command[1] = { 0x28 };
struct i2c_msg msg[] = {
- { .addr = IIC_24C01_addr >> 1, .flags = 0,
- .buf = command, .len = 1 },
- { .addr = IIC_24C01_addr >> 1, .flags = I2C_M_RD,
- .buf = mac, .len = 6 },
+ {
+ .addr = IIC_24C01_addr >> 1,
+ .flags = 0,
+ .buf = command,
+ .len = 1
+ }, {
+ .addr = IIC_24C01_addr >> 1,
+ .flags = I2C_M_RD,
+ .buf = mac,
+ .len = 6
+ },
};
dm1105_i2c_xfer(&dm1105dvb->i2c_adap, msg , 2);
@@ -788,14 +816,22 @@ static int __devinit dm1105_probe(struct pci_dev *pdev,
#else
INIT_WORK(&dm1105dvb->work, dm1105_dmx_buffer);
#endif
+ sprintf(dm1105dvb->wqn, "%s/%d", dvb_adapter->name, dvb_adapter->num);
+ dm1105dvb->wq = create_singlethread_workqueue(dm1105dvb->wqn);
+ if (!dm1105dvb->wq)
+ goto err_dvb_net;
ret = request_irq(pdev->irq, dm1105dvb_irq, IRQF_SHARED,
DRIVER_NAME, dm1105dvb);
if (ret < 0)
- goto err_free_irq;
+ goto err_workqueue;
return 0;
+err_workqueue:
+ destroy_workqueue(dm1105dvb->wq);
+err_dvb_net:
+ dvb_net_release(&dm1105dvb->dvbnet);
err_disconnect_frontend:
dmx->disconnect_frontend(dmx);
err_remove_mem_frontend:
@@ -812,8 +848,6 @@ err_i2c_del_adapter:
i2c_del_adapter(&dm1105dvb->i2c_adap);
err_dm1105dvb_hw_exit:
dm1105dvb_hw_exit(dm1105dvb);
-err_free_irq:
- free_irq(pdev->irq, dm1105dvb);
err_pci_iounmap:
pci_iounmap(pdev, dm1105dvb->io_mem);
err_pci_release_regions:
@@ -870,6 +904,11 @@ static struct pci_device_id dm1105_id_table[] __devinitdata = {
.subvendor = PCI_ANY_ID,
.subdevice = PCI_DEVICE_ID_DW2004,
}, {
+ .vendor = PCI_VENDOR_ID_AXESS,
+ .device = PCI_DEVICE_ID_DM05,
+ .subvendor = PCI_VENDOR_ID_AXESS,
+ .subdevice = PCI_DEVICE_ID_DM05,
+ }, {
/* empty */
},
};
diff --git a/linux/drivers/media/dvb/dvb-core/dvb_net.c b/linux/drivers/media/dvb/dvb-core/dvb_net.c
index 5f4856c6d..1eede48a9 100644
--- a/linux/drivers/media/dvb/dvb-core/dvb_net.c
+++ b/linux/drivers/media/dvb/dvb-core/dvb_net.c
@@ -126,7 +126,9 @@ static void hexdump( const unsigned char *buf, unsigned short len )
struct dvb_net_priv {
int in_use;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 29)
struct net_device_stats stats;
+#endif
u16 pid;
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20)
struct net_device *net;
@@ -391,8 +393,13 @@ static void dvb_net_ule( struct net_device *dev, const u8 *buf, size_t buf_len )
if (priv->ule_skb) {
dev_kfree_skb( priv->ule_skb );
/* Prepare for next SNDU. */
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 29)
priv->stats.rx_errors++;
priv->stats.rx_frame_errors++;
+#else
+ dev->stats.rx_errors++;
+ dev->stats.rx_frame_errors++;
+#endif
}
reset_ule(priv);
priv->need_pusi = 1;
@@ -445,8 +452,13 @@ static void dvb_net_ule( struct net_device *dev, const u8 *buf, size_t buf_len )
dev_kfree_skb( priv->ule_skb );
/* Prepare for next SNDU. */
// reset_ule(priv); moved to below.
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 29)
priv->stats.rx_errors++;
priv->stats.rx_frame_errors++;
+#else
+ dev->stats.rx_errors++;
+ dev->stats.rx_frame_errors++;
+#endif
}
reset_ule(priv);
/* skip to next PUSI. */
@@ -467,8 +479,13 @@ static void dvb_net_ule( struct net_device *dev, const u8 *buf, size_t buf_len )
/* Drop partly decoded SNDU, reset state, resync on PUSI. */
if (priv->ule_skb) {
dev_kfree_skb( priv->ule_skb );
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 29)
priv->stats.rx_errors++;
priv->stats.rx_frame_errors++;
+#else
+ dev->stats.rx_errors++;
+ dev->stats.rx_frame_errors++;
+#endif
}
reset_ule(priv);
priv->need_pusi = 1;
@@ -484,8 +501,13 @@ static void dvb_net_ule( struct net_device *dev, const u8 *buf, size_t buf_len )
if (priv->ule_sndu_remain > 183) {
/* Current SNDU lacks more data than there could be available in the
* current TS cell. */
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 29)
priv->stats.rx_errors++;
priv->stats.rx_length_errors++;
+#else
+ dev->stats.rx_errors++;
+ dev->stats.rx_length_errors++;
+#endif
printk(KERN_WARNING "%lu: Expected %d more SNDU bytes, but "
"got PUSI (pf %d, ts_remain %d). Flushing incomplete payload.\n",
priv->ts_count, priv->ule_sndu_remain, ts[4], ts_remain);
@@ -527,8 +549,13 @@ static void dvb_net_ule( struct net_device *dev, const u8 *buf, size_t buf_len )
if (priv->ule_sndu_len < 5) {
printk(KERN_WARNING "%lu: Invalid ULE SNDU length %u. "
"Resyncing.\n", priv->ts_count, priv->ule_sndu_len);
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 29)
priv->stats.rx_errors++;
priv->stats.rx_length_errors++;
+#else
+ dev->stats.rx_errors++;
+ dev->stats.rx_length_errors++;
+#endif
priv->ule_sndu_len = 0;
priv->need_pusi = 1;
new_ts = 1;
@@ -580,7 +607,11 @@ static void dvb_net_ule( struct net_device *dev, const u8 *buf, size_t buf_len )
if (priv->ule_skb == NULL) {
printk(KERN_NOTICE "%s: Memory squeeze, dropping packet.\n",
dev->name);
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 29)
priv->stats.rx_dropped++;
+#else
+ dev->stats.rx_dropped++;
+#endif
return;
}
@@ -653,8 +684,13 @@ static void dvb_net_ule( struct net_device *dev, const u8 *buf, size_t buf_len )
ule_dump = 1;
#endif
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 29)
priv->stats.rx_errors++;
priv->stats.rx_crc_errors++;
+#else
+ dev->stats.rx_errors++;
+ dev->stats.rx_crc_errors++;
+#endif
dev_kfree_skb(priv->ule_skb);
} else {
/* CRC32 verified OK. */
@@ -764,8 +800,13 @@ static void dvb_net_ule( struct net_device *dev, const u8 *buf, size_t buf_len )
* receive the packet anyhow. */
/* if (priv->ule_dbit && skb->pkt_type == PACKET_OTHERHOST)
priv->ule_skb->pkt_type = PACKET_HOST; */
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 29)
priv->stats.rx_packets++;
priv->stats.rx_bytes += priv->ule_skb->len;
+#else
+ dev->stats.rx_packets++;
+ dev->stats.rx_bytes += priv->ule_skb->len;
+#endif
netif_rx(priv->ule_skb);
}
sndu_done:
@@ -820,8 +861,12 @@ static void dvb_net_sec(struct net_device *dev,
{
u8 *eth;
struct sk_buff *skb;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 29)
struct net_device_stats *stats =
&((struct dvb_net_priv *) netdev_priv(dev))->stats;
+#else
+ struct net_device_stats *stats = &dev->stats;
+#endif
int snap = 0;
/* note: pkt_len includes a 32bit checksum */
@@ -1269,11 +1314,12 @@ static int dvb_net_stop(struct net_device *dev)
return dvb_net_feed_stop(dev);
}
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 29)
static struct net_device_stats * dvb_net_get_stats(struct net_device *dev)
{
return &((struct dvb_net_priv *) netdev_priv(dev))->stats;
}
-
+#endif
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)
static const struct header_ops dvb_header_ops = {
.create = eth_header,
@@ -1282,6 +1328,19 @@ static const struct header_ops dvb_header_ops = {
};
#endif
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 29)
+static const struct net_device_ops dvb_netdev_ops = {
+ .ndo_open = dvb_net_open,
+ .ndo_stop = dvb_net_stop,
+ .ndo_start_xmit = dvb_net_tx,
+ .ndo_set_multicast_list = dvb_net_set_multicast_list,
+ .ndo_set_mac_address = dvb_net_set_mac,
+ .ndo_change_mtu = eth_change_mtu,
+ .ndo_validate_addr = eth_validate_addr,
+};
+#endif
+
static void dvb_net_setup(struct net_device *dev)
{
ether_setup(dev);
@@ -1291,12 +1350,16 @@ static void dvb_net_setup(struct net_device *dev)
#else
dev->hard_header_cache = NULL;
#endif
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 29)
dev->open = dvb_net_open;
dev->stop = dvb_net_stop;
dev->hard_start_xmit = dvb_net_tx;
dev->get_stats = dvb_net_get_stats;
dev->set_multicast_list = dvb_net_set_multicast_list;
dev->set_mac_address = dvb_net_set_mac;
+#else
+ dev->netdev_ops = &dvb_netdev_ops;
+#endif
dev->mtu = 4096;
dev->mc_count = 0;
diff --git a/linux/drivers/media/dvb/dvb-usb/Kconfig b/linux/drivers/media/dvb/dvb-usb/Kconfig
index 60955a70d..496c1a370 100644
--- a/linux/drivers/media/dvb/dvb-usb/Kconfig
+++ b/linux/drivers/media/dvb/dvb-usb/Kconfig
@@ -216,7 +216,7 @@ config DVB_USB_TTUSB2
help
Say Y here to support the Pinnacle 400e DVB-S USB2.0 receiver. The
firmware protocol used by this module is similar to the one used by the
- old ttusb-driver - that's why the module is called dvb-usb-ttusb2.ko.
+ old ttusb-driver - that's why the module is called dvb-usb-ttusb2.
config DVB_USB_DTT200U
tristate "WideView WT-200U and WT-220U (pen) DVB-T USB2.0 support (Yakumo/Hama/Typhoon/Yuan)"
@@ -261,6 +261,7 @@ config DVB_USB_DW2102
select DVB_STB6000 if !DVB_FE_CUSTOMISE
select DVB_CX24116 if !DVB_FE_CUSTOMISE
select DVB_SI21XX if !DVB_FE_CUSTOMISE
+ select DVB_TDA10021 if !DVB_FE_CUSTOMISE
help
Say Y here to support the DvbWorld DVB-S/S2 USB2.0 receivers
and the TeVii S650.
diff --git a/linux/drivers/media/dvb/dvb-usb/af9015.c b/linux/drivers/media/dvb/dvb-usb/af9015.c
index a50bf34af..b6fc8ddf3 100644
--- a/linux/drivers/media/dvb/dvb-usb/af9015.c
+++ b/linux/drivers/media/dvb/dvb-usb/af9015.c
@@ -541,7 +541,7 @@ exit:
/* dump eeprom */
static int af9015_eeprom_dump(struct dvb_usb_device *d)
{
- char buf[52], buf2[4];
+ char buf[4+3*16+1], buf2[4];
u8 reg, val;
for (reg = 0; ; reg++) {
diff --git a/linux/drivers/media/dvb/dvb-usb/dw2102.c b/linux/drivers/media/dvb/dvb-usb/dw2102.c
index 2b8ee587b..0fc9be43a 100644
--- a/linux/drivers/media/dvb/dvb-usb/dw2102.c
+++ b/linux/drivers/media/dvb/dvb-usb/dw2102.c
@@ -1,7 +1,7 @@
/* DVB USB framework compliant Linux driver for the
-* DVBWorld DVB-S 2101, 2102, DVB-S2 2104 Card
-*
-* Copyright (C) 2008 Igor M. Liplianin (liplianin@me.by)
+* DVBWorld DVB-S 2101, 2102, DVB-S2 2104, DVB-C 3101,
+* TeVii S600, S650 Cards
+* Copyright (C) 2008,2009 Igor M. Liplianin (liplianin@me.by)
*
* 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
@@ -17,6 +17,7 @@
#include "stb6000.h"
#include "eds1547.h"
#include "cx24116.h"
+#include "tda1002x.h"
#ifndef USB_PID_DW2102
#define USB_PID_DW2102 0x2102
@@ -26,10 +27,18 @@
#define USB_PID_DW2104 0x2104
#endif
+#ifndef USB_PID_DW3101
+#define USB_PID_DW3101 0x3101
+#endif
+
#ifndef USB_PID_CINERGY_S
#define USB_PID_CINERGY_S 0x0064
#endif
+#ifndef USB_PID_TEVII_S650
+#define USB_PID_TEVII_S650 0xd650
+#endif
+
#define DW210X_READ_MSG 0
#define DW210X_WRITE_MSG 1
@@ -40,18 +49,21 @@
#define DW2102_VOLTAGE_CTRL (0x1800)
#define DW2102_RC_QUERY (0x1a00)
-struct dw210x_state {
- u32 last_key_pressed;
-};
-struct dw210x_rc_keys {
- u32 keycode;
- u32 event;
+struct dvb_usb_rc_keys_table {
+ struct dvb_usb_rc_key *rc_keys;
+ int rc_keys_size;
};
/* debug */
static int dvb_usb_dw2102_debug;
module_param_named(debug, dvb_usb_dw2102_debug, int, 0644);
-MODULE_PARM_DESC(debug, "set debugging level (1=info 2=xfer (or-able))." DVB_USB_DEBUG_STATUS);
+MODULE_PARM_DESC(debug, "set debugging level (1=info 2=xfer 4=rc(or-able))."
+ DVB_USB_DEBUG_STATUS);
+
+/* keymaps */
+static int ir_keymap;
+module_param_named(keymap, ir_keymap, int, 0644);
+MODULE_PARM_DESC(keymap, "set keymap 0=default 1=dvbworld 2=tevii 3=tbs ...");
DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
@@ -79,7 +91,7 @@ static int dw210x_op_rw(struct usb_device *dev, u8 request, u16 value,
static int dw2102_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[],
int num)
{
-struct dvb_usb_device *d = i2c_get_adapdata(adap);
+ struct dvb_usb_device *d = i2c_get_adapdata(adap);
int i = 0, ret = 0;
u8 buf6[] = {0x2c, 0x05, 0xc0, 0, 0, 0, 0};
u16 value;
@@ -205,6 +217,7 @@ static int dw2102_serit_i2c_transfer(struct i2c_adapter *adap,
mutex_unlock(&d->i2c_mutex);
return num;
}
+
static int dw2102_earda_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[], int num)
{
struct dvb_usb_device *d = i2c_get_adapdata(adap);
@@ -219,7 +232,7 @@ static int dw2102_earda_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg ms
case 2: {
/* read */
/* first write first register number */
- u8 ibuf [msg[1].len + 2], obuf[3];
+ u8 ibuf[msg[1].len + 2], obuf[3];
obuf[0] = 0xd0;
obuf[1] = msg[0].len;
obuf[2] = msg[0].buf[0];
@@ -293,7 +306,7 @@ static int dw2104_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[], i
case 2: {
/* read */
/* first write first register number */
- u8 ibuf [msg[1].len + 2], obuf[3];
+ u8 ibuf[msg[1].len + 2], obuf[3];
obuf[0] = 0xaa;
obuf[1] = msg[0].len;
obuf[2] = msg[0].buf[0];
@@ -360,6 +373,69 @@ static int dw2104_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[], i
return num;
}
+static int dw3101_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[],
+ int num)
+{
+ struct dvb_usb_device *d = i2c_get_adapdata(adap);
+ int ret = 0, i;
+
+ if (!d)
+ return -ENODEV;
+ if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
+ return -EAGAIN;
+
+ switch (num) {
+ case 2: {
+ /* read */
+ /* first write first register number */
+ u8 ibuf[msg[1].len + 2], obuf[3];
+ obuf[0] = msg[0].addr << 1;
+ obuf[1] = msg[0].len;
+ obuf[2] = msg[0].buf[0];
+ ret = dw210x_op_rw(d->udev, 0xc2, 0, 0,
+ obuf, msg[0].len + 2, DW210X_WRITE_MSG);
+ /* second read registers */
+ ret = dw210x_op_rw(d->udev, 0xc3, 0x19 , 0,
+ ibuf, msg[1].len + 2, DW210X_READ_MSG);
+ memcpy(msg[1].buf, ibuf + 2, msg[1].len);
+
+ break;
+ }
+ case 1:
+ switch (msg[0].addr) {
+ case 0x60:
+ case 0x0c: {
+ /* write to register */
+ u8 obuf[msg[0].len + 2];
+ obuf[0] = msg[0].addr << 1;
+ obuf[1] = msg[0].len;
+ memcpy(obuf + 2, msg[0].buf, msg[0].len);
+ ret = dw210x_op_rw(d->udev, 0xc2, 0, 0,
+ obuf, msg[0].len + 2, DW210X_WRITE_MSG);
+ break;
+ }
+ case(DW2102_RC_QUERY): {
+ u8 ibuf[2];
+ ret = dw210x_op_rw(d->udev, 0xb8, 0, 0,
+ ibuf, 2, DW210X_READ_MSG);
+ memcpy(msg[0].buf, ibuf , 2);
+ break;
+ }
+ }
+
+ break;
+ }
+
+ for (i = 0; i < num; i++) {
+ deb_xfer("%02x:%02x: %s ", i, msg[i].addr,
+ msg[i].flags == 0 ? ">>>" : "<<<");
+ debug_dump(msg[i].buf, msg[i].len, deb_xfer);
+ }
+
+ mutex_unlock(&d->i2c_mutex);
+ return num;
+}
+
static u32 dw210x_i2c_func(struct i2c_adapter *adapter)
{
return I2C_FUNC_I2C;
@@ -397,6 +473,14 @@ static struct i2c_algorithm dw2104_i2c_algo = {
#endif
};
+static struct i2c_algorithm dw3101_i2c_algo = {
+ .master_xfer = dw3101_i2c_transfer,
+ .functionality = dw210x_i2c_func,
+#ifdef NEED_ALGO_CONTROL
+ .algo_control = dummy_algo_control,
+#endif
+};
+
static int dw210x_read_mac_address(struct dvb_usb_device *d, u8 mac[6])
{
int i;
@@ -416,6 +500,7 @@ static int dw210x_read_mac_address(struct dvb_usb_device *d, u8 mac[6])
debug_dump(eepromline, 16, deb_xfer);
}
}
+
memcpy(mac, eeprom + 8, 6);
return 0;
};
@@ -460,6 +545,11 @@ static struct si21xx_config serit_sp1511lhb_config = {
};
+static struct tda10023_config dw3101_tda10023_config = {
+ .demod_address = 0x0c,
+ .invert = 1,
+};
+
static int dw2104_frontend_attach(struct dvb_usb_adapter *d)
{
if ((d->fe = dvb_attach(cx24116_attach, &dw2104_config,
@@ -472,6 +562,7 @@ static int dw2104_frontend_attach(struct dvb_usb_adapter *d)
}
static struct dvb_usb_device_properties dw2102_properties;
+static struct dvb_usb_device_properties dw2104_properties;
static int dw2102_frontend_attach(struct dvb_usb_adapter *d)
{
@@ -509,6 +600,17 @@ static int dw2102_frontend_attach(struct dvb_usb_adapter *d)
return -EIO;
}
+static int dw3101_frontend_attach(struct dvb_usb_adapter *d)
+{
+ d->fe = dvb_attach(tda10023_attach, &dw3101_tda10023_config,
+ &d->dev->i2c_adap, 0x48);
+ if (d->fe != NULL) {
+ info("Attached tda10023!\n");
+ return 0;
+ }
+ return -EIO;
+}
+
static int dw2102_tuner_attach(struct dvb_usb_adapter *adap)
{
dvb_attach(dvb_pll_attach, adap->fe, 0x60,
@@ -524,6 +626,14 @@ static int dw2102_earda_tuner_attach(struct dvb_usb_adapter *adap)
return 0;
}
+static int dw3101_tuner_attach(struct dvb_usb_adapter *adap)
+{
+ dvb_attach(dvb_pll_attach, adap->fe, 0x60,
+ &adap->dev->i2c_adap, DVB_PLL_TUA6034);
+
+ return 0;
+}
+
static struct dvb_usb_rc_key dw210x_rc_keys[] = {
{ 0xf8, 0x0a, KEY_Q }, /*power*/
{ 0xf8, 0x0c, KEY_M }, /*mute*/
@@ -556,44 +666,147 @@ static struct dvb_usb_rc_key dw210x_rc_keys[] = {
{ 0xf8, 0x40, KEY_F }, /*full*/
{ 0xf8, 0x1e, KEY_W }, /*tvmode*/
{ 0xf8, 0x1b, KEY_B }, /*recall*/
+};
+static struct dvb_usb_rc_key tevii_rc_keys[] = {
+ { 0xf8, 0x0a, KEY_POWER },
+ { 0xf8, 0x0c, KEY_MUTE },
+ { 0xf8, 0x11, KEY_1 },
+ { 0xf8, 0x12, KEY_2 },
+ { 0xf8, 0x13, KEY_3 },
+ { 0xf8, 0x14, KEY_4 },
+ { 0xf8, 0x15, KEY_5 },
+ { 0xf8, 0x16, KEY_6 },
+ { 0xf8, 0x17, KEY_7 },
+ { 0xf8, 0x18, KEY_8 },
+ { 0xf8, 0x19, KEY_9 },
+ { 0xf8, 0x10, KEY_0 },
+ { 0xf8, 0x1c, KEY_MENU },
+ { 0xf8, 0x0f, KEY_VOLUMEDOWN },
+ { 0xf8, 0x1a, KEY_LAST },
+ { 0xf8, 0x0e, KEY_OPEN },
+ { 0xf8, 0x04, KEY_RECORD },
+ { 0xf8, 0x09, KEY_VOLUMEUP },
+ { 0xf8, 0x08, KEY_CHANNELUP },
+ { 0xf8, 0x07, KEY_PVR },
+ { 0xf8, 0x0b, KEY_TIME },
+ { 0xf8, 0x02, KEY_RIGHT },
+ { 0xf8, 0x03, KEY_LEFT },
+ { 0xf8, 0x00, KEY_UP },
+ { 0xf8, 0x1f, KEY_OK },
+ { 0xf8, 0x01, KEY_DOWN },
+ { 0xf8, 0x05, KEY_TUNER },
+ { 0xf8, 0x06, KEY_CHANNELDOWN },
+ { 0xf8, 0x40, KEY_PLAYPAUSE },
+ { 0xf8, 0x1e, KEY_REWIND },
+ { 0xf8, 0x1b, KEY_FAVORITES },
+ { 0xf8, 0x1d, KEY_BACK },
+ { 0xf8, 0x4d, KEY_FASTFORWARD },
+ { 0xf8, 0x44, KEY_EPG },
+ { 0xf8, 0x4c, KEY_INFO },
+ { 0xf8, 0x41, KEY_AB },
+ { 0xf8, 0x43, KEY_AUDIO },
+ { 0xf8, 0x45, KEY_SUBTITLE },
+ { 0xf8, 0x4a, KEY_LIST },
+ { 0xf8, 0x46, KEY_F1 },
+ { 0xf8, 0x47, KEY_F2 },
+ { 0xf8, 0x5e, KEY_F3 },
+ { 0xf8, 0x5c, KEY_F4 },
+ { 0xf8, 0x52, KEY_F5 },
+ { 0xf8, 0x5a, KEY_F6 },
+ { 0xf8, 0x56, KEY_MODE },
+ { 0xf8, 0x58, KEY_SWITCHVIDEOMODE },
};
+static struct dvb_usb_rc_key tbs_rc_keys[] = {
+ { 0xf8, 0x84, KEY_POWER },
+ { 0xf8, 0x94, KEY_MUTE },
+ { 0xf8, 0x87, KEY_1 },
+ { 0xf8, 0x86, KEY_2 },
+ { 0xf8, 0x85, KEY_3 },
+ { 0xf8, 0x8b, KEY_4 },
+ { 0xf8, 0x8a, KEY_5 },
+ { 0xf8, 0x89, KEY_6 },
+ { 0xf8, 0x8f, KEY_7 },
+ { 0xf8, 0x8e, KEY_8 },
+ { 0xf8, 0x8d, KEY_9 },
+ { 0xf8, 0x92, KEY_0 },
+ { 0xf8, 0x96, KEY_CHANNELUP },
+ { 0xf8, 0x91, KEY_CHANNELDOWN },
+ { 0xf8, 0x93, KEY_VOLUMEUP },
+ { 0xf8, 0x8c, KEY_VOLUMEDOWN },
+ { 0xf8, 0x83, KEY_RECORD },
+ { 0xf8, 0x98, KEY_PAUSE },
+ { 0xf8, 0x99, KEY_OK },
+ { 0xf8, 0x9a, KEY_SHUFFLE },
+ { 0xf8, 0x81, KEY_UP },
+ { 0xf8, 0x90, KEY_LEFT },
+ { 0xf8, 0x82, KEY_RIGHT },
+ { 0xf8, 0x88, KEY_DOWN },
+ { 0xf8, 0x95, KEY_FAVORITES },
+ { 0xf8, 0x97, KEY_SUBTITLE },
+ { 0xf8, 0x9d, KEY_ZOOM },
+ { 0xf8, 0x9f, KEY_EXIT },
+ { 0xf8, 0x9e, KEY_MENU },
+ { 0xf8, 0x9c, KEY_EPG },
+ { 0xf8, 0x80, KEY_PREVIOUS },
+ { 0xf8, 0x9b, KEY_MODE }
+};
+static struct dvb_usb_rc_keys_table keys_tables[] = {
+ { dw210x_rc_keys, ARRAY_SIZE(dw210x_rc_keys) },
+ { tevii_rc_keys, ARRAY_SIZE(tevii_rc_keys) },
+ { tbs_rc_keys, ARRAY_SIZE(tbs_rc_keys) },
+};
static int dw2102_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
{
- struct dw210x_state *st = d->priv;
+ struct dvb_usb_rc_key *keymap = d->props.rc_key_map;
+ int keymap_size = d->props.rc_key_map_size;
u8 key[2];
- struct i2c_msg msg[] = {
- {.addr = DW2102_RC_QUERY, .flags = I2C_M_RD, .buf = key,
- .len = 2},
+ struct i2c_msg msg = {
+ .addr = DW2102_RC_QUERY,
+ .flags = I2C_M_RD,
+ .buf = key,
+ .len = 2
};
int i;
+ /* override keymap */
+ if ((ir_keymap > 0) && (ir_keymap <= ARRAY_SIZE(keys_tables))) {
+ keymap = keys_tables[ir_keymap - 1].rc_keys ;
+ keymap_size = keys_tables[ir_keymap - 1].rc_keys_size;
+ }
*state = REMOTE_NO_KEY_PRESSED;
- if (dw2102_i2c_transfer(&d->i2c_adap, msg, 1) == 1) {
- for (i = 0; i < ARRAY_SIZE(dw210x_rc_keys); i++) {
- if (dw210x_rc_keys[i].data == msg[0].buf[0]) {
+ if (dw2102_i2c_transfer(&d->i2c_adap, &msg, 1) == 1) {
+ for (i = 0; i < keymap_size ; i++) {
+ if (keymap[i].data == msg.buf[0]) {
*state = REMOTE_KEY_PRESSED;
- *event = dw210x_rc_keys[i].event;
- st->last_key_pressed =
- dw210x_rc_keys[i].event;
+ *event = keymap[i].event;
break;
}
- st->last_key_pressed = 0;
+
}
+
+ if ((*state) == REMOTE_KEY_PRESSED)
+ deb_rc("%s: found rc key: %x, %x, event: %x\n",
+ __func__, key[0], key[1], (*event));
+ else if (key[0] != 0xff)
+ deb_rc("%s: unknown rc key: %x, %x\n",
+ __func__, key[0], key[1]);
+
}
- /* info("key: %x %x\n",key[0],key[1]); */
+
return 0;
}
static struct usb_device_id dw2102_table[] = {
{USB_DEVICE(USB_VID_CYPRESS, USB_PID_DW2102)},
{USB_DEVICE(USB_VID_CYPRESS, 0x2101)},
- {USB_DEVICE(USB_VID_CYPRESS, 0x2104)},
- {USB_DEVICE(0x9022, 0xd650)},
+ {USB_DEVICE(USB_VID_CYPRESS, USB_PID_DW2104)},
+ {USB_DEVICE(0x9022, USB_PID_TEVII_S650)},
{USB_DEVICE(USB_VID_TERRATEC, USB_PID_CINERGY_S)},
+ {USB_DEVICE(USB_VID_CYPRESS, USB_PID_DW3101)},
{ }
};
@@ -654,11 +867,16 @@ static int dw2102_load_firmware(struct usb_device *dev,
}
/* init registers */
switch (dev->descriptor.idProduct) {
+ case USB_PID_TEVII_S650:
+ dw2104_properties.rc_key_map = tevii_rc_keys;
+ dw2104_properties.rc_key_map_size =
+ ARRAY_SIZE(tevii_rc_keys);
case USB_PID_DW2104:
- case 0xd650:
reset = 1;
dw210x_op_rw(dev, 0xc4, 0x0000, 0, &reset, 1,
DW210X_WRITE_MSG);
+ /* break omitted intentionally */
+ case USB_PID_DW3101:
reset = 0;
dw210x_op_rw(dev, 0xbf, 0x0040, 0, &reset, 0,
DW210X_WRITE_MSG);
@@ -702,6 +920,7 @@ static int dw2102_load_firmware(struct usb_device *dev,
DW210X_READ_MSG);
break;
}
+
msleep(100);
kfree(p);
}
@@ -712,7 +931,6 @@ static struct dvb_usb_device_properties dw2102_properties = {
.caps = DVB_USB_IS_AN_I2C_ADAPTER,
.usb_ctrl = DEVICE_SPECIFIC,
.firmware = "dvb-usb-dw2102.fw",
- .size_of_priv = sizeof(struct dw210x_state),
.no_reconnect = 1,
.i2c_algo = &dw2102_serit_i2c_algo,
@@ -726,7 +944,7 @@ static struct dvb_usb_device_properties dw2102_properties = {
.num_adapters = 1,
.download_firmware = dw2102_load_firmware,
.read_mac_address = dw210x_read_mac_address,
- .adapter = {
+ .adapter = {
{
.frontend_attach = dw2102_frontend_attach,
.streaming_ctrl = NULL,
@@ -764,7 +982,6 @@ static struct dvb_usb_device_properties dw2104_properties = {
.caps = DVB_USB_IS_AN_I2C_ADAPTER,
.usb_ctrl = DEVICE_SPECIFIC,
.firmware = "dvb-usb-dw2104.fw",
- .size_of_priv = sizeof(struct dw210x_state),
.no_reconnect = 1,
.i2c_algo = &dw2104_i2c_algo,
@@ -808,12 +1025,57 @@ static struct dvb_usb_device_properties dw2104_properties = {
}
};
+static struct dvb_usb_device_properties dw3101_properties = {
+ .caps = DVB_USB_IS_AN_I2C_ADAPTER,
+ .usb_ctrl = DEVICE_SPECIFIC,
+ .firmware = "dvb-usb-dw3101.fw",
+ .no_reconnect = 1,
+
+ .i2c_algo = &dw3101_i2c_algo,
+ .rc_key_map = dw210x_rc_keys,
+ .rc_key_map_size = ARRAY_SIZE(dw210x_rc_keys),
+ .rc_interval = 150,
+ .rc_query = dw2102_rc_query,
+
+ .generic_bulk_ctrl_endpoint = 0x81,
+ /* parameter for the MPEG2-data transfer */
+ .num_adapters = 1,
+ .download_firmware = dw2102_load_firmware,
+ .read_mac_address = dw210x_read_mac_address,
+ .adapter = {
+ {
+ .frontend_attach = dw3101_frontend_attach,
+ .streaming_ctrl = NULL,
+ .tuner_attach = dw3101_tuner_attach,
+ .stream = {
+ .type = USB_BULK,
+ .count = 8,
+ .endpoint = 0x82,
+ .u = {
+ .bulk = {
+ .buffersize = 4096,
+ }
+ }
+ },
+ }
+ },
+ .num_device_descs = 1,
+ .devices = {
+ { "DVBWorld DVB-C 3101 USB2.0",
+ {&dw2102_table[5], NULL},
+ {NULL},
+ },
+ }
+};
+
static int dw2102_probe(struct usb_interface *intf,
const struct usb_device_id *id)
{
if (0 == dvb_usb_device_init(intf, &dw2102_properties,
THIS_MODULE, NULL, adapter_nr) ||
0 == dvb_usb_device_init(intf, &dw2104_properties,
+ THIS_MODULE, NULL, adapter_nr) ||
+ 0 == dvb_usb_device_init(intf, &dw3101_properties,
THIS_MODULE, NULL, adapter_nr)) {
return 0;
}
@@ -845,6 +1107,8 @@ module_init(dw2102_module_init);
module_exit(dw2102_module_exit);
MODULE_AUTHOR("Igor M. Liplianin (c) liplianin@me.by");
-MODULE_DESCRIPTION("Driver for DVBWorld DVB-S 2101, 2102, DVB-S2 2104 USB2.0 device");
+MODULE_DESCRIPTION("Driver for DVBWorld DVB-S 2101, 2102, DVB-S2 2104,"
+ " DVB-C 3101 USB2.0,"
+ " TeVii S600, S650 USB2.0 devices");
MODULE_VERSION("0.1");
MODULE_LICENSE("GPL");
diff --git a/linux/drivers/media/dvb/dvb-usb/dw2102.h b/linux/drivers/media/dvb/dvb-usb/dw2102.h
index e3370734e..5cd0b0eb6 100644
--- a/linux/drivers/media/dvb/dvb-usb/dw2102.h
+++ b/linux/drivers/media/dvb/dvb-usb/dw2102.h
@@ -5,4 +5,5 @@
#include "dvb-usb.h"
#define deb_xfer(args...) dprintk(dvb_usb_dw2102_debug, 0x02, args)
+#define deb_rc(args...) dprintk(dvb_usb_dw2102_debug, 0x04, args)
#endif
diff --git a/linux/drivers/media/dvb/frontends/au8522_dig.c b/linux/drivers/media/dvb/frontends/au8522_dig.c
index 41aedcc99..9375905ee 100644
--- a/linux/drivers/media/dvb/frontends/au8522_dig.c
+++ b/linux/drivers/media/dvb/frontends/au8522_dig.c
@@ -367,11 +367,90 @@ static struct {
{ 0x8231, 0x13 },
};
-/* QAM Modulation table */
+/* QAM64 Modulation table */
static struct {
u16 reg;
u16 data;
-} QAM_mod_tab[] = {
+} QAM64_mod_tab[] = {
+ { 0x00a3, 0x09 },
+ { 0x00a4, 0x00 },
+ { 0x0081, 0xc4 },
+ { 0x00a5, 0x40 },
+ { 0x00aa, 0x77 },
+ { 0x00ad, 0x77 },
+ { 0x00a6, 0x67 },
+ { 0x0262, 0x20 },
+ { 0x021c, 0x30 },
+ { 0x00b8, 0x3e },
+ { 0x00b9, 0xf0 },
+ { 0x00ba, 0x01 },
+ { 0x00bb, 0x18 },
+ { 0x00bc, 0x50 },
+ { 0x00bd, 0x00 },
+ { 0x00be, 0xea },
+ { 0x00bf, 0xef },
+ { 0x00c0, 0xfc },
+ { 0x00c1, 0xbd },
+ { 0x00c2, 0x1f },
+ { 0x00c3, 0xfc },
+ { 0x00c4, 0xdd },
+ { 0x00c5, 0xaf },
+ { 0x00c6, 0x00 },
+ { 0x00c7, 0x38 },
+ { 0x00c8, 0x30 },
+ { 0x00c9, 0x05 },
+ { 0x00ca, 0x4a },
+ { 0x00cb, 0xd0 },
+ { 0x00cc, 0x01 },
+ { 0x00cd, 0xd9 },
+ { 0x00ce, 0x6f },
+ { 0x00cf, 0xf9 },
+ { 0x00d0, 0x70 },
+ { 0x00d1, 0xdf },
+ { 0x00d2, 0xf7 },
+ { 0x00d3, 0xc2 },
+ { 0x00d4, 0xdf },
+ { 0x00d5, 0x02 },
+ { 0x00d6, 0x9a },
+ { 0x00d7, 0xd0 },
+ { 0x0250, 0x0d },
+ { 0x0251, 0xcd },
+ { 0x0252, 0xe0 },
+ { 0x0253, 0x05 },
+ { 0x0254, 0xa7 },
+ { 0x0255, 0xff },
+ { 0x0256, 0xed },
+ { 0x0257, 0x5b },
+ { 0x0258, 0xae },
+ { 0x0259, 0xe6 },
+ { 0x025a, 0x3d },
+ { 0x025b, 0x0f },
+ { 0x025c, 0x0d },
+ { 0x025d, 0xea },
+ { 0x025e, 0xf2 },
+ { 0x025f, 0x51 },
+ { 0x0260, 0xf5 },
+ { 0x0261, 0x06 },
+ { 0x021a, 0x00 },
+ { 0x0546, 0x40 },
+ { 0x0210, 0xc7 },
+ { 0x0211, 0xaa },
+ { 0x0212, 0xab },
+ { 0x0213, 0x02 },
+ { 0x0502, 0x00 },
+ { 0x0121, 0x04 },
+ { 0x0122, 0x04 },
+ { 0x052e, 0x10 },
+ { 0x00a4, 0xca },
+ { 0x00a7, 0x40 },
+ { 0x0526, 0x01 },
+};
+
+/* QAM256 Modulation table */
+static struct {
+ u16 reg;
+ u16 data;
+} QAM256_mod_tab[] = {
{ 0x80a3, 0x09 },
{ 0x80a4, 0x00 },
{ 0x8081, 0xc4 },
@@ -464,12 +543,19 @@ static int au8522_enable_modulation(struct dvb_frontend *fe,
au8522_set_if(fe, state->config->vsb_if);
break;
case QAM_64:
+ dprintk("%s() QAM 64\n", __func__);
+ for (i = 0; i < ARRAY_SIZE(QAM64_mod_tab); i++)
+ au8522_writereg(state,
+ QAM64_mod_tab[i].reg,
+ QAM64_mod_tab[i].data);
+ au8522_set_if(fe, state->config->qam_if);
+ break;
case QAM_256:
- dprintk("%s() QAM 64/256\n", __func__);
- for (i = 0; i < ARRAY_SIZE(QAM_mod_tab); i++)
+ dprintk("%s() QAM 256\n", __func__);
+ for (i = 0; i < ARRAY_SIZE(QAM256_mod_tab); i++)
au8522_writereg(state,
- QAM_mod_tab[i].reg,
- QAM_mod_tab[i].data);
+ QAM256_mod_tab[i].reg,
+ QAM256_mod_tab[i].data);
au8522_set_if(fe, state->config->qam_if);
break;
default:
diff --git a/linux/drivers/media/dvb/frontends/lgs8gxx.c b/linux/drivers/media/dvb/frontends/lgs8gxx.c
index 1395f3b5b..1ce30aa53 100644
--- a/linux/drivers/media/dvb/frontends/lgs8gxx.c
+++ b/linux/drivers/media/dvb/frontends/lgs8gxx.c
@@ -37,14 +37,14 @@
} while (0)
static int debug;
-static int fake_signal_str;
+static int fake_signal_str = 1;
module_param(debug, int, 0644);
MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off).");
module_param(fake_signal_str, int, 0644);
MODULE_PARM_DESC(fake_signal_str, "fake signal strength for LGS8913."
-"Signal strength calculation is slow.(default:off).");
+"Signal strength calculation is slow.(default:on).");
/* LGS8GXX internal helper functions */
@@ -650,7 +650,7 @@ static int lgs8gxx_read_signal_agc(struct lgs8gxx_state *priv, u16 *signal)
else
cat = 0;
- *signal = cat;
+ *signal = cat * 65535 / 5;
return 0;
}
@@ -670,8 +670,8 @@ static int lgs8913_read_signal_strength(struct lgs8gxx_state *priv, u16 *signal)
if (fake_signal_str) {
if ((t & 0xC0) == 0xC0) {
- dprintk("Fake signal strength as 50\n");
- *signal = 0x32;
+ dprintk("Fake signal strength\n");
+ *signal = 0x7FFF;
} else
*signal = 0;
return 0;
diff --git a/linux/drivers/media/dvb/frontends/lnbp21.c b/linux/drivers/media/dvb/frontends/lnbp21.c
index 1dcc56f32..71f607fe8 100644
--- a/linux/drivers/media/dvb/frontends/lnbp21.c
+++ b/linux/drivers/media/dvb/frontends/lnbp21.c
@@ -133,7 +133,7 @@ static struct dvb_frontend *lnbx2x_attach(struct dvb_frontend *fe,
/* override frontend ops */
fe->ops.set_voltage = lnbp21_set_voltage;
fe->ops.enable_high_lnb_voltage = lnbp21_enable_high_lnb_voltage;
- printk(KERN_INFO "LNBx2x attached on addr=%x", lnbp21->i2c_addr);
+ printk(KERN_INFO "LNBx2x attached on addr=%x\n", lnbp21->i2c_addr);
return fe;
}
diff --git a/linux/drivers/media/dvb/frontends/stv0900.h b/linux/drivers/media/dvb/frontends/stv0900.h
index 8a1332c20..bf4e9b633 100644
--- a/linux/drivers/media/dvb/frontends/stv0900.h
+++ b/linux/drivers/media/dvb/frontends/stv0900.h
@@ -29,6 +29,11 @@
#include <linux/dvb/frontend.h>
#include "dvb_frontend.h"
+struct stv0900_reg {
+ u16 addr;
+ u8 val;
+};
+
struct stv0900_config {
u8 demod_address;
u32 xtal;
@@ -38,7 +43,7 @@ struct stv0900_config {
u8 path1_mode;
u8 path2_mode;
-
+ struct stv0900_reg *ts_config_regs;
u8 tun1_maddress;/* 0, 1, 2, 3 for 0xc0, 0xc2, 0xc4, 0xc6 */
u8 tun2_maddress;
u8 tun1_adc;/* 1 for stv6110, 2 for stb6100 */
diff --git a/linux/drivers/media/dvb/frontends/stv0900_core.c b/linux/drivers/media/dvb/frontends/stv0900_core.c
index 899b1e7ed..84bf35edb 100644
--- a/linux/drivers/media/dvb/frontends/stv0900_core.c
+++ b/linux/drivers/media/dvb/frontends/stv0900_core.c
@@ -149,31 +149,31 @@ void stv0900_write_reg(struct stv0900_internal *i_params, u16 reg_addr,
dprintk(KERN_ERR "%s: i2c error %d\n", __func__, ret);
}
-u8 stv0900_read_reg(struct stv0900_internal *i_params, u16 reg_addr)
+u8 stv0900_read_reg(struct stv0900_internal *i_params, u16 reg)
{
- u8 data[2];
int ret;
- struct i2c_msg i2cmsg = {
- .addr = i_params->i2c_addr,
- .flags = 0,
- .len = 2,
- .buf = data,
+ u8 b0[] = { MSB(reg), LSB(reg) };
+ u8 buf = 0;
+ struct i2c_msg msg[] = {
+ {
+ .addr = i_params->i2c_addr,
+ .flags = 0,
+ .buf = b0,
+ .len = 2,
+ }, {
+ .addr = i_params->i2c_addr,
+ .flags = I2C_M_RD,
+ .buf = &buf,
+ .len = 1,
+ },
};
- data[0] = MSB(reg_addr);
- data[1] = LSB(reg_addr);
-
- ret = i2c_transfer(i_params->i2c_adap, &i2cmsg, 1);
- if (ret != 1)
- dprintk(KERN_ERR "%s: i2c error %d\n", __func__, ret);
-
- i2cmsg.flags = I2C_M_RD;
- i2cmsg.len = 1;
- ret = i2c_transfer(i_params->i2c_adap, &i2cmsg, 1);
- if (ret != 1)
- dprintk(KERN_ERR "%s: i2c error %d\n", __func__, ret);
+ ret = i2c_transfer(i_params->i2c_adap, msg, 2);
+ if (ret != 2)
+ dprintk(KERN_ERR "%s: i2c error %d, reg[0x%02x]\n",
+ __func__, ret, reg);
- return data[0];
+ return buf;
}
void extract_mask_pos(u32 label, u8 *mask, u8 *pos)
@@ -716,6 +716,44 @@ static s32 stv0900_carr_get_quality(struct dvb_frontend *fe,
return c_n;
}
+static int stv0900_read_ucblocks(struct dvb_frontend *fe, u32 * ucblocks)
+{
+ struct stv0900_state *state = fe->demodulator_priv;
+ struct stv0900_internal *i_params = state->internal;
+ enum fe_stv0900_demod_num demod = state->demod;
+ u8 err_val1, err_val0;
+ s32 err_field1, err_field0;
+ u32 header_err_val = 0;
+
+ *ucblocks = 0x0;
+ if (stv0900_get_standard(fe, demod) == STV0900_DVBS2_STANDARD) {
+ /* DVB-S2 delineator errors count */
+
+ /* retreiving number for errnous headers */
+ dmd_reg(err_field0, R0900_P1_BBFCRCKO0,
+ R0900_P2_BBFCRCKO0);
+ dmd_reg(err_field1, R0900_P1_BBFCRCKO1,
+ R0900_P2_BBFCRCKO1);
+
+ err_val1 = stv0900_read_reg(i_params, err_field1);
+ err_val0 = stv0900_read_reg(i_params, err_field0);
+ header_err_val = (err_val1<<8) | err_val0;
+
+ /* retreiving number for errnous packets */
+ dmd_reg(err_field0, R0900_P1_UPCRCKO0,
+ R0900_P2_UPCRCKO0);
+ dmd_reg(err_field1, R0900_P1_UPCRCKO1,
+ R0900_P2_UPCRCKO1);
+
+ err_val1 = stv0900_read_reg(i_params, err_field1);
+ err_val0 = stv0900_read_reg(i_params, err_field0);
+ *ucblocks = (err_val1<<8) | err_val0;
+ *ucblocks += header_err_val;
+ }
+
+ return 0;
+}
+
static int stv0900_read_snr(struct dvb_frontend *fe, u16 *snr)
{
*snr = stv0900_carr_get_quality(fe,
@@ -1359,7 +1397,7 @@ static enum fe_stv0900_error stv0900_init_internal(struct dvb_frontend *fe,
struct stv0900_state *state = fe->demodulator_priv;
enum fe_stv0900_error error = STV0900_NO_ERROR;
enum fe_stv0900_error demodError = STV0900_NO_ERROR;
- int selosci;
+ int selosci, i;
struct stv0900_inode *temp_int = find_inode(state->i2c_adap,
state->config->demod_address);
@@ -1406,7 +1444,23 @@ static enum fe_stv0900_error stv0900_init_internal(struct dvb_frontend *fe,
stv0900_write_bits(state->internal, F0900_P1_ROLLOFF_CONTROL, p_init->rolloff);
stv0900_write_bits(state->internal, F0900_P2_ROLLOFF_CONTROL, p_init->rolloff);
- stv0900_set_ts_parallel_serial(state->internal, p_init->path1_ts_clock, p_init->path2_ts_clock);
+ state->internal->ts_config = p_init->ts_config;
+ if (state->internal->ts_config == NULL)
+ stv0900_set_ts_parallel_serial(state->internal,
+ p_init->path1_ts_clock,
+ p_init->path2_ts_clock);
+ else {
+ for (i = 0; state->internal->ts_config[i].addr != 0xffff; i++)
+ stv0900_write_reg(state->internal,
+ state->internal->ts_config[i].addr,
+ state->internal->ts_config[i].val);
+
+ stv0900_write_bits(state->internal, F0900_P2_RST_HWARE, 1);
+ stv0900_write_bits(state->internal, F0900_P2_RST_HWARE, 0);
+ stv0900_write_bits(state->internal, F0900_P1_RST_HWARE, 1);
+ stv0900_write_bits(state->internal, F0900_P1_RST_HWARE, 0);
+ }
+
stv0900_write_bits(state->internal, F0900_P1_TUN_MADDRESS, p_init->tun1_maddress);
switch (p_init->tuner1_adc) {
case 1:
@@ -1897,6 +1951,7 @@ static struct dvb_frontend_ops stv0900_ops = {
.read_ber = stv0900_read_ber,
.read_signal_strength = stv0900_read_signal_strength,
.read_snr = stv0900_read_snr,
+ .read_ucblocks = stv0900_read_ucblocks,
};
struct dvb_frontend *stv0900_attach(const struct stv0900_config *config,
@@ -1930,6 +1985,7 @@ struct dvb_frontend *stv0900_attach(const struct stv0900_config *config,
init_params.tun1_iq_inversion = STV0900_IQ_NORMAL;
init_params.tuner1_adc = config->tun1_adc;
init_params.path2_ts_clock = config->path2_mode;
+ init_params.ts_config = config->ts_config_regs;
init_params.tun2_maddress = config->tun2_maddress;
init_params.tuner2_adc = config->tun2_adc;
init_params.tun2_iq_inversion = STV0900_IQ_SWAPPED;
diff --git a/linux/drivers/media/dvb/frontends/stv0900_priv.h b/linux/drivers/media/dvb/frontends/stv0900_priv.h
index 67dc8ec63..5ed7a145c 100644
--- a/linux/drivers/media/dvb/frontends/stv0900_priv.h
+++ b/linux/drivers/media/dvb/frontends/stv0900_priv.h
@@ -271,6 +271,7 @@ struct stv0900_init_params{
/* IQ from the tuner2 to the demod */
enum stv0900_iq_inversion tun2_iq_inversion;
+ struct stv0900_reg *ts_config;
};
struct stv0900_search_params {
@@ -363,6 +364,7 @@ struct stv0900_internal{
u8 i2c_addr;
u8 clkmode;/* 0 for CLKI, 2 for XTALI */
u8 chip_id;
+ struct stv0900_reg *ts_config;
enum fe_stv0900_error errs;
int dmds_used;
};
diff --git a/linux/drivers/media/dvb/frontends/tda10048.c b/linux/drivers/media/dvb/frontends/tda10048.c
index 04596baa9..edf5a19a3 100644
--- a/linux/drivers/media/dvb/frontends/tda10048.c
+++ b/linux/drivers/media/dvb/frontends/tda10048.c
@@ -210,6 +210,7 @@ static struct pll_tab {
{ TDA10048_CLK_4000, TDA10048_IF_36130, 10, 0, 0 },
{ TDA10048_CLK_16000, TDA10048_IF_3300, 10, 3, 0 },
{ TDA10048_CLK_16000, TDA10048_IF_3500, 10, 3, 0 },
+ { TDA10048_CLK_16000, TDA10048_IF_3800, 10, 3, 0 },
{ TDA10048_CLK_16000, TDA10048_IF_4000, 10, 3, 0 },
{ TDA10048_CLK_16000, TDA10048_IF_4300, 10, 3, 0 },
{ TDA10048_CLK_16000, TDA10048_IF_36130, 10, 3, 0 },
diff --git a/linux/drivers/media/dvb/siano/smscoreapi.c b/linux/drivers/media/dvb/siano/smscoreapi.c
index e513408fc..54f59f24e 100644
--- a/linux/drivers/media/dvb/siano/smscoreapi.c
+++ b/linux/drivers/media/dvb/siano/smscoreapi.c
@@ -1477,8 +1477,8 @@ int smscore_gpio_configure(struct smscore_device_t *coredev, u8 PinNum,
struct smscore_gpio_config *pGpioConfig) {
u32 totalLen;
- u32 TranslatedPinNum;
- u32 GroupNum;
+ u32 TranslatedPinNum = 0;
+ u32 GroupNum = 0;
u32 ElectricChar;
u32 groupCfg;
void *buffer;
diff --git a/linux/drivers/media/radio/dsbr100.c b/linux/drivers/media/radio/dsbr100.c
index bd13bef85..2bb867720 100644
--- a/linux/drivers/media/radio/dsbr100.c
+++ b/linux/drivers/media/radio/dsbr100.c
@@ -33,6 +33,10 @@
History:
+ Version 0.46:
+ Removed usb_dsbr100_open/close calls and radio->users counter. Also,
+ radio->muted changed to radio->status and suspend/resume calls updated.
+
Version 0.45:
Converted to v4l2_device.
@@ -101,8 +105,8 @@
*/
#include <linux/version.h> /* for KERNEL_VERSION MACRO */
-#define DRIVER_VERSION "v0.45"
-#define RADIO_VERSION KERNEL_VERSION(0, 4, 5)
+#define DRIVER_VERSION "v0.46"
+#define RADIO_VERSION KERNEL_VERSION(0, 4, 6)
#define DRIVER_AUTHOR "Markus Demleitner <msdemlei@tucana.harvard.edu>"
#define DRIVER_DESC "D-Link DSB-R100 USB FM radio driver"
@@ -122,13 +126,15 @@ devices, that would be 76 and 91. */
#define FREQ_MAX 108.0
#define FREQ_MUL 16000
+/* defines for radio->status */
+#define STARTED 0
+#define STOPPED 1
+
#define videodev_to_radio(d) container_of(d, struct dsbr100_device, videodev)
static int usb_dsbr100_probe(struct usb_interface *intf,
const struct usb_device_id *id);
static void usb_dsbr100_disconnect(struct usb_interface *intf);
-static int usb_dsbr100_open(struct file *file);
-static int usb_dsbr100_close(struct file *file);
static int usb_dsbr100_suspend(struct usb_interface *intf,
pm_message_t message);
static int usb_dsbr100_resume(struct usb_interface *intf);
@@ -146,9 +152,8 @@ struct dsbr100_device {
struct mutex lock; /* buffer locking */
int curfreq;
int stereo;
- int users;
int removed;
- int muted;
+ int status;
};
static struct usb_device_id usb_dsbr100_device_table [] = {
@@ -204,7 +209,7 @@ static int dsbr100_start(struct dsbr100_device *radio)
goto usb_control_msg_failed;
}
- radio->muted = 0;
+ radio->status = STARTED;
mutex_unlock(&radio->lock);
return (radio->transfer_buffer)[0];
@@ -247,7 +252,7 @@ static int dsbr100_stop(struct dsbr100_device *radio)
goto usb_control_msg_failed;
}
- radio->muted = 1;
+ radio->status = STOPPED;
mutex_unlock(&radio->lock);
return (radio->transfer_buffer)[0];
@@ -261,12 +266,12 @@ usb_control_msg_failed:
}
/* set a frequency, freq is defined by v4l's TUNER_LOW, i.e. 1/16th kHz */
-static int dsbr100_setfreq(struct dsbr100_device *radio, int freq)
+static int dsbr100_setfreq(struct dsbr100_device *radio)
{
int retval;
int request;
+ int freq = (radio->curfreq / 16 * 80) / 1000 + 856;
- freq = (freq / 16 * 80) / 1000 + 856;
mutex_lock(&radio->lock);
retval = usb_control_msg(radio->usbdev,
@@ -434,7 +439,7 @@ static int vidioc_s_frequency(struct file *file, void *priv,
radio->curfreq = f->frequency;
mutex_unlock(&radio->lock);
- retval = dsbr100_setfreq(radio, radio->curfreq);
+ retval = dsbr100_setfreq(radio);
if (retval < 0)
dev_warn(&radio->usbdev->dev, "Set frequency failed\n");
return 0;
@@ -476,7 +481,7 @@ static int vidioc_g_ctrl(struct file *file, void *priv,
switch (ctrl->id) {
case V4L2_CID_AUDIO_MUTE:
- ctrl->value = radio->muted;
+ ctrl->value = radio->status;
return 0;
}
return -EINVAL;
@@ -546,65 +551,27 @@ static int vidioc_s_audio(struct file *file, void *priv,
return 0;
}
-static int usb_dsbr100_open(struct file *file)
-{
- struct dsbr100_device *radio = video_drvdata(file);
- int retval;
-
- lock_kernel();
- radio->users = 1;
- radio->muted = 1;
-
- retval = dsbr100_start(radio);
- if (retval < 0) {
- dev_warn(&radio->usbdev->dev,
- "Radio did not start up properly\n");
- radio->users = 0;
- unlock_kernel();
- return -EIO;
- }
-
- retval = dsbr100_setfreq(radio, radio->curfreq);
- if (retval < 0)
- dev_warn(&radio->usbdev->dev,
- "set frequency failed\n");
-
- unlock_kernel();
- return 0;
-}
-
-static int usb_dsbr100_close(struct file *file)
-{
- struct dsbr100_device *radio = video_drvdata(file);
- int retval;
-
- if (!radio)
- return -ENODEV;
-
- mutex_lock(&radio->lock);
- radio->users = 0;
- mutex_unlock(&radio->lock);
-
- if (!radio->removed) {
- retval = dsbr100_stop(radio);
- if (retval < 0) {
- dev_warn(&radio->usbdev->dev,
- "dsbr100_stop failed\n");
- }
-
- }
- return 0;
-}
-
/* Suspend device - stop device. */
static int usb_dsbr100_suspend(struct usb_interface *intf, pm_message_t message)
{
struct dsbr100_device *radio = usb_get_intfdata(intf);
int retval;
- retval = dsbr100_stop(radio);
- if (retval < 0)
- dev_warn(&intf->dev, "dsbr100_stop failed\n");
+ if (radio->status == STARTED) {
+ retval = dsbr100_stop(radio);
+ if (retval < 0)
+ dev_warn(&intf->dev, "dsbr100_stop failed\n");
+
+ /* After dsbr100_stop() status set to STOPPED.
+ * If we want driver to start radio on resume
+ * we set status equal to STARTED.
+ * On resume we will check status and run radio if needed.
+ */
+
+ mutex_lock(&radio->lock);
+ radio->status = STARTED;
+ mutex_unlock(&radio->lock);
+ }
dev_info(&intf->dev, "going into suspend..\n");
@@ -617,9 +584,11 @@ static int usb_dsbr100_resume(struct usb_interface *intf)
struct dsbr100_device *radio = usb_get_intfdata(intf);
int retval;
- retval = dsbr100_start(radio);
- if (retval < 0)
- dev_warn(&intf->dev, "dsbr100_start failed\n");
+ if (radio->status == STARTED) {
+ retval = dsbr100_start(radio);
+ if (retval < 0)
+ dev_warn(&intf->dev, "dsbr100_start failed\n");
+ }
dev_info(&intf->dev, "coming out of suspend..\n");
@@ -639,8 +608,6 @@ static void usb_dsbr100_video_device_release(struct video_device *videodev)
/* File system interface */
static const struct v4l2_file_operations usb_dsbr100_fops = {
.owner = THIS_MODULE,
- .open = usb_dsbr100_open,
- .release = usb_dsbr100_close,
.ioctl = video_ioctl2,
};
@@ -698,9 +665,9 @@ static int usb_dsbr100_probe(struct usb_interface *intf,
mutex_init(&radio->lock);
radio->removed = 0;
- radio->users = 0;
radio->usbdev = interface_to_usbdev(intf);
radio->curfreq = FREQ_MIN * FREQ_MUL;
+ radio->status = STOPPED;
video_set_drvdata(&radio->videodev, radio);
diff --git a/linux/drivers/media/radio/radio-tea5764.c b/linux/drivers/media/radio/radio-tea5764.c
index 9194a70aa..83a5aff7b 100644
--- a/linux/drivers/media/radio/radio-tea5764.c
+++ b/linux/drivers/media/radio/radio-tea5764.c
@@ -326,7 +326,9 @@ static int vidioc_g_tuner(struct file *file, void *priv,
v->rangehigh = FREQ_MAX * FREQ_MUL;
v->capability = V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_STEREO;
if (r->tunchk & TEA5764_TUNCHK_STEREO)
- v->rxsubchans = V4L2_TUNER_SUB_STEREO;
+ v->rxsubchans = V4L2_TUNER_SUB_STEREO;
+ else
+ v->rxsubchans = V4L2_TUNER_SUB_MONO;
v->audmode = tea5764_get_audout_mode(radio);
v->signal = TEA5764_TUNCHK_LEVEL(r->tunchk) * 0xffff / 0xf;
v->afc = TEA5764_TUNCHK_IFCNT(r->tunchk);
diff --git a/linux/drivers/media/video/Kconfig b/linux/drivers/media/video/Kconfig
index 8de867d30..061e147f6 100644
--- a/linux/drivers/media/video/Kconfig
+++ b/linux/drivers/media/video/Kconfig
@@ -776,10 +776,14 @@ config VIDEO_MX1
---help---
This is a v4l2 driver for the i.MX1/i.MXL CMOS Sensor Interface
+config MX3_VIDEO
+ bool
+
config VIDEO_MX3
tristate "i.MX3x Camera Sensor Interface driver"
depends on VIDEO_DEV && MX3_IPU && SOC_CAMERA
select VIDEOBUF_DMA_CONTIG
+ select MX3_VIDEO
---help---
This is a v4l2 driver for the i.MX3x Camera Sensor Interface
@@ -862,9 +866,13 @@ config USB_W9968CF
module will be called w9968cf.
config USB_OV511
- tristate "USB OV511 Camera support"
+ tristate "USB OV511 Camera support (DEPRECATED)"
depends on VIDEO_V4L1
---help---
+ This driver is DEPRECATED please use the gspca ov519 module
+ instead. Note that for the ov511 / ov518 support of the gspca module
+ you need atleast version 0.6.0 of libv4l.
+
Say Y here if you want to connect this type of camera to your
computer's USB port. See <file:Documentation/video4linux/ov511.txt>
for more information and for a list of supported cameras.
diff --git a/linux/drivers/media/video/Makefile b/linux/drivers/media/video/Makefile
index f7d9a4c6f..7fb3add1b 100644
--- a/linux/drivers/media/video/Makefile
+++ b/linux/drivers/media/video/Makefile
@@ -12,6 +12,8 @@ omap2cam-objs := omap24xxcam.o omap24xxcam-dma.o
videodev-objs := v4l2-dev.o v4l2-ioctl.o v4l2-device.o
+# V4L2 core modules
+
obj-$(CONFIG_VIDEO_DEV) += videodev.o v4l2-int-device.o
ifeq ($(CONFIG_COMPAT),y)
obj-$(CONFIG_VIDEO_DEV) += v4l2-compat-ioctl32.o
@@ -23,21 +25,15 @@ ifeq ($(CONFIG_VIDEO_V4L1_COMPAT),y)
obj-$(CONFIG_VIDEO_DEV) += v4l1-compat.o
endif
-obj-$(CONFIG_VIDEO_TUNER) += tuner.o
+# All i2c modules must come first:
-obj-$(CONFIG_VIDEO_BT848) += bt8xx/
-obj-$(CONFIG_VIDEO_IR_I2C) += ir-kbd-i2c.o
+obj-$(CONFIG_VIDEO_TUNER) += tuner.o
obj-$(CONFIG_VIDEO_TVAUDIO) += tvaudio.o
obj-$(CONFIG_VIDEO_TDA7432) += tda7432.o
obj-$(CONFIG_VIDEO_TDA9875) += tda9875.o
-
obj-$(CONFIG_VIDEO_SAA6588) += saa6588.o
obj-$(CONFIG_VIDEO_SAA5246A) += saa5246a.o
obj-$(CONFIG_VIDEO_SAA5249) += saa5249.o
-obj-$(CONFIG_VIDEO_CQCAM) += c-qcam.o
-obj-$(CONFIG_VIDEO_BWQCAM) += bw-qcam.o
-obj-$(CONFIG_VIDEO_W9966) += w9966.o
-
obj-$(CONFIG_VIDEO_TDA9840) += tda9840.o
obj-$(CONFIG_VIDEO_TEA6415C) += tea6415c.o
obj-$(CONFIG_VIDEO_TEA6420) += tea6420.o
@@ -56,11 +52,40 @@ obj-$(CONFIG_VIDEO_BT856) += bt856.o
obj-$(CONFIG_VIDEO_BT866) += bt866.o
obj-$(CONFIG_VIDEO_KS0127) += ks0127.o
obj-$(CONFIG_VIDEO_THS7303) += ths7303.o
+obj-$(CONFIG_VIDEO_VINO) += indycam.o
+obj-$(CONFIG_VIDEO_TVP5150) += tvp5150.o
+obj-$(CONFIG_VIDEO_TVP514X) += tvp514x.o
+obj-$(CONFIG_VIDEO_MSP3400) += msp3400.o
+obj-$(CONFIG_VIDEO_CS5345) += cs5345.o
+obj-$(CONFIG_VIDEO_CS53L32A) += cs53l32a.o
+obj-$(CONFIG_VIDEO_M52790) += m52790.o
+obj-$(CONFIG_VIDEO_TLV320AIC23B) += tlv320aic23b.o
+obj-$(CONFIG_VIDEO_WM8775) += wm8775.o
+obj-$(CONFIG_VIDEO_WM8739) += wm8739.o
+obj-$(CONFIG_VIDEO_VP27SMPX) += vp27smpx.o
+obj-$(CONFIG_VIDEO_CX25840) += cx25840/
+obj-$(CONFIG_VIDEO_UPD64031A) += upd64031a.o
+obj-$(CONFIG_VIDEO_UPD64083) += upd64083.o
+obj-$(CONFIG_VIDEO_OV7670) += ov7670.o
+obj-$(CONFIG_VIDEO_TCM825X) += tcm825x.o
+obj-$(CONFIG_VIDEO_TVEEPROM) += tveeprom.o
-obj-$(CONFIG_VIDEO_ZORAN) += zoran/
+obj-$(CONFIG_SOC_CAMERA_MT9M001) += mt9m001.o
+obj-$(CONFIG_SOC_CAMERA_MT9M111) += mt9m111.o
+obj-$(CONFIG_SOC_CAMERA_MT9T031) += mt9t031.o
+obj-$(CONFIG_SOC_CAMERA_MT9V022) += mt9v022.o
+obj-$(CONFIG_SOC_CAMERA_OV772X) += ov772x.o
+obj-$(CONFIG_SOC_CAMERA_TW9910) += tw9910.o
+
+# And now the v4l2 drivers:
+obj-$(CONFIG_VIDEO_BT848) += bt8xx/
+obj-$(CONFIG_VIDEO_ZORAN) += zoran/
+obj-$(CONFIG_VIDEO_CQCAM) += c-qcam.o
+obj-$(CONFIG_VIDEO_BWQCAM) += bw-qcam.o
+obj-$(CONFIG_VIDEO_W9966) += w9966.o
obj-$(CONFIG_VIDEO_PMS) += pms.o
-obj-$(CONFIG_VIDEO_VINO) += vino.o indycam.o
+obj-$(CONFIG_VIDEO_VINO) += vino.o
obj-$(CONFIG_VIDEO_STRADIS) += stradis.o
obj-$(CONFIG_VIDEO_CPIA) += cpia.o
obj-$(CONFIG_VIDEO_CPIA_PP) += cpia_pp.o
@@ -71,17 +96,7 @@ obj-$(CONFIG_VIDEO_CX88) += cx88/
obj-$(CONFIG_VIDEO_EM28XX) += em28xx/
obj-$(CONFIG_VIDEO_CX231XX) += cx231xx/
obj-$(CONFIG_VIDEO_USBVISION) += usbvision/
-obj-$(CONFIG_VIDEO_TVP5150) += tvp5150.o
-obj-$(CONFIG_VIDEO_TVP514X) += tvp514x.o
obj-$(CONFIG_VIDEO_PVRUSB2) += pvrusb2/
-obj-$(CONFIG_VIDEO_MSP3400) += msp3400.o
-obj-$(CONFIG_VIDEO_CS5345) += cs5345.o
-obj-$(CONFIG_VIDEO_CS53L32A) += cs53l32a.o
-obj-$(CONFIG_VIDEO_M52790) += m52790.o
-obj-$(CONFIG_VIDEO_TLV320AIC23B) += tlv320aic23b.o
-obj-$(CONFIG_VIDEO_WM8775) += wm8775.o
-obj-$(CONFIG_VIDEO_WM8739) += wm8739.o
-obj-$(CONFIG_VIDEO_VP27SMPX) += vp27smpx.o
obj-$(CONFIG_VIDEO_OVCAMCHIP) += ovcamchip/
obj-$(CONFIG_VIDEO_CPIA2) += cpia2/
obj-$(CONFIG_VIDEO_MXB) += mxb.o
@@ -94,19 +109,12 @@ obj-$(CONFIG_VIDEOBUF_DMA_CONTIG) += videobuf-dma-contig.o
obj-$(CONFIG_VIDEOBUF_VMALLOC) += videobuf-vmalloc.o
obj-$(CONFIG_VIDEOBUF_DVB) += videobuf-dvb.o
obj-$(CONFIG_VIDEO_BTCX) += btcx-risc.o
-obj-$(CONFIG_VIDEO_TVEEPROM) += tveeprom.o
obj-$(CONFIG_VIDEO_M32R_AR_M64278) += arv.o
-obj-$(CONFIG_VIDEO_CX25840) += cx25840/
-obj-$(CONFIG_VIDEO_UPD64031A) += upd64031a.o
-obj-$(CONFIG_VIDEO_UPD64083) += upd64083.o
obj-$(CONFIG_VIDEO_CX2341X) += cx2341x.o
obj-$(CONFIG_VIDEO_CAFE_CCIC) += cafe_ccic.o
-obj-$(CONFIG_VIDEO_OV7670) += ov7670.o
-
-obj-$(CONFIG_VIDEO_TCM825X) += tcm825x.o
obj-$(CONFIG_USB_DABUSB) += dabusb.o
obj-$(CONFIG_USB_OV511) += ov511.o
@@ -138,13 +146,7 @@ obj-$(CONFIG_VIDEO_CX23885) += cx23885/
obj-$(CONFIG_VIDEO_OMAP2) += omap2cam.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
-obj-$(CONFIG_SOC_CAMERA_MT9V022) += mt9v022.o
-obj-$(CONFIG_SOC_CAMERA_OV772X) += ov772x.o
obj-$(CONFIG_SOC_CAMERA_PLATFORM) += soc_camera_platform.o
-obj-$(CONFIG_SOC_CAMERA_TW9910) += tw9910.o
# soc-camera host drivers have to be linked after camera drivers
obj-$(CONFIG_VIDEO_MX1) += mx1_camera.o
obj-$(CONFIG_VIDEO_MX3) += mx3_camera.o
@@ -155,6 +157,8 @@ obj-$(CONFIG_VIDEO_AU0828) += au0828/
obj-$(CONFIG_USB_VIDEO_CLASS) += uvc/
+obj-$(CONFIG_VIDEO_IR_I2C) += ir-kbd-i2c.o
+
EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core
EXTRA_CFLAGS += -Idrivers/media/dvb/frontends
EXTRA_CFLAGS += -Idrivers/media/common/tuners
diff --git a/linux/drivers/media/video/bt8xx/bttv-driver.c b/linux/drivers/media/video/bt8xx/bttv-driver.c
index 67d06eb6c..27be1694b 100644
--- a/linux/drivers/media/video/bt8xx/bttv-driver.c
+++ b/linux/drivers/media/video/bt8xx/bttv-driver.c
@@ -3180,6 +3180,7 @@ static unsigned int bttv_poll(struct file *file, poll_table *wait)
struct bttv_fh *fh = file->private_data;
struct bttv_buffer *buf;
enum v4l2_field field;
+ unsigned int rc = POLLERR;
if (V4L2_BUF_TYPE_VBI_CAPTURE == fh->type) {
if (!check_alloc_btres(fh->btv,fh,RESOURCE_VBI))
@@ -3188,9 +3189,10 @@ static unsigned int bttv_poll(struct file *file, poll_table *wait)
}
if (check_btres(fh,RESOURCE_VIDEO_STREAM)) {
+ mutex_lock(&fh->cap.vb_lock);
/* streaming capture */
if (list_empty(&fh->cap.stream))
- return POLLERR;
+ goto err;
buf = list_entry(fh->cap.stream.next,struct bttv_buffer,vb.stream);
} else {
/* read() capture */
@@ -3219,11 +3221,12 @@ static unsigned int bttv_poll(struct file *file, poll_table *wait)
poll_wait(file, &buf->vb.done, wait);
if (buf->vb.state == VIDEOBUF_DONE ||
buf->vb.state == VIDEOBUF_ERROR)
- return POLLIN|POLLRDNORM;
- return 0;
+ rc = POLLIN|POLLRDNORM;
+ else
+ rc = 0;
err:
mutex_unlock(&fh->cap.vb_lock);
- return POLLERR;
+ return rc;
}
static int bttv_open(struct file *file)
diff --git a/linux/drivers/media/video/cx18/cx18-cards.c b/linux/drivers/media/video/cx18/cx18-cards.c
index 8c25ca8e3..fa755a982 100644
--- a/linux/drivers/media/video/cx18/cx18-cards.c
+++ b/linux/drivers/media/video/cx18/cx18-cards.c
@@ -351,13 +351,12 @@ static const struct cx18_card cx18_card_toshiba_qosmio_dvbt = {
static const struct cx18_card_pci_info cx18_pci_leadtek_pvr2100[] = {
{ 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/DVR3100 H",
+ .name = "Leadtek WinFast 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,
@@ -376,15 +375,12 @@ static const struct cx18_card cx18_card_leadtek_pvr2100 = {
{ CX18_CARD_INPUT_LINE_IN1, CX18_AV_AUDIO_SERIAL1, 1 },
},
.tuners = {
- /* XC3028 tuner */
+ /* XC2028 tuner */
{ .std = V4L2_STD_ALL, .tuner = TUNER_XC2028 },
},
.radio_input = { CX18_CARD_INPUT_AUD_TUNER, CX18_AV_AUDIO5, 2 },
.ddr = {
- /*
- * Pointer to proper DDR config values provided by
- * Terry Wu <terrywu at leadtek.com.tw>
- */
+ /* Pointer to proper DDR config values provided by Terry Wu */
.chip_config = 0x303,
.refresh = 0x3bb,
.timing1 = 0x24220e83,
@@ -403,6 +399,58 @@ static const struct cx18_card cx18_card_leadtek_pvr2100 = {
/* ------------------------------------------------------------------------- */
+/* Leadtek WinFast DVR3100 H */
+
+static const struct cx18_card_pci_info cx18_pci_leadtek_dvr3100h[] = {
+ { PCI_DEVICE_ID_CX23418, CX18_PCI_ID_LEADTEK, 0x6690 }, /* DVR3100 H */
+ { 0, 0, 0 }
+};
+
+static const struct cx18_card cx18_card_leadtek_dvr3100h = {
+ .type = CX18_CARD_LEADTEK_DVR3100H,
+ .name = "Leadtek WinFast DVR3100 H",
+ .comment = "Simultaneous DVB-T and Analog capture supported,\n"
+ "\texcept when capturing Analog from the antenna input.\n",
+ .v4l2_capabilities = CX18_CAP_ENCODER,
+ .hw_audio_ctrl = CX18_HW_418_AV,
+ .hw_muxer = CX18_HW_GPIO_MUX,
+ .hw_all = CX18_HW_418_AV | CX18_HW_TUNER | CX18_HW_GPIO_MUX |
+ CX18_HW_DVB | CX18_HW_GPIO_RESET_CTRL,
+ .video_inputs = {
+ { CX18_CARD_INPUT_VID_TUNER, 0, CX18_AV_COMPOSITE2 },
+ { CX18_CARD_INPUT_SVIDEO1, 1,
+ CX18_AV_SVIDEO_LUMA3 | CX18_AV_SVIDEO_CHROMA4 },
+ { CX18_CARD_INPUT_COMPOSITE1, 1, CX18_AV_COMPOSITE7 },
+ },
+ .audio_inputs = {
+ { CX18_CARD_INPUT_AUD_TUNER, CX18_AV_AUDIO5, 0 },
+ { CX18_CARD_INPUT_LINE_IN1, CX18_AV_AUDIO_SERIAL1, 1 },
+ },
+ .tuners = {
+ /* XC3028 tuner */
+ { .std = V4L2_STD_ALL, .tuner = TUNER_XC2028 },
+ },
+ .radio_input = { CX18_CARD_INPUT_AUD_TUNER, CX18_AV_AUDIO5, 2 },
+ .ddr = {
+ /* Pointer to proper DDR config values provided by Terry Wu */
+ .chip_config = 0x303,
+ .refresh = 0x3bb,
+ .timing1 = 0x24220e83,
+ .timing2 = 0x1f,
+ .tune_lane = 0,
+ .initial_emrs = 0x2,
+ },
+ .gpio_init.initial_value = 0x6,
+ .gpio_init.direction = 0x7,
+ .gpio_audio_input = { .mask = 0x7,
+ .tuner = 0x6, .linein = 0x2, .radio = 0x2 },
+ .xceive_pin = 1,
+ .pci_list = cx18_pci_leadtek_dvr3100h,
+ .i2c = &cx18_i2c_std,
+};
+
+/* ------------------------------------------------------------------------- */
+
static const struct cx18_card *cx18_card_list[] = {
&cx18_card_hvr1600_esmt,
&cx18_card_hvr1600_samsung,
@@ -411,6 +459,7 @@ static const struct cx18_card *cx18_card_list[] = {
&cx18_card_cnxt_raptor_pal,
&cx18_card_toshiba_qosmio_dvbt,
&cx18_card_leadtek_pvr2100,
+ &cx18_card_leadtek_dvr3100h,
};
const struct cx18_card *cx18_get_card(u16 index)
diff --git a/linux/drivers/media/video/cx18/cx18-controls.c b/linux/drivers/media/video/cx18/cx18-controls.c
index 8e35c3aed..5136df198 100644
--- a/linux/drivers/media/video/cx18/cx18-controls.c
+++ b/linux/drivers/media/video/cx18/cx18-controls.c
@@ -61,6 +61,8 @@ int cx18_queryctrl(struct file *file, void *fh, struct v4l2_queryctrl *qctrl)
switch (qctrl->id) {
/* Standard V4L2 controls */
+ case V4L2_CID_USER_CLASS:
+ return v4l2_ctrl_query_fill(qctrl, 0, 0, 0, 0);
case V4L2_CID_BRIGHTNESS:
case V4L2_CID_HUE:
case V4L2_CID_SATURATION:
diff --git a/linux/drivers/media/video/cx18/cx18-driver.c b/linux/drivers/media/video/cx18/cx18-driver.c
index f42a97314..7ffdda49c 100644
--- a/linux/drivers/media/video/cx18/cx18-driver.c
+++ b/linux/drivers/media/video/cx18/cx18-driver.c
@@ -152,7 +152,8 @@ 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/DVR3100 H\n"
+ "\t\t\t 7 = Leadtek WinFast PVR2100\n"
+ "\t\t\t 8 = Leadtek WinFast 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/linux/drivers/media/video/cx18/cx18-driver.h b/linux/drivers/media/video/cx18/cx18-driver.h
index f89b82367..c6a1e907f 100644
--- a/linux/drivers/media/video/cx18/cx18-driver.h
+++ b/linux/drivers/media/video/cx18/cx18-driver.h
@@ -80,8 +80,9 @@
#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/DVR3100 H */
-#define CX18_CARD_LAST 6
+#define CX18_CARD_LEADTEK_PVR2100 6 /* Leadtek WinFast PVR2100 */
+#define CX18_CARD_LEADTEK_DVR3100H 7 /* Leadtek WinFast DVR3100 H */
+#define CX18_CARD_LAST 7
#define CX18_ENC_STREAM_TYPE_MPG 0
#define CX18_ENC_STREAM_TYPE_TS 1
diff --git a/linux/drivers/media/video/cx18/cx18-dvb.c b/linux/drivers/media/video/cx18/cx18-dvb.c
index e7285a109..6ea3fe623 100644
--- a/linux/drivers/media/video/cx18/cx18-dvb.c
+++ b/linux/drivers/media/video/cx18/cx18-dvb.c
@@ -26,12 +26,17 @@
#include "cx18-queue.h"
#include "cx18-streams.h"
#include "cx18-cards.h"
+#include "cx18-gpio.h"
#include "s5h1409.h"
#include "mxl5005s.h"
+#include "zl10353.h"
+#include "tuner-xc2028.h"
DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
#define CX18_REG_DMUX_NUM_PORT_0_CONTROL 0xd5a000
+#define CX18_CLOCK_ENABLE2 0xc71024
+#define CX18_DMUX_CLK_MASK 0x0080
static struct mxl5005s_config hauppauge_hvr1600_tuner = {
.i2c_address = 0xC6 >> 1,
@@ -58,7 +63,15 @@ static struct s5h1409_config hauppauge_hvr1600_config = {
.inversion = S5H1409_INVERSION_OFF,
.status_mode = S5H1409_DEMODLOCKING,
.mpeg_timing = S5H1409_MPEGTIMING_CONTINOUS_NONINVERTING_CLOCK
+};
+/* Information/confirmation of proper config values provided by Terry Wu */
+static struct zl10353_config leadtek_dvr3100h_demod = {
+ .demod_address = 0x1e >> 1, /* Datasheet suggested straps */
+ .if2 = 45600, /* 4.560 MHz IF from the XC3028 */
+ .parallel_ts = 1, /* Not a serial TS */
+ .no_tuner = 1, /* XC3028 is not behind the gate */
+ .disable_i2c_gate_ctrl = 1, /* Disable the I2C gate */
};
static int dvb_register(struct cx18_stream *stream);
@@ -99,6 +112,7 @@ static int cx18_dvb_start_feed(struct dvb_demux_feed *feed)
cx18_write_reg(cx, v, CX18_REG_DMUX_NUM_PORT_0_CONTROL);
break;
+ case CX18_CARD_LEADTEK_DVR3100H:
default:
/* Assumption - Parallel transport - Signalling
* undefined or default.
@@ -268,8 +282,7 @@ void cx18_dvb_unregister(struct cx18_stream *stream)
}
/* All the DVB attach calls go here, this function get's modified
- * for each new card. No other function in this file needs
- * to change.
+ * for each new card. cx18_dvb_start_feed() will also need changes.
*/
static int dvb_register(struct cx18_stream *stream)
{
@@ -290,6 +303,29 @@ static int dvb_register(struct cx18_stream *stream)
ret = 0;
}
break;
+ case CX18_CARD_LEADTEK_DVR3100H:
+ dvb->fe = dvb_attach(zl10353_attach,
+ &leadtek_dvr3100h_demod,
+ &cx->i2c_adap[1]);
+ if (dvb->fe != NULL) {
+ struct dvb_frontend *fe;
+ struct xc2028_config cfg = {
+ .i2c_adap = &cx->i2c_adap[1],
+ .i2c_addr = 0xc2 >> 1,
+ .ctrl = NULL,
+ };
+ static struct xc2028_ctrl ctrl = {
+ .fname = XC2028_DEFAULT_FIRMWARE,
+ .max_len = 64,
+ .demod = XC3028_FE_ZARLINK456,
+ .type = XC2028_AUTO,
+ };
+
+ fe = dvb_attach(xc2028_attach, dvb->fe, &cfg);
+ if (fe != NULL && fe->ops.tuner_ops.set_config != NULL)
+ fe->ops.tuner_ops.set_config(fe, &ctrl);
+ }
+ break;
default:
/* No Digital Tv Support */
break;
@@ -300,6 +336,8 @@ static int dvb_register(struct cx18_stream *stream)
return -1;
}
+ dvb->fe->callback = cx18_reset_tuner_gpio;
+
ret = dvb_register_frontend(&dvb->dvb_adapter, dvb->fe);
if (ret < 0) {
if (dvb->fe->ops.release)
@@ -307,5 +345,16 @@ static int dvb_register(struct cx18_stream *stream)
return ret;
}
+ /*
+ * The firmware seems to enable the TS DMUX clock
+ * under various circumstances. However, since we know we
+ * might use it, let's just turn it on ourselves here.
+ */
+ cx18_write_reg_expect(cx,
+ (CX18_DMUX_CLK_MASK << 16) | CX18_DMUX_CLK_MASK,
+ CX18_CLOCK_ENABLE2,
+ CX18_DMUX_CLK_MASK,
+ (CX18_DMUX_CLK_MASK << 16) | CX18_DMUX_CLK_MASK);
+
return ret;
}
diff --git a/linux/drivers/media/video/cx231xx/cx231xx-avcore.c b/linux/drivers/media/video/cx231xx/cx231xx-avcore.c
index bbbb3f50e..28f48f41f 100644
--- a/linux/drivers/media/video/cx231xx/cx231xx-avcore.c
+++ b/linux/drivers/media/video/cx231xx/cx231xx-avcore.c
@@ -2046,7 +2046,7 @@ int cx231xx_initialize_stream_xfer(struct cx231xx *dev, u32 media_type)
int cx231xx_capture_start(struct cx231xx *dev, int start, u8 media_type)
{
- int rc;
+ int rc = -1;
u32 ep_mask = -1;
struct pcb_config *pcb_config;
diff --git a/linux/drivers/media/video/cx2341x.c b/linux/drivers/media/video/cx2341x.c
index 2cf0c5fee..8c468fc86 100644
--- a/linux/drivers/media/video/cx2341x.c
+++ b/linux/drivers/media/video/cx2341x.c
@@ -501,6 +501,8 @@ int cx2341x_ctrl_query(const struct cx2341x_mpeg_params *params,
int err;
switch (qctrl->id) {
+ case V4L2_CID_MPEG_CLASS:
+ return v4l2_ctrl_query_fill(qctrl, 0, 0, 0, 0);
case V4L2_CID_MPEG_STREAM_TYPE:
return v4l2_ctrl_query_fill(qctrl,
V4L2_MPEG_STREAM_TYPE_MPEG2_PS,
diff --git a/linux/drivers/media/video/cx23885/cx23885-dvb.c b/linux/drivers/media/video/cx23885/cx23885-dvb.c
index 9c3259b22..71f196ec5 100644
--- a/linux/drivers/media/video/cx23885/cx23885-dvb.c
+++ b/linux/drivers/media/video/cx23885/cx23885-dvb.c
@@ -46,6 +46,7 @@
#include "dibx000_common.h"
#include "zl10353.h"
#include "stv0900.h"
+#include "stv0900_reg.h"
#include "stv6110.h"
#include "lnbh24.h"
#include "cx24116.h"
@@ -243,12 +244,22 @@ static struct tda18271_std_map hauppauge_tda18271_std_map = {
.if_lvl = 6, .rfagc_top = 0x37 },
};
+static struct tda18271_std_map hauppauge_hvr1200_tda18271_std_map = {
+ .dvbt_6 = { .if_freq = 3300, .agc_mode = 3, .std = 4,
+ .if_lvl = 1, .rfagc_top = 0x37, },
+ .dvbt_7 = { .if_freq = 3800, .agc_mode = 3, .std = 5,
+ .if_lvl = 1, .rfagc_top = 0x37, },
+ .dvbt_8 = { .if_freq = 4300, .agc_mode = 3, .std = 6,
+ .if_lvl = 1, .rfagc_top = 0x37, },
+};
+
static struct tda18271_config hauppauge_tda18271_config = {
.std_map = &hauppauge_tda18271_std_map,
.gate = TDA18271_GATE_ANALOG,
};
static struct tda18271_config hauppauge_hvr1200_tuner_config = {
+ .std_map = &hauppauge_hvr1200_tda18271_std_map,
.gate = TDA18271_GATE_ANALOG,
};
@@ -371,13 +382,25 @@ static struct zl10353_config dvico_fusionhdtv_xc3028 = {
.disable_i2c_gate_ctrl = 1,
};
+static struct stv0900_reg stv0900_ts_regs[] = {
+ { R0900_TSGENERAL, 0x00 },
+ { R0900_P1_TSSPEED, 0x40 },
+ { R0900_P2_TSSPEED, 0x40 },
+ { R0900_P1_TSCFGM, 0xc0 },
+ { R0900_P2_TSCFGM, 0xc0 },
+ { R0900_P1_TSCFGH, 0xe0 },
+ { R0900_P2_TSCFGH, 0xe0 },
+ { R0900_P1_TSCFGL, 0x20 },
+ { R0900_P2_TSCFGL, 0x20 },
+ { 0xffff, 0xff }, /* terminate */
+};
+
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 */
+ .ts_config_regs = stv0900_ts_regs,
.tun1_maddress = 0,/* 0x60 */
.tun2_maddress = 3,/* 0x63 */
.tun1_adc = 1,/* 1 Vpp */
@@ -737,7 +760,8 @@ static int dvb_register(struct cx23885_tsport *port)
if (!dvb_attach(lnbh24_attach,
fe0->dvb.frontend,
&i2c_bus->i2c_adap,
- LNBH24_PCL, 0, 0x09))
+ LNBH24_PCL,
+ LNBH24_TTX, 0x09))
printk(KERN_ERR
"No LNBH24 found!\n");
@@ -757,7 +781,8 @@ static int dvb_register(struct cx23885_tsport *port)
if (!dvb_attach(lnbh24_attach,
fe0->dvb.frontend,
&i2c_bus->i2c_adap,
- LNBH24_PCL, 0, 0x0a))
+ LNBH24_PCL,
+ LNBH24_TTX, 0x0a))
printk(KERN_ERR
"No LNBH24 found!\n");
diff --git a/linux/drivers/media/video/cx23885/cx23885-video.c b/linux/drivers/media/video/cx23885/cx23885-video.c
index 378943605..2248e0216 100644
--- a/linux/drivers/media/video/cx23885/cx23885-video.c
+++ b/linux/drivers/media/video/cx23885/cx23885-video.c
@@ -865,6 +865,7 @@ static unsigned int video_poll(struct file *file,
{
struct cx23885_fh *fh = file->private_data;
struct cx23885_buffer *buf;
+ unsigned int rc = POLLERR;
if (V4L2_BUF_TYPE_VBI_CAPTURE == fh->type) {
if (!res_get(fh->dev, fh, RESOURCE_VBI))
@@ -872,23 +873,28 @@ static unsigned int video_poll(struct file *file,
return videobuf_poll_stream(file, &fh->vbiq, wait);
}
+ mutex_lock(&fh->vidq.vb_lock);
if (res_check(fh, RESOURCE_VIDEO)) {
/* streaming capture */
if (list_empty(&fh->vidq.stream))
- return POLLERR;
+ goto done;
buf = list_entry(fh->vidq.stream.next,
struct cx23885_buffer, vb.stream);
} else {
/* read() capture */
buf = (struct cx23885_buffer *)fh->vidq.read_buf;
if (NULL == buf)
- return POLLERR;
+ goto done;
}
poll_wait(file, &buf->vb.done, wait);
if (buf->vb.state == VIDEOBUF_DONE ||
buf->vb.state == VIDEOBUF_ERROR)
- return POLLIN|POLLRDNORM;
- return 0;
+ rc = POLLIN|POLLRDNORM;
+ else
+ rc = 0;
+done:
+ mutex_unlock(&fh->vidq.vb_lock);
+ return rc;
}
static int video_release(struct file *file)
diff --git a/linux/drivers/media/video/cx88/cx88-alsa.c b/linux/drivers/media/video/cx88/cx88-alsa.c
index 077c9f0d7..4b9f1bb22 100644
--- a/linux/drivers/media/video/cx88/cx88-alsa.c
+++ b/linux/drivers/media/video/cx88/cx88-alsa.c
@@ -939,7 +939,7 @@ static struct pci_driver cx88_audio_pci_driver = {
.name = "cx88_audio",
.id_table = cx88_audio_pci_tbl,
.probe = cx88_audio_initdev,
- .remove = cx88_audio_finidev,
+ .remove = __devexit_p(cx88_audio_finidev),
};
/****************************************************************************
@@ -949,7 +949,7 @@ static struct pci_driver cx88_audio_pci_driver = {
/*
* module init
*/
-static int cx88_audio_init(void)
+static int __init cx88_audio_init(void)
{
printk(KERN_INFO "cx2388x alsa driver version %d.%d.%d loaded\n",
(CX88_VERSION_CODE >> 16) & 0xff,
@@ -965,9 +965,8 @@ static int cx88_audio_init(void)
/*
* module remove
*/
-static void cx88_audio_fini(void)
+static void __exit cx88_audio_fini(void)
{
-
pci_unregister_driver(&cx88_audio_pci_driver);
}
diff --git a/linux/drivers/media/video/cx88/cx88-cards.c b/linux/drivers/media/video/cx88/cx88-cards.c
index 825b1f25d..bf0f26c03 100644
--- a/linux/drivers/media/video/cx88/cx88-cards.c
+++ b/linux/drivers/media/video/cx88/cx88-cards.c
@@ -1557,33 +1557,45 @@ static const struct cx88_board cx88_boards[] = {
},
.mpeg = CX88_MPEG_DVB,
},
+ /* Terry Wu <terrywu2009@gmail.com> */
+ /* TV Audio : set GPIO 2, 18, 19 value to 0, 1, 0 */
+ /* FM Audio : set GPIO 2, 18, 19 value to 0, 0, 0 */
+ /* Line-in Audio : set GPIO 2, 18, 19 value to 0, 1, 1 */
+ /* Mute Audio : set GPIO 2 value to 1 */
[CX88_BOARD_WINFAST_TV2000_XP_GLOBAL] = {
- .name = "Winfast TV2000 XP Global",
+ .name = "Leadtek TV2000 XP Global",
.tuner_type = TUNER_XC2028,
.tuner_addr = 0x61,
+ .radio_type = TUNER_XC2028,
+ .radio_addr = 0x61,
.input = { {
.type = CX88_VMUX_TELEVISION,
.vmux = 0,
- .gpio0 = 0x0400, /* pin 2:mute = 0 (off?) */
+ .gpio0 = 0x0400, /* pin 2 = 0 */
.gpio1 = 0x0000,
- .gpio2 = 0x0800, /* pin 19:audio = 0 (tv) */
-
+ .gpio2 = 0x0C04, /* pin 18 = 1, pin 19 = 0 */
+ .gpio3 = 0x0000,
}, {
.type = CX88_VMUX_COMPOSITE1,
.vmux = 1,
- .gpio0 = 0x0400, /* probably? or 0x0404 to turn mute on */
+ .gpio0 = 0x0400, /* pin 2 = 0 */
.gpio1 = 0x0000,
- .gpio2 = 0x0808, /* pin 19:audio = 1 (line) */
-
+ .gpio2 = 0x0C0C, /* pin 18 = 1, pin 19 = 1 */
+ .gpio3 = 0x0000,
}, {
.type = CX88_VMUX_SVIDEO,
.vmux = 2,
+ .gpio0 = 0x0400, /* pin 2 = 0 */
+ .gpio1 = 0x0000,
+ .gpio2 = 0x0C0C, /* pin 18 = 1, pin 19 = 1 */
+ .gpio3 = 0x0000,
} },
.radio = {
.type = CX88_RADIO,
- .gpio0 = 0x004ff,
- .gpio1 = 0x010ff,
- .gpio2 = 0x0ff,
+ .gpio0 = 0x0400, /* pin 2 = 0 */
+ .gpio1 = 0x0000,
+ .gpio2 = 0x0C00, /* pin 18 = 0, pin 19 = 0 */
+ .gpio3 = 0x0000,
},
},
[CX88_BOARD_POWERCOLOR_REAL_ANGEL] = {
@@ -2471,6 +2483,41 @@ static const struct cx88_subid cx88_subids[] = {
.subvendor = 0x107d,
.subdevice = 0x6654,
.card = CX88_BOARD_WINFAST_DTV1800H,
+ }, {
+ /* PVR2000 PAL Model [107d:6630] */
+ .subvendor = 0x107d,
+ .subdevice = 0x6630,
+ .card = CX88_BOARD_LEADTEK_PVR2000,
+ }, {
+ /* PVR2000 PAL Model [107d:6638] */
+ .subvendor = 0x107d,
+ .subdevice = 0x6638,
+ .card = CX88_BOARD_LEADTEK_PVR2000,
+ }, {
+ /* PVR2000 NTSC Model [107d:6631] */
+ .subvendor = 0x107d,
+ .subdevice = 0x6631,
+ .card = CX88_BOARD_LEADTEK_PVR2000,
+ }, {
+ /* PVR2000 NTSC Model [107d:6637] */
+ .subvendor = 0x107d,
+ .subdevice = 0x6637,
+ .card = CX88_BOARD_LEADTEK_PVR2000,
+ }, {
+ /* PVR2000 NTSC Model [107d:663d] */
+ .subvendor = 0x107d,
+ .subdevice = 0x663d,
+ .card = CX88_BOARD_LEADTEK_PVR2000,
+ }, {
+ /* DV2000 NTSC Model [107d:6621] */
+ .subvendor = 0x107d,
+ .subdevice = 0x6621,
+ .card = CX88_BOARD_WINFAST_DV2000,
+ }, {
+ /* TV2000 XP Global [107d:6618] */
+ .subvendor = 0x107d,
+ .subdevice = 0x6618,
+ .card = CX88_BOARD_WINFAST_TV2000_XP_GLOBAL,
},
};
@@ -2479,12 +2526,6 @@ static const struct cx88_subid cx88_subids[] = {
static void leadtek_eeprom(struct cx88_core *core, u8 *eeprom_data)
{
- /* This is just for the "Winfast 2000XP Expert" board ATM; I don't have data on
- * any others.
- *
- * Byte 0 is 1 on the NTSC board.
- */
-
if (eeprom_data[4] != 0x7d ||
eeprom_data[5] != 0x10 ||
eeprom_data[7] != 0x66) {
@@ -2492,8 +2533,19 @@ static void leadtek_eeprom(struct cx88_core *core, u8 *eeprom_data)
return;
}
- core->board.tuner_type = (eeprom_data[6] == 0x13) ?
- TUNER_PHILIPS_FM1236_MK3 : TUNER_PHILIPS_FM1216ME_MK3;
+ /* Terry Wu <terrywu2009@gmail.com> */
+ switch (eeprom_data[6]) {
+ case 0x13: /* SSID 6613 for TV2000 XP Expert NTSC Model */
+ case 0x21: /* SSID 6621 for DV2000 NTSC Model */
+ case 0x31: /* SSID 6631 for PVR2000 NTSC Model */
+ case 0x37: /* SSID 6637 for PVR2000 NTSC Model */
+ case 0x3d: /* SSID 6637 for PVR2000 NTSC Model */
+ core->board.tuner_type = TUNER_PHILIPS_FM1236_MK3;
+ break;
+ default:
+ core->board.tuner_type = TUNER_PHILIPS_FM1216ME_MK3;
+ break;
+ }
info_printk(core, "Leadtek Winfast 2000XP Expert config: "
"tuner=%d, eeprom[0]=0x%02x\n",
@@ -2746,7 +2798,6 @@ static int cx88_xc2028_tuner_callback(struct cx88_core *core,
{
/* Board-specific callbacks */
switch (core->boardnr) {
- case CX88_BOARD_WINFAST_TV2000_XP_GLOBAL:
case CX88_BOARD_POWERCOLOR_REAL_ANGEL:
case CX88_BOARD_GENIATECH_X8000_MT:
case CX88_BOARD_KWORLD_ATSC_120:
@@ -2758,6 +2809,7 @@ static int cx88_xc2028_tuner_callback(struct cx88_core *core,
case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PRO:
case CX88_BOARD_DVICO_FUSIONHDTV_5_PCI_NANO:
return cx88_dvico_xc2028_callback(core, command, arg);
+ case CX88_BOARD_WINFAST_TV2000_XP_GLOBAL:
case CX88_BOARD_WINFAST_DTV1800H:
return cx88_xc3028_winfast1800h_callback(core, command, arg);
}
@@ -2947,6 +2999,7 @@ static void cx88_card_setup_pre_i2c(struct cx88_core *core)
udelay(1000);
break;
+ case CX88_BOARD_WINFAST_TV2000_XP_GLOBAL:
case CX88_BOARD_WINFAST_DTV1800H:
/* GPIO 12 (xc3028 tuner reset) */
cx_set(MO_GP1_IO, 0x1010);
@@ -2983,6 +3036,7 @@ void cx88_setup_xc3028(struct cx88_core *core, struct xc2028_ctrl *ctl)
case CX88_BOARD_DVICO_FUSIONHDTV_5_PCI_NANO:
ctl->demod = XC3028_FE_OREN538;
break;
+ case CX88_BOARD_WINFAST_TV2000_XP_GLOBAL:
case CX88_BOARD_PROLINK_PV_GLOBAL_XTREME:
case CX88_BOARD_PROLINK_PV_8000GT:
/*
@@ -3026,6 +3080,8 @@ static void cx88_card_setup(struct cx88_core *core)
if (0 == core->i2c_rc)
gdi_eeprom(core, eeprom);
break;
+ case CX88_BOARD_LEADTEK_PVR2000:
+ case CX88_BOARD_WINFAST_DV2000:
case CX88_BOARD_WINFAST2000XP_EXPERT:
if (0 == core->i2c_rc)
leadtek_eeprom(core, eeprom);
diff --git a/linux/drivers/media/video/cx88/cx88-video.c b/linux/drivers/media/video/cx88/cx88-video.c
index 70b086fb7..a55053767 100644
--- a/linux/drivers/media/video/cx88/cx88-video.c
+++ b/linux/drivers/media/video/cx88/cx88-video.c
@@ -1095,6 +1095,7 @@ video_poll(struct file *file, struct poll_table_struct *wait)
{
struct cx8800_fh *fh = file->private_data;
struct cx88_buffer *buf;
+ unsigned int rc = POLLERR;
if (V4L2_BUF_TYPE_VBI_CAPTURE == fh->type) {
if (!res_get(fh->dev,fh,RESOURCE_VBI))
@@ -1102,22 +1103,27 @@ video_poll(struct file *file, struct poll_table_struct *wait)
return videobuf_poll_stream(file, &fh->vbiq, wait);
}
+ mutex_lock(&fh->vidq.vb_lock);
if (res_check(fh,RESOURCE_VIDEO)) {
/* streaming capture */
if (list_empty(&fh->vidq.stream))
- return POLLERR;
+ goto done;
buf = list_entry(fh->vidq.stream.next,struct cx88_buffer,vb.stream);
} else {
/* read() capture */
buf = (struct cx88_buffer*)fh->vidq.read_buf;
if (NULL == buf)
- return POLLERR;
+ goto done;
}
poll_wait(file, &buf->vb.done, wait);
if (buf->vb.state == VIDEOBUF_DONE ||
buf->vb.state == VIDEOBUF_ERROR)
- return POLLIN|POLLRDNORM;
- return 0;
+ rc = POLLIN|POLLRDNORM;
+ else
+ rc = 0;
+done:
+ mutex_unlock(&fh->vidq.vb_lock);
+ return rc;
}
static int video_release(struct file *file)
diff --git a/linux/drivers/media/video/em28xx/em28xx-cards.c b/linux/drivers/media/video/em28xx/em28xx-cards.c
index 5b89c1821..b824eed46 100644
--- a/linux/drivers/media/video/em28xx/em28xx-cards.c
+++ b/linux/drivers/media/video/em28xx/em28xx-cards.c
@@ -122,6 +122,24 @@ static struct em28xx_reg_seq em2870_kworld_355u_digital[] = {
};
#endif
+/* Board - EM2882 Kworld 315U digital */
+static struct em28xx_reg_seq em2882_kworld_315u_digital[] = {
+ {EM28XX_R08_GPIO, 0xff, 0xff, 10},
+ {EM28XX_R08_GPIO, 0xfe, 0xff, 10},
+ {EM2880_R04_GPO, 0x04, 0xff, 10},
+ {EM2880_R04_GPO, 0x0c, 0xff, 10},
+ {EM28XX_R08_GPIO, 0x7e, 0xff, 10},
+ { -1, -1, -1, -1},
+};
+
+static struct em28xx_reg_seq em2882_kworld_315u_tuner_gpio[] = {
+ {EM2880_R04_GPO, 0x08, 0xff, 10},
+ {EM2880_R04_GPO, 0x0c, 0xff, 10},
+ {EM2880_R04_GPO, 0x08, 0xff, 10},
+ {EM2880_R04_GPO, 0x0c, 0xff, 10},
+ { -1, -1, -1, -1},
+};
+
static struct em28xx_reg_seq kworld_330u_analog[] = {
{EM28XX_R08_GPIO, 0x6d, ~EM_GPIO_4, 10},
{EM2880_R04_GPO, 0x00, 0xff, 10},
@@ -134,6 +152,24 @@ static struct em28xx_reg_seq kworld_330u_digital[] = {
{ -1, -1, -1, -1},
};
+/* Evga inDtube
+ GPIO0 - Enable digital power (s5h1409) - low to enable
+ GPIO1 - Enable analog power (tvp5150/emp202) - low to enable
+ GPIO4 - xc3028 reset
+ GOP3 - s5h1409 reset
+ */
+static struct em28xx_reg_seq evga_indtube_analog[] = {
+ {EM28XX_R08_GPIO, 0x79, 0xff, 60},
+ { -1, -1, -1, -1},
+};
+
+static struct em28xx_reg_seq evga_indtube_digital[] = {
+ {EM28XX_R08_GPIO, 0x7a, 0xff, 1},
+ {EM2880_R04_GPO, 0x04, 0xff, 10},
+ {EM2880_R04_GPO, 0x0c, 0xff, 1},
+ { -1, -1, -1, -1},
+};
+
/* Callback for the most boards */
static struct em28xx_reg_seq default_tuner_gpio[] = {
{EM28XX_R08_GPIO, EM_GPIO_4, EM_GPIO_4, 10},
@@ -1160,6 +1196,38 @@ struct em28xx_board em28xx_boards[] = {
.gpio = default_analog,
} },
},
+ [EM2882_BOARD_KWORLD_ATSC_315U] = {
+ .name = "KWorld ATSC 315U HDTV TV Box",
+ .valid = EM28XX_BOARD_NOT_VALIDATED,
+ .tuner_type = TUNER_THOMSON_DTT761X,
+ .tuner_gpio = em2882_kworld_315u_tuner_gpio,
+ .tda9887_conf = TDA9887_PRESENT,
+ .decoder = EM28XX_SAA711X,
+ .has_dvb = 1,
+ .dvb_gpio = em2882_kworld_315u_digital,
+ .xclk = EM28XX_XCLK_FREQUENCY_12MHZ,
+ .i2c_speed = EM28XX_I2C_CLK_WAIT_ENABLE,
+ /* Analog mode - still not ready */
+ /*.input = { {
+ .type = EM28XX_VMUX_TELEVISION,
+ .vmux = SAA7115_COMPOSITE2,
+ .amux = EM28XX_AMUX_VIDEO,
+ .gpio = em2882_kworld_315u_analog,
+ .aout = EM28XX_AOUT_PCM_IN | EM28XX_AOUT_PCM_STEREO,
+ }, {
+ .type = EM28XX_VMUX_COMPOSITE1,
+ .vmux = SAA7115_COMPOSITE0,
+ .amux = EM28XX_AMUX_LINE_IN,
+ .gpio = em2882_kworld_315u_analog1,
+ .aout = EM28XX_AOUT_PCM_IN | EM28XX_AOUT_PCM_STEREO,
+ }, {
+ .type = EM28XX_VMUX_SVIDEO,
+ .vmux = SAA7115_SVIDEO3,
+ .amux = EM28XX_AMUX_LINE_IN,
+ .gpio = em2882_kworld_315u_analog1,
+ .aout = EM28XX_AOUT_PCM_IN | EM28XX_AOUT_PCM_STEREO,
+ } }, */
+ },
[EM2880_BOARD_EMPIRE_DUAL_TV] = {
.name = "Empire dual TV",
.tuner_type = TUNER_XC2028,
@@ -1464,6 +1532,33 @@ struct em28xx_board em28xx_boards[] = {
.gpio = terratec_av350_unmute_gpio,
} },
},
+ [EM2882_BOARD_EVGA_INDTUBE] = {
+ .name = "Evga inDtube",
+ .tuner_type = TUNER_XC2028,
+ .tuner_gpio = default_tuner_gpio,
+ .decoder = EM28XX_TVP5150,
+ .xclk = EM28XX_XCLK_FREQUENCY_12MHZ, /* NEC IR */
+ .mts_firmware = 1,
+ .has_dvb = 1,
+ .dvb_gpio = evga_indtube_digital,
+ .ir_codes = ir_codes_evga_indtube,
+ .input = { {
+ .type = EM28XX_VMUX_TELEVISION,
+ .vmux = TVP5150_COMPOSITE0,
+ .amux = EM28XX_AMUX_VIDEO,
+ .gpio = evga_indtube_analog,
+ }, {
+ .type = EM28XX_VMUX_COMPOSITE1,
+ .vmux = TVP5150_COMPOSITE1,
+ .amux = EM28XX_AMUX_LINE_IN,
+ .gpio = evga_indtube_analog,
+ }, {
+ .type = EM28XX_VMUX_SVIDEO,
+ .vmux = TVP5150_SVIDEO,
+ .amux = EM28XX_AMUX_LINE_IN,
+ .gpio = evga_indtube_analog,
+ } },
+ },
};
const unsigned int em28xx_bcount = ARRAY_SIZE(em28xx_boards);
@@ -1501,6 +1596,8 @@ struct usb_device_id em28xx_id_table[] = {
{ USB_DEVICE(0xeb1a, 0xe310),
.driver_info = EM2880_BOARD_KWORLD_DVB_310U },
#endif
+ { USB_DEVICE(0xeb1a, 0xa313),
+ .driver_info = EM2882_BOARD_KWORLD_ATSC_315U },
{ USB_DEVICE(0xeb1a, 0xa316),
.driver_info = EM2883_BOARD_KWORLD_HYBRID_330U },
{ USB_DEVICE(0xeb1a, 0xe320),
@@ -1588,6 +1685,7 @@ static struct em28xx_hash_table em28xx_eeprom_hash[] = {
{0x72cc5a8b, EM2820_BOARD_PROLINK_PLAYTV_BOX4_USB2, TUNER_YMEC_TVF_5533MF},
{0x966a0441, EM2880_BOARD_KWORLD_DVB_310U, TUNER_XC2028},
{0x9567eb1a, EM2880_BOARD_EMPIRE_DUAL_TV, TUNER_XC2028},
+ {0xcee44a99, EM2882_BOARD_EVGA_INDTUBE, TUNER_XC2028},
};
/* I2C devicelist hash table for devices with generic USB IDs */
@@ -1770,6 +1868,17 @@ void em28xx_pre_card_setup(struct em28xx *dev)
em28xx_write_reg(dev, EM28XX_R08_GPIO, 0xfd);
break;
+ case EM2882_BOARD_KWORLD_ATSC_315U:
+ em28xx_write_reg(dev, EM28XX_R08_GPIO, 0xff);
+ msleep(10);
+ em28xx_write_reg(dev, EM28XX_R08_GPIO, 0xfe);
+ msleep(10);
+ em28xx_write_reg(dev, EM2880_R04_GPO, 0x00);
+ msleep(10);
+ em28xx_write_reg(dev, EM2880_R04_GPO, 0x08);
+ msleep(10);
+ 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);
@@ -1840,6 +1949,10 @@ static void em28xx_setup_xc3028(struct em28xx *dev, struct xc2028_ctrl *ctl)
ctl->demod = XC3028_FE_CHINA;
ctl->fname = XC2028_DEFAULT_FIRMWARE;
break;
+ case EM2882_BOARD_EVGA_INDTUBE:
+ ctl->demod = XC3028_FE_CHINA;
+ ctl->fname = XC3028L_DEFAULT_FIRMWARE;
+ break;
default:
ctl->demod = XC3028_FE_OREN538;
}
@@ -2081,6 +2194,9 @@ void em28xx_card_setup(struct em28xx *dev)
if (em28xx_boards[dev->model].tuner_addr)
dev->tuner_addr = em28xx_boards[dev->model].tuner_addr;
+ if (em28xx_boards[dev->model].tda9887_conf)
+ dev->tda9887_conf = em28xx_boards[dev->model].tda9887_conf;
+
/* request some modules */
switch (dev->model) {
case EM2820_BOARD_HAUPPAUGE_WINTV_USB_2:
@@ -2110,6 +2226,12 @@ void em28xx_card_setup(struct em28xx *dev)
#endif
break;
}
+ case EM2882_BOARD_KWORLD_ATSC_315U:
+ em28xx_write_reg(dev, 0x0d, 0x42);
+ msleep(10);
+ em28xx_write_reg(dev, EM28XX_R08_GPIO, 0xfd);
+ msleep(10);
+ break;
case EM2820_BOARD_KWORLD_PVRTV2800RF:
/* GPIO enables sound on KWORLD PVR TV 2800RF */
em28xx_write_reg(dev, EM28XX_R08_GPIO, 0xf9);
@@ -2132,6 +2254,12 @@ void em28xx_card_setup(struct em28xx *dev)
case EM2880_BOARD_MSI_DIGIVOX_AD:
if (!em28xx_hint_board(dev))
em28xx_set_model(dev);
+
+ /* In cases where we had to use a board hint, the call to
+ em28xx_set_mode() in em28xx_pre_card_setup() was a no-op,
+ so make the call now so the analog GPIOs are set properly
+ before probing the i2c bus. */
+ em28xx_set_mode(dev, EM28XX_ANALOG_MODE);
break;
}
diff --git a/linux/drivers/media/video/em28xx/em28xx-core.c b/linux/drivers/media/video/em28xx/em28xx-core.c
index 02e51af9d..2bce72e4f 100644
--- a/linux/drivers/media/video/em28xx/em28xx-core.c
+++ b/linux/drivers/media/video/em28xx/em28xx-core.c
@@ -500,18 +500,21 @@ int em28xx_audio_setup(struct em28xx *dev)
/* See how this device is configured */
cfg = em28xx_read_reg(dev, EM28XX_R00_CHIPCFG);
- if (cfg < 0)
+ em28xx_info("Config register raw data: 0x%02x\n", cfg);
+ if (cfg < 0) {
+ /* Register read error? */
cfg = EM28XX_CHIPCFG_AC97; /* Be conservative */
- else
- em28xx_info("Config register raw data: 0x%02x\n", cfg);
-
- if ((cfg & EM28XX_CHIPCFG_AUDIOMASK) ==
- EM28XX_CHIPCFG_I2S_3_SAMPRATES) {
+ } else if ((cfg & EM28XX_CHIPCFG_AUDIOMASK) == 0x00) {
+ /* The device doesn't have vendor audio at all */
+ dev->has_alsa_audio = 0;
+ dev->audio_mode.has_audio = 0;
+ return 0;
+ } else if ((cfg & EM28XX_CHIPCFG_AUDIOMASK) ==
+ EM28XX_CHIPCFG_I2S_3_SAMPRATES) {
em28xx_info("I2S Audio (3 sample rates)\n");
dev->audio_mode.i2s_3rates = 1;
- }
- if ((cfg & EM28XX_CHIPCFG_AUDIOMASK) ==
- EM28XX_CHIPCFG_I2S_5_SAMPRATES) {
+ } else if ((cfg & EM28XX_CHIPCFG_AUDIOMASK) ==
+ EM28XX_CHIPCFG_I2S_5_SAMPRATES) {
em28xx_info("I2S Audio (5 sample rates)\n");
dev->audio_mode.i2s_5rates = 1;
}
diff --git a/linux/drivers/media/video/em28xx/em28xx-dvb.c b/linux/drivers/media/video/em28xx/em28xx-dvb.c
index de919504f..85afa0be0 100644
--- a/linux/drivers/media/video/em28xx/em28xx-dvb.c
+++ b/linux/drivers/media/video/em28xx/em28xx-dvb.c
@@ -26,6 +26,8 @@
#include "em28xx.h"
#include <media/v4l2-common.h>
#include <media/videobuf-vmalloc.h>
+#include <media/tuner.h>
+#include "tuner-simple.h"
#include "lgdt330x.h"
#include "zl10353.h"
@@ -444,6 +446,7 @@ static int dvb_init(struct em28xx *dev)
}
break;
case EM2883_BOARD_KWORLD_HYBRID_330U:
+ case EM2882_BOARD_EVGA_INDTUBE:
dvb->frontend = dvb_attach(s5h1409_attach,
&em28xx_s5h1409_with_xc3028,
&dev->i2c_adap);
@@ -452,6 +455,18 @@ static int dvb_init(struct em28xx *dev)
goto out_free;
}
break;
+ case EM2882_BOARD_KWORLD_ATSC_315U:
+ dvb->frontend = dvb_attach(lgdt330x_attach,
+ &em2880_lgdt3303_dev,
+ &dev->i2c_adap);
+ if (dvb->frontend != NULL) {
+ if (!dvb_attach(simple_tuner_attach, dvb->frontend,
+ &dev->i2c_adap, 0x61, TUNER_THOMSON_DTT761X)) {
+ result = -EINVAL;
+ goto out_free;
+ }
+ }
+ break;
case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900_R2:
#ifdef EM28XX_DRX397XD_SUPPORT
/* We don't have the config structure properly populated, so
diff --git a/linux/drivers/media/video/em28xx/em28xx.h b/linux/drivers/media/video/em28xx/em28xx.h
index db07d92f6..6fb890efa 100644
--- a/linux/drivers/media/video/em28xx/em28xx.h
+++ b/linux/drivers/media/video/em28xx/em28xx.h
@@ -106,6 +106,8 @@
#define EM2880_BOARD_EMPIRE_DUAL_TV 66
#define EM2860_BOARD_TERRATEC_GRABBY 67
#define EM2860_BOARD_TERRATEC_AV350 68
+#define EM2882_BOARD_KWORLD_ATSC_315U 69
+#define EM2882_BOARD_EVGA_INDTUBE 70
/* Limits minimum and default number of buffers */
#define EM28XX_MIN_BUF 4
diff --git a/linux/drivers/media/video/gspca/gspca.c b/linux/drivers/media/video/gspca/gspca.c
index 3bf8b4866..f06aac676 100644
--- a/linux/drivers/media/video/gspca/gspca.c
+++ b/linux/drivers/media/video/gspca/gspca.c
@@ -1021,43 +1021,52 @@ out:
return ret;
}
+static const struct ctrl *get_ctrl(struct gspca_dev *gspca_dev,
+ int id)
+{
+ const struct ctrl *ctrls;
+ int i;
+
+ for (i = 0, ctrls = gspca_dev->sd_desc->ctrls;
+ i < gspca_dev->sd_desc->nctrls;
+ i++, ctrls++) {
+ if (gspca_dev->ctrl_dis & (1 << i))
+ continue;
+ if (id == ctrls->qctrl.id)
+ return ctrls;
+ }
+ return NULL;
+}
+
static int vidioc_queryctrl(struct file *file, void *priv,
struct v4l2_queryctrl *q_ctrl)
{
struct gspca_dev *gspca_dev = priv;
- int i, ix;
+ const struct ctrl *ctrls;
+ int i;
u32 id;
- ix = -1;
+ ctrls = NULL;
id = q_ctrl->id;
if (id & V4L2_CTRL_FLAG_NEXT_CTRL) {
id &= V4L2_CTRL_ID_MASK;
id++;
for (i = 0; i < gspca_dev->sd_desc->nctrls; i++) {
- if (gspca_dev->sd_desc->ctrls[i].qctrl.id < id)
+ if (gspca_dev->ctrl_dis & (1 << i))
continue;
- if (ix < 0) {
- ix = i;
+ if (gspca_dev->sd_desc->ctrls[i].qctrl.id < id)
continue;
- }
- if (gspca_dev->sd_desc->ctrls[i].qctrl.id
- > gspca_dev->sd_desc->ctrls[ix].qctrl.id)
+ if (ctrls && gspca_dev->sd_desc->ctrls[i].qctrl.id
+ > ctrls->qctrl.id)
continue;
- ix = i;
- }
- }
- for (i = 0; i < gspca_dev->sd_desc->nctrls; i++) {
- if (id == gspca_dev->sd_desc->ctrls[i].qctrl.id) {
- ix = i;
- break;
+ ctrls = &gspca_dev->sd_desc->ctrls[i];
}
+ } else {
+ ctrls = get_ctrl(gspca_dev, id);
}
- if (ix < 0)
+ if (ctrls == NULL)
return -EINVAL;
- memcpy(q_ctrl, &gspca_dev->sd_desc->ctrls[ix].qctrl,
- sizeof *q_ctrl);
- if (gspca_dev->ctrl_dis & (1 << ix))
- q_ctrl->flags |= V4L2_CTRL_FLAG_DISABLED;
+ memcpy(q_ctrl, ctrls, sizeof *q_ctrl);
return 0;
}
@@ -1066,56 +1075,45 @@ static int vidioc_s_ctrl(struct file *file, void *priv,
{
struct gspca_dev *gspca_dev = priv;
const struct ctrl *ctrls;
- int i, ret;
+ int ret;
- for (i = 0, ctrls = gspca_dev->sd_desc->ctrls;
- i < gspca_dev->sd_desc->nctrls;
- i++, ctrls++) {
- if (ctrl->id != ctrls->qctrl.id)
- continue;
- if (gspca_dev->ctrl_dis & (1 << i))
- return -EINVAL;
- if (ctrl->value < ctrls->qctrl.minimum
- || ctrl->value > ctrls->qctrl.maximum)
- return -ERANGE;
- PDEBUG(D_CONF, "set ctrl [%08x] = %d", ctrl->id, ctrl->value);
- if (mutex_lock_interruptible(&gspca_dev->usb_lock))
- return -ERESTARTSYS;
- if (gspca_dev->present)
- ret = ctrls->set(gspca_dev, ctrl->value);
- else
- ret = -ENODEV;
- mutex_unlock(&gspca_dev->usb_lock);
- return ret;
- }
- return -EINVAL;
+ ctrls = get_ctrl(gspca_dev, ctrl->id);
+ if (ctrls == NULL)
+ return -EINVAL;
+
+ if (ctrl->value < ctrls->qctrl.minimum
+ || ctrl->value > ctrls->qctrl.maximum)
+ return -ERANGE;
+ PDEBUG(D_CONF, "set ctrl [%08x] = %d", ctrl->id, ctrl->value);
+ if (mutex_lock_interruptible(&gspca_dev->usb_lock))
+ return -ERESTARTSYS;
+ if (gspca_dev->present)
+ ret = ctrls->set(gspca_dev, ctrl->value);
+ else
+ ret = -ENODEV;
+ mutex_unlock(&gspca_dev->usb_lock);
+ return ret;
}
static int vidioc_g_ctrl(struct file *file, void *priv,
struct v4l2_control *ctrl)
{
struct gspca_dev *gspca_dev = priv;
-
const struct ctrl *ctrls;
- int i, ret;
+ int ret;
- for (i = 0, ctrls = gspca_dev->sd_desc->ctrls;
- i < gspca_dev->sd_desc->nctrls;
- i++, ctrls++) {
- if (ctrl->id != ctrls->qctrl.id)
- continue;
- if (gspca_dev->ctrl_dis & (1 << i))
- return -EINVAL;
- if (mutex_lock_interruptible(&gspca_dev->usb_lock))
- return -ERESTARTSYS;
- if (gspca_dev->present)
- ret = ctrls->get(gspca_dev, &ctrl->value);
- else
- ret = -ENODEV;
- mutex_unlock(&gspca_dev->usb_lock);
- return ret;
- }
- return -EINVAL;
+ ctrls = get_ctrl(gspca_dev, ctrl->id);
+ if (ctrls == NULL)
+ return -EINVAL;
+
+ if (mutex_lock_interruptible(&gspca_dev->usb_lock))
+ return -ERESTARTSYS;
+ if (gspca_dev->present)
+ ret = ctrls->get(gspca_dev, &ctrl->value);
+ else
+ ret = -ENODEV;
+ mutex_unlock(&gspca_dev->usb_lock);
+ return ret;
}
/*fixme: have an audio flag in gspca_dev?*/
diff --git a/linux/drivers/media/video/gspca/m5602/m5602_ov9650.c b/linux/drivers/media/video/gspca/m5602/m5602_ov9650.c
index bbf9935df..a1245cca1 100644
--- a/linux/drivers/media/video/gspca/m5602/m5602_ov9650.c
+++ b/linux/drivers/media/video/gspca/m5602/m5602_ov9650.c
@@ -47,53 +47,60 @@ static
#endif
struct dmi_system_id ov9650_flip_dmi_table[] = {
{
- .ident = "ASUS A6VA",
+ .ident = "ASUS A6Ja",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."),
- DMI_MATCH(DMI_PRODUCT_NAME, "A6VA")
+ DMI_MATCH(DMI_PRODUCT_NAME, "A6J")
}
},
{
-
- .ident = "ASUS A6VC",
+ .ident = "ASUS A6JC",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."),
- DMI_MATCH(DMI_PRODUCT_NAME, "A6VC")
+ DMI_MATCH(DMI_PRODUCT_NAME, "A6JC")
}
},
{
- .ident = "ASUS A6VM",
+ .ident = "ASUS A6K",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."),
- DMI_MATCH(DMI_PRODUCT_NAME, "A6VM")
+ DMI_MATCH(DMI_PRODUCT_NAME, "A6K")
}
},
{
- .ident = "ASUS A6JC",
+ .ident = "ASUS A6Kt",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."),
- DMI_MATCH(DMI_PRODUCT_NAME, "A6JC")
+ DMI_MATCH(DMI_PRODUCT_NAME, "A6Kt")
}
},
{
- .ident = "ASUS A6Ja",
+ .ident = "ASUS A6VA",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."),
- DMI_MATCH(DMI_PRODUCT_NAME, "A6J")
+ DMI_MATCH(DMI_PRODUCT_NAME, "A6VA")
}
},
{
- .ident = "ASUS A6Kt",
+
+ .ident = "ASUS A6VC",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."),
- DMI_MATCH(DMI_PRODUCT_NAME, "A6Kt")
+ DMI_MATCH(DMI_PRODUCT_NAME, "A6VC")
}
},
{
- .ident = "ASUS A6K",
+ .ident = "ASUS A6VM",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."),
- DMI_MATCH(DMI_PRODUCT_NAME, "A6K")
+ DMI_MATCH(DMI_PRODUCT_NAME, "A6VM")
+ }
+ },
+ {
+ .ident = "ASUS A7V",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."),
+ DMI_MATCH(DMI_PRODUCT_NAME, "A7V")
}
},
{
diff --git a/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.c b/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.c
index 81f24d413..4a105cb38 100644
--- a/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.c
+++ b/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.c
@@ -67,6 +67,12 @@ static
DMI_MATCH(DMI_SYS_VENDOR, "Micro-Star International"),
DMI_MATCH(DMI_PRODUCT_NAME, "MS-1717X")
}
+ }, {
+ .ident = "Lenovo Y300",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "L3000 Y300"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "Y300")
+ }
},
{ }
};
diff --git a/linux/drivers/media/video/gspca/ov519.c b/linux/drivers/media/video/gspca/ov519.c
index bd70e9adb..cde3a0177 100644
--- a/linux/drivers/media/video/gspca/ov519.c
+++ b/linux/drivers/media/video/gspca/ov519.c
@@ -50,6 +50,19 @@ static int i2c_detect_tries = 10;
struct sd {
struct gspca_dev gspca_dev; /* !! must be the first item */
+ __u8 packet_nr;
+
+ char bridge;
+#define BRIDGE_OV511 0
+#define BRIDGE_OV511PLUS 1
+#define BRIDGE_OV518 2
+#define BRIDGE_OV518PLUS 3
+#define BRIDGE_OV519 4
+#define BRIDGE_MASK 7
+
+ char invert_led;
+#define BRIDGE_INVERT_LED 8
+
/* Determined by sensor type */
__u8 sif;
@@ -58,22 +71,25 @@ struct sd {
__u8 colors;
__u8 hflip;
__u8 vflip;
+ __u8 autobrightness;
+ __u8 freq;
__u8 stopped; /* Streaming is temporarily paused */
- __u8 frame_rate; /* current Framerate (OV519 only) */
- __u8 clockdiv; /* clockdiv override for OV519 only */
+ __u8 frame_rate; /* current Framerate */
+ __u8 clockdiv; /* clockdiv override */
char sensor; /* Type of image sensor chip (SEN_*) */
#define SEN_UNKNOWN 0
#define SEN_OV6620 1
#define SEN_OV6630 2
-#define SEN_OV7610 3
-#define SEN_OV7620 4
-#define SEN_OV7640 5
-#define SEN_OV7670 6
-#define SEN_OV76BE 7
-#define SEN_OV8610 8
+#define SEN_OV66308AF 3
+#define SEN_OV7610 4
+#define SEN_OV7620 5
+#define SEN_OV7640 6
+#define SEN_OV7670 7
+#define SEN_OV76BE 8
+#define SEN_OV8610 9
};
/* V4L2 controls supported by the driver */
@@ -87,8 +103,17 @@ static int sd_sethflip(struct gspca_dev *gspca_dev, __s32 val);
static int sd_gethflip(struct gspca_dev *gspca_dev, __s32 *val);
static int sd_setvflip(struct gspca_dev *gspca_dev, __s32 val);
static int sd_getvflip(struct gspca_dev *gspca_dev, __s32 *val);
-
-static struct ctrl sd_ctrls[] = {
+static int sd_setautobrightness(struct gspca_dev *gspca_dev, __s32 val);
+static int sd_getautobrightness(struct gspca_dev *gspca_dev, __s32 *val);
+static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val);
+static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val);
+static void setbrightness(struct gspca_dev *gspca_dev);
+static void setcontrast(struct gspca_dev *gspca_dev);
+static void setcolors(struct gspca_dev *gspca_dev);
+static void setautobrightness(struct sd *sd);
+static void setfreq(struct sd *sd);
+
+static const struct ctrl sd_ctrls[] = {
{
{
.id = V4L2_CID_BRIGHTNESS,
@@ -131,7 +156,7 @@ static struct ctrl sd_ctrls[] = {
.set = sd_setcolors,
.get = sd_getcolors,
},
-/* next controls work with ov7670 only */
+/* The flip controls work with ov7670 only */
#define HFLIP_IDX 3
{
{
@@ -162,9 +187,54 @@ static struct ctrl sd_ctrls[] = {
.set = sd_setvflip,
.get = sd_getvflip,
},
+#define AUTOBRIGHT_IDX 5
+ {
+ {
+ .id = V4L2_CID_AUTOBRIGHTNESS,
+ .type = V4L2_CTRL_TYPE_BOOLEAN,
+ .name = "Auto Brightness",
+ .minimum = 0,
+ .maximum = 1,
+ .step = 1,
+#define AUTOBRIGHT_DEF 1
+ .default_value = AUTOBRIGHT_DEF,
+ },
+ .set = sd_setautobrightness,
+ .get = sd_getautobrightness,
+ },
+#define FREQ_IDX 6
+ {
+ {
+ .id = V4L2_CID_POWER_LINE_FREQUENCY,
+ .type = V4L2_CTRL_TYPE_MENU,
+ .name = "Light frequency filter",
+ .minimum = 0,
+ .maximum = 2, /* 0: 0, 1: 50Hz, 2:60Hz */
+ .step = 1,
+#define FREQ_DEF 0
+ .default_value = FREQ_DEF,
+ },
+ .set = sd_setfreq,
+ .get = sd_getfreq,
+ },
+#define OV7670_FREQ_IDX 7
+ {
+ {
+ .id = V4L2_CID_POWER_LINE_FREQUENCY,
+ .type = V4L2_CTRL_TYPE_MENU,
+ .name = "Light frequency filter",
+ .minimum = 0,
+ .maximum = 3, /* 0: 0, 1: 50Hz, 2:60Hz 3: Auto Hz */
+ .step = 1,
+#define OV7670_FREQ_DEF 3
+ .default_value = OV7670_FREQ_DEF,
+ },
+ .set = sd_setfreq,
+ .get = sd_getfreq,
+ },
};
-static const struct v4l2_pix_format vga_mode[] = {
+static const struct v4l2_pix_format ov519_vga_mode[] = {
{320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
.bytesperline = 320,
.sizeimage = 320 * 240 * 3 / 8 + 590,
@@ -176,12 +246,22 @@ static const struct v4l2_pix_format vga_mode[] = {
.colorspace = V4L2_COLORSPACE_JPEG,
.priv = 0},
};
-static const struct v4l2_pix_format sif_mode[] = {
+static const struct v4l2_pix_format ov519_sif_mode[] = {
+ {160, 120, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
+ .bytesperline = 160,
+ .sizeimage = 160 * 120 * 3 / 8 + 590,
+ .colorspace = V4L2_COLORSPACE_JPEG,
+ .priv = 3},
{176, 144, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
.bytesperline = 176,
.sizeimage = 176 * 144 * 3 / 8 + 590,
.colorspace = V4L2_COLORSPACE_JPEG,
.priv = 1},
+ {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
+ .bytesperline = 320,
+ .sizeimage = 320 * 240 * 3 / 8 + 590,
+ .colorspace = V4L2_COLORSPACE_JPEG,
+ .priv = 2},
{352, 288, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
.bytesperline = 352,
.sizeimage = 352 * 288 * 3 / 8 + 590,
@@ -189,6 +269,123 @@ static const struct v4l2_pix_format sif_mode[] = {
.priv = 0},
};
+/* Note some of the sizeimage values for the ov511 / ov518 may seem
+ larger then necessary, however they need to be this big as the ov511 /
+ ov518 always fills the entire isoc frame, using 0 padding bytes when
+ it doesn't have any data. So with low framerates the amount of data
+ transfered can become quite large (libv4l will remove all the 0 padding
+ in userspace). */
+static const struct v4l2_pix_format ov518_vga_mode[] = {
+ {320, 240, V4L2_PIX_FMT_OV518, V4L2_FIELD_NONE,
+ .bytesperline = 320,
+ .sizeimage = 320 * 240 * 3,
+ .colorspace = V4L2_COLORSPACE_JPEG,
+ .priv = 1},
+ {640, 480, V4L2_PIX_FMT_OV518, V4L2_FIELD_NONE,
+ .bytesperline = 640,
+ .sizeimage = 640 * 480 * 2,
+ .colorspace = V4L2_COLORSPACE_JPEG,
+ .priv = 0},
+};
+static const struct v4l2_pix_format ov518_sif_mode[] = {
+ {160, 120, V4L2_PIX_FMT_OV518, V4L2_FIELD_NONE,
+ .bytesperline = 160,
+ .sizeimage = 70000,
+ .colorspace = V4L2_COLORSPACE_JPEG,
+ .priv = 3},
+ {176, 144, V4L2_PIX_FMT_OV518, V4L2_FIELD_NONE,
+ .bytesperline = 176,
+ .sizeimage = 70000,
+ .colorspace = V4L2_COLORSPACE_JPEG,
+ .priv = 1},
+ {320, 240, V4L2_PIX_FMT_OV518, V4L2_FIELD_NONE,
+ .bytesperline = 320,
+ .sizeimage = 320 * 240 * 3,
+ .colorspace = V4L2_COLORSPACE_JPEG,
+ .priv = 2},
+ {352, 288, V4L2_PIX_FMT_OV518, V4L2_FIELD_NONE,
+ .bytesperline = 352,
+ .sizeimage = 352 * 288 * 3,
+ .colorspace = V4L2_COLORSPACE_JPEG,
+ .priv = 0},
+};
+
+static const struct v4l2_pix_format ov511_vga_mode[] = {
+ {320, 240, V4L2_PIX_FMT_OV511, V4L2_FIELD_NONE,
+ .bytesperline = 320,
+ .sizeimage = 320 * 240 * 3,
+ .colorspace = V4L2_COLORSPACE_JPEG,
+ .priv = 1},
+ {640, 480, V4L2_PIX_FMT_OV511, V4L2_FIELD_NONE,
+ .bytesperline = 640,
+ .sizeimage = 640 * 480 * 2,
+ .colorspace = V4L2_COLORSPACE_JPEG,
+ .priv = 0},
+};
+static const struct v4l2_pix_format ov511_sif_mode[] = {
+ {160, 120, V4L2_PIX_FMT_OV511, V4L2_FIELD_NONE,
+ .bytesperline = 160,
+ .sizeimage = 70000,
+ .colorspace = V4L2_COLORSPACE_JPEG,
+ .priv = 3},
+ {176, 144, V4L2_PIX_FMT_OV511, V4L2_FIELD_NONE,
+ .bytesperline = 176,
+ .sizeimage = 70000,
+ .colorspace = V4L2_COLORSPACE_JPEG,
+ .priv = 1},
+ {320, 240, V4L2_PIX_FMT_OV511, V4L2_FIELD_NONE,
+ .bytesperline = 320,
+ .sizeimage = 320 * 240 * 3,
+ .colorspace = V4L2_COLORSPACE_JPEG,
+ .priv = 2},
+ {352, 288, V4L2_PIX_FMT_OV511, V4L2_FIELD_NONE,
+ .bytesperline = 352,
+ .sizeimage = 352 * 288 * 3,
+ .colorspace = V4L2_COLORSPACE_JPEG,
+ .priv = 0},
+};
+
+/* Registers common to OV511 / OV518 */
+#define R51x_FIFO_PSIZE 0x30 /* 2 bytes wide w/ OV518(+) */
+#define R51x_SYS_RESET 0x50
+ /* Reset type flags */
+ #define OV511_RESET_OMNICE 0x08
+#define R51x_SYS_INIT 0x53
+#define R51x_SYS_SNAP 0x52
+#define R51x_SYS_CUST_ID 0x5F
+#define R51x_COMP_LUT_BEGIN 0x80
+
+/* OV511 Camera interface register numbers */
+#define R511_CAM_DELAY 0x10
+#define R511_CAM_EDGE 0x11
+#define R511_CAM_PXCNT 0x12
+#define R511_CAM_LNCNT 0x13
+#define R511_CAM_PXDIV 0x14
+#define R511_CAM_LNDIV 0x15
+#define R511_CAM_UV_EN 0x16
+#define R511_CAM_LINE_MODE 0x17
+#define R511_CAM_OPTS 0x18
+
+#define R511_SNAP_FRAME 0x19
+#define R511_SNAP_PXCNT 0x1A
+#define R511_SNAP_LNCNT 0x1B
+#define R511_SNAP_PXDIV 0x1C
+#define R511_SNAP_LNDIV 0x1D
+#define R511_SNAP_UV_EN 0x1E
+#define R511_SNAP_UV_EN 0x1E
+#define R511_SNAP_OPTS 0x1F
+
+#define R511_DRAM_FLOW_CTL 0x20
+#define R511_FIFO_OPTS 0x31
+#define R511_I2C_CTL 0x40
+#define R511_SYS_LED_CTL 0x55 /* OV511+ only */
+#define R511_COMP_EN 0x78
+#define R511_COMP_LUT_EN 0x79
+
+/* OV518 Camera interface register numbers */
+#define R518_GPIO_OUT 0x56 /* OV518(+) only */
+#define R518_GPIO_CTL 0x57 /* OV518(+) only */
+
/* OV519 Camera interface register numbers */
#define OV519_R10_H_SIZE 0x10
#define OV519_R11_V_SIZE 0x11
@@ -224,6 +421,8 @@ static const struct v4l2_pix_format sif_mode[] = {
/* OV7610 registers */
#define OV7610_REG_GAIN 0x00 /* gain setting (5:0) */
+#define OV7610_REG_BLUE 0x01 /* blue channel balance */
+#define OV7610_REG_RED 0x02 /* red channel balance */
#define OV7610_REG_SAT 0x03 /* saturation */
#define OV8610_REG_HUE 0x04 /* 04 reserved */
#define OV7610_REG_CNT 0x05 /* Y contrast */
@@ -330,7 +529,7 @@ static const struct ov_i2c_regvals norm_6x20[] = {
{ 0x28, 0x05 },
{ 0x2a, 0x04 }, /* Disable framerate adjust */
/* { 0x2b, 0xac }, * Framerate; Set 2a[7] first */
- { 0x2d, 0x99 },
+ { 0x2d, 0x85 },
{ 0x33, 0xa0 }, /* Color Processing Parameter */
{ 0x34, 0xd2 }, /* Max A/D range */
{ 0x38, 0x8b },
@@ -363,7 +562,7 @@ static const struct ov_i2c_regvals norm_6x30[] = {
{ 0x07, 0x2d }, /* Sharpness */
{ 0x0c, 0x20 },
{ 0x0d, 0x20 },
- { 0x0e, 0x20 },
+ { 0x0e, 0xa0 }, /* Was 0x20, bit7 enables a 2x gain which we need */
{ 0x0f, 0x05 },
{ 0x10, 0x9a },
{ 0x11, 0x00 }, /* Pixel clock = fastest */
@@ -505,7 +704,7 @@ static const struct ov_i2c_regvals norm_7620[] = {
{ 0x23, 0x00 },
{ 0x26, 0xa2 },
{ 0x27, 0xea },
- { 0x28, 0x20 },
+ { 0x28, 0x22 }, /* Was 0x20, bit1 enables a 2x gain which we need */
{ 0x29, 0x00 },
{ 0x2a, 0x10 },
{ 0x2b, 0x00 },
@@ -846,11 +1045,12 @@ static unsigned char ov7670_abs_to_sm(unsigned char v)
static int reg_w(struct sd *sd, __u16 index, __u8 value)
{
int ret;
+ int req = (sd->bridge <= BRIDGE_OV511PLUS) ? 2 : 1;
sd->gspca_dev.usb_buf[0] = value;
ret = usb_control_msg(sd->gspca_dev.dev,
usb_sndctrlpipe(sd->gspca_dev.dev, 0),
- 1, /* REQ_IO (ov518/519) */
+ req,
USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
0, index,
sd->gspca_dev.usb_buf, 1, 500);
@@ -864,10 +1064,11 @@ static int reg_w(struct sd *sd, __u16 index, __u8 value)
static int reg_r(struct sd *sd, __u16 index)
{
int ret;
+ int req = (sd->bridge <= BRIDGE_OV511PLUS) ? 3 : 1;
ret = usb_control_msg(sd->gspca_dev.dev,
usb_rcvctrlpipe(sd->gspca_dev.dev, 0),
- 1, /* REQ_IO */
+ req,
USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
0, index, sd->gspca_dev.usb_buf, 1, 500);
@@ -924,11 +1125,152 @@ static int reg_w_mask(struct sd *sd,
}
/*
+ * Writes multiple (n) byte value to a single register. Only valid with certain
+ * registers (0x30 and 0xc4 - 0xce).
+ */
+static int ov518_reg_w32(struct sd *sd, __u16 index, u32 value, int n)
+{
+ int ret;
+
+ *((u32 *)sd->gspca_dev.usb_buf) = __cpu_to_le32(value);
+
+ ret = usb_control_msg(sd->gspca_dev.dev,
+ usb_sndctrlpipe(sd->gspca_dev.dev, 0),
+ 1 /* REG_IO */,
+ USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+ 0, index,
+ sd->gspca_dev.usb_buf, n, 500);
+ if (ret < 0)
+ PDEBUG(D_ERR, "Write reg32 [%02x] %08x failed", index, value);
+ return ret;
+}
+
+static int ov511_i2c_w(struct sd *sd, __u8 reg, __u8 value)
+{
+ int rc, retries;
+
+ PDEBUG(D_USBO, "i2c 0x%02x -> [0x%02x]", value, reg);
+
+ /* Three byte write cycle */
+ for (retries = 6; ; ) {
+ /* Select camera register */
+ rc = reg_w(sd, R51x_I2C_SADDR_3, reg);
+ if (rc < 0)
+ return rc;
+
+ /* Write "value" to I2C data port of OV511 */
+ rc = reg_w(sd, R51x_I2C_DATA, value);
+ if (rc < 0)
+ return rc;
+
+ /* Initiate 3-byte write cycle */
+ rc = reg_w(sd, R511_I2C_CTL, 0x01);
+ if (rc < 0)
+ return rc;
+
+ do
+ rc = reg_r(sd, R511_I2C_CTL);
+ while (rc > 0 && ((rc & 1) == 0)); /* Retry until idle */
+
+ if (rc < 0)
+ return rc;
+
+ if ((rc & 2) == 0) /* Ack? */
+ break;
+#if 0
+ /* I2C abort */
+ reg_w(sd, R511_I2C_CTL, 0x10);
+#endif
+ if (--retries < 0) {
+ PDEBUG(D_USBO, "i2c write retries exhausted");
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+static int ov511_i2c_r(struct sd *sd, __u8 reg)
+{
+ int rc, value, retries;
+
+ /* Two byte write cycle */
+ for (retries = 6; ; ) {
+ /* Select camera register */
+ rc = reg_w(sd, R51x_I2C_SADDR_2, reg);
+ if (rc < 0)
+ return rc;
+
+ /* Initiate 2-byte write cycle */
+ rc = reg_w(sd, R511_I2C_CTL, 0x03);
+ if (rc < 0)
+ return rc;
+
+ do
+ rc = reg_r(sd, R511_I2C_CTL);
+ while (rc > 0 && ((rc & 1) == 0)); /* Retry until idle */
+
+ if (rc < 0)
+ return rc;
+
+ if ((rc & 2) == 0) /* Ack? */
+ break;
+
+ /* I2C abort */
+ reg_w(sd, R511_I2C_CTL, 0x10);
+
+ if (--retries < 0) {
+ PDEBUG(D_USBI, "i2c write retries exhausted");
+ return -1;
+ }
+ }
+
+ /* Two byte read cycle */
+ for (retries = 6; ; ) {
+ /* Initiate 2-byte read cycle */
+ rc = reg_w(sd, R511_I2C_CTL, 0x05);
+ if (rc < 0)
+ return rc;
+
+ do
+ rc = reg_r(sd, R511_I2C_CTL);
+ while (rc > 0 && ((rc & 1) == 0)); /* Retry until idle */
+
+ if (rc < 0)
+ return rc;
+
+ if ((rc & 2) == 0) /* Ack? */
+ break;
+
+ /* I2C abort */
+ rc = reg_w(sd, R511_I2C_CTL, 0x10);
+ if (rc < 0)
+ return rc;
+
+ if (--retries < 0) {
+ PDEBUG(D_USBI, "i2c read retries exhausted");
+ return -1;
+ }
+ }
+
+ value = reg_r(sd, R51x_I2C_DATA);
+
+ PDEBUG(D_USBI, "i2c [0x%02X] -> 0x%02X", reg, value);
+
+ /* This is needed to make i2c_w() work */
+ rc = reg_w(sd, R511_I2C_CTL, 0x05);
+ if (rc < 0)
+ return rc;
+
+ return value;
+}
+
+/*
* The OV518 I2C I/O procedure is different, hence, this function.
* This is normally only called from i2c_w(). Note that this function
* always succeeds regardless of whether the sensor is present and working.
*/
-static int i2c_w(struct sd *sd,
+static int ov518_i2c_w(struct sd *sd,
__u8 reg,
__u8 value)
{
@@ -963,7 +1305,7 @@ static int i2c_w(struct sd *sd,
* This is normally only called from i2c_r(). Note that this function
* always succeeds regardless of whether the sensor is present and working.
*/
-static int i2c_r(struct sd *sd, __u8 reg)
+static int ov518_i2c_r(struct sd *sd, __u8 reg)
{
int rc, value;
@@ -986,6 +1328,34 @@ static int i2c_r(struct sd *sd, __u8 reg)
return value;
}
+static int i2c_w(struct sd *sd, __u8 reg, __u8 value)
+{
+ switch (sd->bridge) {
+ case BRIDGE_OV511:
+ case BRIDGE_OV511PLUS:
+ return ov511_i2c_w(sd, reg, value);
+ case BRIDGE_OV518:
+ case BRIDGE_OV518PLUS:
+ case BRIDGE_OV519:
+ return ov518_i2c_w(sd, reg, value);
+ }
+ return -1; /* Should never happen */
+}
+
+static int i2c_r(struct sd *sd, __u8 reg)
+{
+ switch (sd->bridge) {
+ case BRIDGE_OV511:
+ case BRIDGE_OV511PLUS:
+ return ov511_i2c_r(sd, reg);
+ case BRIDGE_OV518:
+ case BRIDGE_OV518PLUS:
+ case BRIDGE_OV519:
+ return ov518_i2c_r(sd, reg);
+ }
+ return -1; /* Should never happen */
+}
+
/* Writes bits at positions specified by mask to an I2C reg. Bits that are in
* the same position as 1's in "mask" are cleared and set to "value". Bits
* that are in the same position as 0's in "mask" are preserved, regardless
@@ -1014,20 +1384,47 @@ static inline int ov51x_stop(struct sd *sd)
{
PDEBUG(D_STREAM, "stopping");
sd->stopped = 1;
- return reg_w(sd, OV519_SYS_RESET1, 0x0f);
+ switch (sd->bridge) {
+ case BRIDGE_OV511:
+ case BRIDGE_OV511PLUS:
+ return reg_w(sd, R51x_SYS_RESET, 0x3d);
+ case BRIDGE_OV518:
+ case BRIDGE_OV518PLUS:
+ return reg_w_mask(sd, R51x_SYS_RESET, 0x3a, 0x3a);
+ case BRIDGE_OV519:
+ return reg_w(sd, OV519_SYS_RESET1, 0x0f);
+ }
+
+ return 0;
}
/* Restarts OV511 after ov511_stop() is called. Has no effect if it is not
* actually stopped (for performance). */
static inline int ov51x_restart(struct sd *sd)
{
+ int rc;
+
PDEBUG(D_STREAM, "restarting");
if (!sd->stopped)
return 0;
sd->stopped = 0;
/* Reinitialize the stream */
- return reg_w(sd, OV519_SYS_RESET1, 0x00);
+ switch (sd->bridge) {
+ case BRIDGE_OV511:
+ case BRIDGE_OV511PLUS:
+ return reg_w(sd, R51x_SYS_RESET, 0x00);
+ case BRIDGE_OV518:
+ case BRIDGE_OV518PLUS:
+ rc = reg_w(sd, 0x2f, 0x80);
+ if (rc < 0)
+ return rc;
+ return reg_w(sd, R51x_SYS_RESET, 0x00);
+ case BRIDGE_OV519:
+ return reg_w(sd, OV519_SYS_RESET1, 0x00);
+ }
+
+ return 0;
}
/* This does an initial reset of an OmniVision sensor and ensures that I2C
@@ -1138,7 +1535,6 @@ static int ov8xx0_configure(struct sd *sd)
}
/* Set sensor-specific vars */
-/* sd->sif = 0; already done */
return 0;
}
@@ -1175,15 +1571,13 @@ static int ov7xx0_configure(struct sd *sd)
}
} else if ((rc & 3) == 1) {
/* I don't know what's different about the 76BE yet. */
- if (i2c_r(sd, 0x15) & 1)
+ if (i2c_r(sd, 0x15) & 1) {
PDEBUG(D_PROBE, "Sensor is an OV7620AE");
- else
+ sd->sensor = SEN_OV7620;
+ } else {
PDEBUG(D_PROBE, "Sensor is an OV76BE");
-
- /* OV511+ will return all zero isoc data unless we
- * configure the sensor as a 7620. Someone needs to
- * find the exact reg. setting that causes this. */
- sd->sensor = SEN_OV76BE;
+ sd->sensor = SEN_OV76BE;
+ }
} else if ((rc & 3) == 0) {
/* try to read product id registers */
high = i2c_r(sd, 0x0a);
@@ -1229,7 +1623,6 @@ static int ov7xx0_configure(struct sd *sd)
}
/* Set sensor-specific vars */
-/* sd->sif = 0; already done */
return 0;
}
@@ -1258,13 +1651,14 @@ static int ov6xx0_configure(struct sd *sd)
break;
case 0x01:
sd->sensor = SEN_OV6620;
+ PDEBUG(D_PROBE, "Sensor is an OV6620");
break;
case 0x02:
sd->sensor = SEN_OV6630;
PDEBUG(D_PROBE, "Sensor is an OV66308AE");
break;
case 0x03:
- sd->sensor = SEN_OV6630;
+ sd->sensor = SEN_OV66308AF;
PDEBUG(D_PROBE, "Sensor is an OV66308AF");
break;
case 0x90:
@@ -1287,16 +1681,276 @@ static int ov6xx0_configure(struct sd *sd)
/* Turns on or off the LED. Only has an effect with OV511+/OV518(+)/OV519 */
static void ov51x_led_control(struct sd *sd, int on)
{
- reg_w_mask(sd, OV519_GPIO_DATA_OUT0, !on, 1); /* 0 / 1 */
+ if (sd->invert_led)
+ on = !on;
+
+ switch (sd->bridge) {
+ /* OV511 has no LED control */
+ case BRIDGE_OV511PLUS:
+ reg_w(sd, R511_SYS_LED_CTL, on ? 1 : 0);
+ break;
+ case BRIDGE_OV518:
+ case BRIDGE_OV518PLUS:
+ reg_w_mask(sd, R518_GPIO_OUT, on ? 0x02 : 0x00, 0x02);
+ break;
+ case BRIDGE_OV519:
+ reg_w_mask(sd, OV519_GPIO_DATA_OUT0, !on, 1); /* 0 / 1 */
+ break;
+ }
}
-/* this function is called at probe time */
-static int sd_config(struct gspca_dev *gspca_dev,
- const struct usb_device_id *id)
+static int ov51x_upload_quan_tables(struct sd *sd)
+{
+ const unsigned char yQuanTable511[] = {
+ 0, 1, 1, 2, 2, 3, 3, 4,
+ 1, 1, 1, 2, 2, 3, 4, 4,
+ 1, 1, 2, 2, 3, 4, 4, 4,
+ 2, 2, 2, 3, 4, 4, 4, 4,
+ 2, 2, 3, 4, 4, 5, 5, 5,
+ 3, 3, 4, 4, 5, 5, 5, 5,
+ 3, 4, 4, 4, 5, 5, 5, 5,
+ 4, 4, 4, 4, 5, 5, 5, 5
+ };
+
+ const unsigned char uvQuanTable511[] = {
+ 0, 2, 2, 3, 4, 4, 4, 4,
+ 2, 2, 2, 4, 4, 4, 4, 4,
+ 2, 2, 3, 4, 4, 4, 4, 4,
+ 3, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4
+ };
+
+ /* OV518 quantization tables are 8x4 (instead of 8x8) */
+ const unsigned char yQuanTable518[] = {
+ 5, 4, 5, 6, 6, 7, 7, 7,
+ 5, 5, 5, 5, 6, 7, 7, 7,
+ 6, 6, 6, 6, 7, 7, 7, 8,
+ 7, 7, 6, 7, 7, 7, 8, 8
+ };
+
+ const unsigned char uvQuanTable518[] = {
+ 6, 6, 6, 7, 7, 7, 7, 7,
+ 6, 6, 6, 7, 7, 7, 7, 7,
+ 6, 6, 6, 7, 7, 7, 7, 8,
+ 7, 7, 7, 7, 7, 7, 8, 8
+ };
+
+ const unsigned char *pYTable, *pUVTable;
+ unsigned char val0, val1;
+ int i, size, rc, reg = R51x_COMP_LUT_BEGIN;
+
+ PDEBUG(D_PROBE, "Uploading quantization tables");
+
+ if (sd->bridge == BRIDGE_OV511 || sd->bridge == BRIDGE_OV511PLUS) {
+ pYTable = yQuanTable511;
+ pUVTable = uvQuanTable511;
+ size = 32;
+ } else {
+ pYTable = yQuanTable518;
+ pUVTable = uvQuanTable518;
+ size = 16;
+ }
+
+ for (i = 0; i < size; i++) {
+ val0 = *pYTable++;
+ val1 = *pYTable++;
+ val0 &= 0x0f;
+ val1 &= 0x0f;
+ val0 |= val1 << 4;
+ rc = reg_w(sd, reg, val0);
+ if (rc < 0)
+ return rc;
+
+ val0 = *pUVTable++;
+ val1 = *pUVTable++;
+ val0 &= 0x0f;
+ val1 &= 0x0f;
+ val0 |= val1 << 4;
+ rc = reg_w(sd, reg + size, val0);
+ if (rc < 0)
+ return rc;
+
+ reg++;
+ }
+
+ return 0;
+}
+
+/* This initializes the OV511/OV511+ and the sensor */
+static int ov511_configure(struct gspca_dev *gspca_dev)
{
struct sd *sd = (struct sd *) gspca_dev;
- struct cam *cam;
+ int rc;
+
+ /* For 511 and 511+ */
+ const struct ov_regvals init_511[] = {
+ { R51x_SYS_RESET, 0x7f },
+ { R51x_SYS_INIT, 0x01 },
+ { R51x_SYS_RESET, 0x7f },
+ { R51x_SYS_INIT, 0x01 },
+ { R51x_SYS_RESET, 0x3f },
+ { R51x_SYS_INIT, 0x01 },
+ { R51x_SYS_RESET, 0x3d },
+ };
+
+ const struct ov_regvals norm_511[] = {
+ { R511_DRAM_FLOW_CTL, 0x01 },
+ { R51x_SYS_SNAP, 0x00 },
+ { R51x_SYS_SNAP, 0x02 },
+ { R51x_SYS_SNAP, 0x00 },
+ { R511_FIFO_OPTS, 0x1f },
+ { R511_COMP_EN, 0x00 },
+ { R511_COMP_LUT_EN, 0x03 },
+ };
+
+ const struct ov_regvals norm_511_p[] = {
+ { R511_DRAM_FLOW_CTL, 0xff },
+ { R51x_SYS_SNAP, 0x00 },
+ { R51x_SYS_SNAP, 0x02 },
+ { R51x_SYS_SNAP, 0x00 },
+ { R511_FIFO_OPTS, 0xff },
+ { R511_COMP_EN, 0x00 },
+ { R511_COMP_LUT_EN, 0x03 },
+ };
+
+ const struct ov_regvals compress_511[] = {
+ { 0x70, 0x1f },
+ { 0x71, 0x05 },
+ { 0x72, 0x06 },
+ { 0x73, 0x06 },
+ { 0x74, 0x14 },
+ { 0x75, 0x03 },
+ { 0x76, 0x04 },
+ { 0x77, 0x04 },
+ };
+
+ PDEBUG(D_PROBE, "Device custom id %x", reg_r(sd, R51x_SYS_CUST_ID));
+
+ rc = write_regvals(sd, init_511, ARRAY_SIZE(init_511));
+ if (rc < 0)
+ return rc;
+
+ switch (sd->bridge) {
+ case BRIDGE_OV511:
+ rc = write_regvals(sd, norm_511, ARRAY_SIZE(norm_511));
+ if (rc < 0)
+ return rc;
+ break;
+ case BRIDGE_OV511PLUS:
+ rc = write_regvals(sd, norm_511_p, ARRAY_SIZE(norm_511_p));
+ if (rc < 0)
+ return rc;
+ break;
+ }
+
+ /* Init compression */
+ rc = write_regvals(sd, compress_511, ARRAY_SIZE(compress_511));
+ if (rc < 0)
+ return rc;
+
+ rc = ov51x_upload_quan_tables(sd);
+ if (rc < 0) {
+ PDEBUG(D_ERR, "Error uploading quantization tables");
+ return rc;
+ }
+
+ return 0;
+}
+
+/* This initializes the OV518/OV518+ and the sensor */
+static int ov518_configure(struct gspca_dev *gspca_dev)
+{
+ struct sd *sd = (struct sd *) gspca_dev;
+ int rc;
+
+ /* For 518 and 518+ */
+ const struct ov_regvals init_518[] = {
+ { R51x_SYS_RESET, 0x40 },
+ { R51x_SYS_INIT, 0xe1 },
+ { R51x_SYS_RESET, 0x3e },
+ { R51x_SYS_INIT, 0xe1 },
+ { R51x_SYS_RESET, 0x00 },
+ { R51x_SYS_INIT, 0xe1 },
+ { 0x46, 0x00 },
+ { 0x5d, 0x03 },
+ };
+
+ const struct ov_regvals norm_518[] = {
+ { R51x_SYS_SNAP, 0x02 }, /* Reset */
+ { R51x_SYS_SNAP, 0x01 }, /* Enable */
+ { 0x31, 0x0f },
+ { 0x5d, 0x03 },
+ { 0x24, 0x9f },
+ { 0x25, 0x90 },
+ { 0x20, 0x00 },
+ { 0x51, 0x04 },
+ { 0x71, 0x19 },
+ { 0x2f, 0x80 },
+ };
+
+ const struct ov_regvals norm_518_p[] = {
+ { R51x_SYS_SNAP, 0x02 }, /* Reset */
+ { R51x_SYS_SNAP, 0x01 }, /* Enable */
+ { 0x31, 0x0f },
+ { 0x5d, 0x03 },
+ { 0x24, 0x9f },
+ { 0x25, 0x90 },
+ { 0x20, 0x60 },
+ { 0x51, 0x02 },
+ { 0x71, 0x19 },
+ { 0x40, 0xff },
+ { 0x41, 0x42 },
+ { 0x46, 0x00 },
+ { 0x33, 0x04 },
+ { 0x21, 0x19 },
+ { 0x3f, 0x10 },
+ { 0x2f, 0x80 },
+ };
+
+ /* First 5 bits of custom ID reg are a revision ID on OV518 */
+ PDEBUG(D_PROBE, "Device revision %d",
+ 0x1F & reg_r(sd, R51x_SYS_CUST_ID));
+
+ rc = write_regvals(sd, init_518, ARRAY_SIZE(init_518));
+ if (rc < 0)
+ return rc;
+
+ /* Set LED GPIO pin to output mode */
+ rc = reg_w_mask(sd, R518_GPIO_CTL, 0x00, 0x02);
+ if (rc < 0)
+ return rc;
+
+ switch (sd->bridge) {
+ case BRIDGE_OV518:
+ rc = write_regvals(sd, norm_518, ARRAY_SIZE(norm_518));
+ if (rc < 0)
+ return rc;
+ break;
+ case BRIDGE_OV518PLUS:
+ rc = write_regvals(sd, norm_518_p, ARRAY_SIZE(norm_518_p));
+ if (rc < 0)
+ return rc;
+ break;
+ }
+ rc = ov51x_upload_quan_tables(sd);
+ if (rc < 0) {
+ PDEBUG(D_ERR, "Error uploading quantization tables");
+ return rc;
+ }
+
+ rc = reg_w(sd, 0x2f, 0x80);
+ if (rc < 0)
+ return rc;
+
+ return 0;
+}
+
+static int ov519_configure(struct sd *sd)
+{
static const struct ov_regvals init_519[] = {
{ 0x5a, 0x6d }, /* EnableSystem */
{ 0x53, 0x9b },
@@ -1313,8 +1967,37 @@ static int sd_config(struct gspca_dev *gspca_dev,
/* windows reads 0x55 at this point*/
};
- if (write_regvals(sd, init_519, ARRAY_SIZE(init_519)))
+ return write_regvals(sd, init_519, ARRAY_SIZE(init_519));
+}
+
+/* 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;
+ int ret = 0;
+
+ sd->bridge = id->driver_info & BRIDGE_MASK;
+ sd->invert_led = id->driver_info & BRIDGE_INVERT_LED;
+
+ switch (sd->bridge) {
+ case BRIDGE_OV511:
+ case BRIDGE_OV511PLUS:
+ ret = ov511_configure(gspca_dev);
+ break;
+ case BRIDGE_OV518:
+ case BRIDGE_OV518PLUS:
+ ret = ov518_configure(gspca_dev);
+ break;
+ case BRIDGE_OV519:
+ ret = ov519_configure(sd);
+ break;
+ }
+
+ if (ret)
goto error;
+
ov51x_led_control(sd, 0); /* turn LED off */
/* Test for 76xx */
@@ -1360,21 +2043,60 @@ static int sd_config(struct gspca_dev *gspca_dev,
}
cam = &gspca_dev->cam;
- if (!sd->sif) {
- cam->cam_mode = vga_mode;
- cam->nmodes = ARRAY_SIZE(vga_mode);
- } else {
- cam->cam_mode = sif_mode;
- cam->nmodes = ARRAY_SIZE(sif_mode);
+ switch (sd->bridge) {
+ case BRIDGE_OV511:
+ case BRIDGE_OV511PLUS:
+ if (!sd->sif) {
+ cam->cam_mode = ov511_vga_mode;
+ cam->nmodes = ARRAY_SIZE(ov511_vga_mode);
+ } else {
+ cam->cam_mode = ov511_sif_mode;
+ cam->nmodes = ARRAY_SIZE(ov511_sif_mode);
+ }
+ break;
+ case BRIDGE_OV518:
+ case BRIDGE_OV518PLUS:
+ if (!sd->sif) {
+ cam->cam_mode = ov518_vga_mode;
+ cam->nmodes = ARRAY_SIZE(ov518_vga_mode);
+ } else {
+ cam->cam_mode = ov518_sif_mode;
+ cam->nmodes = ARRAY_SIZE(ov518_sif_mode);
+ }
+ break;
+ case BRIDGE_OV519:
+ if (!sd->sif) {
+ cam->cam_mode = ov519_vga_mode;
+ cam->nmodes = ARRAY_SIZE(ov519_vga_mode);
+ } else {
+ cam->cam_mode = ov519_sif_mode;
+ cam->nmodes = ARRAY_SIZE(ov519_sif_mode);
+ }
+ break;
}
sd->brightness = BRIGHTNESS_DEF;
- sd->contrast = CONTRAST_DEF;
+ if (sd->sensor == SEN_OV6630 || sd->sensor == SEN_OV66308AF)
+ sd->contrast = 200; /* The default is too low for the ov6630 */
+ else
+ sd->contrast = CONTRAST_DEF;
sd->colors = COLOR_DEF;
sd->hflip = HFLIP_DEF;
sd->vflip = VFLIP_DEF;
- if (sd->sensor != SEN_OV7670)
- gspca_dev->ctrl_dis = (1 << HFLIP_IDX)
- | (1 << VFLIP_IDX);
+ sd->autobrightness = AUTOBRIGHT_DEF;
+ if (sd->sensor == SEN_OV7670) {
+ sd->freq = OV7670_FREQ_DEF;
+ gspca_dev->ctrl_dis = 1 << FREQ_IDX;
+ } else {
+ sd->freq = FREQ_DEF;
+ gspca_dev->ctrl_dis = (1 << HFLIP_IDX) | (1 << VFLIP_IDX) |
+ (1 << OV7670_FREQ_IDX);
+ }
+ if (sd->sensor == SEN_OV7640 || sd->sensor == SEN_OV7670)
+ gspca_dev->ctrl_dis |= 1 << AUTOBRIGHT_IDX;
+ /* OV8610 Frequency filter control should work but needs testing */
+ if (sd->sensor == SEN_OV8610)
+ gspca_dev->ctrl_dis |= 1 << FREQ_IDX;
+
return 0;
error:
PDEBUG(D_ERR, "OV519 Config failed");
@@ -1393,6 +2115,7 @@ static int sd_init(struct gspca_dev *gspca_dev)
return -EIO;
break;
case SEN_OV6630:
+ case SEN_OV66308AF:
if (write_i2c_regvals(sd, norm_6x30, ARRAY_SIZE(norm_6x30)))
return -EIO;
break;
@@ -1401,6 +2124,8 @@ static int sd_init(struct gspca_dev *gspca_dev)
/* case SEN_OV76BE: */
if (write_i2c_regvals(sd, norm_7610, ARRAY_SIZE(norm_7610)))
return -EIO;
+ if (i2c_w_mask(sd, 0x0e, 0x00, 0x40))
+ return -EIO;
break;
case SEN_OV7620:
if (write_i2c_regvals(sd, norm_7620, ARRAY_SIZE(norm_7620)))
@@ -1422,6 +2147,248 @@ static int sd_init(struct gspca_dev *gspca_dev)
return 0;
}
+/* Set up the OV511/OV511+ with the given image parameters.
+ *
+ * Do not put any sensor-specific code in here (including I2C I/O functions)
+ */
+static int ov511_mode_init_regs(struct sd *sd)
+{
+ int hsegs, vsegs, packet_size, fps, needed;
+ int interlaced = 0;
+ struct usb_host_interface *alt;
+ struct usb_interface *intf;
+
+ intf = usb_ifnum_to_if(sd->gspca_dev.dev, sd->gspca_dev.iface);
+ alt = usb_altnum_to_altsetting(intf, sd->gspca_dev.alt);
+ if (!alt) {
+ PDEBUG(D_ERR, "Couldn't get altsetting");
+ return -EIO;
+ }
+
+ packet_size = le16_to_cpu(alt->endpoint[0].desc.wMaxPacketSize);
+ reg_w(sd, R51x_FIFO_PSIZE, packet_size >> 5);
+
+ reg_w(sd, R511_CAM_UV_EN, 0x01);
+ reg_w(sd, R511_SNAP_UV_EN, 0x01);
+ reg_w(sd, R511_SNAP_OPTS, 0x03);
+
+ /* Here I'm assuming that snapshot size == image size.
+ * I hope that's always true. --claudio
+ */
+ hsegs = (sd->gspca_dev.width >> 3) - 1;
+ vsegs = (sd->gspca_dev.height >> 3) - 1;
+
+ reg_w(sd, R511_CAM_PXCNT, hsegs);
+ reg_w(sd, R511_CAM_LNCNT, vsegs);
+ reg_w(sd, R511_CAM_PXDIV, 0x00);
+ reg_w(sd, R511_CAM_LNDIV, 0x00);
+
+ /* YUV420, low pass filter on */
+ reg_w(sd, R511_CAM_OPTS, 0x03);
+
+ /* Snapshot additions */
+ reg_w(sd, R511_SNAP_PXCNT, hsegs);
+ reg_w(sd, R511_SNAP_LNCNT, vsegs);
+ reg_w(sd, R511_SNAP_PXDIV, 0x00);
+ reg_w(sd, R511_SNAP_LNDIV, 0x00);
+
+ /******** Set the framerate ********/
+ if (frame_rate > 0)
+ sd->frame_rate = frame_rate;
+
+ switch (sd->sensor) {
+ case SEN_OV6620:
+ /* No framerate control, doesn't like higher rates yet */
+ sd->clockdiv = 3;
+ break;
+
+ /* Note once the FIXME's in mode_init_ov_sensor_regs() are fixed
+ for more sensors we need to do this for them too */
+ case SEN_OV7620:
+ case SEN_OV7640:
+ case SEN_OV76BE:
+ if (sd->gspca_dev.width == 320)
+ interlaced = 1;
+ /* Fall through */
+ case SEN_OV6630:
+ case SEN_OV7610:
+ case SEN_OV7670:
+ switch (sd->frame_rate) {
+ case 30:
+ case 25:
+ /* Not enough bandwidth to do 640x480 @ 30 fps */
+ if (sd->gspca_dev.width != 640) {
+ sd->clockdiv = 0;
+ break;
+ }
+ /* Fall through for 640x480 case */
+ default:
+/* case 20: */
+/* case 15: */
+ sd->clockdiv = 1;
+ break;
+ case 10:
+ sd->clockdiv = 2;
+ break;
+ case 5:
+ sd->clockdiv = 5;
+ break;
+ }
+ if (interlaced) {
+ sd->clockdiv = (sd->clockdiv + 1) * 2 - 1;
+ /* Higher then 10 does not work */
+ if (sd->clockdiv > 10)
+ sd->clockdiv = 10;
+ }
+ break;
+
+ case SEN_OV8610:
+ /* No framerate control ?? */
+ sd->clockdiv = 0;
+ break;
+ }
+
+ /* Check if we have enough bandwidth to disable compression */
+ fps = (interlaced ? 60 : 30) / (sd->clockdiv + 1) + 1;
+ needed = fps * sd->gspca_dev.width * sd->gspca_dev.height * 3 / 2;
+ /* 1400 is a conservative estimate of the max nr of isoc packets/sec */
+ if (needed > 1400 * packet_size) {
+ /* Enable Y and UV quantization and compression */
+ reg_w(sd, R511_COMP_EN, 0x07);
+ reg_w(sd, R511_COMP_LUT_EN, 0x03);
+ } else {
+ reg_w(sd, R511_COMP_EN, 0x06);
+ reg_w(sd, R511_COMP_LUT_EN, 0x00);
+ }
+
+ reg_w(sd, R51x_SYS_RESET, OV511_RESET_OMNICE);
+ reg_w(sd, R51x_SYS_RESET, 0);
+
+ return 0;
+}
+
+/* Sets up the OV518/OV518+ with the given image parameters
+ *
+ * OV518 needs a completely different approach, until we can figure out what
+ * the individual registers do. Also, only 15 FPS is supported now.
+ *
+ * Do not put any sensor-specific code in here (including I2C I/O functions)
+ */
+static int ov518_mode_init_regs(struct sd *sd)
+{
+ int hsegs, vsegs, packet_size;
+ struct usb_host_interface *alt;
+ struct usb_interface *intf;
+
+ intf = usb_ifnum_to_if(sd->gspca_dev.dev, sd->gspca_dev.iface);
+ alt = usb_altnum_to_altsetting(intf, sd->gspca_dev.alt);
+ if (!alt) {
+ PDEBUG(D_ERR, "Couldn't get altsetting");
+ return -EIO;
+ }
+
+ packet_size = le16_to_cpu(alt->endpoint[0].desc.wMaxPacketSize);
+ ov518_reg_w32(sd, R51x_FIFO_PSIZE, packet_size & ~7, 2);
+
+ /******** Set the mode ********/
+
+ reg_w(sd, 0x2b, 0);
+ reg_w(sd, 0x2c, 0);
+ reg_w(sd, 0x2d, 0);
+ reg_w(sd, 0x2e, 0);
+ reg_w(sd, 0x3b, 0);
+ reg_w(sd, 0x3c, 0);
+ reg_w(sd, 0x3d, 0);
+ reg_w(sd, 0x3e, 0);
+
+ if (sd->bridge == BRIDGE_OV518) {
+ /* Set 8-bit (YVYU) input format */
+ reg_w_mask(sd, 0x20, 0x08, 0x08);
+
+ /* Set 12-bit (4:2:0) output format */
+ reg_w_mask(sd, 0x28, 0x80, 0xf0);
+ reg_w_mask(sd, 0x38, 0x80, 0xf0);
+ } else {
+ reg_w(sd, 0x28, 0x80);
+ reg_w(sd, 0x38, 0x80);
+ }
+
+ hsegs = sd->gspca_dev.width / 16;
+ vsegs = sd->gspca_dev.height / 4;
+
+ reg_w(sd, 0x29, hsegs);
+ reg_w(sd, 0x2a, vsegs);
+
+ reg_w(sd, 0x39, hsegs);
+ reg_w(sd, 0x3a, vsegs);
+
+ /* Windows driver does this here; who knows why */
+ reg_w(sd, 0x2f, 0x80);
+
+ /******** Set the framerate ********/
+ sd->clockdiv = 1;
+
+ /* Mode independent, but framerate dependent, regs */
+ /* 0x51: Clock divider; Only works on some cams which use 2 crystals */
+ reg_w(sd, 0x51, 0x04);
+ reg_w(sd, 0x22, 0x18);
+ reg_w(sd, 0x23, 0xff);
+
+ if (sd->bridge == BRIDGE_OV518PLUS) {
+ switch (sd->sensor) {
+ case SEN_OV7620:
+ if (sd->gspca_dev.width == 320) {
+ reg_w(sd, 0x20, 0x00);
+ reg_w(sd, 0x21, 0x19);
+ } else {
+ reg_w(sd, 0x20, 0x60);
+ reg_w(sd, 0x21, 0x1f);
+ }
+ break;
+ default:
+ reg_w(sd, 0x21, 0x19);
+ }
+ } else
+ reg_w(sd, 0x71, 0x17); /* Compression-related? */
+
+ /* FIXME: Sensor-specific */
+ /* Bit 5 is what matters here. Of course, it is "reserved" */
+ i2c_w(sd, 0x54, 0x23);
+
+ reg_w(sd, 0x2f, 0x80);
+
+ if (sd->bridge == BRIDGE_OV518PLUS) {
+ reg_w(sd, 0x24, 0x94);
+ reg_w(sd, 0x25, 0x90);
+ ov518_reg_w32(sd, 0xc4, 400, 2); /* 190h */
+ ov518_reg_w32(sd, 0xc6, 540, 2); /* 21ch */
+ ov518_reg_w32(sd, 0xc7, 540, 2); /* 21ch */
+ ov518_reg_w32(sd, 0xc8, 108, 2); /* 6ch */
+ ov518_reg_w32(sd, 0xca, 131098, 3); /* 2001ah */
+ ov518_reg_w32(sd, 0xcb, 532, 2); /* 214h */
+ ov518_reg_w32(sd, 0xcc, 2400, 2); /* 960h */
+ ov518_reg_w32(sd, 0xcd, 32, 2); /* 20h */
+ ov518_reg_w32(sd, 0xce, 608, 2); /* 260h */
+ } else {
+ reg_w(sd, 0x24, 0x9f);
+ reg_w(sd, 0x25, 0x90);
+ ov518_reg_w32(sd, 0xc4, 400, 2); /* 190h */
+ ov518_reg_w32(sd, 0xc6, 381, 2); /* 17dh */
+ ov518_reg_w32(sd, 0xc7, 381, 2); /* 17dh */
+ ov518_reg_w32(sd, 0xc8, 128, 2); /* 80h */
+ ov518_reg_w32(sd, 0xca, 183331, 3); /* 2cc23h */
+ ov518_reg_w32(sd, 0xcb, 746, 2); /* 2eah */
+ ov518_reg_w32(sd, 0xcc, 1750, 2); /* 6d6h */
+ ov518_reg_w32(sd, 0xcd, 45, 2); /* 2dh */
+ ov518_reg_w32(sd, 0xce, 851, 2); /* 353h */
+ }
+
+ reg_w(sd, 0x2f, 0x80);
+
+ return 0;
+}
+
+
/* Sets up the OV519 with the given image parameters
*
* OV519 needs a completely different approach, until we can figure out what
@@ -1492,7 +2459,11 @@ static int ov519_mode_init_regs(struct sd *sd)
reg_w(sd, OV519_R10_H_SIZE, sd->gspca_dev.width >> 4);
reg_w(sd, OV519_R11_V_SIZE, sd->gspca_dev.height >> 3);
- reg_w(sd, OV519_R12_X_OFFSETL, 0x00);
+ if (sd->sensor == SEN_OV7670 &&
+ sd->gspca_dev.cam.cam_mode[sd->gspca_dev.curr_mode].priv)
+ reg_w(sd, OV519_R12_X_OFFSETL, 0x04);
+ else
+ reg_w(sd, OV519_R12_X_OFFSETL, 0x00);
reg_w(sd, OV519_R13_X_OFFSETH, 0x00);
reg_w(sd, OV519_R14_Y_OFFSETL, 0x00);
reg_w(sd, OV519_R15_Y_OFFSETH, 0x00);
@@ -1584,7 +2555,7 @@ static int mode_init_ov_sensor_regs(struct sd *sd)
int qvga;
gspca_dev = &sd->gspca_dev;
- qvga = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv;
+ qvga = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv & 1;
/******** Mode (VGA/QVGA) and sensor specific regs ********/
switch (sd->sensor) {
@@ -1612,30 +2583,16 @@ static int mode_init_ov_sensor_regs(struct sd *sd)
#endif
break;
case SEN_OV7620:
-/* i2c_w(sd, 0x2b, 0x00); */
- i2c_w_mask(sd, 0x14, qvga ? 0x20 : 0x00, 0x20);
- i2c_w_mask(sd, 0x28, qvga ? 0x00 : 0x20, 0x20);
- i2c_w(sd, 0x24, qvga ? 0x20 : 0x3a);
- i2c_w(sd, 0x25, qvga ? 0x30 : 0x60);
- i2c_w_mask(sd, 0x2d, qvga ? 0x40 : 0x00, 0x40);
- i2c_w_mask(sd, 0x67, qvga ? 0xf0 : 0x90, 0xf0);
- i2c_w_mask(sd, 0x74, qvga ? 0x20 : 0x00, 0x20);
- break;
case SEN_OV76BE:
-/* i2c_w(sd, 0x2b, 0x00); */
i2c_w_mask(sd, 0x14, qvga ? 0x20 : 0x00, 0x20);
-#if 0
- /* FIXME: Enable this once 7620AE uses 7620 initial settings */
i2c_w_mask(sd, 0x28, qvga ? 0x00 : 0x20, 0x20);
i2c_w(sd, 0x24, qvga ? 0x20 : 0x3a);
i2c_w(sd, 0x25, qvga ? 0x30 : 0x60);
i2c_w_mask(sd, 0x2d, qvga ? 0x40 : 0x00, 0x40);
i2c_w_mask(sd, 0x67, qvga ? 0xb0 : 0x90, 0xf0);
i2c_w_mask(sd, 0x74, qvga ? 0x20 : 0x00, 0x20);
-#endif
break;
case SEN_OV7640:
-/* i2c_w(sd, 0x2b, 0x00); */
i2c_w_mask(sd, 0x14, qvga ? 0x20 : 0x00, 0x20);
i2c_w_mask(sd, 0x28, qvga ? 0x00 : 0x20, 0x20);
/* i2c_w(sd, 0x24, qvga ? 0x20 : 0x3a); */
@@ -1654,6 +2611,7 @@ static int mode_init_ov_sensor_regs(struct sd *sd)
break;
case SEN_OV6620:
case SEN_OV6630:
+ case SEN_OV66308AF:
i2c_w_mask(sd, 0x14, qvga ? 0x20 : 0x00, 0x20);
break;
default:
@@ -1661,10 +2619,6 @@ static int mode_init_ov_sensor_regs(struct sd *sd)
}
/******** Palette-specific regs ********/
- if (sd->sensor == SEN_OV7610 || sd->sensor == SEN_OV76BE) {
- /* not valid on the OV6620/OV7620/6630? */
- i2c_w_mask(sd, 0x0e, 0x00, 0x40);
- }
/* The OV518 needs special treatment. Although both the OV518
* and the OV6630 support a 16-bit video bus, only the 8 bit Y
@@ -1674,25 +2628,12 @@ static int mode_init_ov_sensor_regs(struct sd *sd)
/* OV7640 is 8-bit only */
- if (sd->sensor != SEN_OV6630 && sd->sensor != SEN_OV7640)
+ if (sd->sensor != SEN_OV6630 && sd->sensor != SEN_OV66308AF &&
+ sd->sensor != SEN_OV7640)
i2c_w_mask(sd, 0x13, 0x00, 0x20);
/******** Clock programming ********/
- /* The OV6620 needs special handling. This prevents the
- * severe banding that normally occurs */
- if (sd->sensor == SEN_OV6620) {
-
- /* Clock down */
- i2c_w(sd, 0x2a, 0x04);
- i2c_w(sd, 0x11, sd->clockdiv);
- i2c_w(sd, 0x2a, 0x84);
- /* This next setting is critical. It seems to improve
- * the gain or the contrast. The "reserved" bits seem
- * to have some effect in this case. */
- i2c_w(sd, 0x2d, 0x85);
- } else {
- i2c_w(sd, 0x11, sd->clockdiv);
- }
+ i2c_w(sd, 0x11, sd->clockdiv);
/******** Special Features ********/
/* no evidence this is possible with OV7670, either */
@@ -1736,13 +2677,14 @@ static void sethvflip(struct sd *sd)
static int set_ov_sensor_window(struct sd *sd)
{
struct gspca_dev *gspca_dev;
- int qvga;
+ int qvga, crop;
int hwsbase, hwebase, vwsbase, vwebase, hwscale, vwscale;
int ret, hstart, hstop, vstop, vstart;
__u8 v;
gspca_dev = &sd->gspca_dev;
- qvga = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv;
+ qvga = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv & 1;
+ crop = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv & 2;
/* The different sensor ICs handle setting up of window differently.
* IF YOU SET IT WRONG, YOU WILL GET ALL ZERO ISOC DATA FROM OV51x!! */
@@ -1761,10 +2703,20 @@ static int set_ov_sensor_window(struct sd *sd)
break;
case SEN_OV6620:
case SEN_OV6630:
+ case SEN_OV66308AF:
hwsbase = 0x38;
hwebase = 0x3a;
vwsbase = 0x05;
vwebase = 0x06;
+ if (sd->sensor == SEN_OV66308AF && qvga)
+ /* HDG: this fixes U and V getting swapped */
+ hwsbase++;
+ if (crop) {
+ hwsbase += 8;
+ hwebase += 8;
+ vwsbase += 11;
+ vwebase += 11;
+ }
break;
case SEN_OV7620:
hwsbase = 0x2f; /* From 7620.SET (spec is wrong) */
@@ -1788,6 +2740,7 @@ static int set_ov_sensor_window(struct sd *sd)
switch (sd->sensor) {
case SEN_OV6620:
case SEN_OV6630:
+ case SEN_OV66308AF:
if (qvga) { /* QCIF */
hwscale = 0;
vwscale = 0;
@@ -1840,7 +2793,7 @@ static int set_ov_sensor_window(struct sd *sd)
if (qvga) { /* QVGA from ov7670.c by
* Jonathan Corbet */
hstart = 164;
- hstop = 20;
+ hstop = 28;
vstart = 14;
vstop = 494;
} else { /* VGA */
@@ -1866,7 +2819,6 @@ static int set_ov_sensor_window(struct sd *sd)
msleep(10); /* need to sleep between read and write to
* same reg! */
i2c_w(sd, OV7670_REG_VREF, v);
- sethvflip(sd);
} else {
i2c_w(sd, 0x17, hwsbase);
i2c_w(sd, 0x18, hwebase + (sd->gspca_dev.width >> hwscale));
@@ -1880,15 +2832,35 @@ static int set_ov_sensor_window(struct sd *sd)
static int sd_start(struct gspca_dev *gspca_dev)
{
struct sd *sd = (struct sd *) gspca_dev;
- int ret;
+ int ret = 0;
- ret = ov519_mode_init_regs(sd);
+ switch (sd->bridge) {
+ case BRIDGE_OV511:
+ case BRIDGE_OV511PLUS:
+ ret = ov511_mode_init_regs(sd);
+ break;
+ case BRIDGE_OV518:
+ case BRIDGE_OV518PLUS:
+ ret = ov518_mode_init_regs(sd);
+ break;
+ case BRIDGE_OV519:
+ ret = ov519_mode_init_regs(sd);
+ break;
+ }
if (ret < 0)
goto out;
+
ret = set_ov_sensor_window(sd);
if (ret < 0)
goto out;
+ setcontrast(gspca_dev);
+ setbrightness(gspca_dev);
+ setcolors(gspca_dev);
+ sethvflip(sd);
+ setautobrightness(sd);
+ setfreq(sd);
+
ret = ov51x_restart(sd);
if (ret < 0)
goto out;
@@ -1907,7 +2879,95 @@ static void sd_stopN(struct gspca_dev *gspca_dev)
ov51x_led_control(sd, 0);
}
-static void sd_pkt_scan(struct gspca_dev *gspca_dev,
+static void ov511_pkt_scan(struct gspca_dev *gspca_dev,
+ struct gspca_frame *frame, /* target */
+ __u8 *in, /* isoc packet */
+ int len) /* iso packet length */
+{
+ struct sd *sd = (struct sd *) gspca_dev;
+
+ /* SOF/EOF packets have 1st to 8th bytes zeroed and the 9th
+ * byte non-zero. The EOF packet has image width/height in the
+ * 10th and 11th bytes. The 9th byte is given as follows:
+ *
+ * bit 7: EOF
+ * 6: compression enabled
+ * 5: 422/420/400 modes
+ * 4: 422/420/400 modes
+ * 3: 1
+ * 2: snapshot button on
+ * 1: snapshot frame
+ * 0: even/odd field
+ */
+ if (!(in[0] | in[1] | in[2] | in[3] | in[4] | in[5] | in[6] | in[7]) &&
+ (in[8] & 0x08)) {
+ if (in[8] & 0x80) {
+ /* Frame end */
+ if ((in[9] + 1) * 8 != gspca_dev->width ||
+ (in[10] + 1) * 8 != gspca_dev->height) {
+ PDEBUG(D_ERR, "Invalid frame size, got: %dx%d,"
+ " requested: %dx%d\n",
+ (in[9] + 1) * 8, (in[10] + 1) * 8,
+ gspca_dev->width, gspca_dev->height);
+ gspca_dev->last_packet_type = DISCARD_PACKET;
+ return;
+ }
+ /* Add 11 byte footer to frame, might be usefull */
+ gspca_frame_add(gspca_dev, LAST_PACKET, frame, in, 11);
+ return;
+ } else {
+ /* Frame start */
+ gspca_frame_add(gspca_dev, FIRST_PACKET, frame, in, 0);
+ sd->packet_nr = 0;
+ }
+ }
+
+ /* Ignore the packet number */
+ len--;
+
+ /* intermediate packet */
+ gspca_frame_add(gspca_dev, INTER_PACKET, frame, in, len);
+}
+
+static void ov518_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;
+
+ /* A false positive here is likely, until OVT gives me
+ * the definitive SOF/EOF format */
+ if ((!(data[0] | data[1] | data[2] | data[3] | data[5])) && data[6]) {
+ gspca_frame_add(gspca_dev, LAST_PACKET, frame, data, 0);
+ gspca_frame_add(gspca_dev, FIRST_PACKET, frame, data, 0);
+ sd->packet_nr = 0;
+ }
+
+ if (gspca_dev->last_packet_type == DISCARD_PACKET)
+ return;
+
+ /* Does this device use packet numbers ? */
+ if (len & 7) {
+ len--;
+ if (sd->packet_nr == data[len])
+ sd->packet_nr++;
+ /* The last few packets of the frame (which are all 0's
+ except that they may contain part of the footer), are
+ numbered 0 */
+ else if (sd->packet_nr == 0 || data[len]) {
+ PDEBUG(D_ERR, "Invalid packet nr: %d (expect: %d)",
+ (int)data[len], (int)sd->packet_nr);
+ gspca_dev->last_packet_type = DISCARD_PACKET;
+ return;
+ }
+ }
+
+ /* intermediate packet */
+ gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len);
+}
+
+static void ov519_pkt_scan(struct gspca_dev *gspca_dev,
struct gspca_frame *frame, /* target */
__u8 *data, /* isoc packet */
int len) /* iso packet length */
@@ -1951,6 +3011,28 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev,
data, len);
}
+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;
+
+ switch (sd->bridge) {
+ case BRIDGE_OV511:
+ case BRIDGE_OV511PLUS:
+ ov511_pkt_scan(gspca_dev, frame, data, len);
+ break;
+ case BRIDGE_OV518:
+ case BRIDGE_OV518PLUS:
+ ov518_pkt_scan(gspca_dev, frame, data, len);
+ break;
+ case BRIDGE_OV519:
+ ov519_pkt_scan(gspca_dev, frame, data, len);
+ break;
+ }
+}
+
/* -- management routines -- */
static void setbrightness(struct gspca_dev *gspca_dev)
@@ -1965,13 +3047,13 @@ static void setbrightness(struct gspca_dev *gspca_dev)
case SEN_OV76BE:
case SEN_OV6620:
case SEN_OV6630:
+ case SEN_OV66308AF:
case SEN_OV7640:
i2c_w(sd, OV7610_REG_BRT, val);
break;
case SEN_OV7620:
/* 7620 doesn't like manual changes when in auto mode */
-/*fixme
- * if (!sd->auto_brt) */
+ if (!sd->autobrightness)
i2c_w(sd, OV7610_REG_BRT, val);
break;
case SEN_OV7670:
@@ -1994,7 +3076,9 @@ static void setcontrast(struct gspca_dev *gspca_dev)
i2c_w(sd, OV7610_REG_CNT, val);
break;
case SEN_OV6630:
+ case SEN_OV66308AF:
i2c_w_mask(sd, OV7610_REG_CNT, val >> 4, 0x0f);
+ break;
case SEN_OV8610: {
static const __u8 ctab[] = {
0x03, 0x09, 0x0b, 0x0f, 0x53, 0x6f, 0x35, 0x7f
@@ -2037,6 +3121,7 @@ static void setcolors(struct gspca_dev *gspca_dev)
case SEN_OV76BE:
case SEN_OV6620:
case SEN_OV6630:
+ case SEN_OV66308AF:
i2c_w(sd, OV7610_REG_SAT, val);
break;
case SEN_OV7620:
@@ -2057,6 +3142,72 @@ static void setcolors(struct gspca_dev *gspca_dev)
}
}
+static void setautobrightness(struct sd *sd)
+{
+ if (sd->sensor == SEN_OV7640 || sd->sensor == SEN_OV7670)
+ return;
+
+ i2c_w_mask(sd, 0x2d, sd->autobrightness ? 0x10 : 0x00, 0x10);
+}
+
+static void setfreq(struct sd *sd)
+{
+ if (sd->sensor == SEN_OV7670) {
+ switch (sd->freq) {
+ case 0: /* Banding filter disabled */
+ i2c_w_mask(sd, OV7670_REG_COM8, 0, OV7670_COM8_BFILT);
+ break;
+ case 1: /* 50 hz */
+ i2c_w_mask(sd, OV7670_REG_COM8, OV7670_COM8_BFILT,
+ OV7670_COM8_BFILT);
+ i2c_w_mask(sd, OV7670_REG_COM11, 0x08, 0x18);
+ break;
+ case 2: /* 60 hz */
+ i2c_w_mask(sd, OV7670_REG_COM8, OV7670_COM8_BFILT,
+ OV7670_COM8_BFILT);
+ i2c_w_mask(sd, OV7670_REG_COM11, 0x00, 0x18);
+ break;
+ case 3: /* Auto hz */
+ i2c_w_mask(sd, OV7670_REG_COM8, OV7670_COM8_BFILT,
+ OV7670_COM8_BFILT);
+ i2c_w_mask(sd, OV7670_REG_COM11, OV7670_COM11_HZAUTO,
+ 0x18);
+ break;
+ }
+ } else {
+ switch (sd->freq) {
+ case 0: /* Banding filter disabled */
+ i2c_w_mask(sd, 0x2d, 0x00, 0x04);
+ i2c_w_mask(sd, 0x2a, 0x00, 0x80);
+ break;
+ case 1: /* 50 hz (filter on and framerate adj) */
+ i2c_w_mask(sd, 0x2d, 0x04, 0x04);
+ i2c_w_mask(sd, 0x2a, 0x80, 0x80);
+ /* 20 fps -> 16.667 fps */
+ if (sd->sensor == SEN_OV6620 ||
+ sd->sensor == SEN_OV6630 ||
+ sd->sensor == SEN_OV66308AF)
+ i2c_w(sd, 0x2b, 0x5e);
+ else
+ i2c_w(sd, 0x2b, 0xac);
+ break;
+ case 2: /* 60 hz (filter on, ...) */
+ i2c_w_mask(sd, 0x2d, 0x04, 0x04);
+ if (sd->sensor == SEN_OV6620 ||
+ sd->sensor == SEN_OV6630 ||
+ sd->sensor == SEN_OV66308AF) {
+ /* 20 fps -> 15 fps */
+ i2c_w_mask(sd, 0x2a, 0x80, 0x80);
+ i2c_w(sd, 0x2b, 0xa8);
+ } else {
+ /* no framerate adj. */
+ i2c_w_mask(sd, 0x2a, 0x00, 0x80);
+ }
+ break;
+ }
+ }
+}
+
static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
{
struct sd *sd = (struct sd *) gspca_dev;
@@ -2147,6 +3298,71 @@ static int sd_getvflip(struct gspca_dev *gspca_dev, __s32 *val)
return 0;
}
+static int sd_setautobrightness(struct gspca_dev *gspca_dev, __s32 val)
+{
+ struct sd *sd = (struct sd *) gspca_dev;
+
+ sd->autobrightness = val;
+ if (gspca_dev->streaming)
+ setautobrightness(sd);
+ return 0;
+}
+
+static int sd_getautobrightness(struct gspca_dev *gspca_dev, __s32 *val)
+{
+ struct sd *sd = (struct sd *) gspca_dev;
+
+ *val = sd->autobrightness;
+ return 0;
+}
+
+static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val)
+{
+ struct sd *sd = (struct sd *) gspca_dev;
+
+ sd->freq = val;
+ if (gspca_dev->streaming)
+ setfreq(sd);
+ return 0;
+}
+
+static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val)
+{
+ struct sd *sd = (struct sd *) gspca_dev;
+
+ *val = sd->freq;
+ return 0;
+}
+
+static int sd_querymenu(struct gspca_dev *gspca_dev,
+ struct v4l2_querymenu *menu)
+{
+ struct sd *sd = (struct sd *) gspca_dev;
+
+ switch (menu->id) {
+ case V4L2_CID_POWER_LINE_FREQUENCY:
+ switch (menu->index) {
+ case 0: /* V4L2_CID_POWER_LINE_FREQUENCY_DISABLED */
+ strcpy((char *) menu->name, "NoFliker");
+ return 0;
+ case 1: /* V4L2_CID_POWER_LINE_FREQUENCY_50HZ */
+ strcpy((char *) menu->name, "50 Hz");
+ return 0;
+ case 2: /* V4L2_CID_POWER_LINE_FREQUENCY_60HZ */
+ strcpy((char *) menu->name, "60 Hz");
+ return 0;
+ case 3:
+ if (sd->sensor != SEN_OV7670)
+ return -EINVAL;
+
+ strcpy((char *) menu->name, "Automatic");
+ return 0;
+ }
+ break;
+ }
+ return -EINVAL;
+}
+
/* sub-driver description */
static const struct sd_desc sd_desc = {
.name = MODULE_NAME,
@@ -2157,23 +3373,31 @@ static const struct sd_desc sd_desc = {
.start = sd_start,
.stopN = sd_stopN,
.pkt_scan = sd_pkt_scan,
+ .querymenu = sd_querymenu,
};
/* -- module initialisation -- */
static const __devinitdata struct usb_device_id device_table[] = {
- {USB_DEVICE(0x041e, 0x4052)},
- {USB_DEVICE(0x041e, 0x405f)},
- {USB_DEVICE(0x041e, 0x4060)},
- {USB_DEVICE(0x041e, 0x4061)},
- {USB_DEVICE(0x041e, 0x4064)},
- {USB_DEVICE(0x041e, 0x4068)},
- {USB_DEVICE(0x045e, 0x028c)},
- {USB_DEVICE(0x054c, 0x0154)},
- {USB_DEVICE(0x054c, 0x0155)},
- {USB_DEVICE(0x05a9, 0x0519)},
- {USB_DEVICE(0x05a9, 0x0530)},
- {USB_DEVICE(0x05a9, 0x4519)},
- {USB_DEVICE(0x05a9, 0x8519)},
+ {USB_DEVICE(0x041e, 0x4052), .driver_info = BRIDGE_OV519 },
+ {USB_DEVICE(0x041e, 0x405f), .driver_info = BRIDGE_OV519 },
+ {USB_DEVICE(0x041e, 0x4060), .driver_info = BRIDGE_OV519 },
+ {USB_DEVICE(0x041e, 0x4061), .driver_info = BRIDGE_OV519 },
+ {USB_DEVICE(0x041e, 0x4064),
+ .driver_info = BRIDGE_OV519 | BRIDGE_INVERT_LED },
+ {USB_DEVICE(0x041e, 0x4068),
+ .driver_info = BRIDGE_OV519 | BRIDGE_INVERT_LED },
+ {USB_DEVICE(0x045e, 0x028c), .driver_info = BRIDGE_OV519 },
+ {USB_DEVICE(0x054c, 0x0154), .driver_info = BRIDGE_OV519 },
+ {USB_DEVICE(0x054c, 0x0155), .driver_info = BRIDGE_OV519 },
+ {USB_DEVICE(0x05a9, 0x0511), .driver_info = BRIDGE_OV511 },
+ {USB_DEVICE(0x05a9, 0x0518), .driver_info = BRIDGE_OV518 },
+ {USB_DEVICE(0x05a9, 0x0519), .driver_info = BRIDGE_OV519 },
+ {USB_DEVICE(0x05a9, 0x0530), .driver_info = BRIDGE_OV519 },
+ {USB_DEVICE(0x05a9, 0x4519), .driver_info = BRIDGE_OV519 },
+ {USB_DEVICE(0x05a9, 0x8519), .driver_info = BRIDGE_OV519 },
+ {USB_DEVICE(0x05a9, 0xa511), .driver_info = BRIDGE_OV511PLUS },
+ {USB_DEVICE(0x05a9, 0xa518), .driver_info = BRIDGE_OV518PLUS },
+ {USB_DEVICE(0x0813, 0x0002), .driver_info = BRIDGE_OV511PLUS },
{}
};
diff --git a/linux/drivers/media/video/gspca/ov534.c b/linux/drivers/media/video/gspca/ov534.c
index 14341b6be..21a9366c7 100644
--- a/linux/drivers/media/video/gspca/ov534.c
+++ b/linux/drivers/media/video/gspca/ov534.c
@@ -958,9 +958,11 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, struct gspca_frame *frame,
__u32 this_pts;
u16 this_fid;
int remaining_len = len;
+ int payload_len;
+ payload_len = gspca_dev->cam.bulk ? 2048 : 2040;
do {
- len = min(remaining_len, 2040); /*fixme: was 2048*/
+ len = min(remaining_len, payload_len);
/* Payloads are prefixed with a UVC-style header. We
consider a frame to start when the FID toggles, or the PTS
diff --git a/linux/drivers/media/video/gspca/sonixj.c b/linux/drivers/media/video/gspca/sonixj.c
index a4c935d69..a2fb94eb7 100644
--- a/linux/drivers/media/video/gspca/sonixj.c
+++ b/linux/drivers/media/video/gspca/sonixj.c
@@ -46,6 +46,7 @@ struct sd {
u8 gamma;
u8 vflip; /* ov7630/ov7648 only */
u8 infrared; /* mt9v111 only */
+ u8 freq; /* ov76xx only */
u8 quality; /* image quality */
#define QUALITY_MIN 60
#define QUALITY_MAX 95
@@ -96,8 +97,11 @@ static int sd_setvflip(struct gspca_dev *gspca_dev, __s32 val);
static int sd_getvflip(struct gspca_dev *gspca_dev, __s32 *val);
static int sd_setinfrared(struct gspca_dev *gspca_dev, __s32 val);
static int sd_getinfrared(struct gspca_dev *gspca_dev, __s32 *val);
+static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val);
+static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val);
static struct ctrl sd_ctrls[] = {
+#define BRIGHTNESS_IDX 0
{
{
.id = V4L2_CID_BRIGHTNESS,
@@ -113,6 +117,7 @@ static struct ctrl sd_ctrls[] = {
.set = sd_setbrightness,
.get = sd_getbrightness,
},
+#define CONTRAST_IDX 1
{
{
.id = V4L2_CID_CONTRAST,
@@ -128,20 +133,22 @@ static struct ctrl sd_ctrls[] = {
.set = sd_setcontrast,
.get = sd_getcontrast,
},
+#define COLOR_IDX 2
{
{
.id = V4L2_CID_SATURATION,
.type = V4L2_CTRL_TYPE_INTEGER,
- .name = "Color",
+ .name = "Saturation",
.minimum = 0,
.maximum = 40,
.step = 1,
-#define COLOR_DEF 32
+#define COLOR_DEF 25
.default_value = COLOR_DEF,
},
.set = sd_setcolors,
.get = sd_getcolors,
},
+#define BLUE_BALANCE_IDX 3
{
{
.id = V4L2_CID_BLUE_BALANCE,
@@ -156,6 +163,7 @@ static struct ctrl sd_ctrls[] = {
.set = sd_setblue_balance,
.get = sd_getblue_balance,
},
+#define RED_BALANCE_IDX 4
{
{
.id = V4L2_CID_RED_BALANCE,
@@ -170,6 +178,7 @@ static struct ctrl sd_ctrls[] = {
.set = sd_setred_balance,
.get = sd_getred_balance,
},
+#define GAMMA_IDX 5
{
{
.id = V4L2_CID_GAMMA,
@@ -184,7 +193,7 @@ static struct ctrl sd_ctrls[] = {
.set = sd_setgamma,
.get = sd_getgamma,
},
-#define AUTOGAIN_IDX 5
+#define AUTOGAIN_IDX 6
{
{
.id = V4L2_CID_AUTOGAIN,
@@ -200,7 +209,7 @@ static struct ctrl sd_ctrls[] = {
.get = sd_getautogain,
},
/* ov7630/ov7648 only */
-#define VFLIP_IDX 6
+#define VFLIP_IDX 7
{
{
.id = V4L2_CID_VFLIP,
@@ -209,14 +218,14 @@ static struct ctrl sd_ctrls[] = {
.minimum = 0,
.maximum = 1,
.step = 1,
-#define VFLIP_DEF 0 /* vflip def = 1 for ov7630 */
+#define VFLIP_DEF 0
.default_value = VFLIP_DEF,
},
.set = sd_setvflip,
.get = sd_getvflip,
},
/* mt9v111 only */
-#define INFRARED_IDX 7
+#define INFRARED_IDX 8
{
{
.id = V4L2_CID_INFRARED,
@@ -231,32 +240,48 @@ static struct ctrl sd_ctrls[] = {
.set = sd_setinfrared,
.get = sd_getinfrared,
},
+/* ov7630/ov7648/ov7660 only */
+#define FREQ_IDX 9
+ {
+ {
+ .id = V4L2_CID_POWER_LINE_FREQUENCY,
+ .type = V4L2_CTRL_TYPE_MENU,
+ .name = "Light frequency filter",
+ .minimum = 0,
+ .maximum = 2, /* 0: 0, 1: 50Hz, 2:60Hz */
+ .step = 1,
+#define FREQ_DEF 2
+ .default_value = FREQ_DEF,
+ },
+ .set = sd_setfreq,
+ .get = sd_getfreq,
+ },
};
/* table of the disabled controls */
static __u32 ctrl_dis[] = {
- (1 << INFRARED_IDX) | (1 << VFLIP_IDX),
+ (1 << INFRARED_IDX) | (1 << VFLIP_IDX) | (1 << FREQ_IDX),
/* SENSOR_HV7131R 0 */
- (1 << INFRARED_IDX) | (1 << VFLIP_IDX),
+ (1 << INFRARED_IDX) | (1 << VFLIP_IDX) | (1 << FREQ_IDX),
/* SENSOR_MI0360 1 */
- (1 << INFRARED_IDX) | (1 << VFLIP_IDX),
+ (1 << INFRARED_IDX) | (1 << VFLIP_IDX) | (1 << FREQ_IDX),
/* SENSOR_MO4000 2 */
#if 1
- (1 << VFLIP_IDX),
+ (1 << VFLIP_IDX) | (1 << FREQ_IDX),
#else
- (1 << AUTOGAIN_IDX) | (1 << VFLIP_IDX),
+ (1 << AUTOGAIN_IDX) | (1 << VFLIP_IDX) | (1 << FREQ_IDX),
#endif
/* SENSOR_MT9V111 3 */
- (1 << INFRARED_IDX) | (1 << VFLIP_IDX),
+ (1 << INFRARED_IDX) | (1 << VFLIP_IDX) | (1 << FREQ_IDX),
/* SENSOR_OM6802 4 */
- (1 << AUTOGAIN_IDX) | (1 << INFRARED_IDX),
+ (1 << INFRARED_IDX),
/* SENSOR_OV7630 5 */
(1 << INFRARED_IDX),
/* 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 */
+ (1 << AUTOGAIN_IDX) | (1 << INFRARED_IDX) | (1 << VFLIP_IDX) |
+ (1 << FREQ_IDX), /* SENSOR_SP80708 8 */
};
static const struct v4l2_pix_format vga_mode[] = {
@@ -272,7 +297,8 @@ static const struct v4l2_pix_format vga_mode[] = {
.priv = 1},
{640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
.bytesperline = 640,
- .sizeimage = 640 * 480 * 3 / 8 + 590,
+ /* Note 3 / 8 is not large enough, not even 5 / 8 is ?! */
+ .sizeimage = 640 * 480 * 3 / 4 + 590,
.colorspace = V4L2_COLORSPACE_JPEG,
.priv = 0},
};
@@ -612,7 +638,9 @@ static const u8 ov7630_sensor_init[][8] = {
/* win: i2c_r from 00 to 80 */
{0xd1, 0x21, 0x03, 0x80, 0x10, 0x20, 0x80, 0x10},
{0xb1, 0x21, 0x0c, 0x20, 0x20, 0x00, 0x00, 0x10},
- {0xd1, 0x21, 0x11, 0x00, 0x48, 0xc0, 0x00, 0x10},
+/* HDG: 0x11 was 0x00 change to 0x01 for better exposure (15 fps instead of 30)
+ 0x13 was 0xc0 change to 0xc3 for auto gain and exposure */
+ {0xd1, 0x21, 0x11, 0x01, 0x48, 0xc3, 0x00, 0x10},
{0xb1, 0x21, 0x15, 0x80, 0x03, 0x00, 0x00, 0x10},
{0xd1, 0x21, 0x17, 0x1b, 0xbd, 0x05, 0xf6, 0x10},
{0xa1, 0x21, 0x1b, 0x04, 0x00, 0x00, 0x00, 0x10},
@@ -646,9 +674,8 @@ static const u8 ov7630_sensor_init[][8] = {
{0xa1, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10},
{0xb1, 0x21, 0x01, 0x80, 0x80, 0x00, 0x00, 0x10},
/* */
- {0xa1, 0x21, 0x11, 0x00, 0x00, 0x00, 0x00, 0x10},
- {0xa1, 0x21, 0x2a, 0x88, 0x00, 0x00, 0x00, 0x10},
- {0xa1, 0x21, 0x2b, 0x34, 0x00, 0x00, 0x00, 0x10},
+/* {0xa1, 0x21, 0x2a, 0x88, 0x00, 0x00, 0x00, 0x10}, * set by setfreq */
+/* {0xa1, 0x21, 0x2b, 0x34, 0x00, 0x00, 0x00, 0x10}, * set by setfreq */
/* */
{0xa1, 0x21, 0x10, 0x83, 0x00, 0x00, 0x00, 0x10},
/* {0xb1, 0x21, 0x01, 0x88, 0x70, 0x00, 0x00, 0x10}, */
@@ -681,7 +708,7 @@ static const u8 ov7648_sensor_init[][8] = {
{0xd1, 0x21, 0x21, 0x86, 0x00, 0xde, 0xa0, 0x10},
/* {0xd1, 0x21, 0x25, 0x80, 0x32, 0xfe, 0xa0, 0x10}, jfm done */
/* {0xd1, 0x21, 0x29, 0x00, 0x91, 0x00, 0x88, 0x10}, jfm done */
- {0xb1, 0x21, 0x2d, 0x85, 0x00, 0x00, 0x00, 0x10},
+/* {0xb1, 0x21, 0x2d, 0x85, 0x00, 0x00, 0x00, 0x10}, set by setfreq */
/*...*/
/* {0xa1, 0x21, 0x12, 0x08, 0x00, 0x00, 0x00, 0x10}, jfm done */
/* {0xa1, 0x21, 0x75, 0x06, 0x00, 0x00, 0x00, 0x10}, * COMN
@@ -1310,11 +1337,9 @@ static int sd_config(struct gspca_dev *gspca_dev,
sd->gamma = GAMMA_DEF;
sd->autogain = AUTOGAIN_DEF;
sd->ag_cnt = -1;
- if (sd->sensor != SENSOR_OV7630)
- sd->vflip = 0;
- else
- sd->vflip = 1;
+ sd->vflip = VFLIP_DEF;
sd->infrared = INFRARED_DEF;
+ sd->freq = FREQ_DEF;
sd->quality = QUALITY_DEF;
sd->jpegqual = 80;
@@ -1595,7 +1620,7 @@ static void setautogain(struct gspca_dev *gspca_dev)
else
comb = 0xa0;
if (sd->autogain)
- comb |= 0x02;
+ comb |= 0x03;
i2c_w1(&sd->gspca_dev, 0x13, comb);
return;
}
@@ -1611,12 +1636,15 @@ static void setvflip(struct sd *sd)
{
u8 comn;
- if (sd->sensor == SENSOR_OV7630)
+ if (sd->sensor == SENSOR_OV7630) {
comn = 0x02;
- else
+ if (!sd->vflip)
+ comn |= 0x80;
+ } else {
comn = 0x06;
- if (sd->vflip)
- comn |= 0x80;
+ if (sd->vflip)
+ comn |= 0x80;
+ }
i2c_w1(&sd->gspca_dev, 0x75, comn);
}
@@ -1634,6 +1662,58 @@ static void setinfrared(struct sd *sd)
#endif
}
+static void setfreq(struct gspca_dev *gspca_dev)
+{
+ struct sd *sd = (struct sd *) gspca_dev;
+
+ if (sd->sensor == SENSOR_OV7660) {
+ switch (sd->freq) {
+ case 0: /* Banding filter disabled */
+ i2c_w1(gspca_dev, 0x13, 0xdf);
+ break;
+ case 1: /* 50 hz */
+ i2c_w1(gspca_dev, 0x13, 0xff);
+ i2c_w1(gspca_dev, 0x3b, 0x0a);
+ break;
+ case 2: /* 60 hz */
+ i2c_w1(gspca_dev, 0x13, 0xff);
+ i2c_w1(gspca_dev, 0x3b, 0x02);
+ break;
+ }
+ } else {
+ u8 reg2a = 0, reg2b = 0, reg2d = 0;
+
+ /* Get reg2a / reg2d base values */
+ switch (sd->sensor) {
+ case SENSOR_OV7630:
+ reg2a = 0x08;
+ reg2d = 0x01;
+ break;
+ case SENSOR_OV7648:
+ reg2a = 0x11;
+ reg2d = 0x81;
+ break;
+ }
+
+ switch (sd->freq) {
+ case 0: /* Banding filter disabled */
+ break;
+ case 1: /* 50 hz (filter on and framerate adj) */
+ reg2a |= 0x80;
+ reg2b = 0xac;
+ reg2d |= 0x04;
+ break;
+ case 2: /* 60 hz (filter on, no framerate adj) */
+ reg2a |= 0x80;
+ reg2d |= 0x04;
+ break;
+ }
+ i2c_w1(gspca_dev, 0x2a, reg2a);
+ i2c_w1(gspca_dev, 0x2b, reg2b);
+ i2c_w1(gspca_dev, 0x2d, reg2d);
+ }
+}
+
static void setjpegqual(struct gspca_dev *gspca_dev)
{
struct sd *sd = (struct sd *) gspca_dev;
@@ -1865,6 +1945,7 @@ static int sd_start(struct gspca_dev *gspca_dev)
setbrightness(gspca_dev);
setcontrast(gspca_dev);
setautogain(gspca_dev);
+ setfreq(gspca_dev);
return 0;
}
@@ -2168,6 +2249,24 @@ static int sd_getinfrared(struct gspca_dev *gspca_dev, __s32 *val)
return 0;
}
+static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val)
+{
+ struct sd *sd = (struct sd *) gspca_dev;
+
+ sd->freq = val;
+ if (gspca_dev->streaming)
+ setfreq(gspca_dev);
+ return 0;
+}
+
+static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val)
+{
+ struct sd *sd = (struct sd *) gspca_dev;
+
+ *val = sd->freq;
+ return 0;
+}
+
static int sd_set_jcomp(struct gspca_dev *gspca_dev,
struct v4l2_jpegcompression *jcomp)
{
@@ -2196,6 +2295,27 @@ static int sd_get_jcomp(struct gspca_dev *gspca_dev,
return 0;
}
+static int sd_querymenu(struct gspca_dev *gspca_dev,
+ struct v4l2_querymenu *menu)
+{
+ switch (menu->id) {
+ case V4L2_CID_POWER_LINE_FREQUENCY:
+ switch (menu->index) {
+ case 0: /* V4L2_CID_POWER_LINE_FREQUENCY_DISABLED */
+ strcpy((char *) menu->name, "NoFliker");
+ return 0;
+ case 1: /* V4L2_CID_POWER_LINE_FREQUENCY_50HZ */
+ strcpy((char *) menu->name, "50 Hz");
+ return 0;
+ case 2: /* V4L2_CID_POWER_LINE_FREQUENCY_60HZ */
+ strcpy((char *) menu->name, "60 Hz");
+ return 0;
+ }
+ break;
+ }
+ return -EINVAL;
+}
+
/* sub-driver description */
static const struct sd_desc sd_desc = {
.name = MODULE_NAME,
@@ -2210,6 +2330,7 @@ static const struct sd_desc sd_desc = {
.dq_callback = do_autogain,
.get_jcomp = sd_get_jcomp,
.set_jcomp = sd_set_jcomp,
+ .querymenu = sd_querymenu,
};
/* -- module initialisation -- */
@@ -2270,7 +2391,7 @@ static const __devinitdata struct usb_device_id device_table[] = {
{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??)}, */
+ {USB_DEVICE(0x0c45, 0x613e), BSI(SN9C120, OV7630, 0x21)},
{USB_DEVICE(0x0c45, 0x6143), BSI(SN9C120, SP80708, 0x18)},
{}
};
diff --git a/linux/drivers/media/video/gspca/spca505.c b/linux/drivers/media/video/gspca/spca505.c
index 2acec58b1..ea8c9fe2e 100644
--- a/linux/drivers/media/video/gspca/spca505.c
+++ b/linux/drivers/media/video/gspca/spca505.c
@@ -637,19 +637,19 @@ static int sd_config(struct gspca_dev *gspca_dev,
cam->nmodes = ARRAY_SIZE(vga_mode) - 1;
sd->brightness = BRIGHTNESS_DEF;
- if (sd->subtype == Nxultra) {
- if (write_vector(gspca_dev, spca505b_init_data))
- return -EIO;
- } else {
- if (write_vector(gspca_dev, spca505_init_data))
- return -EIO;
- }
return 0;
}
/* 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;
+
+ if (write_vector(gspca_dev,
+ sd->subtype == Nxultra
+ ? spca505b_init_data
+ : spca505_init_data))
+ return -EIO;
return 0;
}
diff --git a/linux/drivers/media/video/gspca/stv06xx/Makefile b/linux/drivers/media/video/gspca/stv06xx/Makefile
index feeaa94ab..2f3c3a606 100644
--- a/linux/drivers/media/video/gspca/stv06xx/Makefile
+++ b/linux/drivers/media/video/gspca/stv06xx/Makefile
@@ -3,7 +3,8 @@ obj-$(CONFIG_USB_STV06XX) += gspca_stv06xx.o
gspca_stv06xx-objs := stv06xx.o \
stv06xx_vv6410.o \
stv06xx_hdcs.o \
- stv06xx_pb0100.o
+ stv06xx_pb0100.o \
+ stv06xx_st6422.o
EXTRA_CFLAGS += -Idrivers/media/video/gspca
diff --git a/linux/drivers/media/video/gspca/stv06xx/stv06xx.c b/linux/drivers/media/video/gspca/stv06xx/stv06xx.c
index 9dff2e65b..0da8e0de0 100644
--- a/linux/drivers/media/video/gspca/stv06xx/stv06xx.c
+++ b/linux/drivers/media/video/gspca/stv06xx/stv06xx.c
@@ -92,11 +92,10 @@ static int stv06xx_write_sensor_finish(struct sd *sd)
{
int err = 0;
- if (IS_850(sd)) {
+ if (sd->bridge == BRIDGE_STV610) {
struct usb_device *udev = sd->gspca_dev.dev;
__u8 *buf = sd->gspca_dev.usb_buf;
- /* Quickam Web needs an extra packet */
buf[0] = 0;
err = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
0x04, 0x40, 0x1704, 0, buf, 1,
@@ -253,7 +252,7 @@ static int stv06xx_init(struct gspca_dev *gspca_dev)
err = sd->sensor->init(sd);
- if (dump_sensor)
+ if (dump_sensor && sd->sensor->dump)
sd->sensor->dump(sd);
return (err < 0) ? err : 0;
@@ -293,8 +292,6 @@ static void stv06xx_stopN(struct gspca_dev *gspca_dev)
goto out;
err = sd->sensor->stop(sd);
- if (err < 0)
- goto out;
out:
if (err < 0)
@@ -320,6 +317,8 @@ static void stv06xx_pkt_scan(struct gspca_dev *gspca_dev,
__u8 *data, /* isoc packet */
int len) /* iso packet length */
{
+ struct sd *sd = (struct sd *) gspca_dev;
+
PDEBUG(D_PACK, "Packet of length %d arrived", len);
/* A packet may contain several frames
@@ -345,14 +344,29 @@ static void stv06xx_pkt_scan(struct gspca_dev *gspca_dev,
if (len < chunk_len) {
PDEBUG(D_ERR, "URB packet length is smaller"
" than the specified chunk length");
+ gspca_dev->last_packet_type = DISCARD_PACKET;
return;
}
+ /* First byte seem to be 02=data 2nd byte is unknown??? */
+ if (sd->bridge == BRIDGE_ST6422 && (id & 0xFF00) == 0x0200)
+ goto frame_data;
+
switch (id) {
case 0x0200:
case 0x4200:
+frame_data:
PDEBUG(D_PACK, "Frame data packet detected");
+ if (sd->to_skip) {
+ int skip = (sd->to_skip < chunk_len) ?
+ sd->to_skip : chunk_len;
+ data += skip;
+ len -= skip;
+ chunk_len -= skip;
+ sd->to_skip -= skip;
+ }
+
gspca_frame_add(gspca_dev, INTER_PACKET, frame,
data, chunk_len);
break;
@@ -367,6 +381,9 @@ static void stv06xx_pkt_scan(struct gspca_dev *gspca_dev,
gspca_frame_add(gspca_dev, FIRST_PACKET,
frame, data, 0);
+ if (sd->bridge == BRIDGE_ST6422)
+ sd->to_skip = gspca_dev->width * 4;
+
if (chunk_len)
PDEBUG(D_ERR, "Chunk length is "
"non-zero on a SOF");
@@ -397,8 +414,12 @@ static void stv06xx_pkt_scan(struct gspca_dev *gspca_dev,
/* Unknown chunk with 2 bytes of data,
occurs 2-3 times per USB interrupt */
break;
+ case 0x42ff:
+ PDEBUG(D_PACK, "Chunk 0x42ff detected");
+ /* Special chunk seen sometimes on the ST6422 */
+ break;
default:
- PDEBUG(D_PACK, "Unknown chunk %d detected", id);
+ PDEBUG(D_PACK, "Unknown chunk 0x%04x detected", id);
/* Unknown chunk */
}
data += chunk_len;
@@ -430,11 +451,16 @@ static int stv06xx_config(struct gspca_dev *gspca_dev,
cam = &gspca_dev->cam;
sd->desc = sd_desc;
+ sd->bridge = id->driver_info;
gspca_dev->sd_desc = &sd->desc;
if (dump_bridge)
stv06xx_dump_bridge(sd);
+ sd->sensor = &stv06xx_sensor_st6422;
+ if (!sd->sensor->probe(sd))
+ return 0;
+
sd->sensor = &stv06xx_sensor_vv6410;
if (!sd->sensor->probe(sd))
return 0;
@@ -459,9 +485,20 @@ static int stv06xx_config(struct gspca_dev *gspca_dev,
/* -- module initialisation -- */
static const __devinitdata struct usb_device_id device_table[] = {
- {USB_DEVICE(0x046d, 0x0840)}, /* QuickCam Express */
- {USB_DEVICE(0x046d, 0x0850)}, /* LEGO cam / QuickCam Web */
- {USB_DEVICE(0x046d, 0x0870)}, /* Dexxa WebCam USB */
+ /* QuickCam Express */
+ {USB_DEVICE(0x046d, 0x0840), .driver_info = BRIDGE_STV600 },
+ /* LEGO cam / QuickCam Web */
+ {USB_DEVICE(0x046d, 0x0850), .driver_info = BRIDGE_STV610 },
+ /* Dexxa WebCam USB */
+ {USB_DEVICE(0x046d, 0x0870), .driver_info = BRIDGE_STV602 },
+ /* QuickCam Messenger */
+ {USB_DEVICE(0x046D, 0x08F0), .driver_info = BRIDGE_ST6422 },
+ /* QuickCam Communicate */
+ {USB_DEVICE(0x046D, 0x08F5), .driver_info = BRIDGE_ST6422 },
+ /* QuickCam Messenger (new) */
+ {USB_DEVICE(0x046D, 0x08F6), .driver_info = BRIDGE_ST6422 },
+ /* QuickCam Messenger (new) */
+ {USB_DEVICE(0x046D, 0x08DA), .driver_info = BRIDGE_ST6422 },
{}
};
MODULE_DEVICE_TABLE(usb, device_table);
diff --git a/linux/drivers/media/video/gspca/stv06xx/stv06xx.h b/linux/drivers/media/video/gspca/stv06xx/stv06xx.h
index 1207e7d17..bb73c3288 100644
--- a/linux/drivers/media/video/gspca/stv06xx/stv06xx.h
+++ b/linux/drivers/media/video/gspca/stv06xx/stv06xx.h
@@ -31,6 +31,7 @@
#define STV06XX_H_
#include "gspca.h"
+#include "compat.h"
#define MODULE_NAME "STV06xx"
@@ -93,6 +94,17 @@ struct sd {
/* Sensor private data */
void *sensor_priv;
+
+ /* The first 4 lines produced by the stv6422 are no good, this keeps
+ track of how many bytes we still need to skip during a frame */
+ int to_skip;
+
+ /* Bridge / Camera type */
+ u8 bridge;
+ #define BRIDGE_STV600 0
+ #define BRIDGE_STV602 1
+ #define BRIDGE_STV610 2
+ #define BRIDGE_ST6422 3 /* With integrated sensor */
};
int stv06xx_write_bridge(struct sd *sd, u16 address, u16 i2c_data);
diff --git a/linux/drivers/media/video/gspca/stv06xx/stv06xx_hdcs.c b/linux/drivers/media/video/gspca/stv06xx/stv06xx_hdcs.c
index b16903814..3039ec208 100644
--- a/linux/drivers/media/video/gspca/stv06xx/stv06xx_hdcs.c
+++ b/linux/drivers/media/video/gspca/stv06xx/stv06xx_hdcs.c
@@ -434,7 +434,7 @@ static int hdcs_probe_1x00(struct sd *sd)
hdcs->exp.er = 100;
/*
- * Frame rate on HDCS-1000 0x46D:0x840 depends on PSMP:
+ * Frame rate on HDCS-1000 with STV600 depends on PSMP:
* 4 = doesn't work at all
* 5 = 7.8 fps,
* 6 = 6.9 fps,
@@ -443,7 +443,7 @@ static int hdcs_probe_1x00(struct sd *sd)
* 15 = 4.4 fps,
* 31 = 2.8 fps
*
- * Frame rate on HDCS-1000 0x46D:0x870 depends on PSMP:
+ * Frame rate on HDCS-1000 with STV602 depends on PSMP:
* 15 = doesn't work at all
* 18 = doesn't work at all
* 19 = 7.3 fps
@@ -453,7 +453,7 @@ static int hdcs_probe_1x00(struct sd *sd)
* 24 = 6.3 fps
* 30 = 5.4 fps
*/
- hdcs->psmp = IS_870(sd) ? 20 : 5;
+ hdcs->psmp = (sd->bridge == BRIDGE_STV602) ? 20 : 5;
sd->sensor_priv = hdcs;
@@ -530,7 +530,7 @@ static int hdcs_init(struct sd *sd)
int i, err = 0;
/* Set the STV0602AA in STV0600 emulation mode */
- if (IS_870(sd))
+ if (sd->bridge == BRIDGE_STV602)
stv06xx_write_bridge(sd, STV_STV0600_EMULATION, 1);
/* Execute the bridge init */
@@ -558,7 +558,7 @@ static int hdcs_init(struct sd *sd)
return err;
/* Set PGA sample duration
- (was 0x7E for IS_870, but caused slow framerate with HDCS-1020) */
+ (was 0x7E for the STV602, but caused slow framerate with HDCS-1020) */
if (IS_1020(sd))
err = stv06xx_write_sensor(sd, HDCS_TCTRL,
(HDCS_ADC_START_SIG_DUR << 6) | hdcs->psmp);
diff --git a/linux/drivers/media/video/gspca/stv06xx/stv06xx_sensor.h b/linux/drivers/media/video/gspca/stv06xx/stv06xx_sensor.h
index e88c42f7d..934b9cebc 100644
--- a/linux/drivers/media/video/gspca/stv06xx/stv06xx_sensor.h
+++ b/linux/drivers/media/video/gspca/stv06xx/stv06xx_sensor.h
@@ -32,14 +32,13 @@
#include "stv06xx.h"
-#define IS_850(sd) ((sd)->gspca_dev.dev->descriptor.idProduct == 0x850)
-#define IS_870(sd) ((sd)->gspca_dev.dev->descriptor.idProduct == 0x870)
#define IS_1020(sd) ((sd)->sensor == &stv06xx_sensor_hdcs1020)
extern const struct stv06xx_sensor stv06xx_sensor_vv6410;
extern const struct stv06xx_sensor stv06xx_sensor_hdcs1x00;
extern const struct stv06xx_sensor stv06xx_sensor_hdcs1020;
extern const struct stv06xx_sensor stv06xx_sensor_pb0100;
+extern const struct stv06xx_sensor stv06xx_sensor_st6422;
struct stv06xx_sensor {
/* Defines the name of a sensor */
diff --git a/linux/drivers/media/video/gspca/stv06xx/stv06xx_st6422.c b/linux/drivers/media/video/gspca/stv06xx/stv06xx_st6422.c
new file mode 100644
index 000000000..87cb5b9dd
--- /dev/null
+++ b/linux/drivers/media/video/gspca/stv06xx/stv06xx_st6422.c
@@ -0,0 +1,453 @@
+/*
+ * Support for the sensor part which is integrated (I think) into the
+ * st6422 stv06xx alike bridge, as its integrated there are no i2c writes
+ * but instead direct bridge writes.
+ *
+ * Copyright (c) 2009 Hans de Goede <hdegoede@redhat.com>
+ *
+ * Strongly based on qc-usb-messenger, which is:
+ * Copyright (c) 2001 Jean-Fredric Clere, Nikolas Zimmermann, Georg Acher
+ * Mark Cave-Ayland, Carlo E Prelz, Dick Streefland
+ * Copyright (c) 2002, 2003 Tuukka Toivonen
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#include "stv06xx_st6422.h"
+
+static struct v4l2_pix_format st6422_mode[] = {
+ /* Note we actually get 124 lines of data, of which we skip the 4st
+ 4 as they are garbage */
+ {
+ 162,
+ 120,
+ V4L2_PIX_FMT_SGRBG8,
+ V4L2_FIELD_NONE,
+ .sizeimage = 162 * 120,
+ .bytesperline = 162,
+ .colorspace = V4L2_COLORSPACE_SRGB,
+ .priv = 1
+ },
+ /* Note we actually get 248 lines of data, of which we skip the 4st
+ 4 as they are garbage, and we tell the app it only gets the
+ first 240 of the 244 lines it actually gets, so that it ignores
+ the last 4. */
+ {
+ 324,
+ 240,
+ V4L2_PIX_FMT_SGRBG8,
+ V4L2_FIELD_NONE,
+ .sizeimage = 324 * 244,
+ .bytesperline = 324,
+ .colorspace = V4L2_COLORSPACE_SRGB,
+ .priv = 0
+ },
+};
+
+static const struct ctrl st6422_ctrl[] = {
+#define BRIGHTNESS_IDX 0
+ {
+ {
+ .id = V4L2_CID_BRIGHTNESS,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "Brightness",
+ .minimum = 0,
+ .maximum = 31,
+ .step = 1,
+ .default_value = 3
+ },
+ .set = st6422_set_brightness,
+ .get = st6422_get_brightness
+ },
+#define CONTRAST_IDX 1
+ {
+ {
+ .id = V4L2_CID_CONTRAST,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "Contrast",
+ .minimum = 0,
+ .maximum = 15,
+ .step = 1,
+ .default_value = 11
+ },
+ .set = st6422_set_contrast,
+ .get = st6422_get_contrast
+ },
+#define GAIN_IDX 2
+ {
+ {
+ .id = V4L2_CID_GAIN,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "Gain",
+ .minimum = 0,
+ .maximum = 255,
+ .step = 1,
+ .default_value = 64
+ },
+ .set = st6422_set_gain,
+ .get = st6422_get_gain
+ },
+#define EXPOSURE_IDX 3
+ {
+ {
+ .id = V4L2_CID_EXPOSURE,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "Exposure",
+ .minimum = 0,
+ .maximum = 1023,
+ .step = 1,
+ .default_value = 256
+ },
+ .set = st6422_set_exposure,
+ .get = st6422_get_exposure
+ },
+};
+
+static int st6422_probe(struct sd *sd)
+{
+ int i;
+ s32 *sensor_settings;
+
+ if (sd->bridge != BRIDGE_ST6422)
+ return -ENODEV;
+
+ info("st6422 sensor detected");
+
+ sensor_settings = kmalloc(ARRAY_SIZE(st6422_ctrl) * sizeof(s32),
+ GFP_KERNEL);
+ if (!sensor_settings)
+ return -ENOMEM;
+
+ sd->gspca_dev.cam.cam_mode = st6422_mode;
+ sd->gspca_dev.cam.nmodes = ARRAY_SIZE(st6422_mode);
+ sd->desc.ctrls = st6422_ctrl;
+ sd->desc.nctrls = ARRAY_SIZE(st6422_ctrl);
+ sd->sensor_priv = sensor_settings;
+
+ for (i = 0; i < sd->desc.nctrls; i++)
+ sensor_settings[i] = st6422_ctrl[i].qctrl.default_value;
+
+ return 0;
+}
+
+static int st6422_init(struct sd *sd)
+{
+ int err = 0, i;
+
+ const u16 st6422_bridge_init[][2] = {
+ { STV_ISO_ENABLE, 0x00 }, /* disable capture */
+ { 0x1436, 0x00 },
+ { 0x1432, 0x03 }, /* 0x00-0x1F brightness */
+ { 0x143a, 0xF9 }, /* 0x00-0x0F contrast */
+ { 0x0509, 0x38 }, /* R */
+ { 0x050a, 0x38 }, /* G */
+ { 0x050b, 0x38 }, /* B */
+ { 0x050c, 0x2A },
+ { 0x050d, 0x01 },
+
+
+ { 0x1431, 0x00 }, /* 0x00-0x07 ??? */
+ { 0x1433, 0x34 }, /* 160x120, 0x00-0x01 night filter */
+ { 0x1438, 0x18 }, /* 640x480 */
+/* 18 bayes */
+/* 10 compressed? */
+
+ { 0x1439, 0x00 },
+/* antiflimmer?? 0xa2 ger perfekt bild mot monitor */
+
+ { 0x143b, 0x05 },
+ { 0x143c, 0x00 }, /* 0x00-0x01 - ??? */
+
+
+/* shutter time 0x0000-0x03FF */
+/* low value give good picures on moving objects (but requires much light) */
+/* high value gives good picures in darkness (but tends to be overexposed) */
+ { 0x143e, 0x01 },
+ { 0x143d, 0x00 },
+
+ { 0x1442, 0xe2 },
+/* write: 1x1x xxxx */
+/* read: 1x1x xxxx */
+/* bit 5 == button pressed and hold if 0 */
+/* write 0xe2,0xea */
+
+/* 0x144a */
+/* 0x00 init */
+/* bit 7 == button has been pressed, but not handled */
+
+/* interrupt */
+/* if(urb->iso_frame_desc[i].status == 0x80) { */
+/* if(urb->iso_frame_desc[i].status == 0x88) { */
+
+ { 0x1500, 0xd0 },
+ { 0x1500, 0xd0 },
+ { 0x1500, 0x50 }, /* 0x00 - 0xFF 0x80 == compr ? */
+
+ { 0x1501, 0xaf },
+/* high val-> ljus area blir morkare. */
+/* low val -> ljus area blir ljusare. */
+ { 0x1502, 0xc2 },
+/* high val-> ljus area blir morkare. */
+/* low val -> ljus area blir ljusare. */
+ { 0x1503, 0x45 },
+/* high val-> ljus area blir morkare. */
+/* low val -> ljus area blir ljusare. */
+
+ { 0x1505, 0x02 },
+/* 2 : 324x248 80352 bytes */
+/* 7 : 248x162 40176 bytes */
+/* c+f: 162*124 20088 bytes */
+
+ { 0x150e, 0x8e },
+ { 0x150f, 0x37 },
+ { 0x15c0, 0x00 },
+ { 0x15c1, 1023 }, /* 160x120, ISOC_PACKET_SIZE */
+ { 0x15c3, 0x08 }, /* 0x04/0x14 ... test pictures ??? */
+
+
+ { 0x143f, 0x01 }, /* commit settings */
+
+ };
+
+ for (i = 0; i < ARRAY_SIZE(st6422_bridge_init) && !err; i++) {
+ err = stv06xx_write_bridge(sd, st6422_bridge_init[i][0],
+ st6422_bridge_init[i][1]);
+ }
+
+ return err;
+}
+
+static void st6422_disconnect(struct sd *sd)
+{
+ sd->sensor = NULL;
+ kfree(sd->sensor_priv);
+}
+
+static int st6422_start(struct sd *sd)
+{
+ int err, packet_size;
+ struct cam *cam = &sd->gspca_dev.cam;
+ s32 *sensor_settings = sd->sensor_priv;
+ struct usb_host_interface *alt;
+ struct usb_interface *intf;
+
+ intf = usb_ifnum_to_if(sd->gspca_dev.dev, sd->gspca_dev.iface);
+ alt = usb_altnum_to_altsetting(intf, sd->gspca_dev.alt);
+ if (!alt) {
+ PDEBUG(D_ERR, "Couldn't get altsetting");
+ return -EIO;
+ }
+
+ packet_size = le16_to_cpu(alt->endpoint[0].desc.wMaxPacketSize);
+ err = stv06xx_write_bridge(sd, 0x15c1, packet_size);
+ if (err < 0)
+ return err;
+
+ if (cam->cam_mode[sd->gspca_dev.curr_mode].priv)
+ err = stv06xx_write_bridge(sd, 0x1505, 0x0f);
+ else
+ err = stv06xx_write_bridge(sd, 0x1505, 0x02);
+ if (err < 0)
+ return err;
+
+ err = st6422_set_brightness(&sd->gspca_dev,
+ sensor_settings[BRIGHTNESS_IDX]);
+ if (err < 0)
+ return err;
+
+ err = st6422_set_contrast(&sd->gspca_dev,
+ sensor_settings[CONTRAST_IDX]);
+ if (err < 0)
+ return err;
+
+ err = st6422_set_exposure(&sd->gspca_dev,
+ sensor_settings[EXPOSURE_IDX]);
+ if (err < 0)
+ return err;
+
+ err = st6422_set_gain(&sd->gspca_dev,
+ sensor_settings[GAIN_IDX]);
+ if (err < 0)
+ return err;
+
+ PDEBUG(D_STREAM, "Starting stream");
+
+ return 0;
+}
+
+static int st6422_stop(struct sd *sd)
+{
+ PDEBUG(D_STREAM, "Halting stream");
+
+ return 0;
+}
+
+static int st6422_get_brightness(struct gspca_dev *gspca_dev, __s32 *val)
+{
+ struct sd *sd = (struct sd *) gspca_dev;
+ s32 *sensor_settings = sd->sensor_priv;
+
+ *val = sensor_settings[BRIGHTNESS_IDX];
+
+ PDEBUG(D_V4L2, "Read brightness %d", *val);
+
+ return 0;
+}
+
+static int st6422_set_brightness(struct gspca_dev *gspca_dev, __s32 val)
+{
+ int err;
+ struct sd *sd = (struct sd *) gspca_dev;
+ s32 *sensor_settings = sd->sensor_priv;
+
+ sensor_settings[BRIGHTNESS_IDX] = val;
+
+ if (!gspca_dev->streaming)
+ return 0;
+
+ /* val goes from 0 -> 31 */
+ PDEBUG(D_V4L2, "Set brightness to %d", val);
+ err = stv06xx_write_bridge(sd, 0x1432, val);
+ if (err < 0)
+ return err;
+
+ /* commit settings */
+ err = stv06xx_write_bridge(sd, 0x143f, 0x01);
+ return (err < 0) ? err : 0;
+}
+
+static int st6422_get_contrast(struct gspca_dev *gspca_dev, __s32 *val)
+{
+ struct sd *sd = (struct sd *) gspca_dev;
+ s32 *sensor_settings = sd->sensor_priv;
+
+ *val = sensor_settings[CONTRAST_IDX];
+
+ PDEBUG(D_V4L2, "Read contrast %d", *val);
+
+ return 0;
+}
+
+static int st6422_set_contrast(struct gspca_dev *gspca_dev, __s32 val)
+{
+ int err;
+ struct sd *sd = (struct sd *) gspca_dev;
+ s32 *sensor_settings = sd->sensor_priv;
+
+ sensor_settings[CONTRAST_IDX] = val;
+
+ if (!gspca_dev->streaming)
+ return 0;
+
+ /* Val goes from 0 -> 15 */
+ PDEBUG(D_V4L2, "Set contrast to %d\n", val);
+ err = stv06xx_write_bridge(sd, 0x143a, 0xf0 | val);
+ if (err < 0)
+ return err;
+
+ /* commit settings */
+ err = stv06xx_write_bridge(sd, 0x143f, 0x01);
+ return (err < 0) ? err : 0;
+}
+
+static int st6422_get_gain(struct gspca_dev *gspca_dev, __s32 *val)
+{
+ struct sd *sd = (struct sd *) gspca_dev;
+ s32 *sensor_settings = sd->sensor_priv;
+
+ *val = sensor_settings[GAIN_IDX];
+
+ PDEBUG(D_V4L2, "Read gain %d", *val);
+
+ return 0;
+}
+
+static int st6422_set_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;
+
+ if (!gspca_dev->streaming)
+ return 0;
+
+ PDEBUG(D_V4L2, "Set gain to %d", val);
+
+ /* Set red, green, blue, gain */
+ err = stv06xx_write_bridge(sd, 0x0509, val);
+ if (err < 0)
+ return err;
+
+ err = stv06xx_write_bridge(sd, 0x050a, val);
+ if (err < 0)
+ return err;
+
+ err = stv06xx_write_bridge(sd, 0x050b, val);
+ if (err < 0)
+ return err;
+
+ /* 2 mystery writes */
+ err = stv06xx_write_bridge(sd, 0x050c, 0x2a);
+ if (err < 0)
+ return err;
+
+ err = stv06xx_write_bridge(sd, 0x050d, 0x01);
+ if (err < 0)
+ return err;
+
+ /* commit settings */
+ err = stv06xx_write_bridge(sd, 0x143f, 0x01);
+ return (err < 0) ? err : 0;
+}
+
+static int st6422_get_exposure(struct gspca_dev *gspca_dev, __s32 *val)
+{
+ struct sd *sd = (struct sd *) gspca_dev;
+ s32 *sensor_settings = sd->sensor_priv;
+
+ *val = sensor_settings[EXPOSURE_IDX];
+
+ PDEBUG(D_V4L2, "Read exposure %d", *val);
+
+ return 0;
+}
+
+static int st6422_set_exposure(struct gspca_dev *gspca_dev, __s32 val)
+{
+ int err;
+ struct sd *sd = (struct sd *) gspca_dev;
+ s32 *sensor_settings = sd->sensor_priv;
+
+ sensor_settings[EXPOSURE_IDX] = val;
+
+ if (!gspca_dev->streaming)
+ return 0;
+
+ PDEBUG(D_V4L2, "Set exposure to %d\n", val);
+ err = stv06xx_write_bridge(sd, 0x143d, val & 0xff);
+ if (err < 0)
+ return err;
+
+ err = stv06xx_write_bridge(sd, 0x143e, val >> 8);
+ if (err < 0)
+ return err;
+
+ /* commit settings */
+ err = stv06xx_write_bridge(sd, 0x143f, 0x01);
+ return (err < 0) ? err : 0;
+}
diff --git a/linux/drivers/media/video/gspca/stv06xx/stv06xx_st6422.h b/linux/drivers/media/video/gspca/stv06xx/stv06xx_st6422.h
new file mode 100644
index 000000000..b2d45fe50
--- /dev/null
+++ b/linux/drivers/media/video/gspca/stv06xx/stv06xx_st6422.h
@@ -0,0 +1,59 @@
+/*
+ * Support for the sensor part which is integrated (I think) into the
+ * st6422 stv06xx alike bridge, as its integrated there are no i2c writes
+ * but instead direct bridge writes.
+ *
+ * Copyright (c) 2009 Hans de Goede <hdegoede@redhat.com>
+ *
+ * Strongly based on qc-usb-messenger, which is:
+ * Copyright (c) 2001 Jean-Fredric Clere, Nikolas Zimmermann, Georg Acher
+ * Mark Cave-Ayland, Carlo E Prelz, Dick Streefland
+ * Copyright (c) 2002, 2003 Tuukka Toivonen
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#ifndef STV06XX_ST6422_H_
+#define STV06XX_ST6422_H_
+
+#include "stv06xx_sensor.h"
+
+static int st6422_probe(struct sd *sd);
+static int st6422_start(struct sd *sd);
+static int st6422_init(struct sd *sd);
+static int st6422_stop(struct sd *sd);
+static void st6422_disconnect(struct sd *sd);
+
+/* V4L2 controls supported by the driver */
+static int st6422_get_brightness(struct gspca_dev *gspca_dev, __s32 *val);
+static int st6422_set_brightness(struct gspca_dev *gspca_dev, __s32 val);
+static int st6422_get_contrast(struct gspca_dev *gspca_dev, __s32 *val);
+static int st6422_set_contrast(struct gspca_dev *gspca_dev, __s32 val);
+static int st6422_get_gain(struct gspca_dev *gspca_dev, __s32 *val);
+static int st6422_set_gain(struct gspca_dev *gspca_dev, __s32 val);
+static int st6422_get_exposure(struct gspca_dev *gspca_dev, __s32 *val);
+static int st6422_set_exposure(struct gspca_dev *gspca_dev, __s32 val);
+
+const struct stv06xx_sensor stv06xx_sensor_st6422 = {
+ .name = "ST6422",
+ .init = st6422_init,
+ .probe = st6422_probe,
+ .start = st6422_start,
+ .stop = st6422_stop,
+ .disconnect = st6422_disconnect,
+};
+
+#endif
diff --git a/linux/drivers/media/video/hdpvr/hdpvr-video.c b/linux/drivers/media/video/hdpvr/hdpvr-video.c
index 3e6ffee8d..ccd47f57f 100644
--- a/linux/drivers/media/video/hdpvr/hdpvr-video.c
+++ b/linux/drivers/media/video/hdpvr/hdpvr-video.c
@@ -181,7 +181,7 @@ static int hdpvr_submit_buffers(struct hdpvr_device *dev)
buff_list);
if (buf->status != BUFSTAT_AVAILABLE) {
v4l2_err(&dev->v4l2_dev,
- "buffer not marked as availbale\n");
+ "buffer not marked as available\n");
ret = -EFAULT;
goto err;
}
diff --git a/linux/drivers/media/video/ivtv/ivtv-controls.c b/linux/drivers/media/video/ivtv/ivtv-controls.c
index 84995bcf4..a3b77ed3f 100644
--- a/linux/drivers/media/video/ivtv/ivtv-controls.c
+++ b/linux/drivers/media/video/ivtv/ivtv-controls.c
@@ -60,6 +60,8 @@ int ivtv_queryctrl(struct file *file, void *fh, struct v4l2_queryctrl *qctrl)
switch (qctrl->id) {
/* Standard V4L2 controls */
+ case V4L2_CID_USER_CLASS:
+ return v4l2_ctrl_query_fill(qctrl, 0, 0, 0, 0);
case V4L2_CID_BRIGHTNESS:
case V4L2_CID_HUE:
case V4L2_CID_SATURATION:
diff --git a/linux/drivers/media/video/ivtv/ivtv-driver.c b/linux/drivers/media/video/ivtv/ivtv-driver.c
index edb81a948..9f91838d7 100644
--- a/linux/drivers/media/video/ivtv/ivtv-driver.c
+++ b/linux/drivers/media/video/ivtv/ivtv-driver.c
@@ -455,7 +455,7 @@ static void ivtv_process_eeprom(struct ivtv *itv)
break;
}
if (tv.tuner_type == TUNER_ABSENT)
- IVTV_ERR("tveeprom cannot autodetect tuner!");
+ IVTV_ERR("tveeprom cannot autodetect tuner!\n");
if (itv->options.tuner == -1)
itv->options.tuner = tv.tuner_type;
diff --git a/linux/drivers/media/video/ivtv/ivtv-i2c.c b/linux/drivers/media/video/ivtv/ivtv-i2c.c
index eed4d2364..484a323f1 100644
--- a/linux/drivers/media/video/ivtv/ivtv-i2c.c
+++ b/linux/drivers/media/video/ivtv/ivtv-i2c.c
@@ -639,6 +639,7 @@ int init_ivtv_i2c(struct ivtv *itv)
retval = i2c_add_adapter(&itv->i2c_adap);
else
retval = i2c_bit_add_bus(&itv->i2c_adap);
+
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 30)
/* Instantiate the IR receiver device, if present */
if (retval == 0) {
@@ -666,6 +667,7 @@ int init_ivtv_i2c(struct ivtv *itv)
i2c_new_probed_device(&itv->i2c_adap, &info, addr_list);
}
#endif
+
return retval;
}
diff --git a/linux/drivers/media/video/ivtv/ivtv-queue.c b/linux/drivers/media/video/ivtv/ivtv-queue.c
index ff7b7dede..7fde36e6d 100644
--- a/linux/drivers/media/video/ivtv/ivtv-queue.c
+++ b/linux/drivers/media/video/ivtv/ivtv-queue.c
@@ -230,7 +230,8 @@ int ivtv_stream_alloc(struct ivtv_stream *s)
return -ENOMEM;
}
if (ivtv_might_use_dma(s)) {
- s->sg_handle = pci_map_single(itv->pdev, 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), PCI_DMA_TODEVICE);
ivtv_stream_sync_for_cpu(s);
}
diff --git a/linux/drivers/media/video/mx3_camera.c b/linux/drivers/media/video/mx3_camera.c
index 4d47eeb14..e605c076e 100644
--- a/linux/drivers/media/video/mx3_camera.c
+++ b/linux/drivers/media/video/mx3_camera.c
@@ -1074,7 +1074,7 @@ static struct soc_camera_host_ops mx3_soc_camera_host_ops = {
.set_bus_param = mx3_camera_set_bus_param,
};
-static int mx3_camera_probe(struct platform_device *pdev)
+static int __devinit mx3_camera_probe(struct platform_device *pdev)
{
struct mx3_camera_dev *mx3_cam;
struct resource *res;
@@ -1194,11 +1194,11 @@ static struct platform_driver mx3_camera_driver = {
.name = MX3_CAM_DRV_NAME,
},
.probe = mx3_camera_probe,
- .remove = __exit_p(mx3_camera_remove),
+ .remove = __devexit_p(mx3_camera_remove),
};
-static int __devinit mx3_camera_init(void)
+static int __init mx3_camera_init(void)
{
return platform_driver_register(&mx3_camera_driver);
}
diff --git a/linux/drivers/media/video/ov511.c b/linux/drivers/media/video/ov511.c
index 12d109eaa..346eed722 100644
--- a/linux/drivers/media/video/ov511.c
+++ b/linux/drivers/media/video/ov511.c
@@ -112,6 +112,8 @@ static int framedrop = -1;
static int fastset;
static int force_palette;
static int backlight;
+/* Bitmask marking allocated devices from 0 to OV511_MAX_UNIT_VIDEO */
+static unsigned long ov511_devused;
static int unit_video[OV511_MAX_UNIT_VIDEO];
static int remove_zeros;
static int mirror;
@@ -209,8 +211,6 @@ static const int i2c_detect_tries = 5;
static struct usb_device_id device_table [] = {
{ USB_DEVICE(VEND_OMNIVISION, PROD_OV511) },
{ USB_DEVICE(VEND_OMNIVISION, PROD_OV511PLUS) },
- { USB_DEVICE(VEND_OMNIVISION, PROD_OV518) },
- { USB_DEVICE(VEND_OMNIVISION, PROD_OV518PLUS) },
{ USB_DEVICE(VEND_MATTEL, PROD_ME2CAM) },
{ } /* Terminating entry */
};
@@ -5724,7 +5724,7 @@ ov51x_probe(struct usb_interface *intf, const struct usb_device_id *id)
struct usb_device *dev = interface_to_usbdev(intf);
struct usb_interface_descriptor *idesc;
struct usb_ov511 *ov;
- int i;
+ int i, rc, nr;
PDEBUG(1, "probing for device...");
@@ -5849,33 +5849,41 @@ ov51x_probe(struct usb_interface *intf, const struct usb_device_id *id)
ov->vdev->parent = &intf->dev;
video_set_drvdata(ov->vdev, ov);
- for (i = 0; i < OV511_MAX_UNIT_VIDEO; i++) {
- /* Minor 0 cannot be specified; assume user wants autodetect */
- if (unit_video[i] == 0)
- break;
+ mutex_lock(&ov->lock);
- if (video_register_device(ov->vdev, VFL_TYPE_GRABBER,
- unit_video[i]) >= 0) {
- break;
- }
- }
+ /* Check to see next free device and mark as used */
+ nr = find_first_zero_bit(&ov511_devused, OV511_MAX_UNIT_VIDEO);
+
+ /* Registers device */
+ if (unit_video[nr] != 0)
+ rc = video_register_device(ov->vdev, VFL_TYPE_GRABBER,
+ unit_video[nr]);
+ else
+ rc = video_register_device(ov->vdev, VFL_TYPE_GRABBER, -1);
- /* Use the next available one */
- if ((ov->vdev->minor == -1) &&
- video_register_device(ov->vdev, VFL_TYPE_GRABBER, -1) < 0) {
+ if (rc < 0) {
err("video_register_device failed");
+ mutex_unlock(&ov->lock);
goto error;
}
+ /* Mark device as used */
+ ov511_devused |= 1 << nr;
+ ov->nr = nr;
+
dev_info(&intf->dev, "Device at %s registered to minor %d\n",
ov->usb_path, ov->vdev->minor);
usb_set_intfdata(intf, ov);
if (ov_create_sysfs(ov->vdev)) {
err("ov_create_sysfs failed");
+ ov511_devused &= ~(1 << nr);
+ mutex_unlock(&ov->lock);
goto error;
}
+ mutex_lock(&ov->lock);
+
return 0;
error:
@@ -5910,10 +5918,16 @@ ov51x_disconnect(struct usb_interface *intf)
PDEBUG(3, "");
+ mutex_lock(&ov->lock);
usb_set_intfdata (intf, NULL);
- if (!ov)
+ if (!ov) {
+ mutex_unlock(&ov->lock);
return;
+ }
+
+ /* Free device number */
+ ov511_devused &= ~(1 << ov->nr);
if (ov->vdev)
video_unregister_device(ov->vdev);
@@ -5931,6 +5945,7 @@ ov51x_disconnect(struct usb_interface *intf)
ov->streaming = 0;
ov51x_unlink_isoc(ov);
+ mutex_unlock(&ov->lock);
ov->dev = NULL;
diff --git a/linux/drivers/media/video/ov511.h b/linux/drivers/media/video/ov511.h
index c303ac5a8..c213d944e 100644
--- a/linux/drivers/media/video/ov511.h
+++ b/linux/drivers/media/video/ov511.h
@@ -495,6 +495,9 @@ struct usb_ov511 {
int has_decoder; /* Device has a video decoder */
int pal; /* Device is designed for PAL resolution */
+ /* ov511 device number ID */
+ int nr; /* Stores a device number */
+
/* I2C interface */
struct mutex i2c_lock; /* Protect I2C controller regs */
unsigned char primary_i2c_slave; /* I2C write id of sensor */
diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-audio.c b/linux/drivers/media/video/pvrusb2/pvrusb2-audio.c
index 86049f412..42875ec21 100644
--- a/linux/drivers/media/video/pvrusb2/pvrusb2-audio.c
+++ b/linux/drivers/media/video/pvrusb2/pvrusb2-audio.c
@@ -49,11 +49,13 @@ static const int routing_scheme0[] = {
MSP_DSP_IN_SCART),
};
-static const struct routing_scheme routing_schemes[] = {
- [PVR2_ROUTING_SCHEME_HAUPPAUGE] = {
- .def = routing_scheme0,
- .cnt = ARRAY_SIZE(routing_scheme0),
- },
+static const struct routing_scheme routing_def0 = {
+ .def = routing_scheme0,
+ .cnt = ARRAY_SIZE(routing_scheme0),
+};
+
+static const struct routing_scheme *routing_schemes[] = {
+ [PVR2_ROUTING_SCHEME_HAUPPAUGE] = &routing_def0,
};
void pvr2_msp3400_subdev_update(struct pvr2_hdw *hdw, struct v4l2_subdev *sd)
@@ -66,7 +68,7 @@ void pvr2_msp3400_subdev_update(struct pvr2_hdw *hdw, struct v4l2_subdev *sd)
pvr2_trace(PVR2_TRACE_CHIPS, "subdev msp3400 v4l2 set_stereo");
if ((sid < ARRAY_SIZE(routing_schemes)) &&
- ((sp = routing_schemes + sid) != NULL) &&
+ ((sp = routing_schemes[sid]) != NULL) &&
(hdw->input_val >= 0) &&
(hdw->input_val < sp->cnt)) {
input = sp->def[hdw->input_val];
diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-cs53l32a.c b/linux/drivers/media/video/pvrusb2/pvrusb2-cs53l32a.c
index f99b77c92..7bcaa0cd4 100644
--- a/linux/drivers/media/video/pvrusb2/pvrusb2-cs53l32a.c
+++ b/linux/drivers/media/video/pvrusb2/pvrusb2-cs53l32a.c
@@ -50,11 +50,13 @@ static const int routing_scheme1[] = {
[PVR2_CVAL_INPUT_SVIDEO] = 0,
};
-static const struct routing_scheme routing_schemes[] = {
- [PVR2_ROUTING_SCHEME_ONAIR] = {
- .def = routing_scheme1,
- .cnt = ARRAY_SIZE(routing_scheme1),
- },
+static const struct routing_scheme routing_def1 = {
+ .def = routing_scheme1,
+ .cnt = ARRAY_SIZE(routing_scheme1),
+};
+
+static const struct routing_scheme *routing_schemes[] = {
+ [PVR2_ROUTING_SCHEME_ONAIR] = &routing_def1,
};
@@ -66,12 +68,11 @@ void pvr2_cs53l32a_subdev_update(struct pvr2_hdw *hdw, struct v4l2_subdev *sd)
u32 input;
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)) {
- input = sp->def[hdw->input_val];
- } else {
+ sp = (sid < ARRAY_SIZE(routing_schemes)) ?
+ routing_schemes[sid] : NULL;
+ if ((sp == NULL) ||
+ (hdw->input_val < 0) ||
+ (hdw->input_val >= sp->cnt)) {
pvr2_trace(PVR2_TRACE_ERROR_LEGS,
"*** WARNING *** subdev v4l2 set_input:"
" Invalid routing scheme (%u)"
@@ -79,6 +80,7 @@ void pvr2_cs53l32a_subdev_update(struct pvr2_hdw *hdw, struct v4l2_subdev *sd)
sid, hdw->input_val);
return;
}
+ input = sp->def[hdw->input_val];
sd->ops->audio->s_routing(sd, input, 0, 0);
}
}
diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.c b/linux/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.c
index ef47c3874..e15d7fb6c 100644
--- a/linux/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.c
+++ b/linux/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.c
@@ -69,6 +69,11 @@ static const struct routing_scheme_item routing_scheme0[] = {
},
};
+static const struct routing_scheme routing_def0 = {
+ .def = routing_scheme0,
+ .cnt = ARRAY_SIZE(routing_scheme0),
+};
+
/* Specific to gotview device */
static const struct routing_scheme_item routing_schemegv[] = {
[PVR2_CVAL_INPUT_TV] = {
@@ -91,15 +96,14 @@ static const struct routing_scheme_item routing_schemegv[] = {
},
};
-static const struct routing_scheme routing_schemes[] = {
- [PVR2_ROUTING_SCHEME_HAUPPAUGE] = {
- .def = routing_scheme0,
- .cnt = ARRAY_SIZE(routing_scheme0),
- },
- [PVR2_ROUTING_SCHEME_GOTVIEW] = {
- .def = routing_schemegv,
- .cnt = ARRAY_SIZE(routing_schemegv),
- },
+static const struct routing_scheme routing_defgv = {
+ .def = routing_schemegv,
+ .cnt = ARRAY_SIZE(routing_schemegv),
+};
+
+static const struct routing_scheme *routing_schemes[] = {
+ [PVR2_ROUTING_SCHEME_HAUPPAUGE] = &routing_def0,
+ [PVR2_ROUTING_SCHEME_GOTVIEW] = &routing_defgv,
};
void pvr2_cx25840_subdev_update(struct pvr2_hdw *hdw, struct v4l2_subdev *sd)
@@ -111,13 +115,11 @@ void pvr2_cx25840_subdev_update(struct pvr2_hdw *hdw, struct v4l2_subdev *sd)
const struct routing_scheme *sp;
unsigned int sid = hdw->hdw_desc->signal_routing_scheme;
- 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 {
+ sp = (sid < ARRAY_SIZE(routing_schemes)) ?
+ routing_schemes[sid] : NULL;
+ if ((sp == NULL) ||
+ (hdw->input_val < 0) ||
+ (hdw->input_val >= sp->cnt)) {
pvr2_trace(PVR2_TRACE_ERROR_LEGS,
"*** WARNING *** subdev cx2584x set_input:"
" Invalid routing scheme (%u)"
@@ -125,7 +127,8 @@ void pvr2_cx25840_subdev_update(struct pvr2_hdw *hdw, struct v4l2_subdev *sd)
sid, hdw->input_val);
return;
}
-
+ vid_input = sp->def[hdw->input_val].vid;
+ aud_input = sp->def[hdw->input_val].aud;
pvr2_trace(PVR2_TRACE_CHIPS,
"subdev cx2584x set_input vid=0x%x aud=0x%x",
vid_input, aud_input);
diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c
index 3411cb36a..0bbd20f13 100644
--- a/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c
+++ b/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c
@@ -86,8 +86,8 @@ MODULE_PARM_DESC(video_std,"specify initial video standard");
module_param_array(tolerance, int, NULL, 0444);
MODULE_PARM_DESC(tolerance,"specify stream error tolerance");
-/* US Broadcast channel 7 (175.25 MHz) */
-static int default_tv_freq = 175250000L;
+/* US Broadcast channel 3 (61.25 MHz), to help with testing */
+static int default_tv_freq = 61250000L;
/* 104.3 MHz, a usable FM station for my area */
static int default_radio_freq = 104300000L;
@@ -2004,6 +2004,34 @@ static unsigned int pvr2_copy_i2c_addr_list(
}
+static void pvr2_hdw_cx25840_vbi_hack(struct pvr2_hdw *hdw)
+{
+ /*
+ Mike Isely <isely@pobox.com> 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;
+ if (hdw->decoder_client_id != PVR2_CLIENT_ID_CX25840) {
+ /* We're not using a cx25840 so don't enable the hack */
+ return;
+ }
+
+ pvr2_trace(PVR2_TRACE_INIT,
+ "Module ID %u:"
+ " Executing cx25840 VBI hack",
+ hdw->decoder_client_id);
+ memset(&fmt, 0, sizeof(fmt));
+ fmt.type = V4L2_BUF_TYPE_SLICED_VBI_CAPTURE;
+ v4l2_device_call_all(&hdw->v4l2_dev, hdw->decoder_client_id,
+ video, s_fmt, &fmt);
+}
+
+
static int pvr2_hdw_load_subdev(struct pvr2_hdw *hdw,
const struct pvr2_device_client_desc *cd)
{
@@ -2095,30 +2123,6 @@ static int pvr2_hdw_load_subdev(struct pvr2_hdw *hdw,
/* client-specific setup... */
switch (mid) {
case PVR2_CLIENT_ID_CX25840:
- hdw->decoder_client_id = mid;
- {
- /*
- Mike Isely <isely@pobox.com> 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;
- 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,
- video, s_fmt, &fmt);
- }
- break;
case PVR2_CLIENT_ID_SAA7115:
hdw->decoder_client_id = mid;
break;
@@ -2219,6 +2223,8 @@ static void pvr2_hdw_setup_low(struct pvr2_hdw *hdw)
cptr->info->set_value(cptr,~0,cptr->info->default_value);
}
+ pvr2_hdw_cx25840_vbi_hack(hdw);
+
/* Set up special default values for the television and radio
frequencies here. It's not really important what these defaults
are, but I set them to something usable in the Chicago area just
@@ -2976,6 +2982,7 @@ static void pvr2_subdev_update(struct pvr2_hdw *hdw)
vs = hdw->std_mask_cur;
v4l2_device_call_all(&hdw->v4l2_dev, 0,
core, s_std, vs);
+ pvr2_hdw_cx25840_vbi_hack(hdw);
}
hdw->tuner_signal_stale = !0;
hdw->cropcap_stale = !0;
@@ -4170,6 +4177,7 @@ int pvr2_hdw_cmd_decoder_reset(struct pvr2_hdw *hdw)
if (hdw->decoder_client_id) {
v4l2_device_call_all(&hdw->v4l2_dev, hdw->decoder_client_id,
core, reset, 0);
+ pvr2_hdw_cx25840_vbi_hack(hdw);
return 0;
}
pvr2_trace(PVR2_TRACE_INIT,
diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-video-v4l.c b/linux/drivers/media/video/pvrusb2/pvrusb2-video-v4l.c
index d240331a6..4be489c45 100644
--- a/linux/drivers/media/video/pvrusb2/pvrusb2-video-v4l.c
+++ b/linux/drivers/media/video/pvrusb2/pvrusb2-video-v4l.c
@@ -55,6 +55,11 @@ static const int routing_scheme0[] = {
[PVR2_CVAL_INPUT_SVIDEO] = SAA7115_SVIDEO2,
};
+static const struct routing_scheme routing_def0 = {
+ .def = routing_scheme0,
+ .cnt = ARRAY_SIZE(routing_scheme0),
+};
+
static const int routing_scheme1[] = {
[PVR2_CVAL_INPUT_TV] = SAA7115_COMPOSITE4,
[PVR2_CVAL_INPUT_RADIO] = SAA7115_COMPOSITE5,
@@ -62,15 +67,14 @@ static const int routing_scheme1[] = {
[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),
- },
+static const struct routing_scheme routing_def1 = {
+ .def = routing_scheme1,
+ .cnt = ARRAY_SIZE(routing_scheme1),
+};
+
+static const struct routing_scheme *routing_schemes[] = {
+ [PVR2_ROUTING_SCHEME_HAUPPAUGE] = &routing_def0,
+ [PVR2_ROUTING_SCHEME_ONAIR] = &routing_def1,
};
void pvr2_saa7115_subdev_update(struct pvr2_hdw *hdw, struct v4l2_subdev *sd)
@@ -82,12 +86,12 @@ void pvr2_saa7115_subdev_update(struct pvr2_hdw *hdw, struct v4l2_subdev *sd)
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)) {
- input = sp->def[hdw->input_val];
- } else {
+
+ sp = (sid < ARRAY_SIZE(routing_schemes)) ?
+ routing_schemes[sid] : NULL;
+ if ((sp == NULL) ||
+ (hdw->input_val < 0) ||
+ (hdw->input_val >= sp->cnt)) {
pvr2_trace(PVR2_TRACE_ERROR_LEGS,
"*** WARNING *** subdev v4l2 set_input:"
" Invalid routing scheme (%u)"
@@ -95,6 +99,7 @@ void pvr2_saa7115_subdev_update(struct pvr2_hdw *hdw, struct v4l2_subdev *sd)
sid, hdw->input_val);
return;
}
+ input = sp->def[hdw->input_val];
sd->ops->video->s_routing(sd, input, 0, 0);
}
}
diff --git a/linux/drivers/media/video/pwc/pwc-if.c b/linux/drivers/media/video/pwc/pwc-if.c
index b3765e280..4087612ee 100644
--- a/linux/drivers/media/video/pwc/pwc-if.c
+++ b/linux/drivers/media/video/pwc/pwc-if.c
@@ -605,7 +605,7 @@ static void pwc_snapshot_button(struct pwc_device *pdev, int down)
#ifdef CONFIG_USB_PWC_INPUT_EVDEV
if (pdev->button_dev) {
- input_report_key(pdev->button_dev, BTN_0, down);
+ input_report_key(pdev->button_dev, KEY_CAMERA, down);
input_sync(pdev->button_dev);
}
#endif
@@ -1791,7 +1791,7 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id
return -ENOMEM;
}
memcpy(pdev->vdev, &pwc_template, sizeof(pwc_template));
- pdev->vdev->parent = &(udev->dev);
+ pdev->vdev->parent = &intf->dev;
strcpy(pdev->vdev->name, name);
video_set_drvdata(pdev->vdev, pdev);
@@ -1859,7 +1859,7 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id
pdev->button_dev->cdev.dev = &pdev->udev->dev;
#endif
pdev->button_dev->evbit[0] = BIT_MASK(EV_KEY);
- pdev->button_dev->keybit[BIT_WORD(BTN_0)] = BIT_MASK(BTN_0);
+ pdev->button_dev->keybit[BIT_WORD(KEY_CAMERA)] = BIT_MASK(KEY_CAMERA);
rc = input_register_device(pdev->button_dev);
if (rc) {
diff --git a/linux/drivers/media/video/pxa_camera.c b/linux/drivers/media/video/pxa_camera.c
index 2c122ec90..8964d60cd 100644
--- a/linux/drivers/media/video/pxa_camera.c
+++ b/linux/drivers/media/video/pxa_camera.c
@@ -1403,13 +1403,15 @@ static int pxa_camera_try_fmt(struct soc_camera_device *icd,
return -EINVAL;
}
- /* Limit to pxa hardware capabilities. YUV422P planar format requires
+ /*
+ * Limit to pxa hardware capabilities. YUV422P planar format requires
* images size to be a multiple of 16 bytes. If not, zeros will be
* inserted between Y and U planes, and U and V planes, which violates
- * the YUV422P standard. */
- v4l2_bound_align_image(&pix->width, 48, 2048, 1,
- &pix->height, 32, 2048, 0,
- xlate->host_fmt->fourcc == V4L2_PIX_FMT_YUV422P ? 4 : 0);
+ * the YUV422P standard.
+ */
+ v4l_bound_align_image(&pix->width, 48, 2048, 1,
+ &pix->height, 32, 2048, 0,
+ xlate->host_fmt->fourcc == V4L2_PIX_FMT_YUV422P ? 4 : 0);
pix->bytesperline = pix->width *
DIV_ROUND_UP(xlate->host_fmt->depth, 8);
@@ -1541,7 +1543,7 @@ static struct soc_camera_host_ops pxa_soc_camera_host_ops = {
.set_bus_param = pxa_camera_set_bus_param,
};
-static int pxa_camera_probe(struct platform_device *pdev)
+static int __devinit pxa_camera_probe(struct platform_device *pdev)
{
struct pxa_camera_dev *pcdev;
struct resource *res;
@@ -1716,11 +1718,11 @@ static struct platform_driver pxa_camera_driver = {
.name = PXA_CAM_DRV_NAME,
},
.probe = pxa_camera_probe,
- .remove = __exit_p(pxa_camera_remove),
+ .remove = __devexit_p(pxa_camera_remove),
};
-static int __devinit pxa_camera_init(void)
+static int __init pxa_camera_init(void)
{
return platform_driver_register(&pxa_camera_driver);
}
diff --git a/linux/drivers/media/video/saa7134/Makefile b/linux/drivers/media/video/saa7134/Makefile
index 3dbaa19a6..604158a8c 100644
--- a/linux/drivers/media/video/saa7134/Makefile
+++ b/linux/drivers/media/video/saa7134/Makefile
@@ -3,8 +3,7 @@ saa7134-objs := saa7134-cards.o saa7134-core.o saa7134-i2c.o \
saa7134-ts.o saa7134-tvaudio.o saa7134-vbi.o \
saa7134-video.o saa7134-input.o
-obj-$(CONFIG_VIDEO_SAA7134) += saa7134.o saa7134-empress.o \
- saa6752hs.o
+obj-$(CONFIG_VIDEO_SAA7134) += saa6752hs.o saa7134.o saa7134-empress.o
obj-$(CONFIG_VIDEO_SAA7134_ALSA) += saa7134-alsa.o
diff --git a/linux/drivers/media/video/saa7134/saa7134-cards.c b/linux/drivers/media/video/saa7134/saa7134-cards.c
index 587209fdd..e2d98ff5c 100644
--- a/linux/drivers/media/video/saa7134/saa7134-cards.c
+++ b/linux/drivers/media/video/saa7134/saa7134-cards.c
@@ -4497,6 +4497,7 @@ struct saa7134_board saa7134_boards[] = {
/* Igor Kuznetsov <igk@igk.ru> */
/* Andrey Melnikoff <temnota@kmv.ru> */
/* Beholder Intl. Ltd. Dmitry Belimov <d.belimov@gmail.com> */
+ /* Alexey Osipov <lion-simba@pridelands.ru> */
.name = "Beholder BeholdTV M6",
.audio_clock = 0x00187de7,
.tuner_type = TUNER_PHILIPS_FM1216ME_MK3,
@@ -4571,6 +4572,7 @@ struct saa7134_board saa7134_boards[] = {
/* Igor Kuznetsov <igk@igk.ru> */
/* Andrey Melnikoff <temnota@kmv.ru> */
/* Beholder Intl. Ltd. Dmitry Belimov <d.belimov@gmail.com> */
+ /* Alexey Osipov <lion-simba@pridelands.ru> */
.name = "Beholder BeholdTV M6 Extra",
.audio_clock = 0x00187de7,
.tuner_type = TUNER_PHILIPS_FM1216ME_MK3, /* FIXME to MK5 */
@@ -6239,6 +6241,12 @@ struct pci_device_id saa7134_pci_tbl[] = {
}, {
.vendor = PCI_VENDOR_ID_PHILIPS,
.device = PCI_DEVICE_ID_PHILIPS_SAA7133,
+ .subvendor = 0x1461, /* Avermedia Technologies Inc */
+ .subdevice = 0xf736,
+ .driver_data = SAA7134_BOARD_AVERMEDIA_M103,
+ }, {
+ .vendor = PCI_VENDOR_ID_PHILIPS,
+ .device = PCI_DEVICE_ID_PHILIPS_SAA7133,
.subvendor = 0x1043,
.subdevice = 0x4878, /* REV:1.02G */
.driver_data = SAA7134_BOARD_ASUSTeK_TIGER_3IN1,
diff --git a/linux/drivers/media/video/saa7134/saa7134-core.c b/linux/drivers/media/video/saa7134/saa7134-core.c
index dc692d7a7..da73430ad 100644
--- a/linux/drivers/media/video/saa7134/saa7134-core.c
+++ b/linux/drivers/media/video/saa7134/saa7134-core.c
@@ -380,6 +380,10 @@ void saa7134_buffer_next(struct saa7134_dev *dev,
dprintk("buffer_next %p\n",NULL);
saa7134_set_dmabits(dev);
del_timer(&q->timeout);
+
+ if (card_has_mpeg(dev))
+ if (dev->ts_started)
+ saa7134_ts_stop(dev);
}
}
@@ -465,6 +469,19 @@ int saa7134_set_dmabits(struct saa7134_dev *dev)
ctrl |= SAA7134_MAIN_CTRL_TE5;
irq |= SAA7134_IRQ1_INTE_RA2_1 |
SAA7134_IRQ1_INTE_RA2_0;
+
+ /* dma: setup channel 5 (= TS) */
+
+ saa_writeb(SAA7134_TS_DMA0, (dev->ts.nr_packets - 1) & 0xff);
+ saa_writeb(SAA7134_TS_DMA1,
+ ((dev->ts.nr_packets - 1) >> 8) & 0xff);
+ /* TSNOPIT=0, TSCOLAP=0 */
+ saa_writeb(SAA7134_TS_DMA2,
+ (((dev->ts.nr_packets - 1) >> 16) & 0x3f) | 0x00);
+ saa_writel(SAA7134_RS_PITCH(5), TS_PACKET_SIZE);
+ saa_writel(SAA7134_RS_CONTROL(5), SAA7134_RS_CONTROL_BURST_16 |
+ SAA7134_RS_CONTROL_ME |
+ (dev->ts.pt_ts.dma >> 12));
}
/* set task conditions + field handling */
diff --git a/linux/drivers/media/video/saa7134/saa7134-empress.c b/linux/drivers/media/video/saa7134/saa7134-empress.c
index dd22a5215..96334a20b 100644
--- a/linux/drivers/media/video/saa7134/saa7134-empress.c
+++ b/linux/drivers/media/video/saa7134/saa7134-empress.c
@@ -255,6 +255,16 @@ static int empress_s_fmt_vid_cap(struct file *file, void *priv,
return 0;
}
+static int empress_try_fmt_vid_cap(struct file *file, void *priv,
+ struct v4l2_format *f)
+{
+ struct saa7134_dev *dev = file->private_data;
+
+ f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG;
+ f->fmt.pix.sizeimage = TS_PACKET_SIZE * dev->ts.nr_packets;
+
+ return 0;
+}
static int empress_reqbufs(struct file *file, void *priv,
struct v4l2_requestbuffers *p)
@@ -450,6 +460,7 @@ static const struct v4l2_file_operations ts_fops =
static const struct v4l2_ioctl_ops ts_ioctl_ops = {
.vidioc_querycap = empress_querycap,
.vidioc_enum_fmt_vid_cap = empress_enum_fmt_vid_cap,
+ .vidioc_try_fmt_vid_cap = empress_try_fmt_vid_cap,
.vidioc_s_fmt_vid_cap = empress_s_fmt_vid_cap,
.vidioc_g_fmt_vid_cap = empress_g_fmt_vid_cap,
.vidioc_reqbufs = empress_reqbufs,
diff --git a/linux/drivers/media/video/saa7134/saa7134-ts.c b/linux/drivers/media/video/saa7134/saa7134-ts.c
index b8ff459d0..3fa652279 100644
--- a/linux/drivers/media/video/saa7134/saa7134-ts.c
+++ b/linux/drivers/media/video/saa7134/saa7134-ts.c
@@ -67,33 +67,8 @@ static int buffer_activate(struct saa7134_dev *dev,
mod_timer(&dev->ts_q.timeout, jiffies+TS_BUFFER_TIMEOUT);
- if (dev->ts_state == SAA7134_TS_BUFF_DONE) {
- /* Clear TS cache */
- dev->buff_cnt = 0;
- saa_writeb(SAA7134_TS_SERIAL1, 0x00);
- saa_writeb(SAA7134_TS_SERIAL1, 0x03);
- saa_writeb(SAA7134_TS_SERIAL1, 0x00);
- saa_writeb(SAA7134_TS_SERIAL1, 0x01);
-
- /* TS clock non-inverted */
- saa_writeb(SAA7134_TS_SERIAL1, 0x00);
-
- /* Start TS stream */
- 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;
- }
+ if (!dev->ts_started)
+ saa7134_ts_start(dev);
return 0;
}
@@ -104,7 +79,6 @@ static int buffer_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb,
struct saa7134_dev *dev = q->priv_data;
struct saa7134_buf *buf = container_of(vb,struct saa7134_buf,vb);
unsigned int lines, llength, size;
- u32 control;
int err;
dprintk("buffer_prepare [%p,%s]\n",buf,v4l2_field_names[field]);
@@ -121,8 +95,11 @@ static int buffer_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb,
}
if (VIDEOBUF_NEEDS_INIT == buf->vb.state) {
+
struct videobuf_dmabuf *dma=videobuf_to_dma(&buf->vb);
+ dprintk("buffer_prepare: needs_init\n");
+
buf->vb.width = llength;
buf->vb.height = lines;
buf->vb.size = size;
@@ -139,23 +116,6 @@ static int buffer_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb,
goto oops;
}
- dev->buff_cnt++;
-
- if (dev->buff_cnt == dev->ts.nr_bufs) {
- dev->ts_state = SAA7134_TS_BUFF_DONE;
- /* dma: setup channel 5 (= TS) */
- control = SAA7134_RS_CONTROL_BURST_16 |
- SAA7134_RS_CONTROL_ME |
- (buf->pt->dma >> 12);
-
- saa_writeb(SAA7134_TS_DMA0, (lines - 1) & 0xff);
- saa_writeb(SAA7134_TS_DMA1, ((lines - 1) >> 8) & 0xff);
- /* TSNOPIT=0, TSCOLAP=0 */
- saa_writeb(SAA7134_TS_DMA2, (((lines - 1) >> 16) & 0x3f) | 0x00);
- saa_writel(SAA7134_RS_PITCH(5), TS_PACKET_SIZE);
- saa_writel(SAA7134_RS_CONTROL(5), control);
- }
-
buf->vb.state = VIDEOBUF_PREPARED;
buf->activate = buffer_activate;
buf->vb.field = field;
@@ -175,8 +135,7 @@ buffer_setup(struct videobuf_queue *q, unsigned int *count, unsigned int *size)
if (0 == *count)
*count = dev->ts.nr_bufs;
*count = saa7134_buffer_count(*size,*count);
- dev->buff_cnt = 0;
- dev->ts_state = SAA7134_TS_STOPPED;
+
return 0;
}
@@ -193,11 +152,9 @@ static void buffer_release(struct videobuf_queue *q, struct videobuf_buffer *vb)
struct saa7134_buf *buf = container_of(vb,struct saa7134_buf,vb);
struct saa7134_dev *dev = q->priv_data;
- if (dev->ts_state == SAA7134_TS_STARTED) {
- /* Stop TS transport */
- saa_writeb(SAA7134_TS_PARALLEL, 0x6c);
- dev->ts_state = SAA7134_TS_STOPPED;
- }
+ if (dev->ts_started)
+ saa7134_ts_stop(dev);
+
saa7134_dma_free(q,buf);
}
@@ -214,7 +171,7 @@ EXPORT_SYMBOL_GPL(saa7134_ts_qops);
static unsigned int tsbufs = 8;
module_param(tsbufs, int, 0444);
-MODULE_PARM_DESC(tsbufs,"number of ts buffers, range 2-32");
+MODULE_PARM_DESC(tsbufs, "number of ts buffers for read/write IO, range 2-32");
static unsigned int ts_nr_packets = 64;
module_param(ts_nr_packets, int, 0444);
@@ -256,6 +213,7 @@ int saa7134_ts_init1(struct saa7134_dev *dev)
dev->ts_q.timeout.data = (unsigned long)(&dev->ts_q);
dev->ts_q.dev = dev;
dev->ts_q.need_two = 1;
+ dev->ts_started = 0;
saa7134_pgtable_alloc(dev->pci,&dev->ts.pt_ts);
/* init TS hw */
@@ -264,13 +222,67 @@ int saa7134_ts_init1(struct saa7134_dev *dev)
return 0;
}
+/* Function for stop TS */
+int saa7134_ts_stop(struct saa7134_dev *dev)
+{
+ dprintk("TS stop\n");
+
+ BUG_ON(!dev->ts_started);
+
+ /* Stop TS stream */
+ switch (saa7134_boards[dev->board].ts_type) {
+ case SAA7134_MPEG_TS_PARALLEL:
+ saa_writeb(SAA7134_TS_PARALLEL, 0x6c);
+ dev->ts_started = 0;
+ break;
+ case SAA7134_MPEG_TS_SERIAL:
+ saa_writeb(SAA7134_TS_SERIAL0, 0x40);
+ dev->ts_started = 0;
+ break;
+ }
+ return 0;
+}
+
+/* Function for start TS */
+int saa7134_ts_start(struct saa7134_dev *dev)
+{
+ dprintk("TS start\n");
+
+ BUG_ON(dev->ts_started);
+
+ saa_writeb(SAA7134_TS_SERIAL1, 0x00);
+ saa_writeb(SAA7134_TS_SERIAL1, 0x03);
+ saa_writeb(SAA7134_TS_SERIAL1, 0x00);
+ saa_writeb(SAA7134_TS_SERIAL1, 0x01);
+
+ /* TS clock non-inverted */
+ saa_writeb(SAA7134_TS_SERIAL1, 0x00);
+
+ /* Start TS stream */
+ 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_started = 1;
+
+ return 0;
+}
+
int saa7134_ts_fini(struct saa7134_dev *dev)
{
saa7134_pgtable_free(dev->pci,&dev->ts.pt_ts);
return 0;
}
-
void saa7134_irq_ts_done(struct saa7134_dev *dev, unsigned long status)
{
enum v4l2_field field;
diff --git a/linux/drivers/media/video/saa7134/saa7134-video.c b/linux/drivers/media/video/saa7134/saa7134-video.c
index 518de9b2c..4212c4ec8 100644
--- a/linux/drivers/media/video/saa7134/saa7134-video.c
+++ b/linux/drivers/media/video/saa7134/saa7134-video.c
@@ -1057,6 +1057,7 @@ static int buffer_prepare(struct videobuf_queue *q,
buf->vb.field = field;
buf->fmt = fh->fmt;
buf->pt = &fh->pt_cap;
+ dev->video_q.curr = NULL;
err = videobuf_iolock(q,&buf->vb,&dev->ovbuf);
if (err)
diff --git a/linux/drivers/media/video/saa7134/saa7134.h b/linux/drivers/media/video/saa7134/saa7134.h
index 385bc26bd..454802e73 100644
--- a/linux/drivers/media/video/saa7134/saa7134.h
+++ b/linux/drivers/media/video/saa7134/saa7134.h
@@ -498,12 +498,6 @@ struct saa7134_mpeg_ops {
void (*signal_change)(struct saa7134_dev *dev);
};
-enum saa7134_ts_status {
- SAA7134_TS_STOPPED,
- SAA7134_TS_BUFF_DONE,
- SAA7134_TS_STARTED,
-};
-
/* global device status */
struct saa7134_dev {
struct list_head devlist;
@@ -598,8 +592,7 @@ struct saa7134_dev {
/* SAA7134_MPEG_* */
struct saa7134_ts ts;
struct saa7134_dmaqueue ts_q;
- enum saa7134_ts_status ts_state;
- unsigned int buff_cnt;
+ int ts_started;
struct saa7134_mpeg_ops *mops;
/* SAA7134_MPEG_EMPRESS only */
@@ -757,6 +750,9 @@ void saa7134_ts_unregister(struct saa7134_mpeg_ops *ops);
int saa7134_ts_init_hw(struct saa7134_dev *dev);
+int saa7134_ts_start(struct saa7134_dev *dev);
+int saa7134_ts_stop(struct saa7134_dev *dev);
+
/* ----------------------------------------------------------- */
/* saa7134-vbi.c */
diff --git a/linux/drivers/media/video/se401.c b/linux/drivers/media/video/se401.c
index cca1cb0c4..1274a5966 100644
--- a/linux/drivers/media/video/se401.c
+++ b/linux/drivers/media/video/se401.c
@@ -38,7 +38,7 @@ static const char version[] = "0.24";
static int flickerless;
static int video_nr = -1;
-static struct usb_device_id device_table [] = {
+static struct usb_device_id device_table[] = {
{ USB_DEVICE(0x03e8, 0x0004) },/* Endpoints/Aox SE401 */
{ USB_DEVICE(0x0471, 0x030b) },/* Philips PCVC665K */
{ USB_DEVICE(0x047d, 0x5001) },/* Kensington 67014 */
@@ -53,7 +53,8 @@ MODULE_AUTHOR("Jeroen Vreeken <pe1rxq@amsat.org>");
MODULE_DESCRIPTION("SE401 USB Camera Driver");
MODULE_LICENSE("GPL");
module_param(flickerless, int, 0);
-MODULE_PARM_DESC(flickerless, "Net frequency to adjust exposure time to (0/50/60)");
+MODULE_PARM_DESC(flickerless,
+ "Net frequency to adjust exposure time to (0/50/60)");
module_param(video_nr, int, 0);
static struct usb_driver se401_driver;
@@ -78,8 +79,8 @@ static void *rvmalloc(unsigned long size)
adr = (unsigned long) mem;
while (size > 0) {
SetPageReserved(vmalloc_to_page((void *)adr));
- adr += PAGE_SIZE;
- size -= PAGE_SIZE;
+ adr += PAGE_SIZE;
+ size -= PAGE_SIZE;
}
return mem;
@@ -95,8 +96,8 @@ static void rvfree(void *mem, unsigned long size)
adr = (unsigned long) mem;
while ((long) size > 0) {
ClearPageReserved(vmalloc_to_page((void *)adr));
- adr += PAGE_SIZE;
- size -= PAGE_SIZE;
+ adr += PAGE_SIZE;
+ size -= PAGE_SIZE;
}
vfree(mem);
}
@@ -112,7 +113,7 @@ static void rvfree(void *mem, unsigned long size)
static int se401_sndctrl(int set, struct usb_se401 *se401, unsigned short req,
unsigned short value, unsigned char *cp, int size)
{
- return usb_control_msg (
+ return usb_control_msg(
se401->dev,
set ? usb_sndctrlpipe(se401->dev, 0) : usb_rcvctrlpipe(se401->dev, 0),
req,
@@ -132,7 +133,7 @@ static int se401_set_feature(struct usb_se401 *se401, unsigned short selector,
and the param in index, but in the logs of the windows driver they do
this the other way around...
*/
- return usb_control_msg (
+ return usb_control_msg(
se401->dev,
usb_sndctrlpipe(se401->dev, 0),
SE401_REQ_SET_EXT_FEATURE,
@@ -152,7 +153,7 @@ static unsigned short se401_get_feature(struct usb_se401 *se401,
wrong here to....
*/
unsigned char cp[2];
- usb_control_msg (
+ usb_control_msg(
se401->dev,
usb_rcvctrlpipe(se401->dev, 0),
SE401_REQ_GET_EXT_FEATURE,
@@ -175,46 +176,51 @@ static unsigned short se401_get_feature(struct usb_se401 *se401,
static int se401_send_pict(struct usb_se401 *se401)
{
- se401_set_feature(se401, HV7131_REG_TITL, se401->expose_l);/* integration time low */
- se401_set_feature(se401, HV7131_REG_TITM, se401->expose_m);/* integration time mid */
- se401_set_feature(se401, HV7131_REG_TITU, se401->expose_h);/* integration time mid */
- se401_set_feature(se401, HV7131_REG_ARLV, se401->resetlevel);/* reset level value */
- se401_set_feature(se401, HV7131_REG_ARCG, se401->rgain);/* red color gain */
- se401_set_feature(se401, HV7131_REG_AGCG, se401->ggain);/* green color gain */
- se401_set_feature(se401, HV7131_REG_ABCG, se401->bgain);/* blue color gain */
+ /* integration time low */
+ se401_set_feature(se401, HV7131_REG_TITL, se401->expose_l);
+ /* integration time mid */
+ se401_set_feature(se401, HV7131_REG_TITM, se401->expose_m);
+ /* integration time mid */
+ se401_set_feature(se401, HV7131_REG_TITU, se401->expose_h);
+ /* reset level value */
+ se401_set_feature(se401, HV7131_REG_ARLV, se401->resetlevel);
+ /* red color gain */
+ se401_set_feature(se401, HV7131_REG_ARCG, se401->rgain);
+ /* green color gain */
+ se401_set_feature(se401, HV7131_REG_AGCG, se401->ggain);
+ /* blue color gain */
+ se401_set_feature(se401, HV7131_REG_ABCG, se401->bgain);
return 0;
}
static void se401_set_exposure(struct usb_se401 *se401, int brightness)
{
- int integration=brightness<<5;
-
- if (flickerless==50) {
- integration=integration-integration%106667;
- }
- if (flickerless==60) {
- integration=integration-integration%88889;
- }
- se401->brightness=integration>>5;
- se401->expose_h=(integration>>16)&0xff;
- se401->expose_m=(integration>>8)&0xff;
- se401->expose_l=integration&0xff;
+ int integration = brightness << 5;
+
+ if (flickerless == 50)
+ integration = integration-integration % 106667;
+ if (flickerless == 60)
+ integration = integration-integration % 88889;
+ se401->brightness = integration >> 5;
+ se401->expose_h = (integration >> 16) & 0xff;
+ se401->expose_m = (integration >> 8) & 0xff;
+ se401->expose_l = integration & 0xff;
}
static int se401_get_pict(struct usb_se401 *se401, struct video_picture *p)
{
- p->brightness=se401->brightness;
- if (se401->enhance) {
- p->whiteness=32768;
- } else {
- p->whiteness=0;
- }
- p->colour=65535;
- p->contrast=65535;
- p->hue=se401->rgain<<10;
- p->palette=se401->palette;
- p->depth=3; /* rgb24 */
+ p->brightness = se401->brightness;
+ if (se401->enhance)
+ p->whiteness = 32768;
+ else
+ p->whiteness = 0;
+
+ p->colour = 65535;
+ p->contrast = 65535;
+ p->hue = se401->rgain << 10;
+ p->palette = se401->palette;
+ p->depth = 3; /* rgb24 */
return 0;
}
@@ -223,20 +229,19 @@ static int se401_set_pict(struct usb_se401 *se401, struct video_picture *p)
{
if (p->palette != VIDEO_PALETTE_RGB24)
return 1;
- se401->palette=p->palette;
- if (p->hue!=se401->hue) {
- se401->rgain= p->hue>>10;
- se401->bgain= 0x40-(p->hue>>10);
- se401->hue=p->hue;
+ se401->palette = p->palette;
+ if (p->hue != se401->hue) {
+ se401->rgain = p->hue >> 10;
+ se401->bgain = 0x40-(p->hue >> 10);
+ se401->hue = p->hue;
}
- if (p->brightness!=se401->brightness) {
+ if (p->brightness != se401->brightness)
se401_set_exposure(se401, p->brightness);
- }
- if (p->whiteness>=32768) {
- se401->enhance=1;
- } else {
- se401->enhance=0;
- }
+
+ if (p->whiteness >= 32768)
+ se401->enhance = 1;
+ else
+ se401->enhance = 0;
se401_send_pict(se401);
se401_send_pict(se401);
return 0;
@@ -249,7 +254,7 @@ static int se401_set_pict(struct usb_se401 *se401, struct video_picture *p)
static void se401_auto_resetlevel(struct usb_se401 *se401)
{
unsigned int ahrc, alrc;
- int oldreset=se401->resetlevel;
+ int oldreset = se401->resetlevel;
/* For some reason this normally read-only register doesn't get reset
to zero after reading them just once...
@@ -258,24 +263,24 @@ static void se401_auto_resetlevel(struct usb_se401 *se401)
se401_get_feature(se401, HV7131_REG_HIREFNOL);
se401_get_feature(se401, HV7131_REG_LOREFNOH);
se401_get_feature(se401, HV7131_REG_LOREFNOL);
- ahrc=256*se401_get_feature(se401, HV7131_REG_HIREFNOH) +
+ ahrc = 256*se401_get_feature(se401, HV7131_REG_HIREFNOH) +
se401_get_feature(se401, HV7131_REG_HIREFNOL);
- alrc=256*se401_get_feature(se401, HV7131_REG_LOREFNOH) +
+ alrc = 256*se401_get_feature(se401, HV7131_REG_LOREFNOH) +
se401_get_feature(se401, HV7131_REG_LOREFNOL);
/* Not an exact science, but it seems to work pretty well... */
if (alrc > 10) {
- while (alrc>=10 && se401->resetlevel < 63) {
+ while (alrc >= 10 && se401->resetlevel < 63) {
se401->resetlevel++;
- alrc /=2;
+ alrc /= 2;
}
} else if (ahrc > 20) {
- while (ahrc>=20 && se401->resetlevel > 0) {
+ while (ahrc >= 20 && se401->resetlevel > 0) {
se401->resetlevel--;
- ahrc /=2;
+ ahrc /= 2;
}
}
- if (se401->resetlevel!=oldreset)
+ if (se401->resetlevel != oldreset)
se401_set_feature(se401, HV7131_REG_ARLV, se401->resetlevel);
return;
@@ -304,21 +309,22 @@ static void se401_button_irq(struct urb *urb)
case -ENOENT:
case -ESHUTDOWN:
/* this urb is terminated, clean up */
- dbg("%s - urb shutting down with status: %d", __func__, urb->status);
+ dbg("%s - urb shutting down with status: %d",
+ __func__, urb->status);
return;
default:
- dbg("%s - nonzero urb status received: %d", __func__, urb->status);
+ dbg("%s - nonzero urb status received: %d",
+ __func__, urb->status);
goto exit;
}
- if (urb->actual_length >=2) {
+ if (urb->actual_length >= 2)
if (se401->button)
- se401->buttonpressed=1;
- }
+ se401->buttonpressed = 1;
exit:
- status = usb_submit_urb (urb, GFP_ATOMIC);
+ status = usb_submit_urb(urb, GFP_ATOMIC);
if (status)
- err ("%s - usb_submit_urb failed with result %d",
+ err("%s - usb_submit_urb failed with result %d",
__func__, status);
}
@@ -344,55 +350,52 @@ static void se401_video_irq(struct urb *urb)
keeps sending them forever...
*/
if (length && !urb->status) {
- se401->nullpackets=0;
- switch(se401->scratch[se401->scratch_next].state) {
- case BUFFER_READY:
- case BUFFER_BUSY: {
- se401->dropped++;
- break;
- }
- case BUFFER_UNUSED: {
- memcpy(se401->scratch[se401->scratch_next].data, (unsigned char *)urb->transfer_buffer, length);
- se401->scratch[se401->scratch_next].state=BUFFER_READY;
- se401->scratch[se401->scratch_next].offset=se401->bayeroffset;
- se401->scratch[se401->scratch_next].length=length;
- if (waitqueue_active(&se401->wq)) {
- wake_up_interruptible(&se401->wq);
- }
- se401->scratch_overflow=0;
- se401->scratch_next++;
- if (se401->scratch_next>=SE401_NUMSCRATCH)
- se401->scratch_next=0;
- break;
- }
- }
- se401->bayeroffset+=length;
- if (se401->bayeroffset>=se401->cheight*se401->cwidth) {
- se401->bayeroffset=0;
+ se401->nullpackets = 0;
+ switch (se401->scratch[se401->scratch_next].state) {
+ case BUFFER_READY:
+ case BUFFER_BUSY:
+ se401->dropped++;
+ break;
+ case BUFFER_UNUSED:
+ memcpy(se401->scratch[se401->scratch_next].data,
+ (unsigned char *)urb->transfer_buffer, length);
+ se401->scratch[se401->scratch_next].state
+ = BUFFER_READY;
+ se401->scratch[se401->scratch_next].offset
+ = se401->bayeroffset;
+ se401->scratch[se401->scratch_next].length = length;
+ if (waitqueue_active(&se401->wq))
+ wake_up_interruptible(&se401->wq);
+ se401->scratch_overflow = 0;
+ se401->scratch_next++;
+ if (se401->scratch_next >= SE401_NUMSCRATCH)
+ se401->scratch_next = 0;
+ break;
}
+ se401->bayeroffset += length;
+ if (se401->bayeroffset >= se401->cheight * se401->cwidth)
+ se401->bayeroffset = 0;
} else {
se401->nullpackets++;
- if (se401->nullpackets > SE401_MAX_NULLPACKETS) {
- if (waitqueue_active(&se401->wq)) {
+ if (se401->nullpackets > SE401_MAX_NULLPACKETS)
+ if (waitqueue_active(&se401->wq))
wake_up_interruptible(&se401->wq);
- }
- }
}
/* Resubmit urb for new data */
- urb->status=0;
- urb->dev=se401->dev;
- if(usb_submit_urb(urb, GFP_KERNEL))
+ urb->status = 0;
+ urb->dev = se401->dev;
+ if (usb_submit_urb(urb, GFP_KERNEL))
dev_info(&urb->dev->dev, "urb burned down\n");
return;
}
static void se401_send_size(struct usb_se401 *se401, int width, int height)
{
- int i=0;
- int mode=0x03; /* No compression */
- int sendheight=height;
- int sendwidth=width;
+ int i = 0;
+ int mode = 0x03; /* No compression */
+ int sendheight = height;
+ int sendwidth = width;
/* JangGu compression can only be used with the camera supported sizes,
but bayer seems to work with any size that fits on the sensor.
@@ -400,18 +403,21 @@ static void se401_send_size(struct usb_se401 *se401, int width, int height)
4 or 16 times subcapturing, if not we use uncompressed bayer data
but this will result in cutouts of the maximum size....
*/
- while (i<se401->sizes && !(se401->width[i]==width && se401->height[i]==height))
+ while (i < se401->sizes && !(se401->width[i] == width &&
+ se401->height[i] == height))
i++;
- while (i<se401->sizes) {
- if (se401->width[i]==width*2 && se401->height[i]==height*2) {
- sendheight=se401->height[i];
- sendwidth=se401->width[i];
- mode=0x40;
+ while (i < se401->sizes) {
+ if (se401->width[i] == width * 2 &&
+ se401->height[i] == height * 2) {
+ sendheight = se401->height[i];
+ sendwidth = se401->width[i];
+ mode = 0x40;
}
- if (se401->width[i]==width*4 && se401->height[i]==height*4) {
- sendheight=se401->height[i];
- sendwidth=se401->width[i];
- mode=0x42;
+ if (se401->width[i] == width * 4 &&
+ se401->height[i] == height * 4) {
+ sendheight = se401->height[i];
+ sendwidth = se401->width[i];
+ mode = 0x42;
}
i++;
}
@@ -420,13 +426,10 @@ static void se401_send_size(struct usb_se401 *se401, int width, int height)
se401_sndctrl(1, se401, SE401_REQ_SET_HEIGHT, sendheight, NULL, 0);
se401_set_feature(se401, SE401_OPERATINGMODE, mode);
- if (mode==0x03) {
- se401->format=FMT_BAYER;
- } else {
- se401->format=FMT_JANGGU;
- }
-
- return;
+ if (mode == 0x03)
+ se401->format = FMT_BAYER;
+ else
+ se401->format = FMT_JANGGU;
}
/*
@@ -437,29 +440,31 @@ static void se401_send_size(struct usb_se401 *se401, int width, int height)
static int se401_start_stream(struct usb_se401 *se401)
{
struct urb *urb;
- int err=0, i;
- se401->streaming=1;
+ int err = 0, i;
+ se401->streaming = 1;
se401_sndctrl(1, se401, SE401_REQ_CAMERA_POWER, 1, NULL, 0);
se401_sndctrl(1, se401, SE401_REQ_LED_CONTROL, 1, NULL, 0);
/* Set picture settings */
- se401_set_feature(se401, HV7131_REG_MODE_B, 0x05);/*windowed + pix intg */
+ /* windowed + pix intg */
+ se401_set_feature(se401, HV7131_REG_MODE_B, 0x05);
se401_send_pict(se401);
se401_send_size(se401, se401->cwidth, se401->cheight);
- se401_sndctrl(1, se401, SE401_REQ_START_CONTINUOUS_CAPTURE, 0, NULL, 0);
+ se401_sndctrl(1, se401, SE401_REQ_START_CONTINUOUS_CAPTURE,
+ 0, NULL, 0);
/* Do some memory allocation */
- for (i=0; i<SE401_NUMFRAMES; i++) {
- se401->frame[i].data=se401->fbuf + i * se401->maxframesize;
- se401->frame[i].curpix=0;
+ for (i = 0; i < SE401_NUMFRAMES; i++) {
+ se401->frame[i].data = se401->fbuf + i * se401->maxframesize;
+ se401->frame[i].curpix = 0;
}
- for (i=0; i<SE401_NUMSBUF; i++) {
- se401->sbuf[i].data=kmalloc(SE401_PACKETSIZE, GFP_KERNEL);
+ for (i = 0; i < SE401_NUMSBUF; i++) {
+ se401->sbuf[i].data = kmalloc(SE401_PACKETSIZE, GFP_KERNEL);
if (!se401->sbuf[i].data) {
- for(i = i - 1; i >= 0; i--) {
+ for (i = i - 1; i >= 0; i--) {
kfree(se401->sbuf[i].data);
se401->sbuf[i].data = NULL;
}
@@ -467,26 +472,26 @@ static int se401_start_stream(struct usb_se401 *se401)
}
}
- se401->bayeroffset=0;
- se401->scratch_next=0;
- se401->scratch_use=0;
- se401->scratch_overflow=0;
- for (i=0; i<SE401_NUMSCRATCH; i++) {
- se401->scratch[i].data=kmalloc(SE401_PACKETSIZE, GFP_KERNEL);
+ se401->bayeroffset = 0;
+ se401->scratch_next = 0;
+ se401->scratch_use = 0;
+ se401->scratch_overflow = 0;
+ for (i = 0; i < SE401_NUMSCRATCH; i++) {
+ se401->scratch[i].data = kmalloc(SE401_PACKETSIZE, GFP_KERNEL);
if (!se401->scratch[i].data) {
- for(i = i - 1; i >= 0; i--) {
+ for (i = i - 1; i >= 0; i--) {
kfree(se401->scratch[i].data);
se401->scratch[i].data = NULL;
}
goto nomem_sbuf;
}
- se401->scratch[i].state=BUFFER_UNUSED;
+ se401->scratch[i].state = BUFFER_UNUSED;
}
- for (i=0; i<SE401_NUMSBUF; i++) {
- urb=usb_alloc_urb(0, GFP_KERNEL);
- if(!urb) {
- for(i = i - 1; i >= 0; i--) {
+ for (i = 0; i < SE401_NUMSBUF; i++) {
+ urb = usb_alloc_urb(0, GFP_KERNEL);
+ if (!urb) {
+ for (i = i - 1; i >= 0; i--) {
usb_kill_urb(se401->urb[i]);
usb_free_urb(se401->urb[i]);
se401->urb[i] = NULL;
@@ -500,24 +505,24 @@ static int se401_start_stream(struct usb_se401 *se401)
se401_video_irq,
se401);
- se401->urb[i]=urb;
+ se401->urb[i] = urb;
- err=usb_submit_urb(se401->urb[i], GFP_KERNEL);
- if(err)
+ err = usb_submit_urb(se401->urb[i], GFP_KERNEL);
+ if (err)
err("urb burned down");
}
- se401->framecount=0;
+ se401->framecount = 0;
return 0;
nomem_scratch:
- for (i=0; i<SE401_NUMSCRATCH; i++) {
+ for (i = 0; i < SE401_NUMSCRATCH; i++) {
kfree(se401->scratch[i].data);
se401->scratch[i].data = NULL;
}
nomem_sbuf:
- for (i=0; i<SE401_NUMSBUF; i++) {
+ for (i = 0; i < SE401_NUMSBUF; i++) {
kfree(se401->sbuf[i].data);
se401->sbuf[i].data = NULL;
}
@@ -531,22 +536,23 @@ static int se401_stop_stream(struct usb_se401 *se401)
if (!se401->streaming || !se401->dev)
return 1;
- se401->streaming=0;
+ se401->streaming = 0;
se401_sndctrl(1, se401, SE401_REQ_STOP_CONTINUOUS_CAPTURE, 0, NULL, 0);
se401_sndctrl(1, se401, SE401_REQ_LED_CONTROL, 0, NULL, 0);
se401_sndctrl(1, se401, SE401_REQ_CAMERA_POWER, 0, NULL, 0);
- for (i=0; i<SE401_NUMSBUF; i++) if (se401->urb[i]) {
- usb_kill_urb(se401->urb[i]);
- usb_free_urb(se401->urb[i]);
- se401->urb[i]=NULL;
- kfree(se401->sbuf[i].data);
- }
- for (i=0; i<SE401_NUMSCRATCH; i++) {
+ for (i = 0; i < SE401_NUMSBUF; i++)
+ if (se401->urb[i]) {
+ usb_kill_urb(se401->urb[i]);
+ usb_free_urb(se401->urb[i]);
+ se401->urb[i] = NULL;
+ kfree(se401->sbuf[i].data);
+ }
+ for (i = 0; i < SE401_NUMSCRATCH; i++) {
kfree(se401->scratch[i].data);
- se401->scratch[i].data=NULL;
+ se401->scratch[i].data = NULL;
}
return 0;
@@ -554,9 +560,9 @@ static int se401_stop_stream(struct usb_se401 *se401)
static int se401_set_size(struct usb_se401 *se401, int width, int height)
{
- int wasstreaming=se401->streaming;
+ int wasstreaming = se401->streaming;
/* Check to see if we need to change */
- if (se401->cwidth==width && se401->cheight==height)
+ if (se401->cwidth == width && se401->cheight == height)
return 0;
/* Check for a valid mode */
@@ -564,16 +570,16 @@ static int se401_set_size(struct usb_se401 *se401, int width, int height)
return 1;
if ((width & 1) || (height & 1))
return 1;
- if (width>se401->width[se401->sizes-1])
+ if (width > se401->width[se401->sizes-1])
return 1;
- if (height>se401->height[se401->sizes-1])
+ if (height > se401->height[se401->sizes-1])
return 1;
/* Stop a current stream and start it again at the new size */
if (wasstreaming)
se401_stop_stream(se401);
- se401->cwidth=width;
- se401->cheight=height;
+ se401->cwidth = width;
+ se401->cheight = height;
if (wasstreaming)
se401_start_stream(se401);
return 0;
@@ -594,68 +600,68 @@ static int se401_set_size(struct usb_se401 *se401, int width, int height)
static inline void enhance_picture(unsigned char *frame, int len)
{
while (len--) {
- *frame=(((*frame^255)*(*frame^255))/255)^255;
+ *frame = (((*frame^255)*(*frame^255))/255)^255;
frame++;
}
}
static inline void decode_JangGu_integrate(struct usb_se401 *se401, int data)
{
- struct se401_frame *frame=&se401->frame[se401->curframe];
- int linelength=se401->cwidth*3;
+ struct se401_frame *frame = &se401->frame[se401->curframe];
+ int linelength = se401->cwidth * 3;
if (frame->curlinepix >= linelength) {
- frame->curlinepix=0;
- frame->curline+=linelength;
+ frame->curlinepix = 0;
+ frame->curline += linelength;
}
/* First three are absolute, all others relative.
* Format is rgb from right to left (mirrorred image),
* we flip it to get bgr from left to right. */
- if (frame->curlinepix < 3) {
- *(frame->curline-frame->curlinepix)=1+data*4;
- } else {
- *(frame->curline-frame->curlinepix)=
- *(frame->curline-frame->curlinepix+3)+data*4;
- }
+ if (frame->curlinepix < 3)
+ *(frame->curline-frame->curlinepix) = 1 + data * 4;
+ else
+ *(frame->curline-frame->curlinepix) =
+ *(frame->curline-frame->curlinepix + 3) + data * 4;
frame->curlinepix++;
}
-static inline void decode_JangGu_vlc (struct usb_se401 *se401, unsigned char *data, int bit_exp, int packetlength)
+static inline void decode_JangGu_vlc(struct usb_se401 *se401,
+ unsigned char *data, int bit_exp, int packetlength)
{
- int pos=0;
- int vlc_cod=0;
- int vlc_size=0;
- int vlc_data=0;
+ int pos = 0;
+ int vlc_cod = 0;
+ int vlc_size = 0;
+ int vlc_data = 0;
int bit_cur;
int bit;
- data+=4;
+ data += 4;
while (pos < packetlength) {
- bit_cur=8;
+ bit_cur = 8;
while (bit_cur && bit_exp) {
- bit=((*data)>>(bit_cur-1))&1;
+ bit = ((*data) >> (bit_cur-1))&1;
if (!vlc_cod) {
if (bit) {
vlc_size++;
} else {
- if (!vlc_size) {
+ if (!vlc_size)
decode_JangGu_integrate(se401, 0);
- } else {
- vlc_cod=2;
- vlc_data=0;
+ else {
+ vlc_cod = 2;
+ vlc_data = 0;
}
}
} else {
- if (vlc_cod==2) {
+ if (vlc_cod == 2) {
if (!bit)
- vlc_data = -(1<<vlc_size) + 1;
+ vlc_data = -(1 << vlc_size) + 1;
vlc_cod--;
}
vlc_size--;
- vlc_data+=bit<<vlc_size;
+ vlc_data += bit << vlc_size;
if (!vlc_size) {
decode_JangGu_integrate(se401, vlc_data);
- vlc_cod=0;
+ vlc_cod = 0;
}
}
bit_cur--;
@@ -666,186 +672,188 @@ static inline void decode_JangGu_vlc (struct usb_se401 *se401, unsigned char *da
}
}
-static inline void decode_JangGu (struct usb_se401 *se401, struct se401_scratch *buffer)
+static inline void decode_JangGu(struct usb_se401 *se401,
+ struct se401_scratch *buffer)
{
- unsigned char *data=buffer->data;
- int len=buffer->length;
- int bit_exp=0, pix_exp=0, frameinfo=0, packetlength=0, size;
- int datapos=0;
+ unsigned char *data = buffer->data;
+ int len = buffer->length;
+ int bit_exp = 0, pix_exp = 0, frameinfo = 0, packetlength = 0, size;
+ int datapos = 0;
/* New image? */
if (!se401->frame[se401->curframe].curpix) {
- se401->frame[se401->curframe].curlinepix=0;
- se401->frame[se401->curframe].curline=
+ se401->frame[se401->curframe].curlinepix = 0;
+ se401->frame[se401->curframe].curline =
se401->frame[se401->curframe].data+
- se401->cwidth*3-1;
- if (se401->frame[se401->curframe].grabstate==FRAME_READY)
- se401->frame[se401->curframe].grabstate=FRAME_GRABBING;
- se401->vlcdatapos=0;
+ se401->cwidth * 3 - 1;
+ if (se401->frame[se401->curframe].grabstate == FRAME_READY)
+ se401->frame[se401->curframe].grabstate = FRAME_GRABBING;
+ se401->vlcdatapos = 0;
}
while (datapos < len) {
- size=1024-se401->vlcdatapos;
+ size = 1024 - se401->vlcdatapos;
if (size+datapos > len)
- size=len-datapos;
+ size = len-datapos;
memcpy(se401->vlcdata+se401->vlcdatapos, data+datapos, size);
- se401->vlcdatapos+=size;
- packetlength=0;
+ se401->vlcdatapos += size;
+ packetlength = 0;
if (se401->vlcdatapos >= 4) {
- bit_exp=se401->vlcdata[3]+(se401->vlcdata[2]<<8);
- pix_exp=se401->vlcdata[1]+((se401->vlcdata[0]&0x3f)<<8);
- frameinfo=se401->vlcdata[0]&0xc0;
- packetlength=((bit_exp+47)>>4)<<1;
+ bit_exp = se401->vlcdata[3] + (se401->vlcdata[2] << 8);
+ pix_exp = se401->vlcdata[1] +
+ ((se401->vlcdata[0] & 0x3f) << 8);
+ frameinfo = se401->vlcdata[0] & 0xc0;
+ packetlength = ((bit_exp + 47) >> 4) << 1;
if (packetlength > 1024) {
- se401->vlcdatapos=0;
- datapos=len;
- packetlength=0;
+ se401->vlcdatapos = 0;
+ datapos = len;
+ packetlength = 0;
se401->error++;
- se401->frame[se401->curframe].curpix=0;
+ se401->frame[se401->curframe].curpix = 0;
}
}
if (packetlength && se401->vlcdatapos >= packetlength) {
- decode_JangGu_vlc(se401, se401->vlcdata, bit_exp, packetlength);
- se401->frame[se401->curframe].curpix+=pix_exp*3;
- datapos+=size-(se401->vlcdatapos-packetlength);
- se401->vlcdatapos=0;
- if (se401->frame[se401->curframe].curpix>=se401->cwidth*se401->cheight*3) {
- if (se401->frame[se401->curframe].curpix==se401->cwidth*se401->cheight*3) {
- if (se401->frame[se401->curframe].grabstate==FRAME_GRABBING) {
- se401->frame[se401->curframe].grabstate=FRAME_DONE;
+ decode_JangGu_vlc(se401, se401->vlcdata, bit_exp,
+ packetlength);
+ se401->frame[se401->curframe].curpix += pix_exp * 3;
+ datapos += size-(se401->vlcdatapos-packetlength);
+ se401->vlcdatapos = 0;
+ if (se401->frame[se401->curframe].curpix >= se401->cwidth * se401->cheight * 3) {
+ if (se401->frame[se401->curframe].curpix == se401->cwidth * se401->cheight * 3) {
+ if (se401->frame[se401->curframe].grabstate == FRAME_GRABBING) {
+ se401->frame[se401->curframe].grabstate = FRAME_DONE;
se401->framecount++;
se401->readcount++;
}
- if (se401->frame[(se401->curframe+1)&(SE401_NUMFRAMES-1)].grabstate==FRAME_READY) {
- se401->curframe=(se401->curframe+1) & (SE401_NUMFRAMES-1);
- }
- } else {
+ if (se401->frame[(se401->curframe + 1) & (SE401_NUMFRAMES - 1)].grabstate == FRAME_READY)
+ se401->curframe = (se401->curframe + 1) & (SE401_NUMFRAMES - 1);
+ } else
se401->error++;
- }
- se401->frame[se401->curframe].curpix=0;
- datapos=len;
+ se401->frame[se401->curframe].curpix = 0;
+ datapos = len;
}
- } else {
- datapos+=size;
- }
+ } else
+ datapos += size;
}
}
-static inline void decode_bayer (struct usb_se401 *se401, struct se401_scratch *buffer)
+static inline void decode_bayer(struct usb_se401 *se401,
+ struct se401_scratch *buffer)
{
- unsigned char *data=buffer->data;
- int len=buffer->length;
- int offset=buffer->offset;
- int datasize=se401->cwidth*se401->cheight;
- struct se401_frame *frame=&se401->frame[se401->curframe];
+ unsigned char *data = buffer->data;
+ int len = buffer->length;
+ int offset = buffer->offset;
+ int datasize = se401->cwidth * se401->cheight;
+ struct se401_frame *frame = &se401->frame[se401->curframe];
+ unsigned char *framedata = frame->data, *curline, *nextline;
+ int width = se401->cwidth;
+ int blineoffset = 0, bline;
+ int linelength = width * 3, i;
- unsigned char *framedata=frame->data, *curline, *nextline;
- int width=se401->cwidth;
- int blineoffset=0, bline;
- int linelength=width*3, i;
+ if (frame->curpix == 0) {
+ if (frame->grabstate == FRAME_READY)
+ frame->grabstate = FRAME_GRABBING;
- if (frame->curpix==0) {
- if (frame->grabstate==FRAME_READY) {
- frame->grabstate=FRAME_GRABBING;
- }
- frame->curline=framedata+linelength;
- frame->curlinepix=0;
+ frame->curline = framedata + linelength;
+ frame->curlinepix = 0;
}
- if (offset!=frame->curpix) {
+ if (offset != frame->curpix) {
/* Regard frame as lost :( */
- frame->curpix=0;
+ frame->curpix = 0;
se401->error++;
return;
}
/* Check if we have to much data */
- if (frame->curpix+len > datasize) {
- len=datasize-frame->curpix;
- }
- if (se401->cheight%4)
- blineoffset=1;
- bline=frame->curpix/se401->cwidth+blineoffset;
-
- curline=frame->curline;
- nextline=curline+linelength;
- if (nextline >= framedata+datasize*3)
- nextline=curline;
+ if (frame->curpix + len > datasize)
+ len = datasize-frame->curpix;
+
+ if (se401->cheight % 4)
+ blineoffset = 1;
+ bline = frame->curpix / se401->cwidth+blineoffset;
+
+ curline = frame->curline;
+ nextline = curline + linelength;
+ if (nextline >= framedata+datasize * 3)
+ nextline = curline;
while (len) {
- if (frame->curlinepix>=width) {
- frame->curlinepix-=width;
- bline=frame->curpix/width+blineoffset;
- curline+=linelength*2;
- nextline+=linelength*2;
- if (curline >= framedata+datasize*3) {
+ if (frame->curlinepix >= width) {
+ frame->curlinepix -= width;
+ bline = frame->curpix / width + blineoffset;
+ curline += linelength*2;
+ nextline += linelength*2;
+ if (curline >= framedata+datasize * 3) {
frame->curlinepix++;
- curline-=3;
- nextline-=3;
+ curline -= 3;
+ nextline -= 3;
len--;
data++;
frame->curpix++;
}
if (nextline >= framedata+datasize*3)
- nextline=curline;
+ nextline = curline;
}
- if ((bline&1)) {
- if ((frame->curlinepix&1)) {
- *(curline+2)=*data;
- *(curline-1)=*data;
- *(nextline+2)=*data;
- *(nextline-1)=*data;
+ if (bline & 1) {
+ if (frame->curlinepix & 1) {
+ *(curline + 2) = *data;
+ *(curline - 1) = *data;
+ *(nextline + 2) = *data;
+ *(nextline - 1) = *data;
} else {
- *(curline+1)=
- (*(curline+1)+*data)/2;
- *(curline-2)=
- (*(curline-2)+*data)/2;
- *(nextline+1)=*data;
- *(nextline-2)=*data;
+ *(curline + 1) =
+ (*(curline + 1) + *data) / 2;
+ *(curline-2) =
+ (*(curline - 2) + *data) / 2;
+ *(nextline + 1) = *data;
+ *(nextline - 2) = *data;
}
} else {
- if ((frame->curlinepix&1)) {
- *(curline+1)=
- (*(curline+1)+*data)/2;
- *(curline-2)=
- (*(curline-2)+*data)/2;
- *(nextline+1)=*data;
- *(nextline-2)=*data;
+ if (frame->curlinepix & 1) {
+ *(curline + 1) =
+ (*(curline + 1) + *data) / 2;
+ *(curline - 2) =
+ (*(curline - 2) + *data) / 2;
+ *(nextline + 1) = *data;
+ *(nextline - 2) = *data;
} else {
- *curline=*data;
- *(curline-3)=*data;
- *nextline=*data;
- *(nextline-3)=*data;
+ *curline = *data;
+ *(curline - 3) = *data;
+ *nextline = *data;
+ *(nextline - 3) = *data;
}
}
frame->curlinepix++;
- curline-=3;
- nextline-=3;
+ curline -= 3;
+ nextline -= 3;
len--;
data++;
frame->curpix++;
}
- frame->curline=curline;
+ frame->curline = curline;
- if (frame->curpix>=datasize) {
+ if (frame->curpix >= datasize) {
/* Fix the top line */
- framedata+=linelength;
- for (i=0; i<linelength; i++) {
+ framedata += linelength;
+ for (i = 0; i < linelength; i++) {
framedata--;
- *framedata=*(framedata+linelength);
+ *framedata = *(framedata + linelength);
}
/* Fix the left side (green is already present) */
- for (i=0; i<se401->cheight; i++) {
- *framedata=*(framedata+3);
- *(framedata+1)=*(framedata+4);
- *(framedata+2)=*(framedata+5);
- framedata+=linelength;
+ for (i = 0; i < se401->cheight; i++) {
+ *framedata = *(framedata + 3);
+ *(framedata + 1) = *(framedata + 4);
+ *(framedata + 2) = *(framedata + 5);
+ framedata += linelength;
}
- frame->curpix=0;
- frame->grabstate=FRAME_DONE;
+ frame->curpix = 0;
+ frame->grabstate = FRAME_DONE;
se401->framecount++;
se401->readcount++;
- if (se401->frame[(se401->curframe+1)&(SE401_NUMFRAMES-1)].grabstate==FRAME_READY) {
- se401->curframe=(se401->curframe+1) & (SE401_NUMFRAMES-1);
+ if (se401->frame[(se401->curframe + 1) &
+ (SE401_NUMFRAMES - 1)].grabstate == FRAME_READY) {
+ se401->curframe = (se401->curframe+1) &
+ (SE401_NUMFRAMES-1);
}
}
}
@@ -853,72 +861,76 @@ static inline void decode_bayer (struct usb_se401 *se401, struct se401_scratch *
static int se401_newframe(struct usb_se401 *se401, int framenr)
{
DECLARE_WAITQUEUE(wait, current);
- int errors=0;
+ int errors = 0;
while (se401->streaming &&
- (se401->frame[framenr].grabstate==FRAME_READY ||
- se401->frame[framenr].grabstate==FRAME_GRABBING) ) {
- if(!se401->frame[framenr].curpix) {
+ (se401->frame[framenr].grabstate == FRAME_READY ||
+ se401->frame[framenr].grabstate == FRAME_GRABBING)) {
+ if (!se401->frame[framenr].curpix)
errors++;
- }
+
wait_interruptible(
- se401->scratch[se401->scratch_use].state!=BUFFER_READY,
- &se401->wq,
- &wait
- );
+ se401->scratch[se401->scratch_use].state != BUFFER_READY,
+ &se401->wq, &wait);
if (se401->nullpackets > SE401_MAX_NULLPACKETS) {
- se401->nullpackets=0;
+ se401->nullpackets = 0;
dev_info(&se401->dev->dev,
- "too many null length packets, restarting capture\n");
+ "too many null length packets, restarting capture\n");
se401_stop_stream(se401);
se401_start_stream(se401);
} else {
- if (se401->scratch[se401->scratch_use].state!=BUFFER_READY) {
- se401->frame[framenr].grabstate=FRAME_ERROR;
+ if (se401->scratch[se401->scratch_use].state !=
+ BUFFER_READY) {
+ se401->frame[framenr].grabstate = FRAME_ERROR;
return -EIO;
}
- se401->scratch[se401->scratch_use].state=BUFFER_BUSY;
- if (se401->format==FMT_JANGGU) {
- decode_JangGu(se401, &se401->scratch[se401->scratch_use]);
- } else {
- decode_bayer(se401, &se401->scratch[se401->scratch_use]);
- }
- se401->scratch[se401->scratch_use].state=BUFFER_UNUSED;
+ se401->scratch[se401->scratch_use].state = BUFFER_BUSY;
+ if (se401->format == FMT_JANGGU)
+ decode_JangGu(se401,
+ &se401->scratch[se401->scratch_use]);
+ else
+ decode_bayer(se401,
+ &se401->scratch[se401->scratch_use]);
+
+ se401->scratch[se401->scratch_use].state =
+ BUFFER_UNUSED;
se401->scratch_use++;
- if (se401->scratch_use>=SE401_NUMSCRATCH)
- se401->scratch_use=0;
+ if (se401->scratch_use >= SE401_NUMSCRATCH)
+ se401->scratch_use = 0;
if (errors > SE401_MAX_ERRORS) {
- errors=0;
+ errors = 0;
dev_info(&se401->dev->dev,
- "too many errors, restarting capture\n");
+ "too many errors, restarting capture\n");
se401_stop_stream(se401);
se401_start_stream(se401);
}
}
}
- if (se401->frame[framenr].grabstate==FRAME_DONE)
+ if (se401->frame[framenr].grabstate == FRAME_DONE)
if (se401->enhance)
- enhance_picture(se401->frame[framenr].data, se401->cheight*se401->cwidth*3);
+ enhance_picture(se401->frame[framenr].data,
+ se401->cheight * se401->cwidth * 3);
return 0;
}
-static void usb_se401_remove_disconnected (struct usb_se401 *se401)
+static void usb_se401_remove_disconnected(struct usb_se401 *se401)
{
int i;
se401->dev = NULL;
- for (i=0; i<SE401_NUMSBUF; i++)
+ for (i = 0; i < SE401_NUMSBUF; i++)
if (se401->urb[i]) {
usb_kill_urb(se401->urb[i]);
usb_free_urb(se401->urb[i]);
se401->urb[i] = NULL;
kfree(se401->sbuf[i].data);
}
- for (i=0; i<SE401_NUMSCRATCH; i++) {
+
+ for (i = 0; i < SE401_NUMSCRATCH; i++)
kfree(se401->scratch[i].data);
- }
+
if (se401->inturb) {
usb_kill_urb(se401->inturb);
usb_free_urb(se401->inturb);
@@ -973,11 +985,11 @@ static int se401_close(struct file *file)
dev_info(&se401->dev->dev, "device unregistered\n");
usb_se401_remove_disconnected(se401);
} else {
- for (i=0; i<SE401_NUMFRAMES; i++)
- se401->frame[i].grabstate=FRAME_UNUSED;
+ for (i = 0; i < SE401_NUMFRAMES; i++)
+ se401->frame[i].grabstate = FRAME_UNUSED;
if (se401->streaming)
se401_stop_stream(se401);
- se401->user=0;
+ se401->user = 0;
}
file->private_data = NULL;
return 0;
@@ -1073,7 +1085,7 @@ static long se401_do_ioctl(struct file *file, unsigned int cmd, void *arg)
memset(vm, 0, sizeof(*vm));
vm->size = SE401_NUMFRAMES * se401->maxframesize;
vm->frames = SE401_NUMFRAMES;
- for (i=0; i<SE401_NUMFRAMES; i++)
+ for (i = 0; i < SE401_NUMFRAMES; i++)
vm->offsets[i] = se401->maxframesize * i;
return 0;
}
@@ -1091,16 +1103,16 @@ static long se401_do_ioctl(struct file *file, unsigned int cmd, void *arg)
/* Is this according to the v4l spec??? */
if (se401_set_size(se401, vm->width, vm->height))
return -EINVAL;
- se401->frame[vm->frame].grabstate=FRAME_READY;
+ se401->frame[vm->frame].grabstate = FRAME_READY;
if (!se401->streaming)
se401_start_stream(se401);
/* Set the picture properties */
- if (se401->framecount==0)
+ if (se401->framecount == 0)
se401_send_pict(se401);
/* Calibrate the reset level after a few frames. */
- if (se401->framecount%20==1)
+ if (se401->framecount % 20 == 1)
se401_auto_resetlevel(se401);
return 0;
@@ -1108,13 +1120,13 @@ static long se401_do_ioctl(struct file *file, unsigned int cmd, void *arg)
case VIDIOCSYNC:
{
int *frame = arg;
- int ret=0;
+ int ret = 0;
- if(*frame <0 || *frame >= SE401_NUMFRAMES)
+ if (*frame < 0 || *frame >= SE401_NUMFRAMES)
return -EINVAL;
- ret=se401_newframe(se401, *frame);
- se401->frame[*frame].grabstate=FRAME_UNUSED;
+ ret = se401_newframe(se401, *frame);
+ se401->frame[*frame].grabstate = FRAME_UNUSED;
return ret;
}
case VIDIOCGFBUF:
@@ -1155,36 +1167,36 @@ static long se401_ioctl(struct file *file,
static ssize_t se401_read(struct file *file, char __user *buf,
size_t count, loff_t *ppos)
{
- int realcount=count, ret=0;
+ int realcount = count, ret = 0;
struct video_device *dev = file->private_data;
struct usb_se401 *se401 = (struct usb_se401 *)dev;
- if (se401->dev == NULL)
+ if (se401->dev == NULL)
return -EIO;
if (realcount > se401->cwidth*se401->cheight*3)
- realcount=se401->cwidth*se401->cheight*3;
+ realcount = se401->cwidth*se401->cheight*3;
/* Shouldn't happen: */
- if (se401->frame[0].grabstate==FRAME_GRABBING)
+ if (se401->frame[0].grabstate == FRAME_GRABBING)
return -EBUSY;
- se401->frame[0].grabstate=FRAME_READY;
- se401->frame[1].grabstate=FRAME_UNUSED;
- se401->curframe=0;
+ se401->frame[0].grabstate = FRAME_READY;
+ se401->frame[1].grabstate = FRAME_UNUSED;
+ se401->curframe = 0;
if (!se401->streaming)
se401_start_stream(se401);
/* Set the picture properties */
- if (se401->framecount==0)
+ if (se401->framecount == 0)
se401_send_pict(se401);
/* Calibrate the reset level after a few frames. */
- if (se401->framecount%20==1)
+ if (se401->framecount%20 == 1)
se401_auto_resetlevel(se401);
- ret=se401_newframe(se401, 0);
+ ret = se401_newframe(se401, 0);
- se401->frame[0].grabstate=FRAME_UNUSED;
+ se401->frame[0].grabstate = FRAME_UNUSED;
if (ret)
return ret;
if (copy_to_user(buf, se401->frame[0].data, realcount))
@@ -1203,11 +1215,12 @@ static int se401_mmap(struct file *file, struct vm_area_struct *vma)
mutex_lock(&se401->lock);
- if (se401->dev == NULL) {
+ if (se401->dev == NULL) {
mutex_unlock(&se401->lock);
return -EIO;
}
- if (size > (((SE401_NUMFRAMES * se401->maxframesize) + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1))) {
+ if (size > (((SE401_NUMFRAMES * se401->maxframesize) + PAGE_SIZE - 1)
+ & ~(PAGE_SIZE - 1))) {
mutex_unlock(&se401->lock);
return -EINVAL;
}
@@ -1218,10 +1231,10 @@ static int se401_mmap(struct file *file, struct vm_area_struct *vma)
mutex_unlock(&se401->lock);
return -EAGAIN;
}
- start += PAGE_SIZE;
- pos += PAGE_SIZE;
+ start += PAGE_SIZE;
+ pos += PAGE_SIZE;
if (size > PAGE_SIZE)
- size -= PAGE_SIZE;
+ size -= PAGE_SIZE;
else
size = 0;
}
@@ -1231,7 +1244,7 @@ static int se401_mmap(struct file *file, struct vm_area_struct *vma)
}
static const struct v4l2_file_operations se401_fops = {
- .owner = THIS_MODULE,
+ .owner = THIS_MODULE,
.open = se401_open,
.release = se401_close,
.read = se401_read,
@@ -1249,71 +1262,76 @@ static struct video_device se401_template = {
/***************************/
static int se401_init(struct usb_se401 *se401, int button)
{
- int i=0, rc;
+ int i = 0, rc;
unsigned char cp[0x40];
char temp[200];
+ int slen;
/* led on */
se401_sndctrl(1, se401, SE401_REQ_LED_CONTROL, 1, NULL, 0);
/* get camera descriptor */
- rc=se401_sndctrl(0, se401, SE401_REQ_GET_CAMERA_DESCRIPTOR, 0, cp, sizeof(cp));
- if (cp[1]!=0x41) {
+ rc = se401_sndctrl(0, se401, SE401_REQ_GET_CAMERA_DESCRIPTOR, 0,
+ cp, sizeof(cp));
+ if (cp[1] != 0x41) {
err("Wrong descriptor type");
return 1;
}
- sprintf (temp, "ExtraFeatures: %d", cp[3]);
+ slen = snprintf(temp, 200, "ExtraFeatures: %d", cp[3]);
- se401->sizes=cp[4]+cp[5]*256;
- se401->width=kmalloc(se401->sizes*sizeof(int), GFP_KERNEL);
+ se401->sizes = cp[4] + cp[5] * 256;
+ se401->width = kmalloc(se401->sizes*sizeof(int), GFP_KERNEL);
if (!se401->width)
return 1;
- se401->height=kmalloc(se401->sizes*sizeof(int), GFP_KERNEL);
+ se401->height = kmalloc(se401->sizes*sizeof(int), GFP_KERNEL);
if (!se401->height) {
kfree(se401->width);
return 1;
}
- for (i=0; i<se401->sizes; i++) {
- se401->width[i]=cp[6+i*4+0]+cp[6+i*4+1]*256;
- se401->height[i]=cp[6+i*4+2]+cp[6+i*4+3]*256;
+ for (i = 0; i < se401->sizes; i++) {
+ se401->width[i] = cp[6 + i * 4 + 0] + cp[6 + i*4 + 1] * 256;
+ se401->height[i] = cp[6 + i * 4 + 2] + cp[6 + i * 4 + 3] * 256;
}
- sprintf (temp, "%s Sizes:", temp);
- for (i=0; i<se401->sizes; i++) {
- sprintf(temp, "%s %dx%d", temp, se401->width[i], se401->height[i]);
+ slen += snprintf(temp + slen, 200 - slen, " Sizes:");
+ for (i = 0; i < se401->sizes; i++) {
+ slen += snprintf(temp + slen, 200 - slen,
+ " %dx%d", se401->width[i], se401->height[i]);
}
dev_info(&se401->dev->dev, "%s\n", temp);
- se401->maxframesize=se401->width[se401->sizes-1]*se401->height[se401->sizes-1]*3;
+ se401->maxframesize = se401->width[se401->sizes-1] *
+ se401->height[se401->sizes - 1] * 3;
- rc=se401_sndctrl(0, se401, SE401_REQ_GET_WIDTH, 0, cp, sizeof(cp));
- se401->cwidth=cp[0]+cp[1]*256;
- rc=se401_sndctrl(0, se401, SE401_REQ_GET_HEIGHT, 0, cp, sizeof(cp));
- se401->cheight=cp[0]+cp[1]*256;
+ rc = se401_sndctrl(0, se401, SE401_REQ_GET_WIDTH, 0, cp, sizeof(cp));
+ se401->cwidth = cp[0]+cp[1]*256;
+ rc = se401_sndctrl(0, se401, SE401_REQ_GET_HEIGHT, 0, cp, sizeof(cp));
+ se401->cheight = cp[0]+cp[1]*256;
if (!(cp[2] & SE401_FORMAT_BAYER)) {
err("Bayer format not supported!");
return 1;
}
/* set output mode (BAYER) */
- se401_sndctrl(1, se401, SE401_REQ_SET_OUTPUT_MODE, SE401_FORMAT_BAYER, NULL, 0);
+ se401_sndctrl(1, se401, SE401_REQ_SET_OUTPUT_MODE,
+ SE401_FORMAT_BAYER, NULL, 0);
- rc=se401_sndctrl(0, se401, SE401_REQ_GET_BRT, 0, cp, sizeof(cp));
- se401->brightness=cp[0]+cp[1]*256;
+ rc = se401_sndctrl(0, se401, SE401_REQ_GET_BRT, 0, cp, sizeof(cp));
+ se401->brightness = cp[0]+cp[1]*256;
/* some default values */
- se401->resetlevel=0x2d;
- se401->rgain=0x20;
- se401->ggain=0x20;
- se401->bgain=0x20;
+ se401->resetlevel = 0x2d;
+ se401->rgain = 0x20;
+ se401->ggain = 0x20;
+ se401->bgain = 0x20;
se401_set_exposure(se401, 20000);
- se401->palette=VIDEO_PALETTE_RGB24;
- se401->enhance=1;
- se401->dropped=0;
- se401->error=0;
- se401->framecount=0;
- se401->readcount=0;
+ se401->palette = VIDEO_PALETTE_RGB24;
+ se401->enhance = 1;
+ se401->dropped = 0;
+ se401->error = 0;
+ se401->framecount = 0;
+ se401->readcount = 0;
/* Start interrupt transfers for snapshot button */
if (button) {
- se401->inturb=usb_alloc_urb(0, GFP_KERNEL);
+ se401->inturb = usb_alloc_urb(0, GFP_KERNEL);
if (!se401->inturb) {
dev_info(&se401->dev->dev,
"Allocation of inturb failed\n");
@@ -1331,7 +1349,7 @@ static int se401_init(struct usb_se401 *se401, int button)
return 1;
}
} else
- se401->inturb=NULL;
+ se401->inturb = NULL;
/* Flash the led */
se401_sndctrl(1, se401, SE401_REQ_CAMERA_POWER, 1, NULL, 0);
@@ -1348,8 +1366,8 @@ static int se401_probe(struct usb_interface *intf,
struct usb_device *dev = interface_to_usbdev(intf);
struct usb_interface_descriptor *interface;
struct usb_se401 *se401;
- char *camera_name=NULL;
- int button=1;
+ char *camera_name = NULL;
+ int button = 1;
/* We don't handle multi-config cameras */
if (dev->descriptor.bNumConfigurations != 1)
@@ -1358,22 +1376,22 @@ static int se401_probe(struct usb_interface *intf,
interface = &intf->cur_altsetting->desc;
/* Is it an se401? */
- if (le16_to_cpu(dev->descriptor.idVendor) == 0x03e8 &&
- le16_to_cpu(dev->descriptor.idProduct) == 0x0004) {
- camera_name="Endpoints/Aox SE401";
- } else if (le16_to_cpu(dev->descriptor.idVendor) == 0x0471 &&
- le16_to_cpu(dev->descriptor.idProduct) == 0x030b) {
- camera_name="Philips PCVC665K";
- } else if (le16_to_cpu(dev->descriptor.idVendor) == 0x047d &&
- le16_to_cpu(dev->descriptor.idProduct) == 0x5001) {
- camera_name="Kensington VideoCAM 67014";
- } else if (le16_to_cpu(dev->descriptor.idVendor) == 0x047d &&
- le16_to_cpu(dev->descriptor.idProduct) == 0x5002) {
- camera_name="Kensington VideoCAM 6701(5/7)";
- } else if (le16_to_cpu(dev->descriptor.idVendor) == 0x047d &&
- le16_to_cpu(dev->descriptor.idProduct) == 0x5003) {
- camera_name="Kensington VideoCAM 67016";
- button=0;
+ if (le16_to_cpu(dev->descriptor.idVendor) == 0x03e8 &&
+ le16_to_cpu(dev->descriptor.idProduct) == 0x0004) {
+ camera_name = "Endpoints/Aox SE401";
+ } else if (le16_to_cpu(dev->descriptor.idVendor) == 0x0471 &&
+ le16_to_cpu(dev->descriptor.idProduct) == 0x030b) {
+ camera_name = "Philips PCVC665K";
+ } else if (le16_to_cpu(dev->descriptor.idVendor) == 0x047d &&
+ le16_to_cpu(dev->descriptor.idProduct) == 0x5001) {
+ camera_name = "Kensington VideoCAM 67014";
+ } else if (le16_to_cpu(dev->descriptor.idVendor) == 0x047d &&
+ le16_to_cpu(dev->descriptor.idProduct) == 0x5002) {
+ camera_name = "Kensington VideoCAM 6701(5/7)";
+ } else if (le16_to_cpu(dev->descriptor.idVendor) == 0x047d &&
+ le16_to_cpu(dev->descriptor.idProduct) == 0x5003) {
+ camera_name = "Kensington VideoCAM 67016";
+ button = 0;
} else
return -ENODEV;
@@ -1386,7 +1404,8 @@ static int se401_probe(struct usb_interface *intf,
/* We found one */
dev_info(&intf->dev, "SE401 camera found: %s\n", camera_name);
- if ((se401 = kzalloc(sizeof(*se401), GFP_KERNEL)) == NULL) {
+ se401 = kzalloc(sizeof(*se401), GFP_KERNEL);
+ if (se401 == NULL) {
err("couldn't kmalloc se401 struct");
return -ENOMEM;
}
@@ -1404,12 +1423,14 @@ static int se401_probe(struct usb_interface *intf,
}
memcpy(&se401->vdev, &se401_template, sizeof(se401_template));
- memcpy(se401->vdev.name, se401->camera_name, strlen(se401->camera_name));
+ memcpy(se401->vdev.name, se401->camera_name,
+ strlen(se401->camera_name));
init_waitqueue_head(&se401->wq);
mutex_init(&se401->lock);
wmb();
- if (video_register_device(&se401->vdev, VFL_TYPE_GRABBER, video_nr) < 0) {
+ if (video_register_device(&se401->vdev,
+ VFL_TYPE_GRABBER, video_nr) < 0) {
kfree(se401);
err("video_register_device failed");
return -EIO;
@@ -1417,20 +1438,20 @@ static int se401_probe(struct usb_interface *intf,
dev_info(&intf->dev, "registered new video device: video%d\n",
se401->vdev.num);
- usb_set_intfdata (intf, se401);
+ usb_set_intfdata(intf, se401);
return 0;
}
static void se401_disconnect(struct usb_interface *intf)
{
- struct usb_se401 *se401 = usb_get_intfdata (intf);
+ struct usb_se401 *se401 = usb_get_intfdata(intf);
- usb_set_intfdata (intf, NULL);
+ usb_set_intfdata(intf, NULL);
if (se401) {
video_unregister_device(&se401->vdev);
- if (!se401->user){
+ if (!se401->user)
usb_se401_remove_disconnected(se401);
- } else {
+ else {
se401->frame[0].grabstate = FRAME_ERROR;
se401->frame[0].grabstate = FRAME_ERROR;
@@ -1443,10 +1464,10 @@ static void se401_disconnect(struct usb_interface *intf)
}
static struct usb_driver se401_driver = {
- .name = "se401",
- .id_table = device_table,
- .probe = se401_probe,
- .disconnect = se401_disconnect,
+ .name = "se401",
+ .id_table = device_table,
+ .probe = se401_probe,
+ .disconnect = se401_disconnect,
};
@@ -1459,9 +1480,10 @@ static struct usb_driver se401_driver = {
static int __init usb_se401_init(void)
{
- printk(KERN_INFO "SE401 usb camera driver version %s registering\n", version);
+ printk(KERN_INFO "SE401 usb camera driver version %s registering\n",
+ version);
if (flickerless)
- if (flickerless!=50 && flickerless!=60) {
+ if (flickerless != 50 && flickerless != 60) {
printk(KERN_ERR "Invallid flickerless value, use 0, 50 or 60.\n");
return -1;
}
diff --git a/linux/drivers/media/video/se401.h b/linux/drivers/media/video/se401.h
index 0be02c48b..00f0ddbf4 100644
--- a/linux/drivers/media/video/se401.h
+++ b/linux/drivers/media/video/se401.h
@@ -2,7 +2,7 @@
#ifndef __LINUX_se401_H
#define __LINUX_se401_H
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
#include "compat.h"
#include <linux/videodev.h>
#include <media/v4l2-common.h>
@@ -13,9 +13,10 @@
#ifdef se401_DEBUG
# define PDEBUG(level, fmt, args...) \
-if (debug >= level) info("[" __PRETTY_FUNCTION__ ":%d] " fmt, __LINE__ , ## args)
+if (debug >= level) \
+ info("[" __PRETTY_FUNCTION__ ":%d] " fmt, __LINE__ , ## args)
#else
-# define PDEBUG(level, fmt, args...) do {} while(0)
+# define PDEBUG(level, fmt, args...) do {} while (0)
#endif
/* An almost drop-in replacement for sleep_on_interruptible */
diff --git a/linux/drivers/media/video/soc_camera.c b/linux/drivers/media/video/soc_camera.c
index 822052b25..e4056a9c2 100644
--- a/linux/drivers/media/video/soc_camera.c
+++ b/linux/drivers/media/video/soc_camera.c
@@ -1206,7 +1206,7 @@ static int __devexit soc_camera_pdrv_remove(struct platform_device *pdev)
static struct platform_driver __refdata soc_camera_pdrv = {
.probe = soc_camera_pdrv_probe,
- .remove = __exit_p(soc_camera_pdrv_remove),
+ .remove = __devexit_p(soc_camera_pdrv_remove),
.driver = {
.name = "soc-camera-pdrv",
.owner = THIS_MODULE,
diff --git a/linux/drivers/media/video/tcm825x.c b/linux/drivers/media/video/tcm825x.c
index 559ade821..d778c41ef 100644
--- a/linux/drivers/media/video/tcm825x.c
+++ b/linux/drivers/media/video/tcm825x.c
@@ -882,7 +882,7 @@ static int tcm825x_probe(struct i2c_client *client,
return rval;
}
-static int __exit tcm825x_remove(struct i2c_client *client)
+static int tcm825x_remove(struct i2c_client *client)
{
struct tcm825x_sensor *sensor = i2c_get_clientdata(client);
@@ -908,7 +908,7 @@ static struct i2c_driver tcm825x_i2c_driver = {
.name = TCM825X_NAME,
},
.probe = tcm825x_probe,
- .remove = __exit_p(tcm825x_remove),
+ .remove = tcm825x_remove,
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26)
.id_table = tcm825x_id,
#endif
diff --git a/linux/drivers/media/video/tveeprom.c b/linux/drivers/media/video/tveeprom.c
index 7d6459dd2..5e3c9f4e2 100644
--- a/linux/drivers/media/video/tveeprom.c
+++ b/linux/drivers/media/video/tveeprom.c
@@ -185,7 +185,7 @@ hauppauge_tuner[] =
{ TUNER_ABSENT, "Silicon TDA8275C1 8290 FM"},
{ TUNER_ABSENT, "Thompson DTT757"},
/* 80-89 */
- { TUNER_PHILIPS_FM1216ME_MK3, "Philips FQ1216LME MK3"},
+ { TUNER_PHILIPS_FQ1216LME_MK3, "Philips FQ1216LME MK3"},
{ TUNER_LG_PAL_NEW_TAPC, "LG TAPC G701D"},
{ TUNER_LG_NTSC_NEW_TAPC, "LG TAPC H791F"},
{ TUNER_LG_PAL_NEW_TAPC, "TCL 2002MB 3"},
@@ -230,7 +230,7 @@ hauppauge_tuner[] =
{ TUNER_ABSENT, "Samsung THPD5222FG30A"},
/* 120-129 */
{ TUNER_XC2028, "Xceive XC3028"},
- { TUNER_ABSENT, "Philips FQ1216LME MK5"},
+ { TUNER_PHILIPS_FQ1216LME_MK3, "Philips FQ1216LME MK5"},
{ TUNER_ABSENT, "Philips FQD1216LME"},
{ TUNER_ABSENT, "Conexant CX24118A"},
{ TUNER_ABSENT, "TCL DMF11WIP"},
diff --git a/linux/drivers/media/video/tvp514x.c b/linux/drivers/media/video/tvp514x.c
index 4262e60b8..3750f7fad 100644
--- a/linux/drivers/media/video/tvp514x.c
+++ b/linux/drivers/media/video/tvp514x.c
@@ -692,7 +692,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;
diff --git a/linux/drivers/media/video/usbvideo/Kconfig b/linux/drivers/media/video/usbvideo/Kconfig
index e4cb99c1f..adb1c044a 100644
--- a/linux/drivers/media/video/usbvideo/Kconfig
+++ b/linux/drivers/media/video/usbvideo/Kconfig
@@ -38,10 +38,13 @@ config USB_KONICAWC
module will be called konicawc.
config USB_QUICKCAM_MESSENGER
- tristate "USB Logitech Quickcam Messenger"
+ tristate "USB Logitech Quickcam Messenger (DEPRECATED)"
depends on VIDEO_V4L1
select VIDEO_USBVIDEO
---help---
+ This driver is DEPRECATED please use the gspca stv06xx module
+ instead.
+
Say Y or M here to enable support for the USB Logitech Quickcam
Messenger webcam.
diff --git a/linux/drivers/media/video/usbvideo/konicawc.c b/linux/drivers/media/video/usbvideo/konicawc.c
index 75485168e..07bc85761 100644
--- a/linux/drivers/media/video/usbvideo/konicawc.c
+++ b/linux/drivers/media/video/usbvideo/konicawc.c
@@ -249,7 +249,7 @@ static void konicawc_register_input(struct konicawc *cam, struct usb_device *dev
#endif
input_dev->evbit[0] = BIT_MASK(EV_KEY);
- input_dev->keybit[BIT_WORD(BTN_0)] = BIT_MASK(BTN_0);
+ input_dev->keybit[BIT_WORD(KEY_CAMERA)] = BIT_MASK(KEY_CAMERA);
error = input_register_device(cam->input);
if (error) {
@@ -272,7 +272,7 @@ static void konicawc_unregister_input(struct konicawc *cam)
static void konicawc_report_buttonstat(struct konicawc *cam)
{
if (cam->input) {
- input_report_key(cam->input, BTN_0, cam->buttonsts);
+ input_report_key(cam->input, KEY_CAMERA, cam->buttonsts);
input_sync(cam->input);
}
}
diff --git a/linux/drivers/media/video/usbvideo/quickcam_messenger.c b/linux/drivers/media/video/usbvideo/quickcam_messenger.c
index f129bea11..ab30ef54a 100644
--- a/linux/drivers/media/video/usbvideo/quickcam_messenger.c
+++ b/linux/drivers/media/video/usbvideo/quickcam_messenger.c
@@ -112,7 +112,7 @@ static void qcm_register_input(struct qcm *cam, struct usb_device *dev)
#endif
input_dev->evbit[0] = BIT_MASK(EV_KEY);
- input_dev->keybit[BIT_WORD(BTN_0)] = BIT_MASK(BTN_0);
+ input_dev->keybit[BIT_WORD(KEY_CAMERA)] = BIT_MASK(KEY_CAMERA);
error = input_register_device(cam->input);
if (error) {
@@ -135,7 +135,7 @@ static void qcm_unregister_input(struct qcm *cam)
static void qcm_report_buttonstat(struct qcm *cam)
{
if (cam->input) {
- input_report_key(cam->input, BTN_0, cam->button_sts);
+ input_report_key(cam->input, KEY_CAMERA, cam->button_sts);
input_sync(cam->input);
}
}
diff --git a/linux/drivers/media/video/usbvision/usbvision-core.c b/linux/drivers/media/video/usbvision/usbvision-core.c
index 9253ec6dd..baf2e5621 100644
--- a/linux/drivers/media/video/usbvision/usbvision-core.c
+++ b/linux/drivers/media/video/usbvision/usbvision-core.c
@@ -390,10 +390,9 @@ int usbvision_scratch_alloc(struct usb_usbvision *usbvision)
void usbvision_scratch_free(struct usb_usbvision *usbvision)
{
- if (usbvision->scratch != NULL) {
- vfree(usbvision->scratch);
- usbvision->scratch = NULL;
- }
+ vfree(usbvision->scratch);
+ usbvision->scratch = NULL;
+
}
/*
@@ -506,10 +505,9 @@ int usbvision_decompress_alloc(struct usb_usbvision *usbvision)
*/
void usbvision_decompress_free(struct usb_usbvision *usbvision)
{
- if (usbvision->IntraFrameBuffer != NULL) {
- vfree(usbvision->IntraFrameBuffer);
- usbvision->IntraFrameBuffer = NULL;
- }
+ vfree(usbvision->IntraFrameBuffer);
+ usbvision->IntraFrameBuffer = NULL;
+
}
/************************************************************
diff --git a/linux/drivers/media/video/usbvision/usbvision-video.c b/linux/drivers/media/video/usbvision/usbvision-video.c
index d03e5922d..90b58914f 100644
--- a/linux/drivers/media/video/usbvision/usbvision-video.c
+++ b/linux/drivers/media/video/usbvision/usbvision-video.c
@@ -1794,7 +1794,7 @@ static struct usb_driver usbvision_driver = {
.name = "usbvision",
.id_table = usbvision_table,
.probe = usbvision_probe,
- .disconnect = usbvision_disconnect
+ .disconnect = __devexit_p(usbvision_disconnect),
};
/*
diff --git a/linux/drivers/media/video/uvc/uvc_ctrl.c b/linux/drivers/media/video/uvc/uvc_ctrl.c
index 7774ce6b5..ef55bc35a 100644
--- a/linux/drivers/media/video/uvc/uvc_ctrl.c
+++ b/linux/drivers/media/video/uvc/uvc_ctrl.c
@@ -1374,21 +1374,19 @@ end:
}
/*
- * Prune an entity of its bogus controls. This currently includes processing
- * unit auto controls for which no corresponding manual control is available.
- * Such auto controls make little sense if any, and are known to crash at
- * least the SiGma Micro webcam.
+ * Prune an entity of its bogus controls using a blacklist. Bogus controls
+ * are currently the ones that crash the camera or unconditionally return an
+ * error when queried.
*/
static void
-uvc_ctrl_prune_entity(struct uvc_entity *entity)
+uvc_ctrl_prune_entity(struct uvc_device *dev, struct uvc_entity *entity)
{
static const struct {
- u8 idx_manual;
- u8 idx_auto;
+ struct usb_device_id id;
+ u8 index;
} blacklist[] = {
- { 2, 11 }, /* Hue */
- { 6, 12 }, /* White Balance Temperature */
- { 7, 13 }, /* White Balance Component */
+ { { USB_DEVICE(0x1c4f, 0x3000) }, 6 }, /* WB Temperature */
+ { { USB_DEVICE(0x5986, 0x0241) }, 2 }, /* Hue */
};
u8 *controls;
@@ -1402,19 +1400,17 @@ uvc_ctrl_prune_entity(struct uvc_entity *entity)
size = entity->processing.bControlSize;
for (i = 0; i < ARRAY_SIZE(blacklist); ++i) {
- if (blacklist[i].idx_auto >= 8 * size ||
- blacklist[i].idx_manual >= 8 * size)
+ if (!usb_match_id(dev->intf, &blacklist[i].id))
continue;
- if (!uvc_test_bit(controls, blacklist[i].idx_auto) ||
- uvc_test_bit(controls, blacklist[i].idx_manual))
+ if (blacklist[i].index >= 8 * size ||
+ !uvc_test_bit(controls, blacklist[i].index))
continue;
- uvc_trace(UVC_TRACE_CONTROL, "Auto control %u/%u has no "
- "matching manual control, removing it.\n", entity->id,
- blacklist[i].idx_auto);
+ uvc_trace(UVC_TRACE_CONTROL, "%u/%u control is black listed, "
+ "removing it.\n", entity->id, blacklist[i].index);
- uvc_clear_bit(controls, blacklist[i].idx_auto);
+ uvc_clear_bit(controls, blacklist[i].index);
}
}
@@ -1444,8 +1440,7 @@ int uvc_ctrl_init_device(struct uvc_device *dev)
bControlSize = entity->camera.bControlSize;
}
- if (dev->quirks & UVC_QUIRK_PRUNE_CONTROLS)
- uvc_ctrl_prune_entity(entity);
+ uvc_ctrl_prune_entity(dev, entity);
for (i = 0; i < bControlSize; ++i)
ncontrols += hweight8(bmControls[i]);
diff --git a/linux/drivers/media/video/uvc/uvc_driver.c b/linux/drivers/media/video/uvc/uvc_driver.c
index 8d193376c..40df6828f 100644
--- a/linux/drivers/media/video/uvc/uvc_driver.c
+++ b/linux/drivers/media/video/uvc/uvc_driver.c
@@ -644,7 +644,7 @@ static int uvc_parse_streaming(struct uvc_device *dev,
_buflen = buflen;
/* Count the format and frame descriptors. */
- while (_buflen > 2) {
+ while (_buflen > 2 && _buffer[1] == CS_INTERFACE) {
switch (_buffer[2]) {
case VS_FORMAT_UNCOMPRESSED:
case VS_FORMAT_MJPEG:
@@ -709,7 +709,7 @@ static int uvc_parse_streaming(struct uvc_device *dev,
streaming->nformats = nformats;
/* Parse the format descriptors. */
- while (buflen > 2) {
+ while (buflen > 2 && buffer[1] == CS_INTERFACE) {
switch (buffer[2]) {
case VS_FORMAT_UNCOMPRESSED:
case VS_FORMAT_MJPEG:
@@ -1919,6 +1919,15 @@ static struct usb_device_id uvc_ids[] = {
.bInterfaceSubClass = 1,
.bInterfaceProtocol = 0,
.driver_info = UVC_QUIRK_STREAM_NO_FID },
+ /* Aveo Technology USB 2.0 Camera */
+ { .match_flags = USB_DEVICE_ID_MATCH_DEVICE
+ | USB_DEVICE_ID_MATCH_INT_INFO,
+ .idVendor = 0x1871,
+ .idProduct = 0x0306,
+ .bInterfaceClass = USB_CLASS_VIDEO,
+ .bInterfaceSubClass = 1,
+ .bInterfaceProtocol = 0,
+ .driver_info = UVC_QUIRK_PROBE_EXTRAFIELDS },
/* Ecamm Pico iMage */
{ .match_flags = USB_DEVICE_ID_MATCH_DEVICE
| USB_DEVICE_ID_MATCH_INT_INFO,
@@ -1928,6 +1937,15 @@ static struct usb_device_id uvc_ids[] = {
.bInterfaceSubClass = 1,
.bInterfaceProtocol = 0,
.driver_info = UVC_QUIRK_PROBE_EXTRAFIELDS },
+ /* FSC WebCam V30S */
+ { .match_flags = USB_DEVICE_ID_MATCH_DEVICE
+ | USB_DEVICE_ID_MATCH_INT_INFO,
+ .idVendor = 0x18ec,
+ .idProduct = 0x3288,
+ .bInterfaceClass = USB_CLASS_VIDEO,
+ .bInterfaceSubClass = 1,
+ .bInterfaceProtocol = 0,
+ .driver_info = UVC_QUIRK_PROBE_MINMAX },
/* Bodelin ProScopeHR */
{ .match_flags = USB_DEVICE_ID_MATCH_DEVICE
| USB_DEVICE_ID_MATCH_DEV_HI
@@ -1948,8 +1966,7 @@ static struct usb_device_id uvc_ids[] = {
.bInterfaceSubClass = 1,
.bInterfaceProtocol = 0,
.driver_info = UVC_QUIRK_PROBE_MINMAX
- | UVC_QUIRK_IGNORE_SELECTOR_UNIT
- | UVC_QUIRK_PRUNE_CONTROLS },
+ | UVC_QUIRK_IGNORE_SELECTOR_UNIT },
/* Generic USB Video Class */
{ USB_INTERFACE_INFO(USB_CLASS_VIDEO, 1, 0) },
{}
diff --git a/linux/drivers/media/video/uvc/uvc_queue.c b/linux/drivers/media/video/uvc/uvc_queue.c
index 0155752e4..f854698c4 100644
--- a/linux/drivers/media/video/uvc/uvc_queue.c
+++ b/linux/drivers/media/video/uvc/uvc_queue.c
@@ -172,6 +172,20 @@ int uvc_free_buffers(struct uvc_video_queue *queue)
return 0;
}
+/*
+ * Check if buffers have been allocated.
+ */
+int uvc_queue_allocated(struct uvc_video_queue *queue)
+{
+ int allocated;
+
+ mutex_lock(&queue->mutex);
+ allocated = queue->count != 0;
+ mutex_unlock(&queue->mutex);
+
+ return allocated;
+}
+
static void __uvc_query_buffer(struct uvc_buffer *buf,
struct v4l2_buffer *v4l2_buf)
{
diff --git a/linux/drivers/media/video/uvc/uvc_v4l2.c b/linux/drivers/media/video/uvc/uvc_v4l2.c
index 160c01314..0be85adf3 100644
--- a/linux/drivers/media/video/uvc/uvc_v4l2.c
+++ b/linux/drivers/media/video/uvc/uvc_v4l2.c
@@ -251,7 +251,7 @@ static int uvc_v4l2_set_format(struct uvc_video_device *video,
if (fmt->type != video->streaming->type)
return -EINVAL;
- if (uvc_queue_streaming(&video->queue))
+ if (uvc_queue_allocated(&video->queue))
return -EBUSY;
ret = uvc_v4l2_try_format(video, fmt, &probe, &format, &frame);
@@ -538,7 +538,10 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg)
memset(&xctrl, 0, sizeof xctrl);
xctrl.id = ctrl->id;
- uvc_ctrl_begin(video);
+ ret = uvc_ctrl_begin(video);
+ if (ret < 0)
+ return ret;
+
ret = uvc_ctrl_get(video, &xctrl);
uvc_ctrl_rollback(video);
if (ret >= 0)
@@ -555,7 +558,10 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg)
xctrl.id = ctrl->id;
xctrl.value = ctrl->value;
- uvc_ctrl_begin(video);
+ ret = uvc_ctrl_begin(video);
+ if (ret < 0)
+ return ret;
+
ret = uvc_ctrl_set(video, &xctrl);
if (ret < 0) {
uvc_ctrl_rollback(video);
@@ -574,7 +580,10 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg)
struct v4l2_ext_control *ctrl = ctrls->controls;
unsigned int i;
- uvc_ctrl_begin(video);
+ ret = uvc_ctrl_begin(video);
+ if (ret < 0)
+ return ret;
+
for (i = 0; i < ctrls->count; ++ctrl, ++i) {
ret = uvc_ctrl_get(video, ctrl);
if (ret < 0) {
diff --git a/linux/drivers/media/video/uvc/uvcvideo.h b/linux/drivers/media/video/uvc/uvcvideo.h
index 6b254fd39..de13c86f2 100644
--- a/linux/drivers/media/video/uvc/uvcvideo.h
+++ b/linux/drivers/media/video/uvc/uvcvideo.h
@@ -314,7 +314,6 @@ struct uvc_xu_control {
#define UVC_QUIRK_BUILTIN_ISIGHT 0x00000008
#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 */
@@ -749,6 +748,7 @@ extern struct uvc_buffer *uvc_queue_next_buffer(struct uvc_video_queue *queue,
struct uvc_buffer *buf);
extern unsigned int uvc_queue_poll(struct uvc_video_queue *queue,
struct file *file, poll_table *wait);
+extern int uvc_queue_allocated(struct uvc_video_queue *queue);
static inline int uvc_queue_streaming(struct uvc_video_queue *queue)
{
return queue->flags & UVC_QUEUE_STREAMING;
diff --git a/linux/drivers/media/video/v4l2-common.c b/linux/drivers/media/video/v4l2-common.c
index af1a64969..ab91734b1 100644
--- a/linux/drivers/media/video/v4l2-common.c
+++ b/linux/drivers/media/video/v4l2-common.c
@@ -1163,6 +1163,8 @@ const unsigned short *v4l2_i2c_tuner_addrs(enum v4l2_i2c_tuner_type type)
}
EXPORT_SYMBOL_GPL(v4l2_i2c_tuner_addrs);
+#endif /* defined(CONFIG_I2C) */
+
/* Clamp x to be between min and max, aligned to a multiple of 2^align. min
* and max don't have to be aligned, but there must be at least one valid
* value. E.g., min=17,max=31,align=4 is not allowed as there are no multiples
@@ -1219,10 +1221,13 @@ void v4l_bound_align_image(u32 *w, unsigned int wmin, unsigned int wmax,
if (walign + halign < salign) {
/* Max walign where there is still a valid width */
unsigned int wmaxa = __fls(wmax ^ (wmin - 1));
+ /* Max halign where there is still a valid height */
+ unsigned int hmaxa = __fls(hmax ^ (hmin - 1));
/* up the smaller alignment until we have enough */
do {
- if (walign <= halign && walign < wmaxa) {
+ if (halign >= hmaxa ||
+ (walign <= halign && walign < wmaxa)) {
*w = clamp_align(*w, wmin, wmax, walign + 1);
walign = __ffs(*w);
} else {
@@ -1233,5 +1238,3 @@ void v4l_bound_align_image(u32 *w, unsigned int wmin, unsigned int wmax,
}
}
EXPORT_SYMBOL_GPL(v4l_bound_align_image);
-
-#endif
diff --git a/linux/drivers/media/video/v4l2-ioctl.c b/linux/drivers/media/video/v4l2-ioctl.c
index 22b380dfd..625fe7698 100644
--- a/linux/drivers/media/video/v4l2-ioctl.c
+++ b/linux/drivers/media/video/v4l2-ioctl.c
@@ -1718,24 +1718,29 @@ static long __video_do_ioctl(struct file *file,
ret = ops->vidioc_enum_framesizes(file, fh, p);
dbgarg(cmd,
- "index=%d, pixelformat=%d, type=%d ",
- p->index, p->pixel_format, p->type);
+ "index=%d, pixelformat=%c%c%c%c, type=%d ",
+ p->index,
+ (p->pixel_format & 0xff),
+ (p->pixel_format >> 8) & 0xff,
+ (p->pixel_format >> 16) & 0xff,
+ (p->pixel_format >> 24) & 0xff,
+ p->type);
switch (p->type) {
case V4L2_FRMSIZE_TYPE_DISCRETE:
- dbgarg2("width = %d, height=%d\n",
+ printk("width = %d, height=%d\n",
p->discrete.width, p->discrete.height);
break;
case V4L2_FRMSIZE_TYPE_STEPWISE:
- dbgarg2("min %dx%d, max %dx%d, step %dx%d\n",
+ printk("min %dx%d, max %dx%d, step %dx%d\n",
p->stepwise.min_width, p->stepwise.min_height,
p->stepwise.step_width, p->stepwise.step_height,
p->stepwise.max_width, p->stepwise.max_height);
break;
case V4L2_FRMSIZE_TYPE_CONTINUOUS:
- dbgarg2("continuous\n");
+ printk("continuous\n");
break;
default:
- dbgarg2("- Unknown type!\n");
+ printk("- Unknown type!\n");
}
break;
diff --git a/linux/drivers/media/video/videobuf-core.c b/linux/drivers/media/video/videobuf-core.c
index e9696385d..faf912403 100644
--- a/linux/drivers/media/video/videobuf-core.c
+++ b/linux/drivers/media/video/videobuf-core.c
@@ -119,6 +119,7 @@ void videobuf_queue_core_init(struct videobuf_queue *q,
void *priv,
struct videobuf_qtype_ops *int_ops)
{
+ BUG_ON(!q);
memset(q, 0, sizeof(*q));
q->irqlock = irqlock;
q->dev = dev;
diff --git a/linux/drivers/media/video/videobuf-dma-sg.c b/linux/drivers/media/video/videobuf-dma-sg.c
index 623e2fc12..da83ac706 100644
--- a/linux/drivers/media/video/videobuf-dma-sg.c
+++ b/linux/drivers/media/video/videobuf-dma-sg.c
@@ -253,7 +253,7 @@ int videobuf_dma_map(struct videobuf_queue* q, struct videobuf_dmabuf *dma)
vfree(dma->sglist);
dma->sglist = NULL;
dma->sglen = 0;
- return -EIO;
+ return -ENOMEM;
}
}
return 0;
diff --git a/linux/drivers/media/video/vino.c b/linux/drivers/media/video/vino.c
index 808d9434d..7c39b43ee 100644
--- a/linux/drivers/media/video/vino.c
+++ b/linux/drivers/media/video/vino.c
@@ -868,9 +868,9 @@ static void vino_sync_buffer(struct vino_framebuffer *fb)
dprintk("vino_sync_buffer():\n");
for (i = 0; i < fb->desc_table.page_count; i++)
- dma_sync_single(NULL,
- fb->desc_table.dma_cpu[VINO_PAGE_RATIO * i],
- PAGE_SIZE, DMA_FROM_DEVICE);
+ dma_sync_single_for_cpu(NULL,
+ fb->desc_table.dma_cpu[VINO_PAGE_RATIO * i],
+ PAGE_SIZE, DMA_FROM_DEVICE);
}
/* Framebuffer fifo functions (need to be locked externally) */
diff --git a/linux/drivers/media/video/zoran/zoran_card.c b/linux/drivers/media/video/zoran/zoran_card.c
index 67ab10878..85f63116d 100644
--- a/linux/drivers/media/video/zoran/zoran_card.c
+++ b/linux/drivers/media/video/zoran/zoran_card.c
@@ -1478,7 +1478,7 @@ static struct pci_driver zoran_driver = {
.name = "zr36067",
.id_table = zr36067_pci_tbl,
.probe = zoran_probe,
- .remove = zoran_remove,
+ .remove = __devexit_p(zoran_remove),
};
static int __init zoran_init(void)
diff --git a/linux/drivers/media/video/zr364xx.c b/linux/drivers/media/video/zr364xx.c
index b8f47acab..8746f067d 100644
--- a/linux/drivers/media/video/zr364xx.c
+++ b/linux/drivers/media/video/zr364xx.c
@@ -883,9 +883,11 @@ static void zr364xx_disconnect(struct usb_interface *intf)
video_unregister_device(cam->vdev);
cam->vdev = NULL;
kfree(cam->buffer);
- if (cam->framebuf)
- vfree(cam->framebuf);
+ cam->buffer = NULL;
+ vfree(cam->framebuf);
+ cam->framebuf = NULL;
kfree(cam);
+ cam = NULL;
}
diff --git a/linux/include/linux/mmc/sdio_ids.h b/linux/include/linux/mmc/sdio_ids.h
index 3d7533d1e..39751c8cd 100644
--- a/linux/include/linux/mmc/sdio_ids.h
+++ b/linux/include/linux/mmc/sdio_ids.h
@@ -24,14 +24,16 @@
*/
#define SDIO_VENDOR_ID_MARVELL 0x02df
-#define SDIO_VENDOR_ID_SIANO 0x039a
-
#define SDIO_DEVICE_ID_MARVELL_LIBERTAS 0x9103
-#define SDIO_DEVICE_ID_SIANO_STELLAR 0x5347
-#define SDIO_DEVICE_ID_SIANO_NOVA_A0 0x1100
+#define SDIO_DEVICE_ID_MARVELL_8688WLAN 0x9104
+#define SDIO_DEVICE_ID_MARVELL_8688BT 0x9105
+
+#define SDIO_VENDOR_ID_SIANO 0x039a
#define SDIO_DEVICE_ID_SIANO_NOVA_B0 0x0201
#define SDIO_DEVICE_ID_SIANO_NICE 0x0202
#define SDIO_DEVICE_ID_SIANO_VEGA_A0 0x0300
#define SDIO_DEVICE_ID_SIANO_VENICE 0x0301
+#define SDIO_DEVICE_ID_SIANO_NOVA_A0 0x1100
+#define SDIO_DEVICE_ID_SIANO_STELLAR 0x5347
#endif
diff --git a/linux/include/linux/videodev2.h b/linux/include/linux/videodev2.h
index 82f9e723e..699ea62a7 100644
--- a/linux/include/linux/videodev2.h
+++ b/linux/include/linux/videodev2.h
@@ -347,7 +347,9 @@ struct v4l2_pix_format {
#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 */
+#define V4L2_PIX_FMT_YVYU v4l2_fourcc('Y', 'V', 'Y', 'U') /* 16 YVU 4:2:2 */
+#define V4L2_PIX_FMT_OV511 v4l2_fourcc('O', '5', '1', '1') /* ov511 JPEG */
+#define V4L2_PIX_FMT_OV518 v4l2_fourcc('O', '5', '1', '8') /* ov518 JPEG */
/*
* F O R M A T E N U M E R A T I O N
@@ -893,9 +895,10 @@ enum v4l2_colorfx {
V4L2_COLORFX_BW = 1,
V4L2_COLORFX_SEPIA = 2,
};
+#define V4L2_CID_AUTOBRIGHTNESS (V4L2_CID_BASE+32)
/* last CID + 1 */
-#define V4L2_CID_LASTP1 (V4L2_CID_BASE+32)
+#define V4L2_CID_LASTP1 (V4L2_CID_BASE+33)
/* MPEG-class control IDs defined by V4L2 */
#define V4L2_CID_MPEG_BASE (V4L2_CTRL_CLASS_MPEG | 0x900)
diff --git a/linux/include/media/ir-common.h b/linux/include/media/ir-common.h
index 7b5b91f60..9dcb632f6 100644
--- a/linux/include/media/ir-common.h
+++ b/linux/include/media/ir-common.h
@@ -162,6 +162,8 @@ 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];
extern IR_KEYTAB_TYPE ir_codes_dm1105_nec[IR_KEYTAB_SIZE];
+extern IR_KEYTAB_TYPE ir_codes_evga_indtube[IR_KEYTAB_SIZE];
+
#endif
/*
diff --git a/linux/include/media/tuner.h b/linux/include/media/tuner.h
index 735a2a941..cbf97f45f 100644
--- a/linux/include/media/tuner.h
+++ b/linux/include/media/tuner.h
@@ -125,6 +125,7 @@
#define TUNER_TCL_MF02GIP_5N 77 /* TCL MF02GIP_5N */
#define TUNER_PHILIPS_FMD1216MEX_MK3 78
#define TUNER_PHILIPS_FM1216MK5 79
+#define TUNER_PHILIPS_FQ1216LME_MK3 80 /* Active loopthrough, no FM */
/* tv card specific */
#define TDA9887_PRESENT (1<<0)
diff --git a/linux/include/media/v4l2-i2c-drv.h b/linux/include/media/v4l2-i2c-drv.h
index 121f0ada0..f5e4ffe27 100644
--- a/linux/include/media/v4l2-i2c-drv.h
+++ b/linux/include/media/v4l2-i2c-drv.h
@@ -22,7 +22,7 @@
*/
/* NOTE: the full version of this header is in the v4l-dvb repository
- * and allows v4l i2c drivers to be compiled on older kernels as well.
+ * and allows v4l i2c drivers to be compiled on pre-2.6.26 kernels.
* The version of this header as it appears in the kernel is a stripped
* version (without all the backwards compatibility stuff) and so it
* looks a bit odd.
@@ -30,6 +30,9 @@
* If you look at the full version then you will understand the reason
* for introducing this header since you really don't want to have all
* the tricky backwards compatibility code in each and every i2c driver.
+ *
+ * If the i2c driver will never be compiled for pre-2.6.26 kernels, then
+ * DO NOT USE this header! Just write it as a regular i2c driver.
*/
#ifndef __V4L2_I2C_DRV_H__
diff --git a/linux/sound/pci/bt87x.c b/linux/sound/pci/bt87x.c
index 11b10d70e..59e73e2b0 100644
--- a/linux/sound/pci/bt87x.c
+++ b/linux/sound/pci/bt87x.c
@@ -375,7 +375,8 @@ static struct snd_pcm_hardware snd_bt87x_digital_hw = {
.info = SNDRV_PCM_INFO_MMAP |
SNDRV_PCM_INFO_INTERLEAVED |
SNDRV_PCM_INFO_BLOCK_TRANSFER |
- SNDRV_PCM_INFO_MMAP_VALID,
+ SNDRV_PCM_INFO_MMAP_VALID |
+ SNDRV_PCM_INFO_BATCH,
.formats = SNDRV_PCM_FMTBIT_S16_LE,
.rates = 0, /* set at runtime */
.channels_min = 2,
@@ -391,7 +392,8 @@ static struct snd_pcm_hardware snd_bt87x_analog_hw = {
.info = SNDRV_PCM_INFO_MMAP |
SNDRV_PCM_INFO_INTERLEAVED |
SNDRV_PCM_INFO_BLOCK_TRANSFER |
- SNDRV_PCM_INFO_MMAP_VALID,
+ SNDRV_PCM_INFO_MMAP_VALID |
+ SNDRV_PCM_INFO_BATCH,
.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S8,
.rates = SNDRV_PCM_RATE_KNOT,
.rate_min = ANALOG_CLOCK / CLOCK_DIV_MAX,
@@ -834,6 +836,8 @@ static struct pci_device_id snd_bt87x_ids[] = {
BT_DEVICE(PCI_DEVICE_ID_BROOKTREE_878, 0x107d, 0x6606, GENERIC),
/* Voodoo TV 200 */
BT_DEVICE(PCI_DEVICE_ID_BROOKTREE_878, 0x121a, 0x3000, GENERIC),
+ /* Askey Computer Corp. MagicTView'99 */
+ BT_DEVICE(PCI_DEVICE_ID_BROOKTREE_878, 0x144f, 0x3000, GENERIC),
/* AVerMedia Studio No. 103, 203, ...? */
BT_DEVICE(PCI_DEVICE_ID_BROOKTREE_878, 0x1461, 0x0003, AVPHONE98),
/* Prolink PixelView PV-M4900 */