提交 04fc0a40 编写于 作者: L Linus Torvalds

Merge branch 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-2.6

* 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-2.6: (34 commits)
  V4L/DVB (12303): cx23885: check pointers before dereferencing in dprintk macro
  V4L/DVB (12302): cx23885-417: fix broken IOCTL handling
  V4L/DVB (12300): bttv: fix regression: tvaudio must be loaded before tuner
  V4L/DVB (12291): b2c2: fix frontends compiled into kernel
  V4L/DVB (12286): sn9c20x: reorder includes to be like other drivers
  V4L/DVB (12284): gspca - jpeg subdrivers: Check the result of kmalloc(jpeg header).
  V4L/DVB (12283): gspca - sn9c20x: New subdriver for sn9c201 and sn9c202 bridges.
  V4L/DVB (12282): gspca - main: Support for vidioc_g_chip_ident and vidioc_g/s_register.
  V4L/DVB (12269): af9013: auto-detect parameters in case of garbage given by app
  V4L/DVB (12267): gspca - sonixj: Bad sensor init of non ov76xx sensors.
  V4L/DVB (12265): em28xx: fix tuning problem in HVR-900 (R1)
  V4L/DVB (12263): em28xx: set demod profile for Pinnacle Hybrid Pro 320e
  V4L/DVB (12262): em28xx: Make sure the tuner is initialized if generic empia USB id was used
  V4L/DVB (12261): em28xx: set GPIO properly for Pinnacle Hybrid Pro analog support
  V4L/DVB (12260): em28xx: make support work for the Pinnacle Hybrid Pro (eb1a:2881)
  V4L/DVB (12258): em28xx: fix typo in mt352 init sequence for Terratec Cinergy T XS USB
  V4L/DVB (12257): em28xx: make tuning work for Terratec Cinergy T XS USB (mt352 variant)
  V4L/DVB (12245): em28xx: add support for mt9m001 webcams
  V4L/DVB (12244): em28xx: adjust vinmode/vinctl based on the stream input format
  V4L/DVB (12243): em28xx: allow specifying sensor xtal frequency
  ...
