Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 8668d504 authored by Hans de Goede's avatar Hans de Goede Committed by Mauro Carvalho Chehab
Browse files

V4L/DVB (12082): gspca_stv06xx: Add support for st6422 bridge and sensor



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: default avatarHans de Goede <hdegoede@redhat.com>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@redhat.com>
parent ae49c404
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -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
+46 −7
Original line number Diff line number Diff line
@@ -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 −0
Original line number Diff line number Diff line
@@ -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);
+5 −5
Original line number Diff line number Diff line
@@ -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);
+1 −2
Original line number Diff line number Diff line
@@ -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 */
Loading