Skip to content

Commit

Permalink
V4L/DVB (12082): gspca_stv06xx: Add support for st6422 bridge and sensor
Browse files Browse the repository at this point in the history
Add support for st6422 bridge and sensor to the stv06xx gspca sub driver,
tested with:
Logitech QuickCam Messenger     046d:08f0       ST6422  integrated
Logitech QuickCam Mess. Plus    046d:08f6       ST6422  integrated

Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
  • Loading branch information
Hans de Goede authored and Mauro Carvalho Chehab committed Jun 23, 2009
1 parent ae49c40 commit 8668d50
Showing 7 changed files with 577 additions and 15 deletions.
3 changes: 2 additions & 1 deletion drivers/media/video/gspca/stv06xx/Makefile
Original file line number Diff line number Diff line change
@@ -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

53 changes: 46 additions & 7 deletions drivers/media/video/gspca/stv06xx/stv06xx.c
Original file line number Diff line number Diff line change
@@ -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;
@@ -318,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
@@ -343,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;
@@ -365,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");
@@ -395,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;
@@ -428,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;
@@ -457,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);
11 changes: 11 additions & 0 deletions drivers/media/video/gspca/stv06xx/stv06xx.h
Original file line number Diff line number Diff line change
@@ -93,6 +93,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);
10 changes: 5 additions & 5 deletions drivers/media/video/gspca/stv06xx/stv06xx_hdcs.c
Original file line number Diff line number Diff line change
@@ -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);
3 changes: 1 addition & 2 deletions drivers/media/video/gspca/stv06xx/stv06xx_sensor.h
Original file line number Diff line number Diff line change
@@ -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 */
453 changes: 453 additions & 0 deletions drivers/media/video/gspca/stv06xx/stv06xx_st6422.c

Large diffs are not rendered by default.

59 changes: 59 additions & 0 deletions drivers/media/video/gspca/stv06xx/stv06xx_st6422.h
Original file line number Diff line number Diff line change
@@ -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

0 comments on commit 8668d50

Please sign in to comment.