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

📄 ov511.c

📁 EVC 写的 wince usb camera 代码
💻 C
📖 第 1 页 / 共 5 页
字号:
			if (rc < 0)				return rc;		}		reg++;	}	return 0;}static intov51x_reset(struct usb_ov511 *ov, unsigned char reset_type){	int rc;	/* Setting bit 0 not allowed on 518/518Plus */	if (ov->bclass == BCL_OV518)		reset_type &= 0xfe;	PDEBUG(4, "Reset: type=0x%02X", reset_type);	rc = reg_w(ov, R51x_SYS_RESET, reset_type);	rc = reg_w(ov, R51x_SYS_RESET, 0);	if (rc < 0)		err("reset: command failed");	return rc;}/********************************************************************** * * Low-level I2C I/O functions * **********************************************************************//* NOTE: Do not call this function directly! * The OV518 I2C I/O procedure is different, hence, this function. * This is normally only called from i2c_w(). Note that this function * always succeeds regardless of whether the sensor is present and working. */static intov518_i2c_write_internal(struct usb_ov511 *ov,			 unsigned char reg,			 unsigned char value){	int rc;	PDEBUG(5, "0x%02X:0x%02X", reg, value);	/* Select camera register */	rc = reg_w(ov, R51x_I2C_SADDR_3, reg);	if (rc < 0)		return rc;	/* Write "value" to I2C data port of OV511 */	rc = reg_w(ov, R51x_I2C_DATA, value);	if (rc < 0)		return rc;	/* Initiate 3-byte write cycle */	rc = reg_w(ov, R518_I2C_CTL, 0x01);	if (rc < 0)		return rc;	return 0;}/* NOTE: Do not call this function directly! */static intov511_i2c_write_internal(struct usb_ov511 *ov,			 unsigned char reg,			 unsigned char value){	int rc, retries;	PDEBUG(5, "0x%02X:0x%02X", reg, value);	/* Three byte write cycle */	for (retries = OV511_I2C_RETRIES; ; ) {		/* Select camera register */		rc = reg_w(ov, R51x_I2C_SADDR_3, reg);		if (rc < 0)			break;		/* Write "value" to I2C data port of OV511 */		rc = reg_w(ov, R51x_I2C_DATA, value);		if (rc < 0)			break;		/* Initiate 3-byte write cycle */		rc = reg_w(ov, R511_I2C_CTL, 0x01);		if (rc < 0)			break;		/* Retry until idle */		do			rc = reg_r(ov, R511_I2C_CTL);		while (rc > 0 && ((rc&1) == 0)); 		if (rc < 0)			break;		/* Ack? */		if ((rc&2) == 0) {			rc = 0;			break;		}#if 0		/* I2C abort */		reg_w(ov, R511_I2C_CTL, 0x10);#endif		if (--retries < 0) {			err("i2c write retries exhausted");			rc = -1;			break;		}	}	return rc;}/* NOTE: Do not call this function directly! * The OV518 I2C I/O procedure is different, hence, this function. * This is normally only called from i2c_r(). Note that this function * always succeeds regardless of whether the sensor is present and working. */static intov518_i2c_read_internal(struct usb_ov511 *ov, unsigned char reg){	int rc, value;	/* Select camera register */	rc = reg_w(ov, R51x_I2C_SADDR_2, reg);	if (rc < 0)		return rc;	/* Initiate 2-byte write cycle */	rc = reg_w(ov, R518_I2C_CTL, 0x03);	if (rc < 0)		return rc;	/* Initiate 2-byte read cycle */	rc = reg_w(ov, R518_I2C_CTL, 0x05);	if (rc < 0)		return rc;	value = reg_r(ov, R51x_I2C_DATA);	PDEBUG(5, "0x%02X:0x%02X", reg, value);	return value;}/* NOTE: Do not call this function directly! * returns: negative is error, pos or zero is data */static intov511_i2c_read_internal(struct usb_ov511 *ov, unsigned char reg){	int rc, value, retries;	/* Two byte write cycle */	for (retries = OV511_I2C_RETRIES; ; ) {		/* Select camera register */		rc = reg_w(ov, R51x_I2C_SADDR_2, reg);		if (rc < 0)			return rc;		/* Initiate 2-byte write cycle */		rc = reg_w(ov, R511_I2C_CTL, 0x03);		if (rc < 0)			return rc;		/* Retry until idle */		do			 rc = reg_r(ov, R511_I2C_CTL);		while (rc > 0 && ((rc&1) == 0));		if (rc < 0)			return rc;		if ((rc&2) == 0) /* Ack? */			break;		/* I2C abort */		reg_w(ov, R511_I2C_CTL, 0x10);		if (--retries < 0) {			err("i2c write retries exhausted");			return -1;		}	}	/* Two byte read cycle */	for (retries = OV511_I2C_RETRIES; ; ) {		/* Initiate 2-byte read cycle */		rc = reg_w(ov, R511_I2C_CTL, 0x05);		if (rc < 0)			return rc;		/* Retry until idle */		do			rc = reg_r(ov, R511_I2C_CTL);		while (rc > 0 && ((rc&1) == 0));		if (rc < 0)			return rc;		if ((rc&2) == 0) /* Ack? */			break;		/* I2C abort */		rc = reg_w(ov, R511_I2C_CTL, 0x10);		if (rc < 0)			return rc;		if (--retries < 0) {			err("i2c read retries exhausted");			return -1;		}	}	value = reg_r(ov, R51x_I2C_DATA);	PDEBUG(5, "0x%02X:0x%02X", reg, value);	/* This is needed to make i2c_w() work */	rc = reg_w(ov, R511_I2C_CTL, 0x05);	if (rc < 0)		return rc;	return value;}/* returns: negative is error, pos or zero is data */static inti2c_r(struct usb_ov511 *ov, unsigned char reg){	int rc;	down(&ov->i2c_lock);	if (ov->bclass == BCL_OV518)		rc = ov518_i2c_read_internal(ov, reg);	else		rc = ov511_i2c_read_internal(ov, reg);	up(&ov->i2c_lock);	return rc;}static inti2c_w(struct usb_ov511 *ov, unsigned char reg, unsigned char value){	int rc;	down(&ov->i2c_lock);	if (ov->bclass == BCL_OV518)		rc = ov518_i2c_write_internal(ov, reg, value);	else		rc = ov511_i2c_write_internal(ov, reg, value);	up(&ov->i2c_lock);	return rc;}/* Do not call this function directly! */static intov51x_i2c_write_mask_internal(struct usb_ov511 *ov,			      unsigned char reg,			      unsigned char value,			      unsigned char mask){	int rc;	unsigned char oldval, newval;	if (mask == 0xff) {		newval = value;	} else {		if (ov->bclass == BCL_OV518)			rc = ov518_i2c_read_internal(ov, reg);		else			rc = ov511_i2c_read_internal(ov, reg);		if (rc < 0)			return rc;		oldval = (unsigned char) rc;		oldval &= (~mask);		/* Clear the masked bits */		value &= mask;			/* Enforce mask on value */		newval = oldval | value;	/* Set the desired bits */	}	if (ov->bclass == BCL_OV518)		return (ov518_i2c_write_internal(ov, reg, newval));	else		return (ov511_i2c_write_internal(ov, reg, newval));}/* Writes bits at positions specified by mask to an I2C reg. Bits that are in * the same position as 1's in "mask" are cleared and set to "value". Bits * that are in the same position as 0's in "mask" are preserved, regardless * of their respective state in "value". */static inti2c_w_mask(struct usb_ov511 *ov,	   unsigned char reg,	   unsigned char value,	   unsigned char mask){	int rc;	down(&ov->i2c_lock);	rc = ov51x_i2c_write_mask_internal(ov, reg, value, mask);	up(&ov->i2c_lock);	return rc;}/* Set the read and write slave IDs. The "slave" argument is the write slave, * and the read slave will be set to (slave + 1). ov->i2c_lock should be held * when calling this. This should not be called from outside the i2c I/O * functions. */static inti2c_set_slave_internal(struct usb_ov511 *ov, unsigned char slave){	int rc;	rc = reg_w(ov, R51x_I2C_W_SID, slave);	if (rc < 0)		return rc;	rc = reg_w(ov, R51x_I2C_R_SID, slave + 1);	if (rc < 0)		return rc;	return 0;}/* Write to a specific I2C slave ID and register, using the specified mask */static inti2c_w_slave(struct usb_ov511 *ov,	    unsigned char slave,	    unsigned char reg,	    unsigned char value,	    unsigned char mask){	int rc = 0;	down(&ov->i2c_lock);	/* Set new slave IDs */	rc = i2c_set_slave_internal(ov, slave);	if (rc < 0)		goto out;	rc = ov51x_i2c_write_mask_internal(ov, reg, value, mask);out:	/* Restore primary IDs */	if (i2c_set_slave_internal(ov, ov->primary_i2c_slave) < 0)		err("Couldn't restore primary I2C slave");	up(&ov->i2c_lock);	return rc;}/* Read from a specific I2C slave ID and register */static inti2c_r_slave(struct usb_ov511 *ov,	    unsigned char slave,	    unsigned char reg){	int rc;	down(&ov->i2c_lock);	/* Set new slave IDs */	rc = i2c_set_slave_internal(ov, slave);	if (rc < 0)		goto out;	if (ov->bclass == BCL_OV518)		rc = ov518_i2c_read_internal(ov, reg);	else		rc = ov511_i2c_read_internal(ov, reg);out:	/* Restore primary IDs */	if (i2c_set_slave_internal(ov, ov->primary_i2c_slave) < 0)		err("Couldn't restore primary I2C slave");	up(&ov->i2c_lock);	return rc;}/* Sets I2C read and write slave IDs. Returns <0 for error */static intov51x_set_slave_ids(struct usb_ov511 *ov, unsigned char sid){	int rc;	down(&ov->i2c_lock);	rc = i2c_set_slave_internal(ov, sid);	if (rc < 0)		goto out;	// FIXME: Is this actually necessary?	rc = ov51x_reset(ov, OV511_RESET_NOREGS);out:	up(&ov->i2c_lock);	return rc;}static intwrite_regvals(struct usb_ov511 *ov, struct ov511_regvals * pRegvals){	int rc;	while (pRegvals->bus != OV511_DONE_BUS) {		if (pRegvals->bus == OV511_REG_BUS) {			if ((rc = reg_w(ov, pRegvals->reg, pRegvals->val)) < 0)				return rc;		} else if (pRegvals->bus == OV511_I2C_BUS) {			if ((rc = i2c_w(ov, pRegvals->reg, pRegvals->val)) < 0)				return rc;		} else {			err("Bad regval array");			return -1;		}		pRegvals++;	}	return 0;}#ifdef OV511_DEBUGstatic voiddump_i2c_range(struct usb_ov511 *ov, int reg1, int regn){	int i, rc;	for (i = reg1; i <= regn; i++) {		rc = i2c_r(ov, i);		info("Sensor[0x%02X] = 0x%02X", i, rc);	}}static voiddump_i2c_regs(struct usb_ov511 *ov){	info("I2C REGS");	dump_i2c_range(ov, 0x00, 0x7C);}static voiddump_reg_range(struct usb_ov511 *ov, int reg1, int regn){	int i, rc;	for (i = reg1; i <= regn; i++) {		rc = reg_r(ov, i);		info("OV511[0x%02X] = 0x%02X", i, rc);	}}static voidov511_dump_regs(struct usb_ov511 *ov){	info("CAMERA INTERFACE REGS");	dump_reg_range(ov, 0x10, 0x1f);	info("DRAM INTERFACE REGS");	dump_reg_range(ov, 0x20, 0x23);	info("ISO FIFO REGS");	dump_reg_range(ov, 0x30, 0x31);	info("PIO REGS");	dump_reg_range(ov, 0x38, 0x39);	dump_reg_range(ov, 0x3e, 0x3e);	info("I2C REGS");	dump_reg_range(ov, 0x40, 0x49);	info("SYSTEM CONTROL REGS");	dump_reg_range(ov, 0x50, 0x55);	dump_reg_range(ov, 0x5e, 0x5f);	info("OmniCE REGS");	dump_reg_range(ov, 0x70, 0x79);	/* NOTE: Quantization tables are not readable. You will get the value	 * in reg. 0x79 for every table register */	dump_reg_range(ov, 0x80, 0x9f);	dump_reg_range(ov, 0xa0, 0xbf);}static voidov518_dump_regs(struct usb_ov511 *ov){	info("VIDEO MODE REGS");	dump_reg_range(ov, 0x20, 0x2f);	info("DATA PUMP AND SNAPSHOT REGS");	dump_reg_range(ov, 0x30, 0x3f);	info("I2C REGS");	dump_reg_range(ov, 0x40, 0x4f);	info("SYSTEM CONTROL AND VENDOR REGS");	dump_reg_range(ov, 0x50, 0x5f);	info("60 - 6F");	dump_reg_range(ov, 0x60, 0x6f);	info("70 - 7F");	dump_reg_range(ov, 0x70, 0x7f);	info("Y QUANTIZATION TABLE");	dump_reg_range(ov, 0x80, 0x8f);	info("UV QUANTIZATION TABLE");	dump_reg_range(ov, 0x90, 0x9f);	info("A0 - BF");	dump_reg_range(ov, 0xa0, 0xbf);	info("CBR");	dump_reg_range(ov, 0xc0, 0xcf);}#endif/*****************************************************************************//* Temporarily stops OV511 from functioning. Must do this before changing * registers while the camera is streaming */static inline intov51x_stop(struct usb_ov511 *ov){	PDEBUG(4, "stopping");	ov->stopped = 1;	if (ov->bclass == BCL_OV518)		return (reg_w_mask(ov, R51x_SYS_RESET, 0x3a, 0x3a));	else		return (reg_w(ov, R51x_SYS_RESET, 0x3d));}/* Restarts OV511 after ov511_stop() is called. Has no effect if it is not * actually stopped (for performance). */static inline intov51x_restart(struct usb_ov511 *ov){	if (ov->stopped) {		PDEBUG(4, "restarting");		ov->stopped = 0;		/* Reinitialize the stream */		if (ov->bclass == BCL_OV518)			reg_w(ov, 0x2f, 0x80);		return (reg_w(ov, R51x_SYS_RESET, 0x00));	}	return 0;}/* Sleeps until no frames are active. Returns !0 if got signal */static intov51x_wait_frames_inactive(struct usb_ov511 *ov){	return wait_event_interruptible(ov->wq, ov->curframe < 0);}

⌨️ 快捷键说明

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