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

📄 ov511.c

📁 linux下的usb接口驱动程序
💻 C
📖 第 1 页 / 共 5 页
字号:
	int rc, value;	/* Select camera register */	rc = reg_w(ov, R51x_I2C_SADDR_2, reg);	if (rc < 0) goto error;	/* Initiate 2-byte write cycle */	rc = reg_w(ov, R518_I2C_CTL, 0x03);	if (rc < 0) goto error;	/* Initiate 2-byte read cycle */	rc = reg_w(ov, R518_I2C_CTL, 0x05);	if (rc < 0) goto error;	value = reg_r(ov, R51x_I2C_DATA);	PDEBUG(5, "0x%02X:0x%02X", reg, value);	return value;error:	err("ov518 i2c read: error %d", rc);	return rc;}/* NOTE: Do not call this function directly! * returns: negative is error, pos or zero is data */static int ov511_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) goto error;		/* Initiate 2-byte write cycle */		rc = reg_w(ov, R511_I2C_CTL, 0x03);		if (rc < 0) goto error;		do rc = reg_r(ov, R511_I2C_CTL);		while (rc > 0 && ((rc&1) == 0)); /* Retry until idle */		if (rc < 0) goto error;		if ((rc&2) == 0) /* Ack? */			break;		/* I2C abort */			reg_w(ov, R511_I2C_CTL, 0x10);		if (--retries < 0) {			err("i2c write retries exhausted");			rc = -1;			goto error;		}	}	/* 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) goto error;		do rc = reg_r(ov, R511_I2C_CTL);		while (rc > 0 && ((rc&1) == 0)); /* Retry until idle */		if (rc < 0) goto error;		if ((rc&2) == 0) /* Ack? */			break;		/* I2C abort */			rc = reg_w(ov, R511_I2C_CTL, 0x10);		if (rc < 0) goto error;		if (--retries < 0) {			err("i2c read retries exhausted");			rc = -1;			goto error;		}	}	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)		goto error;		return value;error:	err("i2c read: error %d", rc);	return rc;}/* returns: negative is error, pos or zero is data */static int i2c_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 int i2c_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 int ov51x_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 int i2c_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;}/* Write to a specific I2C slave ID and register, using the specified mask */static int i2c_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 */	if (reg_w(ov, R51x_I2C_W_SID, slave) < 0) {		rc = -EIO;		goto out;	}	if (reg_w(ov, R51x_I2C_R_SID, slave + 1) < 0) {		rc = -EIO;		goto out;	}	rc = ov51x_i2c_write_mask_internal(ov, reg, value, mask);	/* Don't bail out yet if error; IDs must be restored */	/* Restore primary IDs */	slave = ov->primary_i2c_slave;	if (reg_w(ov, R51x_I2C_W_SID, slave) < 0) {		rc = -EIO;		goto out;	}	if (reg_w(ov, R51x_I2C_R_SID, slave + 1) < 0) {		rc = -EIO;		goto out;	}out:	up(&ov->i2c_lock);	return rc;}/* Read from a specific I2C slave ID and register */static int i2c_r_slave(struct usb_ov511 *ov,	    unsigned char slave,	    unsigned char reg){	int rc;	down(&ov->i2c_lock);	/* Set new slave IDs */	if (reg_w(ov, R51x_I2C_W_SID, slave) < 0) {		rc = -EIO;		goto out;	}	if (reg_w(ov, R51x_I2C_R_SID, slave + 1) < 0) {		rc = -EIO;		goto out;	}	if (ov->bclass == BCL_OV518)		rc = ov518_i2c_read_internal(ov, reg);	else		rc = ov511_i2c_read_internal(ov, reg);	/* Don't bail out yet if error; IDs must be restored */	/* Restore primary IDs */	slave = ov->primary_i2c_slave;	if (reg_w(ov, R51x_I2C_W_SID, slave) < 0) {		rc = -EIO;		goto out;	}	if (reg_w(ov, R51x_I2C_R_SID, slave + 1) < 0) {		rc = -EIO;		goto out;	}out:	up(&ov->i2c_lock);	return rc;}/* Sets I2C read and write slave IDs. Returns <0 for error */static int ov51x_set_slave_ids(struct usb_ov511 *ov, unsigned char sid){	down(&ov->i2c_lock);	if (reg_w(ov, R51x_I2C_W_SID, sid) < 0)		return -EIO;	if (reg_w(ov, R51x_I2C_R_SID, sid + 1) < 0)		return -EIO;	if (ov51x_reset(ov, OV511_RESET_NOREGS) < 0)		return -EIO;	up(&ov->i2c_lock);	return 0;}static int write_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)				goto error;		} else if (pRegvals->bus == OV511_I2C_BUS) {			if ((rc = i2c_w(ov, pRegvals->reg, pRegvals->val)) < 0)				goto error;		} else {			err("Bad regval array");			rc = -1;			goto error;		}		pRegvals++;	}	return 0;error:	err("write regvals: error %d", rc);	return rc;}#ifdef OV511_DEBUG static void dump_i2c_range(struct usb_ov511 *ov, int reg1, int regn){	int i;	int rc;	for (i = reg1; i <= regn; i++) {		rc = i2c_r(ov, i);		info("OV7610[0x%X] = 0x%X", i, rc);	}}static void dump_i2c_regs(struct usb_ov511 *ov){	info("I2C REGS");	dump_i2c_range(ov, 0x00, 0x7C);}static void dump_reg_range(struct usb_ov511 *ov, int reg1, int regn){	int i;	int rc;	for (i = reg1; i <= regn; i++) {		rc = reg_r(ov, i);		info("OV511[0x%X] = 0x%X", i, rc);	}}/* FIXME: Should there be an OV518 version of this? */static void ov511_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);}#endif/********************************************************************** * * Kernel I2C Interface * **********************************************************************//* For as-yet unimplemented I2C interface */static void call_i2c_clients(struct usb_ov511 *ov, unsigned int cmd,		 void *arg){	/* Do nothing */}/*****************************************************************************//* Temporarily stops OV511 from functioning. Must do this before changing * registers while the camera is streaming */static inline int ov51x_stop(struct usb_ov511 *ov){	PDEBUG(4, "stopping");	ov->stopped = 1;		if (ov->bclass == BCL_OV518)		return (reg_w(ov, R51x_SYS_RESET, 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 int ov51x_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;}/* Resets the hardware snapshot button */static void ov51x_clear_snapshot(struct usb_ov511 *ov){	if (ov->bclass == BCL_OV511) {		reg_w(ov, R51x_SYS_SNAP, 0x01);		reg_w(ov, R51x_SYS_SNAP, 0x03);		reg_w(ov, R51x_SYS_SNAP, 0x01);	} else if (ov->bclass == BCL_OV518) {		warn("snapshot reset not supported yet on OV518(+)");	} else {		err("clear snap: invalid bridge type");	}	}/* Checks the status of the snapshot button. Returns 1 if it was pressed since * it was last cleared, and zero in all other cases (including errors) */static int ov51x_check_snapshot(struct usb_ov511 *ov){	int ret, status = 0;	if (ov->bclass == BCL_OV511) {		ret = reg_r(ov, R51x_SYS_SNAP);		if (ret < 0) {			err("Error checking snspshot status (%d)", ret);		} else if (ret & 0x08) {			status = 1;		}	} else if (ov->bclass == BCL_OV518) {		warn("snapshot check not supported yet on OV518(+)");	} else {		err("check snap: invalid bridge type");	}	return status;}/* This does an initial reset of an OmniVision sensor and ensures that I2C * is synchronized. Returns <0 for failure. */static int init_ov_sensor(struct usb_ov511 *ov){	int i, success;	/* Reset the sensor */ 	if (i2c_w(ov, 0x12, 0x80) < 0) return -EIO;	/* Wait for it to initialize */ 	schedule_timeout (1 + 150 * HZ / 1000);	for (i = 0, success = 0; i < i2c_detect_tries && !success; i++) {		if ((i2c_r(ov, OV7610_REG_ID_HIGH) == 0x7F) &&		    (i2c_r(ov, OV7610_REG_ID_LOW) == 0xA2)) {			success = 1;			continue;		}		/* Reset the sensor */ 		if (i2c_w(ov, 0x12, 0x80) < 0) return -EIO;		/* Wait for it to initialize */ 		schedule_timeout(1 + 150 * HZ / 1000);		/* Dummy read to sync I2C */		if (i2c_r(ov, 0x00) < 0) return -EIO;	}	if (!success)		return -EIO;		PDEBUG(1, "I2C synced in %d attempt(s)", i);	return 0;}static int ov51x_set_packet_size(struct usb_ov511 *ov, int size){	int alt, mult;	if (ov51x_stop(ov) < 0)		return -EIO;	mult = size >> 5;	if (ov->bridge == BRG_OV511) {		if (size == 0) alt = OV511_ALT_SIZE_0;		else if (size == 257) alt = OV511_ALT_SIZE_257;		else if (size == 513) alt = OV511_ALT_SIZE_513;		else if (size == 769) alt = OV511_ALT_SIZE_769;		else if (size == 993) alt = OV511_ALT_SIZE_993;		else {			err("Set packet size: invalid size (%d)", size);			return -EINVAL;		}	} else if (ov->bridge == BRG_OV511PLUS) {		if (size == 0) alt = OV511PLUS_ALT_SIZE_0;		else if (size == 33) alt = OV511PLUS_ALT_SIZE_33;		else if (size == 129) alt = OV511PLUS_ALT_SIZE_129;		else if (size == 257) alt = OV511PLUS_ALT_SIZE_257;		else if (size == 385) alt = OV511PLUS_ALT_SIZE_385;		else if (size == 513) alt = OV511PLUS_ALT_SIZE_513;		else if (size == 769) alt = OV511PLUS_ALT_SIZE_769;		else if (size == 961) alt = OV511PLUS_ALT_SIZE_961;		else {			err("Set packet size: invalid size (%d)", size);

⌨️ 快捷键说明

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