Commit 2e0903b0 authored by Jean-Francois Moine's avatar Jean-Francois Moine Committed by Mauro Carvalho Chehab
Browse files

V4L/DVB (9552): gspca: Simplify the ISOC packet scanning in tv8532.



This patch
- makes unuseful the temporary buffers
- and also fixes the bad colors problem.

Signed-off-by: default avatarJean-Francois Moine <moinejf@free.fr>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@redhat.com>
parent 42ec3135
Loading
Loading
Loading
Loading
+25 −97
Original line number Diff line number Diff line
@@ -30,10 +30,6 @@ MODULE_LICENSE("GPL");
struct sd {
	struct gspca_dev gspca_dev;	/* !! must be the first item */

	__u32 buflen;			/* current length of tmpbuf */
	__u8 tmpbuf[352 * 288 + 10 * 288];	/* no protection... */
	__u8 tmpbuf2[352 * 288];		/* no protection... */

	__u16 brightness;
	__u16 contrast;

@@ -391,6 +387,8 @@ static void setbrightness(struct gspca_dev *gspca_dev)
/* -- start the camera -- */
static int sd_start(struct gspca_dev *gspca_dev)
{
	struct sd *sd = (struct sd *) gspca_dev;

	reg_w_1(gspca_dev, TV8532_AD_SLOPE, 0x32);
	reg_w_1(gspca_dev, TV8532_AD_BITCTRL, 0x00);
	tv_8532ReadRegisters(gspca_dev);
@@ -444,6 +442,7 @@ static int sd_start(struct gspca_dev *gspca_dev)
	reg_w_1(gspca_dev, TV8532_UDP_UPDATE, 0x00);	/* 0x31 */

	gspca_dev->empty_packet = 0;		/* check the empty packets */
	sd->packet = 0;				/* ignore the first packets */

	return 0;
}
@@ -453,107 +452,36 @@ static void sd_stopN(struct gspca_dev *gspca_dev)
	reg_w_1(gspca_dev, TV8532_GPIO_OE, 0x0b);
}

static void tv8532_preprocess(struct gspca_dev *gspca_dev)
{
	struct sd *sd = (struct sd *) gspca_dev;
/* we should received a whole frame with header and EOL marker
 * in sd->tmpbuf and return a GBRG pattern in sd->tmpbuf2
 * sequence 2bytes header the Alternate pixels bayer GB 4 bytes
 * Alternate pixels bayer RG 4 bytes EOL */
	int width = gspca_dev->width;
	int height = gspca_dev->height;
	unsigned char *dst = sd->tmpbuf2;
	unsigned char *data = sd->tmpbuf;
	int i;

	/* precompute where is the good bayer line */
	if (((data[3] + data[width + 7]) >> 1)
	    + (data[4] >> 2)
	    + (data[width + 6] >> 1) >= ((data[2] + data[width + 6]) >> 1)
	    + (data[3] >> 2)
	    + (data[width + 5] >> 1))
		data += 3;
	else
		data += 2;
	for (i = 0; i < height / 2; i++) {
		memcpy(dst, data, width);
		data += width + 3;
		dst += width;
		memcpy(dst, data, width);
		data += width + 7;
		dst += width;
	}
}

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;
	int packet_type0, packet_type1;

	if (data[0] != 0x80) {
		sd->packet++;
		if (sd->buflen + len > sizeof sd->tmpbuf) {
			if (gspca_dev->last_packet_type != DISCARD_PACKET) {
				PDEBUG(D_PACK, "buffer overflow");
				gspca_dev->last_packet_type = DISCARD_PACKET;
			}
			return;
		}
		memcpy(&sd->tmpbuf[sd->buflen], data, len);
		sd->buflen += len;
		return;
	}

	/* here we detect 0x80 */
	/* counter is limited so we need few header for a frame :) */

	/* header 0x80 0x80 0x80 0x80 0x80 */
	/* packet  00   63  127  145  00   */
	/* empty    1    0   0    1    1   */

	/* update sequence */
	if (sd->packet == 63 || sd->packet == 127)
		gspca_dev->empty_packet = 0;

	/* is there a frame start ? */
	/* (each packet is 2 lines plus 10 bytes) */
	if (sd->packet >= (gspca_dev->height >> 1) - 1) {
		PDEBUG(D_PACK, "empty %d packet %d",
			gspca_dev->empty_packet, sd->packet);
		if (gspca_dev->empty_packet) {	/* start of frame */
			if (gspca_dev->last_packet_type == FIRST_PACKET) {
				tv8532_preprocess(gspca_dev);
				frame = gspca_frame_add(gspca_dev,
							LAST_PACKET,
							frame, sd->tmpbuf2,
							gspca_dev->height *
							    gspca_dev->width);
			}
			gspca_frame_add(gspca_dev, FIRST_PACKET,
					frame, data, 0);
			memcpy(sd->tmpbuf, data, len);
			sd->buflen = len;
			sd->packet = 0;
			return;
		}
		if (gspca_dev->last_packet_type != DISCARD_PACKET) {
			PDEBUG(D_PACK,
			       "Warning wrong TV8532 frame detection %d",
			       sd->packet);
			gspca_dev->last_packet_type = DISCARD_PACKET;
		}
		return;
	}

	packet_type0 = packet_type1 = INTER_PACKET;
	if (gspca_dev->empty_packet) {
		/* Drop packet frame corrupt */
		PDEBUG(D_PACK, "DROP empty %d packet %d",
			gspca_dev->empty_packet, sd->packet);
		sd->packet = 0;
		gspca_dev->last_packet_type = DISCARD_PACKET;
	}
		gspca_dev->empty_packet = 0;
		sd->packet = gspca_dev->height / 2;
		packet_type0 = FIRST_PACKET;
	} else if (sd->packet == 0)
		return;			/* 2 more lines in 352x288 ! */
	sd->packet--;
	if (sd->packet == 0)
		packet_type1 = LAST_PACKET;

	/* each packet contains:
	 * - header 2 bytes
	 * - RG line
	 * - 4 bytes
	 * - GB line
	 * - 4 bytes
	 */
	gspca_frame_add(gspca_dev, packet_type0,
			frame, data + 2, gspca_dev->width);
	gspca_frame_add(gspca_dev, packet_type1,
			frame, data + gspca_dev->width + 6, gspca_dev->width);
}

static void setcontrast(struct gspca_dev *gspca_dev)