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
Show file tree
Hide file tree
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
Expand Up @@ -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
Expand Up @@ -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,
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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
Expand All @@ -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;
Expand All @@ -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");
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand All @@ -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);
Expand Down
11 changes: 11 additions & 0 deletions drivers/media/video/gspca/stv06xx/stv06xx.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
10 changes: 5 additions & 5 deletions drivers/media/video/gspca/stv06xx/stv06xx_hdcs.c
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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
Expand All @@ -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;

Expand Down Expand Up @@ -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 */
Expand Down Expand Up @@ -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);
Expand Down
3 changes: 1 addition & 2 deletions drivers/media/video/gspca/stv06xx/stv06xx_sensor.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
Expand Down
Loading

0 comments on commit 8668d50

Please sign in to comment.