......@@ -20,7 +20,7 @@
19 -> EM2860/SAA711X Reference Design (em2860)
20 -> AMD ATI TV Wonder HD 600 (em2880) [0438:b002]
21 -> eMPIA Technology, Inc. GrabBeeX+ Video Encoder (em2800) [eb1a:2801]
22 -> Unknown EM2750/EM2751 webcam grabber (em2750) [eb1a:2750,eb1a:2751]
22 -> EM2710/EM2750/EM2751 webcam grabber (em2750) [eb1a:2750,eb1a:2751]
23 -> Huaqi DLCW-130 (em2750)
24 -> D-Link DUB-T210 TV Tuner (em2820/em2840) [2001:f112]
25 -> Gadmei UTV310 (em2820/em2840)
......
......@@ -44,7 +44,9 @@ zc3xx 0458:7007 Genius VideoCam V2
zc3xx 0458:700c Genius VideoCam V3
zc3xx 0458:700f Genius VideoCam Web V2
sonixj 0458:7025 Genius Eye 311Q
sn9c20x 0458:7029 Genius Look 320s
sonixj 0458:702e Genius Slim 310 NB
sn9c20x 045e:00f4 LifeCam VX-6000 (SN9C20x + OV9650)
sonixj 045e:00f5 MicroSoft VX3000
sonixj 045e:00f7 MicroSoft VX1000
ov519 045e:028c Micro$oft xbox cam
......@@ -282,6 +284,28 @@ sonixj 0c45:613a Microdia Sonix PC Camera
sonixj 0c45:613b Surfer SN-206
sonixj 0c45:613c Sonix Pccam168
sonixj 0c45:6143 Sonix Pccam168
sn9c20x 0c45:6240 PC Camera (SN9C201 + MT9M001)
sn9c20x 0c45:6242 PC Camera (SN9C201 + MT9M111)
sn9c20x 0c45:6248 PC Camera (SN9C201 + OV9655)
sn9c20x 0c45:624e PC Camera (SN9C201 + SOI968)
sn9c20x 0c45:624f PC Camera (SN9C201 + OV9650)
sn9c20x 0c45:6251 PC Camera (SN9C201 + OV9650)
sn9c20x 0c45:6253 PC Camera (SN9C201 + OV9650)
sn9c20x 0c45:6260 PC Camera (SN9C201 + OV7670)
sn9c20x 0c45:6270 PC Camera (SN9C201 + MT9V011/MT9V111/MT9V112)
sn9c20x 0c45:627b PC Camera (SN9C201 + OV7660)
sn9c20x 0c45:627c PC Camera (SN9C201 + HV7131R)
sn9c20x 0c45:627f PC Camera (SN9C201 + OV9650)
sn9c20x 0c45:6280 PC Camera (SN9C202 + MT9M001)
sn9c20x 0c45:6282 PC Camera (SN9C202 + MT9M111)
sn9c20x 0c45:6288 PC Camera (SN9C202 + OV9655)
sn9c20x 0c45:628e PC Camera (SN9C202 + SOI968)
sn9c20x 0c45:628f PC Camera (SN9C202 + OV9650)
sn9c20x 0c45:62a0 PC Camera (SN9C202 + OV7670)
sn9c20x 0c45:62b0 PC Camera (SN9C202 + MT9V011/MT9V111/MT9V112)
sn9c20x 0c45:62b3 PC Camera (SN9C202 + OV9655)
sn9c20x 0c45:62bb PC Camera (SN9C202 + OV7660)
sn9c20x 0c45:62bc PC Camera (SN9C202 + HV7131R)
sunplus 0d64:0303 Sunplus FashionCam DXG
etoms 102c:6151 Qcam Sangha CIF
etoms 102c:6251 Qcam xxxxxx VGA
......@@ -290,6 +314,7 @@ spca561 10fd:7e50 FlyCam Usb 100
zc3xx 10fd:8050 Typhoon Webshot II USB 300k
ov534 1415:2000 Sony HD Eye for PS3 (SLEH 00201)
pac207 145f:013a Trust WB-1300N
sn9c20x 145f:013d Trust WB-3600R
vc032x 15b8:6001 HP 2.0 Megapixel
vc032x 15b8:6002 HP 2.0 Megapixel rz406aa
spca501 1776:501c Arowana 300K CMOS Camera
......@@ -300,4 +325,11 @@ spca500 2899:012c Toptro Industrial
spca508 8086:0110 Intel Easy PC Camera
spca500 8086:0630 Intel Pocket PC Camera
spca506 99fa:8988 Grandtec V.cap
sn9c20x a168:0610 Dino-Lite Digital Microscope (SN9C201 + HV7131R)
sn9c20x a168:0611 Dino-Lite Digital Microscope (SN9C201 + HV7131R)
sn9c20x a168:0613 Dino-Lite Digital Microscope (SN9C201 + HV7131R)
sn9c20x a168:0618 Dino-Lite Digital Microscope (SN9C201 + HV7131R)
sn9c20x a168:0614 Dino-Lite Digital Microscope (SN9C201 + MT9M111)
sn9c20x a168:0615 Dino-Lite Digital Microscope (SN9C201 + MT9M111)
sn9c20x a168:0617 Dino-Lite Digital Microscope (SN9C201 + MT9M111)
spca561 abcd:cdee Petcam
......@@ -20,8 +20,14 @@
#include "tuner-simple.h"
#include "stv0297.h"
/* Can we use the specified front-end? Remember that if we are compiled
* into the kernel we can't call code that's in modules. */
#define FE_SUPPORTED(fe) (defined(CONFIG_DVB_##fe) || \
(defined(CONFIG_DVB_##fe##_MODULE) && defined(MODULE)))
/* lnb control */
#if defined(CONFIG_DVB_MT312_MODULE) || defined(CONFIG_DVB_STV0299_MODULE)
#if FE_SUPPORTED(MT312) || FE_SUPPORTED(STV0299)
static int flexcop_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage)
{
struct flexcop_device *fc = fe->dvb->priv;
......@@ -49,8 +55,7 @@ static int flexcop_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage
}
#endif
#if defined(CONFIG_DVB_S5H1420_MODULE) || defined(CONFIG_DVB_STV0299_MODULE) \
|| defined(CONFIG_DVB_MT312_MODULE)
#if FE_SUPPORTED(S5H1420) || FE_SUPPORTED(STV0299) || FE_SUPPORTED(MT312)
static int flexcop_sleep(struct dvb_frontend* fe)
{
struct flexcop_device *fc = fe->dvb->priv;
......@@ -61,7 +66,7 @@ static int flexcop_sleep(struct dvb_frontend* fe)
#endif
/* SkyStar2 DVB-S rev 2.3 */
#if defined(CONFIG_DVB_MT312_MODULE)
#if FE_SUPPORTED(MT312)
static int flexcop_set_tone(struct dvb_frontend *fe, fe_sec_tone_mode_t tone)
{
/* u16 wz_half_period_for_45_mhz[] = { 0x01ff, 0x0154, 0x00ff, 0x00cc }; */
......@@ -193,10 +198,12 @@ static int skystar2_rev23_attach(struct flexcop_device *fc,
}
return 0;
}
#else
#define skystar2_rev23_attach NULL
#endif
/* SkyStar2 DVB-S rev 2.6 */
#if defined(CONFIG_DVB_STV0299_MODULE)
#if FE_SUPPORTED(STV0299)
static int samsung_tbmu24112_set_symbol_rate(struct dvb_frontend *fe,
u32 srate, u32 ratio)
{
......@@ -321,10 +328,12 @@ static int skystar2_rev26_attach(struct flexcop_device *fc,
}
return 0;
}
#else
#define skystar2_rev26_attach NULL
#endif
/* SkyStar2 DVB-S rev 2.7 */
#if defined(CONFIG_DVB_S5H1420_MODULE)
#if FE_SUPPORTED(S5H1420) && FE_SUPPORTED(ISL6421) && FE_SUPPORTED(TUNER_ITD1000)
static struct s5h1420_config skystar2_rev2_7_s5h1420_config = {
.demod_address = 0x53,
.invert = 1,
......@@ -385,10 +394,12 @@ static int skystar2_rev27_attach(struct flexcop_device *fc,
fc->fc_i2c_adap[0].no_base_addr = 0;
return 0;
}
#else
#define skystar2_rev27_attach NULL
#endif
/* SkyStar2 rev 2.8 */
#if defined(CONFIG_DVB_CX24123_MODULE)
#if FE_SUPPORTED(CX24123) && FE_SUPPORTED(ISL6421) && FE_SUPPORTED(TUNER_CX24113)
static struct cx24123_config skystar2_rev2_8_cx24123_config = {
.demod_address = 0x55,
.dont_use_pll = 1,
......@@ -433,10 +444,12 @@ static int skystar2_rev28_attach(struct flexcop_device *fc,
* IR-receiver (PIC16F818) - but the card has no input for that ??? */
return 1;
}
#else
#define skystar2_rev28_attach NULL
#endif
/* AirStar DVB-T */
#if defined(CONFIG_DVB_MT352_MODULE)
#if FE_SUPPORTED(MT352)
static int samsung_tdtc9251dh0_demod_init(struct dvb_frontend *fe)
{
static u8 mt352_clock_config[] = { 0x89, 0x18, 0x2d };
......@@ -495,10 +508,12 @@ static int airstar_dvbt_attach(struct flexcop_device *fc,
}
return 0;
}
#else
#define airstar_dvbt_attach NULL
#endif
/* AirStar ATSC 1st generation */
#if defined(CONFIG_DVB_BCM3510_MODULE)
#if FE_SUPPORTED(BCM3510)
static int flexcop_fe_request_firmware(struct dvb_frontend *fe,
const struct firmware **fw, char* name)
{
......@@ -517,10 +532,12 @@ static int airstar_atsc1_attach(struct flexcop_device *fc,
fc->fe = dvb_attach(bcm3510_attach, &air2pc_atsc_first_gen_config, i2c);
return fc->fe != NULL;
}
#else
#define airstar_atsc1_attach NULL
#endif
/* AirStar ATSC 2nd generation */
#if defined(CONFIG_DVB_NXT200X_MODULE)
#if FE_SUPPORTED(NXT200X) && FE_SUPPORTED(PLL)
static struct nxt200x_config samsung_tbmv_config = {
.demod_address = 0x0a,
};
......@@ -535,10 +552,12 @@ static int airstar_atsc2_attach(struct flexcop_device *fc,
return !!dvb_attach(dvb_pll_attach, fc->fe, 0x61, NULL,
DVB_PLL_SAMSUNG_TBMV);
}
#else
#define airstar_atsc2_attach NULL
#endif
/* AirStar ATSC 3rd generation */
#if defined(CONFIG_DVB_LGDT330X_MODULE)
#if FE_SUPPORTED(LGDT330X)
static struct lgdt330x_config air2pc_atsc_hd5000_config = {
.demod_address = 0x59,
.demod_chip = LGDT3303,
......@@ -556,10 +575,12 @@ static int airstar_atsc3_attach(struct flexcop_device *fc,
return !!dvb_attach(simple_tuner_attach, fc->fe, i2c, 0x61,
TUNER_LG_TDVS_H06XF);
}
#else
#define airstar_atsc3_attach NULL
#endif
/* CableStar2 DVB-C */
#if defined(CONFIG_DVB_STV0297_MODULE)
#if FE_SUPPORTED(STV0297)
static int alps_tdee4_stv0297_tuner_set_params(struct dvb_frontend* fe,
struct dvb_frontend_parameters *fep)
{
......@@ -698,39 +719,23 @@ static int cablestar2_attach(struct flexcop_device *fc,
fc->fe->ops.tuner_ops.set_params = alps_tdee4_stv0297_tuner_set_params;
return 1;
}
#else
#define cablestar2_attach NULL
#endif
static struct {
flexcop_device_type_t type;
int (*attach)(struct flexcop_device *, struct i2c_adapter *);
} flexcop_frontends[] = {
#if defined(CONFIG_DVB_S5H1420_MODULE)
{ FC_SKY_REV27, skystar2_rev27_attach },
#endif
#if defined(CONFIG_DVB_CX24123_MODULE)
{ FC_SKY_REV28, skystar2_rev28_attach },
#endif
#if defined(CONFIG_DVB_STV0299_MODULE)
{ FC_SKY_REV26, skystar2_rev26_attach },
#endif
#if defined(CONFIG_DVB_MT352_MODULE)
{ FC_AIR_DVBT, airstar_dvbt_attach },
#endif
#if defined(CONFIG_DVB_NXT200X_MODULE)
{ FC_AIR_ATSC2, airstar_atsc2_attach },
#endif
#if defined(CONFIG_DVB_LGDT330X_MODULE)
{ FC_AIR_ATSC3, airstar_atsc3_attach },
#endif
#if defined(CONFIG_DVB_BCM3510_MODULE)
{ FC_AIR_ATSC1, airstar_atsc1_attach },
#endif
#if defined(CONFIG_DVB_STV0297_MODULE)
{ FC_CABLE, cablestar2_attach },
#endif
#if defined(CONFIG_DVB_MT312_MODULE)
{ FC_SKY_REV23, skystar2_rev23_attach },
#endif
};
/* try to figure out the frontend */
......@@ -738,6 +743,8 @@ int flexcop_frontend_init(struct flexcop_device *fc)
{
int i;
for (i = 0; i < ARRAY_SIZE(flexcop_frontends); i++) {
if (!flexcop_frontends[i].attach)
continue;
/* type needs to be set before, because of some workarounds
* done based on the probed card type */
fc->dev_type = flexcop_frontends[i].type;
......
......@@ -527,6 +527,10 @@ static int af9013_set_ofdm_params(struct af9013_state *state,
u8 i, buf[3] = {0, 0, 0};
*auto_mode = 0; /* set if parameters are requested to auto set */
/* Try auto-detect transmission parameters in case of AUTO requested or
garbage parameters given by application for compatibility.
MPlayer seems to provide garbage parameters currently. */
switch (params->transmission_mode) {
case TRANSMISSION_MODE_AUTO:
*auto_mode = 1;
......@@ -536,7 +540,8 @@ static int af9013_set_ofdm_params(struct af9013_state *state,
buf[0] |= (1 << 0);
break;
default:
return -EINVAL;
deb_info("%s: invalid transmission_mode\n", __func__);
*auto_mode = 1;
}
switch (params->guard_interval) {
......@@ -554,7 +559,8 @@ static int af9013_set_ofdm_params(struct af9013_state *state,
buf[0] |= (3 << 2);
break;
default:
return -EINVAL;
deb_info("%s: invalid guard_interval\n", __func__);
*auto_mode = 1;
}
switch (params->hierarchy_information) {
......@@ -572,7 +578,8 @@ static int af9013_set_ofdm_params(struct af9013_state *state,
buf[0] |= (3 << 4);
break;
default:
return -EINVAL;
deb_info("%s: invalid hierarchy_information\n", __func__);
*auto_mode = 1;
};
switch (params->constellation) {
......@@ -587,7 +594,8 @@ static int af9013_set_ofdm_params(struct af9013_state *state,
buf[1] |= (2 << 6);
break;
default:
return -EINVAL;
deb_info("%s: invalid constellation\n", __func__);
*auto_mode = 1;
}
/* Use HP. How and which case we can switch to LP? */
......@@ -611,7 +619,8 @@ static int af9013_set_ofdm_params(struct af9013_state *state,
buf[2] |= (4 << 0);
break;
default:
return -EINVAL;
deb_info("%s: invalid code_rate_HP\n", __func__);
*auto_mode = 1;
}
switch (params->code_rate_LP) {
......@@ -638,7 +647,8 @@ static int af9013_set_ofdm_params(struct af9013_state *state,
if (params->hierarchy_information == HIERARCHY_AUTO)
break;
default:
return -EINVAL;
deb_info("%s: invalid code_rate_LP\n", __func__);
*auto_mode = 1;
}
switch (params->bandwidth) {
......@@ -651,7 +661,8 @@ static int af9013_set_ofdm_params(struct af9013_state *state,
buf[1] |= (2 << 2);
break;
default:
return -EINVAL;
deb_info("%s: invalid bandwidth\n", __func__);
buf[1] |= (2 << 2); /* cannot auto-detect BW, try 8 MHz */
}
/* program */
......
......@@ -3324,8 +3324,6 @@ void __devinit bttv_init_card1(struct bttv *btv)
/* initialization part two -- after registering i2c bus */
void __devinit bttv_init_card2(struct bttv *btv)
{
int addr=ADDR_UNSET;
btv->tuner_type = UNSET;
if (BTTV_BOARD_UNKNOWN == btv->c.type) {
......@@ -3470,9 +3468,6 @@ void __devinit bttv_init_card2(struct bttv *btv)
btv->pll.pll_current = -1;
/* tuner configuration (from card list / autodetect / insmod option) */
if (ADDR_UNSET != bttv_tvcards[btv->c.type].tuner_addr)
addr = bttv_tvcards[btv->c.type].tuner_addr;
if (UNSET != bttv_tvcards[btv->c.type].tuner_type)
if (UNSET == btv->tuner_type)
btv->tuner_type = bttv_tvcards[btv->c.type].tuner_type;
......@@ -3496,40 +3491,6 @@ void __devinit bttv_init_card2(struct bttv *btv)
if (UNSET == btv->tuner_type)
btv->tuner_type = TUNER_ABSENT;
if (btv->tuner_type != TUNER_ABSENT) {
struct tuner_setup tun_setup;
/* Load tuner module before issuing tuner config call! */
if (bttv_tvcards[btv->c.type].has_radio)
v4l2_i2c_new_probed_subdev(&btv->c.v4l2_dev,
&btv->c.i2c_adap, "tuner", "tuner",
v4l2_i2c_tuner_addrs(ADDRS_RADIO));
v4l2_i2c_new_probed_subdev(&btv->c.v4l2_dev,
&btv->c.i2c_adap, "tuner", "tuner",
v4l2_i2c_tuner_addrs(ADDRS_DEMOD));
v4l2_i2c_new_probed_subdev(&btv->c.v4l2_dev,
&btv->c.i2c_adap, "tuner", "tuner",
v4l2_i2c_tuner_addrs(ADDRS_TV_WITH_DEMOD));
tun_setup.mode_mask = T_ANALOG_TV | T_DIGITAL_TV;
tun_setup.type = btv->tuner_type;
tun_setup.addr = addr;
if (bttv_tvcards[btv->c.type].has_radio)
tun_setup.mode_mask |= T_RADIO;
bttv_call_all(btv, tuner, s_type_addr, &tun_setup);
}
if (btv->tda9887_conf) {
struct v4l2_priv_tun_config tda9887_cfg;
tda9887_cfg.tuner = TUNER_TDA9887;
tda9887_cfg.priv = &btv->tda9887_conf;
bttv_call_all(btv, tuner, s_config, &tda9887_cfg);
}
btv->dig = bttv_tvcards[btv->c.type].has_dig_in ?
bttv_tvcards[btv->c.type].video_inputs - 1 : UNSET;
btv->svhs = bttv_tvcards[btv->c.type].svhs == NO_SVHS ?
......@@ -3540,15 +3501,15 @@ void __devinit bttv_init_card2(struct bttv *btv)
btv->has_remote = remote[btv->c.nr];
if (bttv_tvcards[btv->c.type].has_radio)
btv->has_radio=1;
btv->has_radio = 1;
if (bttv_tvcards[btv->c.type].has_remote)
btv->has_remote=1;
btv->has_remote = 1;
if (!bttv_tvcards[btv->c.type].no_gpioirq)
btv->gpioirq=1;
btv->gpioirq = 1;
if (bttv_tvcards[btv->c.type].volume_gpio)
btv->volume_gpio=bttv_tvcards[btv->c.type].volume_gpio;
btv->volume_gpio = bttv_tvcards[btv->c.type].volume_gpio;
if (bttv_tvcards[btv->c.type].audio_mode_gpio)
btv->audio_mode_gpio=bttv_tvcards[btv->c.type].audio_mode_gpio;
btv->audio_mode_gpio = bttv_tvcards[btv->c.type].audio_mode_gpio;
if (btv->tuner_type == TUNER_ABSENT)
return; /* no tuner or related drivers to load */
......@@ -3666,6 +3627,49 @@ void __devinit bttv_init_card2(struct bttv *btv)
}
/* initialize the tuner */
void __devinit bttv_init_tuner(struct bttv *btv)
{
int addr = ADDR_UNSET;
if (ADDR_UNSET != bttv_tvcards[btv->c.type].tuner_addr)
addr = bttv_tvcards[btv->c.type].tuner_addr;
if (btv->tuner_type != TUNER_ABSENT) {
struct tuner_setup tun_setup;
/* Load tuner module before issuing tuner config call! */
if (bttv_tvcards[btv->c.type].has_radio)
v4l2_i2c_new_probed_subdev(&btv->c.v4l2_dev,
&btv->c.i2c_adap, "tuner", "tuner",
v4l2_i2c_tuner_addrs(ADDRS_RADIO));
v4l2_i2c_new_probed_subdev(&btv->c.v4l2_dev,
&btv->c.i2c_adap, "tuner", "tuner",
v4l2_i2c_tuner_addrs(ADDRS_DEMOD));
v4l2_i2c_new_probed_subdev(&btv->c.v4l2_dev,
&btv->c.i2c_adap, "tuner", "tuner",
v4l2_i2c_tuner_addrs(ADDRS_TV_WITH_DEMOD));
tun_setup.mode_mask = T_ANALOG_TV | T_DIGITAL_TV;
tun_setup.type = btv->tuner_type;
tun_setup.addr = addr;
if (bttv_tvcards[btv->c.type].has_radio)
tun_setup.mode_mask |= T_RADIO;
bttv_call_all(btv, tuner, s_type_addr, &tun_setup);
}
if (btv->tda9887_conf) {
struct v4l2_priv_tun_config tda9887_cfg;
tda9887_cfg.tuner = TUNER_TDA9887;
tda9887_cfg.priv = &btv->tda9887_conf;
bttv_call_all(btv, tuner, s_config, &tda9887_cfg);
}
}
/* ----------------------------------------------------------------------- */
static void modtec_eeprom(struct bttv *btv)
......
......@@ -4419,6 +4419,7 @@ static int __devinit bttv_probe(struct pci_dev *dev,
/* some card-specific stuff (needs working i2c) */
bttv_init_card2(btv);
bttv_init_tuner(btv);
init_irqreg(btv);
/* register video4linux + input */
......
......@@ -283,6 +283,7 @@ extern struct tvcard bttv_tvcards[];
extern void bttv_idcard(struct bttv *btv);
extern void bttv_init_card1(struct bttv *btv);
extern void bttv_init_card2(struct bttv *btv);
extern void bttv_init_tuner(struct bttv *btv);
/* card-specific funtions */
extern void tea5757_set_freq(struct bttv *btv, unsigned short freq);
......
......@@ -58,7 +58,8 @@ MODULE_PARM_DESC(v4l_debug, "enable V4L debug messages");
#define dprintk(level, fmt, arg...)\
do { if (v4l_debug >= level) \
printk(KERN_DEBUG "%s: " fmt, dev->name , ## arg);\
printk(KERN_DEBUG "%s: " fmt, \
(dev) ? dev->name : "cx23885[?]", ## arg); \
} while (0)
static struct cx23885_tvnorm cx23885_tvnorms[] = {
......@@ -1677,6 +1678,7 @@ static struct v4l2_file_operations mpeg_fops = {
.read = mpeg_read,
.poll = mpeg_poll,
.mmap = mpeg_mmap,
.ioctl = video_ioctl2,
};
static const struct v4l2_ioctl_ops mpeg_ioctl_ops = {
......
......@@ -58,8 +58,6 @@ static unsigned int card[] = {[0 ... (EM28XX_MAXBOARDS - 1)] = UNSET };
module_param_array(card, int, NULL, 0444);
MODULE_PARM_DESC(card, "card type");
#define MT9V011_VERSION 0x8243
/* Bitmask marking allocated devices from 0 to EM28XX_MAXBOARDS */
static unsigned long em28xx_devused;
......@@ -159,6 +157,20 @@ static struct em28xx_reg_seq evga_indtube_digital[] = {
{ -1, -1, -1, -1},
};
/* Pinnacle Hybrid Pro eb1a:2881 */
static struct em28xx_reg_seq pinnacle_hybrid_pro_analog[] = {
{EM28XX_R08_GPIO, 0xfd, ~EM_GPIO_4, 10},
{ -1, -1, -1, -1},
};
static struct em28xx_reg_seq pinnacle_hybrid_pro_digital[] = {
{EM28XX_R08_GPIO, 0x6e, ~EM_GPIO_4, 10},
{EM2880_R04_GPO, 0x04, 0xff, 100},/* zl10353 reset */
{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},
......@@ -205,13 +217,15 @@ static struct em28xx_reg_seq silvercrest_reg_seq[] = {
*/
struct em28xx_board em28xx_boards[] = {
[EM2750_BOARD_UNKNOWN] = {
.name = "Unknown EM2750/EM2751 webcam grabber",
.name = "EM2710/EM2750/EM2751 webcam grabber",
.xclk = EM28XX_XCLK_FREQUENCY_48MHZ,
.tuner_type = TUNER_ABSENT, /* This is a webcam */
.tuner_type = TUNER_ABSENT,
.is_webcam = 1,
.input = { {
.type = EM28XX_VMUX_COMPOSITE1,
.vmux = 0,
.amux = EM28XX_AMUX_VIDEO,
.gpio = silvercrest_reg_seq,
} },
},
[EM2800_BOARD_UNKNOWN] = {
......@@ -233,13 +247,15 @@ struct em28xx_board em28xx_boards[] = {
[EM2820_BOARD_UNKNOWN] = {
.name = "Unknown EM2750/28xx video grabber",
.tuner_type = TUNER_ABSENT,
.is_webcam = 1, /* To enable sensor probe */
},
[EM2750_BOARD_DLCW_130] = {
/* Beijing Huaqi Information Digital Technology Co., Ltd */
.name = "Huaqi DLCW-130",
.valid = EM28XX_BOARD_NOT_VALIDATED,
.xclk = EM28XX_XCLK_FREQUENCY_48MHZ,
.tuner_type = TUNER_ABSENT, /* This is a webcam */
.tuner_type = TUNER_ABSENT,
.is_webcam = 1,
.input = { {
.type = EM28XX_VMUX_COMPOSITE1,
.vmux = 0,
......@@ -440,7 +456,8 @@ struct em28xx_board em28xx_boards[] = {
[EM2820_BOARD_VIDEOLOGY_20K14XUSB] = {
.name = "Videology 20K14XUSB USB2.0",
.valid = EM28XX_BOARD_NOT_VALIDATED,
.tuner_type = TUNER_ABSENT, /* This is a webcam */
.tuner_type = TUNER_ABSENT,
.is_webcam = 1,
.input = { {
.type = EM28XX_VMUX_COMPOSITE1,
.vmux = 0,
......@@ -450,8 +467,7 @@ struct em28xx_board em28xx_boards[] = {
[EM2820_BOARD_SILVERCREST_WEBCAM] = {
.name = "Silvercrest Webcam 1.3mpix",
.tuner_type = TUNER_ABSENT,
.is_27xx = 1,
.decoder = EM28XX_MT9V011,
.is_webcam = 1,
.input = { {
.type = EM28XX_VMUX_COMPOSITE1,
.vmux = 0,
......@@ -500,7 +516,8 @@ struct em28xx_board em28xx_boards[] = {
/* Beijing Huaqi Information Digital Technology Co., Ltd */
.name = "NetGMBH Cam",
.valid = EM28XX_BOARD_NOT_VALIDATED,
.tuner_type = TUNER_ABSENT, /* This is a webcam */
.tuner_type = TUNER_ABSENT,
.is_webcam = 1,
.input = { {
.type = EM28XX_VMUX_COMPOSITE1,
.vmux = 0,
......@@ -1250,25 +1267,26 @@ struct em28xx_board em28xx_boards[] = {
},
[EM2881_BOARD_PINNACLE_HYBRID_PRO] = {
.name = "Pinnacle Hybrid Pro",
.valid = EM28XX_BOARD_NOT_VALIDATED,
.tuner_type = TUNER_XC2028,
.tuner_gpio = default_tuner_gpio,
.decoder = EM28XX_TVP5150,
.has_dvb = 1,
.dvb_gpio = pinnacle_hybrid_pro_digital,
.input = { {
.type = EM28XX_VMUX_TELEVISION,
.vmux = TVP5150_COMPOSITE0,
.amux = EM28XX_AMUX_VIDEO,
.gpio = default_analog,
.gpio = pinnacle_hybrid_pro_analog,
}, {
.type = EM28XX_VMUX_COMPOSITE1,
.vmux = TVP5150_COMPOSITE1,
.amux = EM28XX_AMUX_LINE_IN,
.gpio = default_analog,
.gpio = pinnacle_hybrid_pro_analog,
}, {
.type = EM28XX_VMUX_SVIDEO,
.vmux = TVP5150_SVIDEO,
.amux = EM28XX_AMUX_LINE_IN,
.gpio = default_analog,
.gpio = pinnacle_hybrid_pro_analog,
} },
},
[EM2882_BOARD_PINNACLE_HYBRID_PRO] = {
......@@ -1638,6 +1656,7 @@ static struct em28xx_hash_table em28xx_eeprom_hash[] = {
{0x966a0441, EM2880_BOARD_KWORLD_DVB_310U, TUNER_XC2028},
{0x9567eb1a, EM2880_BOARD_EMPIRE_DUAL_TV, TUNER_XC2028},
{0xcee44a99, EM2882_BOARD_EVGA_INDTUBE, TUNER_XC2028},
{0xb8846b20, EM2881_BOARD_PINNACLE_HYBRID_PRO, TUNER_XC2028},
};
/* I2C devicelist hash table for devices with generic USB IDs */
......@@ -1704,6 +1723,32 @@ static inline void em28xx_set_model(struct em28xx *dev)
EM28XX_I2C_FREQ_100_KHZ;
}
/* FIXME: Should be replaced by a proper mt9m001 driver */
static int em28xx_initialize_mt9m001(struct em28xx *dev)
{
int i;
unsigned char regs[][3] = {
{ 0x0d, 0x00, 0x01, },
{ 0x0d, 0x00, 0x00, },
{ 0x04, 0x05, 0x00, }, /* hres = 1280 */
{ 0x03, 0x04, 0x00, }, /* vres = 1024 */
{ 0x20, 0x11, 0x00, },
{ 0x06, 0x00, 0x10, },
{ 0x2b, 0x00, 0x24, },
{ 0x2e, 0x00, 0x24, },
{ 0x35, 0x00, 0x24, },
{ 0x2d, 0x00, 0x20, },
{ 0x2c, 0x00, 0x20, },
{ 0x09, 0x0a, 0xd4, },
{ 0x35, 0x00, 0x57, },
};
for (i = 0; i < ARRAY_SIZE(regs); i++)
i2c_master_send(&dev->i2c_client, &regs[i][0], 3);
return 0;
}
/* HINT method: webcam I2C chips
*
* This method work for webcams with Micron sensors
......@@ -1716,9 +1761,6 @@ static int em28xx_hint_sensor(struct em28xx *dev)
__be16 version_be;
u16 version;
if (dev->model != EM2820_BOARD_UNKNOWN)
return 0;
dev->i2c_client.addr = 0xba >> 1;
cmd = 0;
i2c_master_send(&dev->i2c_client, &cmd, 1);
......@@ -1729,16 +1771,38 @@ static int em28xx_hint_sensor(struct em28xx *dev)
version = be16_to_cpu(version_be);
switch (version) {
case MT9V011_VERSION:
case 0x8243: /* mt9v011 640x480 1.3 Mpix sensor */
dev->model = EM2820_BOARD_SILVERCREST_WEBCAM;
sensor_name = "mt9v011";
dev->em28xx_sensor = EM28XX_MT9V011;
dev->sensor_xres = 640;
dev->sensor_yres = 480;
dev->sensor_xtal = 6300000;
/* probably means GRGB 16 bit bayer */
dev->vinmode = 0x0d;
dev->vinctl = 0x00;
break;
case 0x8431:
dev->model = EM2750_BOARD_UNKNOWN;
sensor_name = "mt9m001";
dev->em28xx_sensor = EM28XX_MT9M001;
em28xx_initialize_mt9m001(dev);
dev->sensor_xres = 1280;
dev->sensor_yres = 1024;
/* probably means BGGR 16 bit bayer */
dev->vinmode = 0x0c;
dev->vinctl = 0x00;
break;
default:
printk("Unknown Sensor 0x%04x\n", be16_to_cpu(version));
printk("Unknown Micron Sensor 0x%04x\n", be16_to_cpu(version));
return -EINVAL;
}
em28xx_errdev("Sensor is %s, assuming that webcam is %s\n",
em28xx_errdev("Sensor is %s, using model %s entry.\n",
sensor_name, em28xx_boards[dev->model].name);
return 0;
......@@ -1772,10 +1836,7 @@ void em28xx_pre_card_setup(struct em28xx *dev)
em28xx_info("chip ID is em2750\n");
break;
case CHIP_ID_EM2820:
if (dev->board.is_27xx)
em28xx_info("chip is em2710\n");
else
em28xx_info("chip ID is em2820\n");
em28xx_info("chip ID is em2710 or em2820\n");
break;
case CHIP_ID_EM2840:
em28xx_info("chip ID is em2840\n");
......@@ -1929,6 +1990,7 @@ static void em28xx_setup_xc3028(struct em28xx *dev, struct xc2028_ctrl *ctl)
ctl->demod = XC3028_FE_ZARLINK456;
break;
case EM2880_BOARD_TERRATEC_HYBRID_XS:
case EM2881_BOARD_PINNACLE_HYBRID_PRO:
ctl->demod = XC3028_FE_ZARLINK456;
break;
case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900_R2:
......@@ -2225,6 +2287,7 @@ void em28xx_card_setup(struct em28xx *dev)
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_gpio_set(dev, dev->board.tuner_gpio);
em28xx_set_mode(dev, EM28XX_ANALOG_MODE);
break;
case EM2820_BOARD_SILVERCREST_WEBCAM:
......@@ -2262,9 +2325,14 @@ void em28xx_card_setup(struct em28xx *dev)
v4l2_i2c_new_probed_subdev(&dev->v4l2_dev, &dev->i2c_adap,
"tvp5150", "tvp5150", tvp5150_addrs);
if (dev->board.decoder == EM28XX_MT9V011)
v4l2_i2c_new_probed_subdev(&dev->v4l2_dev, &dev->i2c_adap,
"mt9v011", "mt9v011", mt9v011_addrs);
if (dev->em28xx_sensor == EM28XX_MT9V011) {
struct v4l2_subdev *sd;
sd = v4l2_i2c_new_probed_subdev(&dev->v4l2_dev,
&dev->i2c_adap, "mt9v011", "mt9v011", mt9v011_addrs);
v4l2_subdev_call(sd, core, s_config, 0, &dev->sensor_xtal);
}
if (dev->board.adecoder == EM28XX_TVAUDIO)
v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_adap,
......@@ -2410,7 +2478,19 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev,
return errCode;
}
em28xx_hint_sensor(dev);
/*
* Default format, used for tvp5150 or saa711x output formats
*/
dev->vinmode = 0x10;
dev->vinctl = 0x11;
/*
* If the device can be a webcam, seek for a sensor.
* If sensor is not found, then it isn't a webcam.
*/
if (dev->board.is_webcam)
if (em28xx_hint_sensor(dev) < 0)
dev->board.is_webcam = 0;
/* Do board specific init and eeprom reading */
em28xx_card_setup(dev);
......
......@@ -648,28 +648,17 @@ int em28xx_capture_start(struct em28xx *dev, int start)
int em28xx_set_outfmt(struct em28xx *dev)
{
int ret;
int vinmode, vinctl, outfmt;
outfmt = dev->format->reg;
if (dev->board.is_27xx) {
vinmode = 0x0d;
vinctl = 0x00;
} else {
vinmode = 0x10;
vinctl = 0x11;
}
ret = em28xx_write_reg_bits(dev, EM28XX_R27_OUTFMT,
outfmt | 0x20, 0xff);
dev->format->reg | 0x20, 0xff);
if (ret < 0)
return ret;
ret = em28xx_write_reg(dev, EM28XX_R10_VINMODE, vinmode);
ret = em28xx_write_reg(dev, EM28XX_R10_VINMODE, dev->vinmode);
if (ret < 0)
return ret;
return em28xx_write_reg(dev, EM28XX_R11_VINCTRL, vinctl);
return em28xx_write_reg(dev, EM28XX_R11_VINCTRL, dev->vinctl);
}
static int em28xx_accumulator_set(struct em28xx *dev, u8 xmin, u8 xmax,
......@@ -707,10 +696,7 @@ static int em28xx_scaler_set(struct em28xx *dev, u16 h, u16 v)
u8 mode;
/* the em2800 scaler only supports scaling down to 50% */
if (dev->board.is_27xx) {
/* FIXME: Don't use the scaler yet */
mode = 0;
} else if (dev->board.is_em2800) {
if (dev->board.is_em2800) {
mode = (v ? 0x20 : 0x00) | (h ? 0x10 : 0x00);
} else {
u8 buf[2];
......
......@@ -31,6 +31,8 @@
#include "lgdt330x.h"
#include "zl10353.h"
#include "s5h1409.h"
#include "mt352.h"
#include "mt352_priv.h" /* FIXME */
MODULE_DESCRIPTION("driver for em28xx based DVB cards");
MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@infradead.org>");
......@@ -243,7 +245,7 @@ static struct s5h1409_config em28xx_s5h1409_with_xc3028 = {
.mpeg_timing = S5H1409_MPEGTIMING_CONTINOUS_NONINVERTING_CLOCK
};
static struct zl10353_config em28xx_terratec_xs_zl10353_xc3028 = {
static struct zl10353_config em28xx_zl10353_xc3028_no_i2c_gate = {
.demod_address = (0x1e >> 1),
.no_tuner = 1,
.disable_i2c_gate_ctrl = 1,
......@@ -258,6 +260,41 @@ static struct drx397xD_config em28xx_drx397xD_with_xc3028 = {
};
#endif
static int mt352_terratec_xs_init(struct dvb_frontend *fe)
{
/* Values extracted from a USB trace of the Terratec Windows driver */
static u8 clock_config[] = { CLOCK_CTL, 0x38, 0x2c };
static u8 reset[] = { RESET, 0x80 };
static u8 adc_ctl_1_cfg[] = { ADC_CTL_1, 0x40 };
static u8 agc_cfg[] = { AGC_TARGET, 0x28, 0xa0 };
static u8 input_freq_cfg[] = { INPUT_FREQ_1, 0x31, 0xb8 };
static u8 rs_err_cfg[] = { RS_ERR_PER_1, 0x00, 0x4d };
static u8 capt_range_cfg[] = { CAPT_RANGE, 0x32 };
static u8 trl_nom_cfg[] = { TRL_NOMINAL_RATE_1, 0x64, 0x00 };
static u8 tps_given_cfg[] = { TPS_GIVEN_1, 0x40, 0x80, 0x50 };
static u8 tuner_go[] = { TUNER_GO, 0x01};
mt352_write(fe, clock_config, sizeof(clock_config));
udelay(200);
mt352_write(fe, reset, sizeof(reset));
mt352_write(fe, adc_ctl_1_cfg, sizeof(adc_ctl_1_cfg));
mt352_write(fe, agc_cfg, sizeof(agc_cfg));
mt352_write(fe, input_freq_cfg, sizeof(input_freq_cfg));
mt352_write(fe, rs_err_cfg, sizeof(rs_err_cfg));
mt352_write(fe, capt_range_cfg, sizeof(capt_range_cfg));
mt352_write(fe, trl_nom_cfg, sizeof(trl_nom_cfg));
mt352_write(fe, tps_given_cfg, sizeof(tps_given_cfg));
mt352_write(fe, tuner_go, sizeof(tuner_go));
return 0;
}
static struct mt352_config terratec_xs_mt352_cfg = {
.demod_address = (0x1e >> 1),
.no_tuner = 1,
.if2 = 45600,
.demod_init = mt352_terratec_xs_init,
};
/* ------------------------------------------------------------------ */
static int attach_xc3028(u8 addr, struct em28xx *dev)
......@@ -440,7 +477,6 @@ static int dvb_init(struct em28xx *dev)
goto out_free;
}
break;
case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900:
case EM2880_BOARD_KWORLD_DVB_310U:
case EM2880_BOARD_EMPIRE_DUAL_TV:
dvb->frontend = dvb_attach(zl10353_attach,
......@@ -451,20 +487,28 @@ static int dvb_init(struct em28xx *dev)
goto out_free;
}
break;
case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900:
dvb->frontend = dvb_attach(zl10353_attach,
&em28xx_zl10353_xc3028_no_i2c_gate,
&dev->i2c_adap);
if (attach_xc3028(0x61, dev) < 0) {
result = -EINVAL;
goto out_free;
}
break;
case EM2880_BOARD_TERRATEC_HYBRID_XS:
case EM2881_BOARD_PINNACLE_HYBRID_PRO:
dvb->frontend = dvb_attach(zl10353_attach,
&em28xx_terratec_xs_zl10353_xc3028,
&em28xx_zl10353_xc3028_no_i2c_gate,
&dev->i2c_adap);
if (dvb->frontend == NULL) {
/* This board could have either a zl10353 or a mt352.
If the chip id isn't for zl10353, try mt352 */
/* FIXME: make support for mt352 work */
printk(KERN_ERR "version of this board with mt352 not "
"currently supported\n");
result = -EINVAL;
goto out_free;
dvb->frontend = dvb_attach(mt352_attach,
&terratec_xs_mt352_cfg,
&dev->i2c_adap);
}
if (attach_xc3028(0x61, dev) < 0) {
result = -EINVAL;
goto out_free;
......
......@@ -657,8 +657,8 @@ static void get_scale(struct em28xx *dev,
unsigned int width, unsigned int height,
unsigned int *hscale, unsigned int *vscale)
{
unsigned int maxw = norm_maxw(dev);
unsigned int maxh = norm_maxh(dev);
unsigned int maxw = norm_maxw(dev);
unsigned int maxh = norm_maxh(dev);
*hscale = (((unsigned long)maxw) << 12) / width - 4096L;
if (*hscale >= 0x4000)
......@@ -726,11 +726,7 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
return -EINVAL;
}
if (dev->board.is_27xx) {
/* FIXME: This is the only supported fmt */
width = 640;
height = 480;
} else if (dev->board.is_em2800) {
if (dev->board.is_em2800) {
/* the em2800 can only scale down to 50% */
height = height > (3 * maxh / 4) ? maxh : maxh / 2;
width = width > (3 * maxw / 4) ? maxw : maxw / 2;
......@@ -767,12 +763,6 @@ static int em28xx_set_video_format(struct em28xx *dev, unsigned int fourcc,
{
struct em28xx_fmt *fmt;
/* FIXME: This is the only supported fmt */
if (dev->board.is_27xx) {
width = 640;
height = 480;
}
fmt = format_by_fourcc(fourcc);
if (!fmt)
return -EINVAL;
......
......@@ -358,10 +358,15 @@ struct em28xx_input {
#define INPUT(nr) (&em28xx_boards[dev->model].input[nr])
enum em28xx_decoder {
EM28XX_NODECODER,
EM28XX_NODECODER = 0,
EM28XX_TVP5150,
EM28XX_SAA711X,
};
enum em28xx_sensor {
EM28XX_NOSENSOR = 0,
EM28XX_MT9V011,
EM28XX_MT9M001,
};
enum em28xx_adecoder {
......@@ -390,7 +395,7 @@ struct em28xx_board {
unsigned int max_range_640_480:1;
unsigned int has_dvb:1;
unsigned int has_snapshot_button:1;
unsigned int is_27xx:1;
unsigned int is_webcam:1;
unsigned int valid:1;
unsigned char xclk, i2c_speed;
......@@ -474,6 +479,14 @@ struct em28xx {
struct v4l2_device v4l2_dev;
struct em28xx_board board;
/* Webcam specific fields */
enum em28xx_sensor em28xx_sensor;
int sensor_xres, sensor_yres;
int sensor_xtal;
/* Vinmode/Vinctl used at the driver */
int vinmode, vinctl;
unsigned int stream_on:1; /* Locks streams */
unsigned int has_audio_class:1;
unsigned int has_alsa_audio:1;
......@@ -754,17 +767,23 @@ static inline int em28xx_gamma_set(struct em28xx *dev, s32 val)
/*FIXME: maxw should be dependent of alt mode */
static inline unsigned int norm_maxw(struct em28xx *dev)
{
if (dev->board.is_webcam)
return dev->sensor_xres;
if (dev->board.max_range_640_480)
return 640;
else
return 720;
return 720;
}
static inline unsigned int norm_maxh(struct em28xx *dev)
{
if (dev->board.is_webcam)
return dev->sensor_yres;
if (dev->board.max_range_640_480)
return 480;
else
return (dev->norm & V4L2_STD_625_50) ? 576 : 480;
return (dev->norm & V4L2_STD_625_50) ? 576 : 480;
}
#endif
......@@ -102,6 +102,22 @@ config USB_GSPCA_PAC7311
To compile this driver as a module, choose M here: the
module will be called gspca_pac7311.
config USB_GSPCA_SN9C20X
tristate "SN9C20X USB Camera Driver"
depends on VIDEO_V4L2 && USB_GSPCA
help
Say Y here if you want support for cameras based on the
sn9c20x chips (SN9C201 and SN9C202).
To compile this driver as a module, choose M here: the
module will be called gspca_sn9c20x.
config USB_GSPCA_SN9C20X_EVDEV
bool "Enable evdev support"
depends on USB_GSPCA_SN9C20X
---help---
Say Y here in order to enable evdev support for sn9c20x webcam button.
config USB_GSPCA_SONIXB
tristate "SONIX Bayer USB Camera Driver"
depends on VIDEO_V4L2 && USB_GSPCA
......
......@@ -8,6 +8,7 @@ obj-$(CONFIG_USB_GSPCA_OV519) += gspca_ov519.o
obj-$(CONFIG_USB_GSPCA_OV534) += gspca_ov534.o
obj-$(CONFIG_USB_GSPCA_PAC207) += gspca_pac207.o
obj-$(CONFIG_USB_GSPCA_PAC7311) += gspca_pac7311.o
obj-$(CONFIG_USB_GSPCA_SN9C20X) += gspca_sn9c20x.o
obj-$(CONFIG_USB_GSPCA_SONIXB) += gspca_sonixb.o
obj-$(CONFIG_USB_GSPCA_SONIXJ) += gspca_sonixj.o
obj-$(CONFIG_USB_GSPCA_SPCA500) += gspca_spca500.o
......@@ -35,6 +36,7 @@ gspca_ov519-objs := ov519.o
gspca_ov534-objs := ov534.o
gspca_pac207-objs := pac207.o
gspca_pac7311-objs := pac7311.o
gspca_sn9c20x-objs := sn9c20x.o
gspca_sonixb-objs := sonixb.o
gspca_sonixj-objs := sonixj.o
gspca_spca500-objs := spca500.o
......
......@@ -846,6 +846,8 @@ static int sd_start(struct gspca_dev *gspca_dev)
/* create the JPEG header */
sd->jpeg_hdr = kmalloc(JPEG_HDR_SZ, GFP_KERNEL);
if (!sd->jpeg_hdr)
return -ENOMEM;
jpeg_define(sd->jpeg_hdr, gspca_dev->height, gspca_dev->width,
0x22); /* JPEG 411 */
jpeg_set_qual(sd->jpeg_hdr, sd->quality);
......
......@@ -727,6 +727,74 @@ static int gspca_get_mode(struct gspca_dev *gspca_dev,
return -EINVAL;
}
#ifdef CONFIG_VIDEO_ADV_DEBUG
static int vidioc_g_register(struct file *file, void *priv,
struct v4l2_dbg_register *reg)
{
int ret;
struct gspca_dev *gspca_dev = priv;
if (!gspca_dev->sd_desc->get_chip_ident)
return -EINVAL;
if (!gspca_dev->sd_desc->get_register)
return -EINVAL;
if (mutex_lock_interruptible(&gspca_dev->usb_lock))
return -ERESTARTSYS;
if (gspca_dev->present)
ret = gspca_dev->sd_desc->get_register(gspca_dev, reg);
else
ret = -ENODEV;
mutex_unlock(&gspca_dev->usb_lock);
return ret;
}
static int vidioc_s_register(struct file *file, void *priv,
struct v4l2_dbg_register *reg)
{
int ret;
struct gspca_dev *gspca_dev = priv;
if (!gspca_dev->sd_desc->get_chip_ident)
return -EINVAL;
if (!gspca_dev->sd_desc->set_register)
return -EINVAL;
if (mutex_lock_interruptible(&gspca_dev->usb_lock))
return -ERESTARTSYS;
if (gspca_dev->present)
ret = gspca_dev->sd_desc->set_register(gspca_dev, reg);
else
ret = -ENODEV;
mutex_unlock(&gspca_dev->usb_lock);
return ret;
}
#endif
static int vidioc_g_chip_ident(struct file *file, void *priv,
struct v4l2_dbg_chip_ident *chip)
{
int ret;
struct gspca_dev *gspca_dev = priv;
if (!gspca_dev->sd_desc->get_chip_ident)
return -EINVAL;
if (mutex_lock_interruptible(&gspca_dev->usb_lock))
return -ERESTARTSYS;
if (gspca_dev->present)
ret = gspca_dev->sd_desc->get_chip_ident(gspca_dev, chip);
else
ret = -ENODEV;
mutex_unlock(&gspca_dev->usb_lock);
return ret;
}
static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv,
struct v4l2_fmtdesc *fmtdesc)
{
......@@ -1883,6 +1951,11 @@ static const struct v4l2_ioctl_ops dev_ioctl_ops = {
.vidioc_s_parm = vidioc_s_parm,
.vidioc_s_std = vidioc_s_std,
.vidioc_enum_framesizes = vidioc_enum_framesizes,
#ifdef CONFIG_VIDEO_ADV_DEBUG
.vidioc_g_register = vidioc_g_register,
.vidioc_s_register = vidioc_s_register,
#endif
.vidioc_g_chip_ident = vidioc_g_chip_ident,
#ifdef CONFIG_VIDEO_V4L1_COMPAT
.vidiocgmbuf = vidiocgmbuf,
#endif
......
......@@ -69,6 +69,10 @@ typedef void (*cam_v_op) (struct gspca_dev *);
typedef int (*cam_cf_op) (struct gspca_dev *, const struct usb_device_id *);
typedef int (*cam_jpg_op) (struct gspca_dev *,
struct v4l2_jpegcompression *);
typedef int (*cam_reg_op) (struct gspca_dev *,
struct v4l2_dbg_register *);
typedef int (*cam_ident_op) (struct gspca_dev *,
struct v4l2_dbg_chip_ident *);
typedef int (*cam_streamparm_op) (struct gspca_dev *,
struct v4l2_streamparm *);
typedef int (*cam_qmnu_op) (struct gspca_dev *,
......@@ -105,6 +109,11 @@ struct sd_desc {
cam_qmnu_op querymenu;
cam_streamparm_op get_streamparm;
cam_streamparm_op set_streamparm;
#ifdef CONFIG_VIDEO_ADV_DEBUG
cam_reg_op set_register;
cam_reg_op get_register;
#endif
cam_ident_op get_chip_ident;
};
/* packet types when moving from iso buf to frame buf */
......
......@@ -474,9 +474,6 @@ static int s5k4aa_set_vflip(struct gspca_dev *gspca_dev, __s32 val)
PDEBUG(D_V4L2, "Set vertical flip to %d", val);
err = m5602_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1);
if (err < 0)
return err;
err = m5602_write_sensor(sd, S5K4AA_READ_MODE, &data, 1);
if (err < 0)
return err;
......@@ -522,9 +519,6 @@ static int s5k4aa_set_hflip(struct gspca_dev *gspca_dev, __s32 val)
PDEBUG(D_V4L2, "Set horizontal flip to %d", val);
err = m5602_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1);
if (err < 0)
return err;
err = m5602_write_sensor(sd, S5K4AA_READ_MODE, &data, 1);
if (err < 0)
return err;
......
......@@ -201,6 +201,8 @@ static int sd_start(struct gspca_dev *gspca_dev)
/* create the JPEG header */
sd->jpeg_hdr = kmalloc(JPEG_HDR_SZ, GFP_KERNEL);
if (!sd->jpeg_hdr)
return -ENOMEM;
jpeg_define(sd->jpeg_hdr, gspca_dev->height, gspca_dev->width,
0x21); /* JPEG 422 */
jpeg_set_qual(sd->jpeg_hdr, sd->quality);
......
此差异已折叠。
......@@ -1634,6 +1634,8 @@ static void setfreq(struct gspca_dev *gspca_dev)
{
struct sd *sd = (struct sd *) gspca_dev;
if (gspca_dev->ctrl_dis & (1 << FREQ_IDX))
return;
if (sd->sensor == SENSOR_OV7660) {
switch (sd->freq) {
case 0: /* Banding filter disabled */
......@@ -1735,6 +1737,8 @@ static int sd_start(struct gspca_dev *gspca_dev)
/* create the JPEG header */
sd->jpeg_hdr = kmalloc(JPEG_HDR_SZ, GFP_KERNEL);
if (!sd->jpeg_hdr)
return -ENOMEM;
jpeg_define(sd->jpeg_hdr, gspca_dev->height, gspca_dev->width,
0x21); /* JPEG 422 */
jpeg_set_qual(sd->jpeg_hdr, sd->quality);
......
......@@ -670,6 +670,8 @@ static int sd_start(struct gspca_dev *gspca_dev)
/* create the JPEG header */
sd->jpeg_hdr = kmalloc(JPEG_HDR_SZ, GFP_KERNEL);
if (!sd->jpeg_hdr)
return -ENOMEM;
jpeg_define(sd->jpeg_hdr, gspca_dev->height, gspca_dev->width,
0x22); /* JPEG 411 */
jpeg_set_qual(sd->jpeg_hdr, sd->quality);
......
......@@ -333,6 +333,8 @@ static int sd_start(struct gspca_dev *gspca_dev)
/* create the JPEG header */
sd->jpeg_hdr = kmalloc(JPEG_HDR_SZ, GFP_KERNEL);
if (!sd->jpeg_hdr)
return -ENOMEM;
jpeg_define(sd->jpeg_hdr, gspca_dev->height, gspca_dev->width,
0x22); /* JPEG 411 */
jpeg_set_qual(sd->jpeg_hdr, sd->quality);
......
......@@ -64,7 +64,7 @@ static struct v4l2_pix_format hdcs1x00_mode[] = {
{
HDCS_1X00_DEF_WIDTH,
HDCS_1X00_DEF_HEIGHT,
V4L2_PIX_FMT_SBGGR8,
V4L2_PIX_FMT_SGRBG8,
V4L2_FIELD_NONE,
.sizeimage =
HDCS_1X00_DEF_WIDTH * HDCS_1X00_DEF_HEIGHT,
......@@ -80,7 +80,7 @@ static struct v4l2_pix_format hdcs1020_mode[] = {
{
HDCS_1020_DEF_WIDTH,
HDCS_1020_DEF_HEIGHT,
V4L2_PIX_FMT_SBGGR8,
V4L2_PIX_FMT_SGRBG8,
V4L2_FIELD_NONE,
.sizeimage =
HDCS_1020_DEF_WIDTH * HDCS_1020_DEF_HEIGHT,
......@@ -131,9 +131,11 @@ static int hdcs_reg_write_seq(struct sd *sd, u8 reg, u8 *vals, u8 len)
(reg + len > 0xff)))
return -EINVAL;
for (i = 0; i < len; i++, reg++) {
regs[2*i] = reg;
regs[2*i+1] = vals[i];
for (i = 0; i < len; i++) {
regs[2 * i] = reg;
regs[2 * i + 1] = vals[i];
/* All addresses are shifted left one bit as bit 0 toggles r/w */
reg += 2;
}
return stv06xx_write_sensor_bytes(sd, regs, len);
......@@ -174,7 +176,9 @@ static int hdcs_set_state(struct sd *sd, enum hdcs_power_state state)
}
ret = stv06xx_write_sensor(sd, HDCS_REG_CONTROL(sd), val);
if (ret < 0)
/* Update the state if the write succeeded */
if (!ret)
hdcs->state = state;
return ret;
......
......@@ -973,6 +973,8 @@ static int sd_start(struct gspca_dev *gspca_dev)
/* create the JPEG header */
sd->jpeg_hdr = kmalloc(JPEG_HDR_SZ, GFP_KERNEL);
if (!sd->jpeg_hdr)
return -ENOMEM;
jpeg_define(sd->jpeg_hdr, gspca_dev->height, gspca_dev->width,
0x22); /* JPEG 411 */
jpeg_set_qual(sd->jpeg_hdr, sd->quality);
......
......@@ -7243,6 +7243,8 @@ static int sd_start(struct gspca_dev *gspca_dev)
/* create the JPEG header */
sd->jpeg_hdr = kmalloc(JPEG_HDR_SZ, GFP_KERNEL);
if (!sd->jpeg_hdr)
return -ENOMEM;
jpeg_define(sd->jpeg_hdr, gspca_dev->height, gspca_dev->width,
0x21); /* JPEG 422 */
jpeg_set_qual(sd->jpeg_hdr, sd->quality);
......
......@@ -8,6 +8,7 @@
#include <linux/i2c.h>
#include <linux/videodev2.h>
#include <linux/delay.h>
#include <asm/div64.h>
#include <media/v4l2-device.h>
#include "mt9v011.h"
#include <media/v4l2-i2c-drv.h>
......@@ -57,6 +58,7 @@ static struct v4l2_queryctrl mt9v011_qctrl[] = {
struct mt9v011 {
struct v4l2_subdev sd;
unsigned width, height;
unsigned xtal;
u16 global_gain, red_bal, blue_bal;
};
......@@ -131,7 +133,7 @@ static const struct i2c_reg_value mt9v011_init_default[] = {
{ R1E_MT9V011_DIGITAL_ZOOM, 0x0000 },
{ R20_MT9V011_READ_MODE, 0x1000 },
{ R07_MT9V011_OUT_CTRL, 0x000a }, /* chip enable */
{ R07_MT9V011_OUT_CTRL, 0x0002 }, /* chip enable */
};
static void set_balance(struct v4l2_subdev *sd)
......@@ -154,6 +156,31 @@ static void set_balance(struct v4l2_subdev *sd)
mt9v011_write(sd, R2D_MT9V011_RED_GAIN, red_gain);
}
static void calc_fps(struct v4l2_subdev *sd)
{
struct mt9v011 *core = to_mt9v011(sd);
unsigned height, width, hblank, vblank, speed;
unsigned row_time, t_time;
u64 frames_per_ms;
unsigned tmp;
height = mt9v011_read(sd, R03_MT9V011_HEIGHT);
width = mt9v011_read(sd, R04_MT9V011_WIDTH);
hblank = mt9v011_read(sd, R05_MT9V011_HBLANK);
vblank = mt9v011_read(sd, R06_MT9V011_VBLANK);
speed = mt9v011_read(sd, R0A_MT9V011_CLK_SPEED);
row_time = (width + 113 + hblank) * (speed + 2);
t_time = row_time * (height + vblank + 1);
frames_per_ms = core->xtal * 1000l;
do_div(frames_per_ms, t_time);
tmp = frames_per_ms;
v4l2_dbg(1, debug, sd, "Programmed to %u.%03u fps (%d pixel clcks)\n",
tmp / 1000, tmp % 1000, t_time);
}
static void set_res(struct v4l2_subdev *sd)
{
struct mt9v011 *core = to_mt9v011(sd);
......@@ -175,10 +202,12 @@ static void set_res(struct v4l2_subdev *sd)
mt9v011_write(sd, R04_MT9V011_WIDTH, core->width);
mt9v011_write(sd, R05_MT9V011_HBLANK, 771 - core->width);
vstart = 8 + (640 - core->height) / 2;
vstart = 8 + (480 - core->height) / 2;
mt9v011_write(sd, R01_MT9V011_ROWSTART, vstart);
mt9v011_write(sd, R03_MT9V011_HEIGHT, core->height);
mt9v011_write(sd, R06_MT9V011_VBLANK, 508 - core->height);
calc_fps(sd);
};
static int mt9v011_reset(struct v4l2_subdev *sd, u32 val)
......@@ -215,6 +244,23 @@ static int mt9v011_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
return -EINVAL;
}
static int mt9v011_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qc)
{
int i;
v4l2_dbg(1, debug, sd, "queryctrl called\n");
for (i = 0; i < ARRAY_SIZE(mt9v011_qctrl); i++)
if (qc->id && qc->id == mt9v011_qctrl[i].id) {
memcpy(qc, &(mt9v011_qctrl[i]),
sizeof(*qc));
return 0;
}
return -EINVAL;
}
static int mt9v011_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
{
struct mt9v011 *core = to_mt9v011(sd);
......@@ -294,6 +340,22 @@ static int mt9v011_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt)
return 0;
}
static int mt9v011_s_config(struct v4l2_subdev *sd, int dumb, void *data)
{
struct mt9v011 *core = to_mt9v011(sd);
unsigned *xtal = data;
v4l2_dbg(1, debug, sd, "s_config called\n");
if (xtal) {
core->xtal = *xtal;
v4l2_dbg(1, debug, sd, "xtal set to %d.%03d MHz\n",
*xtal / 1000000, (*xtal / 1000) % 1000);
}
return 0;
}
#ifdef CONFIG_VIDEO_ADV_DEBUG
static int mt9v011_g_register(struct v4l2_subdev *sd,
......@@ -338,9 +400,11 @@ static int mt9v011_g_chip_ident(struct v4l2_subdev *sd,
}
static const struct v4l2_subdev_core_ops mt9v011_core_ops = {
.queryctrl = mt9v011_queryctrl,
.g_ctrl = mt9v011_g_ctrl,
.s_ctrl = mt9v011_s_ctrl,
.reset = mt9v011_reset,
.s_config = mt9v011_s_config,
.g_chip_ident = mt9v011_g_chip_ident,
#ifdef CONFIG_VIDEO_ADV_DEBUG
.g_register = mt9v011_g_register,
......@@ -395,6 +459,7 @@ static int mt9v011_probe(struct i2c_client *c,
core->global_gain = 0x0024;
core->width = 640;
core->height = 480;
core->xtal = 27000000; /* Hz */
v4l_info(c, "chip found @ 0x%02x (%s)\n",
c->addr << 1, c->adapter->name);
......
......@@ -338,6 +338,7 @@ struct v4l2_pix_format {
/* Vendor-specific formats */
#define V4L2_PIX_FMT_WNVA v4l2_fourcc('W', 'N', 'V', 'A') /* Winnov hw compress */
#define V4L2_PIX_FMT_SN9C10X v4l2_fourcc('S', '9', '1', '0') /* SN9C10x compression */
#define V4L2_PIX_FMT_SN9C20X_I420 v4l2_fourcc('S', '9', '2', '0') /* SN9C20x YUV 4:2:0 */
#define V4L2_PIX_FMT_PWC1 v4l2_fourcc('P', 'W', 'C', '1') /* pwc older webcam */
#define V4L2_PIX_FMT_PWC2 v4l2_fourcc('P', 'W', 'C', '2') /* pwc newer webcam */
#define V4L2_PIX_FMT_ET61X251 v4l2_fourcc('E', '6', '2', '5') /* ET61X251 compression */
......
......@@ -60,6 +60,10 @@ enum {
V4L2_IDENT_OV7670 = 250,
V4L2_IDENT_OV7720 = 251,
V4L2_IDENT_OV7725 = 252,
V4L2_IDENT_OV7660 = 253,
V4L2_IDENT_OV9650 = 254,
V4L2_IDENT_OV9655 = 255,
V4L2_IDENT_SOI968 = 256,
/* module saa7146: reserved range 300-309 */
V4L2_IDENT_SAA7146 = 300,
......@@ -161,6 +165,9 @@ enum {
/* module tw9910: just ident 9910 */
V4L2_IDENT_TW9910 = 9910,
/* module sn9c20x: just ident 10000 */
V4L2_IDENT_SN9C20X = 10000,
/* module msp3400: reserved range 34000-34999 and 44000-44999 */
V4L2_IDENT_MSPX4XX = 34000, /* generic MSPX4XX identifier, only
use internally (tveeprom.c). */
......@@ -237,6 +244,11 @@ enum {
V4L2_IDENT_MT9V022IX7ATC = 45010, /* No way to detect "normal" I77ATx */
V4L2_IDENT_MT9V022IX7ATM = 45015, /* and "lead free" IA7ATx chips */
V4L2_IDENT_MT9T031 = 45020,
V4L2_IDENT_MT9V111 = 45031,
V4L2_IDENT_MT9V112 = 45032,
/* HV7131R CMOS sensor: just ident 46000 */
V4L2_IDENT_HV7131R = 46000,
/* module cs53132a: just ident 53132 */
V4L2_IDENT_CS53l32A = 53132,
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册