⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 qc-vv6450.c

📁 Webcam Linux driver for Quickcam
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * qce-ga, linux V4L driver for the Quickcam Express and Dexxa Quickcam * * vv6450.c - Sensor Implementation for Quickcam Messenger??? *            The sensor is NOT called 6450, I just copied the vv6410.c *            to have something to work with. * * 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 **/#ifdef NOKERNEL#include "quickcam.h"#else#include <linux/quickcam.h>#endif/* LSB bit of I2C address signifies write (0) or read (1) *//* I2C Registers *//* Status registers */#define VV6450_DEVICEH		0xE00A	/* Chip identification number including revision indicator */#define VV6450_STATUS0		0x02	/* User can determine whether timed I2C data has been consumed by interrogating flag states */#define VV6450_LINECOUNTH	0x03	/* Current line counter value */#define VV6450_LINECOUNTL	0x04#define VV6450_XENDH		0x05	/* End x coordinate of image size */#define VV6450_XENDL		0x06#define VV6450_YENDH		0x07	/* End y coordinate of image size */#define VV6450_YENDL		0x08#define VV6450_DARKAVGH		0x09	/* This is the average pixel value returned from the dark line offset cancellation algorithm */#define VV6450_DARKAVGL		0x0A#define VV6450_BLACKAVGH	0x0B	/* This is the average pixel value returned from the black line offset cancellation algorithm  */#define VV6450_BLACKAVGL	0x0C#define VV6450_STATUS1		0x0D	/* Flags to indicate whether the x or y image coordinates have been clipped *//* Setup registers */#define VV6450_SETUP0		0x10	/* Low-power/sleep modes & video timing */#define VV6450_SETUP1		0x11	/* Various parameters */#define VV6450_SYNCVALUE	0x12	/* Contains pixel counter reset value used by external sync */#define VV6450_FGMODES		0x14	/* Frame grabbing modes (FST, LST and QCK) */#define VV6450_PINMAPPING	0x15	/* FST and QCK mapping modes. */#define VV6450_DATAFORMAT	0x16	/* Data resolution */#define VV6450_OPFORMAT		0x17	/* Output coding formats */#define VV6450_MODESELECT	0x18	/* Various mode select bits *//* Exposure registers */#define VV6450_FINEH		0x20	/* Fine exposure. */#define VV6450_FINEL		0x21#define VV6450_COARSEH		0x22	/* Coarse exposure */#define VV6450_COARSEL		0x23#define VV6450_ANALOGGAIN	0x24	/* Analog gain setting */#define VV6450_CLKDIV		0x25	/* Clock division */#define VV6450_DARKOFFSETH	0x2C	/* Dark line offset cancellation value */#define VV6450_DARKOFFSETL	0x2D#define VV6450_DARKOFFSETSETUP	0x2E	/* Dark line offset cancellation enable *//* Colour registers (none on this camera!) *//* Video timing registers */#define VV6450_LINELENGTHH	0x52	/* Line Length (Pixel Clocks) */#define VV6450_LINELENGTHL	0x53#define VV6450_XOFFSETH		0x57	/* X-co-ordinate of top left corner of region of interest (x-offset) */#define VV6450_XOFFSETL		0x58#define VV6450_YOFFSETH		0x59	/* Y-co-ordinate of top left corner of region of interest (y-offset) */#define VV6450_YOFFSETL		0x5A#define VV6450_FIELDLENGTHH	0x61	/* Field length (Lines) */#define VV6450_FIELDLENGTHL	0x62/* Text overlay registers (none on this camera!) *//* I2C autoload registers (none on this camera!) *//* System registers */#define VV6450_BLACKOFFSETH	0x70	/* Black offset cancellation default value */#define VV6450_BLACKOFFSETL	0x71#define VV6450_BLACKOFFSETSETUP	0x72	/* Black offset cancellation setup */#define VV6450_CR0		0x75	/* Analog Control Register 0 */#define VV6450_CR1		0x76	/* Analog Control Register 1 */#define VV6450_AS0		0x77	/* ADC Setup Register */#define VV6450_AT0		0x78	/* Analog Test Register */#define VV6450_AT1		0x79	/* Audio Amplifier Setup Register *///#define I2C_SET_CHECK(reg,val)	if ((r = qc_i2c_set(qc,(reg),(val)))<0) goto fail#define I2C_SET_CHECK(reg,val)	do {} while(0)#define STV_SET_CHECK(reg,val)	if ((r = qc_stv_set(qc,(reg),(val)))<0) goto fail#define STV_SETW_CHECK(reg,val)	if ((r = qc_stv_setw(qc,(reg),(val)))<0) goto fail/** * Set window size */static int vv6450_set_size(struct quickcam *qc, unsigned int width, unsigned int height){	int r = 0;	struct qc_sensor_data *sd = &qc->sensor_data;	if (qcdebug&QC_DEBUGLOGIC)	  PDEBUG("vv6450_set_size(quickcam=%p,width=%i,height=%i)",qc,width,height);	if ( (width <= 162) && (height <= 124) )	{		sd->width = 162;		sd->height = 124;		STV_SET_CHECK(0x1505, 0x0f);		if(r) goto fail;	} else#ifndef MIN#define MIN(a, b) ((a) < (b) ? (a) : (b))#endif	if ( (width <= 176) && (height <= 144) )	{		/* exception for small QCIF even if not good fit */		sd->width = 162;		sd->height = 124;		qc->vwin.width = MIN(sd->width, width);		qc->vwin.height = MIN(sd->height, height);		STV_SET_CHECK(0x1505, 0x0f);		if(r) goto fail;		//return 0;	} else	if ( (width <= 162) && (height <= 248) )	{		sd->width = 162;		sd->height = 248;		STV_SET_CHECK(0x1505, 0x08);		if(r) goto fail;	} else	if ( (width <= 324) && (height <= 124) )	{		sd->width = 324;		sd->height = 124;		STV_SET_CHECK(0x1505, 0x04);		if(r) goto fail;	} else	if ( (width <= 324) && (height <= 248) )	{		sd->width = 324;		sd->height = 248;		STV_SET_CHECK(0x1505, 0x02);		if(r) goto fail;	} else	if ( (width <= 352) && (height <= 288) )	{		/* exception for CIF even if not good fit */		sd->width = 324;		sd->height = 248;		qc->vwin.width = MIN(sd->width, width);		qc->vwin.height = MIN(sd->height, height);		STV_SET_CHECK(0x1505, 0x02);		if(r) goto fail;		//return 0;	} else#ifdef TRY_HIGHRES	if ( (width <= 648) && (height <= 496) )	{		// this doesn't work yet		sd->width = 648;		sd->height = 496;		STV_SET_CHECK(0x1505, 0x01);		if(r) goto fail;	} else#endif	{#if 1		PDEBUG("Unknown resolution %dx%d, set 324x248", width, height);		sd->width = 324;		sd->height = 248;		qc->vwin.width = sd->width;		qc->vwin.height = sd->height;		STV_SET_CHECK(0x1505, 0x02);		if(r) goto fail;#endif		goto fail;	}#if 0	qc->vwin.width = width;	qc->vwin.height = height;	qc->vwin.width = sd->width;	qc->vwin.height = sd->height;#endif	qc->vwin.width = MIN(sd->width, width);	qc->vwin.height = MIN(sd->height, height);	PDEBUG("set sensor=%dx%d vwin=%dx%d", sd->width, sd->height, qc->vwin.width, qc->vwin.height);	return 0;fail:	return -1;}/* start grabbing */static int vv6450_start(struct quickcam *qc){	int r = 0;		if (qcdebug&QC_DEBUGLOGIC) PDEBUG("vv6450_start(quickcam=%p)",qc);	if (PARANOID && !qc)  { PDEBUG("qc==NULL"); return -EINVAL; }	r = qc_i2c_wait(qc);	STV_SET_CHECK(STV_ISO_ENABLE, 0x01);	return 0;fail:	//PDEBUG("Error start");	return r;}/* stop grabbing */static int vv6450_stop(struct quickcam *qc){	static const int low_power_mode = 1;	static const int sleep_mode     = 1;	struct qc_sensor_data *sd = &qc->sensor_data;	unsigned char cmd;	int r = 0;	if (qcdebug&QC_DEBUGLOGIC) PDEBUG("vv6450_stop(quickcam=%p)",qc);	cmd = (sleep_mode << 1) | low_power_mode;	if (sd->subsample) cmd |= BIT(7)|BIT(6);		/* sub-sampled QCIF mode */	r = qc_i2c_wait(qc);		STV_SET_CHECK(STV_ISO_ENABLE, 0x00);	return 0;fail:	//PDEBUG("Error stop");	return r;}struct stv_init {	const u8 *data;	/* If NULL, only single value to write, stored in len */	u16 start;        u16 len;};/*  * initialise parameters for vv6450 sensor. * Just try to send the same commands as Windoze Quickcam soft. */static int vv6450_init(struct quickcam *qc){	struct qc_sensor_data *sd = &qc->sensor_data;	int r = 0;	static const struct stv_init stv_init[] = {/* LOGTAG */ { NULL, STV_ISO_ENABLE, 0x00 },	/* disable capture *//* LOGTAG */ { NULL, 0x1436, 0x00 },/* LOGTAG */ { NULL, 0x1432, 0x03 },				/* 0x00-0x1F contrast ? *//* LOGTAG */ { NULL, 0x143a, 0xF9 },				/* 0x00-0x0F - gain *//* LOGTAG */ { NULL, 0x0509, 0x38 },				/* R *//* LOGTAG */ { NULL, 0x050a, 0x38 },				/* G *//* LOGTAG */ { NULL, 0x050b, 0x38 },				/* B *//* LOGTAG */ { NULL, 0x050c, 0x2A },/* LOGTAG */ { NULL, 0x050d, 0x01 },/* LOGTAG */ { NULL, 0x1431, 0x00 },				/* 0x00-0x07 ??? *//* LOGTAG */ { NULL, 0x1433, 0x34 },	/* 160x120 */		/* 0x00-0x01 night filter *//* LOGTAG */ { NULL, 0x1438, 0x18 },	/* 640x480 */// 18 bayes// 10 compressed?/* LOGTAG */ { NULL, 0x1439, 0x00 },// antiflimmer??  0xa2 ger perfekt bild mot monitor/* LOGTAG */ { NULL, 0x143b, 0x05 },/* LOGTAG */ { NULL, 0x143c, 0x00 },				/* 0x00-0x01 - ??? */// shutter time 0x0000-0x03FF// low value  give good picures on moving objects (but requires much light)// high value gives good picures in darkness (but tends to be overexposed)/* LOGTAG */ { NULL, 0x143e, 0x01 },/* LOGTAG */ { NULL, 0x143d, 0x00 },/* LOGTAG */ { NULL, 0x1442, 0xe2 },// write: 1x1x xxxx// read:  1x1x xxxx//        bit 5 == button pressed and hold if 0// write 0xe2,0xea// 0x144a// 0x00 init// bit 7 == button has been pressed, but not handled// interrupt//if(urb->iso_frame_desc[i].status == 0x80) {//if(urb->iso_frame_desc[i].status == 0x88) {/* LOGTAG */ { NULL, 0x1500, 0xd0 },/* LOGTAG */ { NULL, 0x1500, 0xd0 },/* LOGTAG */ { NULL, 0x1500, 0x50 },	/* 0x00 - 0xFF  0x80 == compr ? *//* LOGTAG */ { NULL, 0x1501, 0xaf },// high val-> ljus area blir morkare.// low val -> ljus area blir ljusare./* LOGTAG */ { NULL, 0x1502, 0xc2 },// high val-> ljus area blir morkare.

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -