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

📄 ov511.c

📁 基于S3CEB2410平台LINUX操作系统下 USB驱动源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
			goto error;		}	}	return 0;error:	err("i2c write: error %d", rc);	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 ov51x_i2c_read(). Note that this function * always succeeds regardless of whether the sensor is present and working. */static int ov518_i2c_read_internal(struct usb_device *dev, unsigned char reg){	int rc, value;	/* Select camera register */	rc = ov511_reg_write(dev, OV511_REG_I2C_SUB_ADDRESS_2_BYTE, reg);	if (rc < 0) goto error;	/* Initiate 2-byte write cycle */	rc = ov511_reg_write(dev, OV518_REG_I2C_CONTROL, 0x03);	if (rc < 0) goto error;	/* Initiate 2-byte read cycle */	rc = ov511_reg_write(dev, OV518_REG_I2C_CONTROL, 0x05);	if (rc < 0) goto error;	value = ov511_reg_read(dev, OV511_REG_I2C_DATA_PORT);	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_device *dev, unsigned char reg){	int rc, value, retries;	/* Two byte write cycle */	for (retries = OV511_I2C_RETRIES; ; ) {		/* Select camera register */		rc = ov511_reg_write(dev, OV511_REG_I2C_SUB_ADDRESS_2_BYTE,				     reg);		if (rc < 0) goto error;		/* Initiate 2-byte write cycle */		rc = ov511_reg_write(dev, OV511_REG_I2C_CONTROL, 0x03);		if (rc < 0) goto error;		do rc = ov511_reg_read(dev, OV511_REG_I2C_CONTROL);		while (rc > 0 && ((rc&1) == 0)); /* Retry until idle */		if (rc < 0) goto error;		if ((rc&2) == 0) /* Ack? */			break;		/* I2C abort */			ov511_reg_write(dev, OV511_REG_I2C_CONTROL, 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 = ov511_reg_write(dev, OV511_REG_I2C_CONTROL, 0x05);		if (rc < 0) goto error;		do rc = ov511_reg_read(dev, OV511_REG_I2C_CONTROL);		while (rc > 0 && ((rc&1) == 0)); /* Retry until idle */		if (rc < 0) goto error;		if ((rc&2) == 0) /* Ack? */			break;		/* I2C abort */			rc = ov511_reg_write(dev, OV511_REG_I2C_CONTROL, 0x10);		if (rc < 0) goto error;		if (--retries < 0) {			err("i2c read retries exhausted");			rc = -1;			goto error;		}	}	value = ov511_reg_read(dev, OV511_REG_I2C_DATA_PORT);	PDEBUG(5, "0x%02X:0x%02X", reg, value);			/* This is needed to make ov51x_i2c_write() work */	rc = ov511_reg_write(dev, OV511_REG_I2C_CONTROL, 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 ov51x_i2c_read(struct usb_ov511 *ov511, unsigned char reg){	int rc;	struct usb_device *dev = ov511->dev;	down(&ov511->i2c_lock);	if (dev->descriptor.idProduct == PROD_OV518 ||	    dev->descriptor.idProduct == PROD_OV518PLUS)		rc = ov518_i2c_read_internal(dev, reg);	else		rc = ov511_i2c_read_internal(dev, reg);	up(&ov511->i2c_lock);	return rc;}static int ov51x_i2c_write(struct usb_ov511 *ov511,		unsigned char reg,		unsigned char value){	int rc;	struct usb_device *dev = ov511->dev;	down(&ov511->i2c_lock);	if (dev->descriptor.idProduct == PROD_OV518 ||	    dev->descriptor.idProduct == PROD_OV518PLUS)		rc = ov518_i2c_write_internal(dev, reg, value);	else		rc = ov511_i2c_write_internal(dev, reg, value);	up(&ov511->i2c_lock);	return rc;}/* Do not call this function directly! */static int ov51x_i2c_write_mask_internal(struct usb_device *dev,			      unsigned char reg,			      unsigned char value,			      unsigned char mask){	int rc;	unsigned char oldval, newval;	if (mask == 0xff) {		newval = value;	} else {		if (dev->descriptor.idProduct == PROD_OV518 ||		    dev->descriptor.idProduct == PROD_OV518PLUS)			rc = ov518_i2c_read_internal(dev, reg);		else			rc = ov511_i2c_read_internal(dev, 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 (dev->descriptor.idProduct == PROD_OV518 ||	    dev->descriptor.idProduct == PROD_OV518PLUS)		return (ov518_i2c_write_internal(dev, reg, newval));	else		return (ov511_i2c_write_internal(dev, 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 ov51x_i2c_write_mask(struct usb_ov511 *ov511,		     unsigned char reg,		     unsigned char value,		     unsigned char mask){	int rc;	struct usb_device *dev = ov511->dev;	down(&ov511->i2c_lock);	rc = ov51x_i2c_write_mask_internal(dev, reg, value, mask);	up(&ov511->i2c_lock);	return rc;}/* Write to a specific I2C slave ID and register, using the specified mask */static int ov51x_i2c_write_slave(struct usb_ov511 *ov511,		      unsigned char slave,		      unsigned char reg,		      unsigned char value,		      unsigned char mask){	int rc = 0;	struct usb_device *dev = ov511->dev;	down(&ov511->i2c_lock);	/* Set new slave IDs */	if (ov511_reg_write(dev, OV511_REG_I2C_SLAVE_ID_WRITE, slave) < 0) {		rc = -EIO;		goto out;	}	if (ov511_reg_write(dev, OV511_REG_I2C_SLAVE_ID_READ, slave + 1) < 0) {		rc = -EIO;		goto out;	}	rc = ov51x_i2c_write_mask_internal(dev, reg, value, mask);	/* Don't bail out yet if error; IDs must be restored */	/* Restore primary IDs */	slave = ov511->primary_i2c_slave;	if (ov511_reg_write(dev, OV511_REG_I2C_SLAVE_ID_WRITE, slave) < 0) {		rc = -EIO;		goto out;	}	if (ov511_reg_write(dev, OV511_REG_I2C_SLAVE_ID_READ, slave + 1) < 0) {		rc = -EIO;		goto out;	}out:	up(&ov511->i2c_lock);	return rc;}/* Read from a specific I2C slave ID and register */static int ov51x_i2c_read_slave(struct usb_ov511 *ov511,		     unsigned char slave,		     unsigned char reg){	int rc;	struct usb_device *dev = ov511->dev;	down(&ov511->i2c_lock);	/* Set new slave IDs */	if (ov511_reg_write(dev, OV511_REG_I2C_SLAVE_ID_WRITE, slave) < 0) {		rc = -EIO;		goto out;	}	if (ov511_reg_write(dev, OV511_REG_I2C_SLAVE_ID_READ, slave + 1) < 0) {		rc = -EIO;		goto out;	}	if (dev->descriptor.idProduct == PROD_OV518 ||	    dev->descriptor.idProduct == PROD_OV518PLUS)		rc = ov518_i2c_read_internal(dev, reg);	else		rc = ov511_i2c_read_internal(dev, reg);	/* Don't bail out yet if error; IDs must be restored */	/* Restore primary IDs */	slave = ov511->primary_i2c_slave;	if (ov511_reg_write(dev, OV511_REG_I2C_SLAVE_ID_WRITE, slave) < 0) {		rc = -EIO;		goto out;	}	if (ov511_reg_write(dev, OV511_REG_I2C_SLAVE_ID_READ, slave + 1) < 0) {		rc = -EIO;		goto out;	}out:	up(&ov511->i2c_lock);	return rc;}static int ov511_write_regvals(struct usb_ov511 *ov511,		    struct ov511_regvals * pRegvals){	int rc;	struct usb_device *dev = ov511->dev;	while (pRegvals->bus != OV511_DONE_BUS) {		if (pRegvals->bus == OV511_REG_BUS) {			if ((rc = ov511_reg_write(dev, pRegvals->reg,			                          pRegvals->val)) < 0)				goto error;		} else if (pRegvals->bus == OV511_I2C_BUS) {			if ((rc = ov51x_i2c_write(ov511, 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 ov511_dump_i2c_range(struct usb_ov511 *ov511, int reg1, int regn){	int i;	int rc;	for (i = reg1; i <= regn; i++) {		rc = ov51x_i2c_read(ov511, i);		info("OV7610[0x%X] = 0x%X", i, rc);	}}static void ov51x_dump_i2c_regs(struct usb_ov511 *ov511){	info("I2C REGS");	ov511_dump_i2c_range(ov511, 0x00, 0x7C);}static void ov511_dump_reg_range(struct usb_device *dev, int reg1, int regn){	int i;	int rc;	for (i = reg1; i <= regn; i++) {	  rc = ov511_reg_read(dev, i);	  info("OV511[0x%X] = 0x%X", i, rc);	}}static void ov511_dump_regs(struct usb_device *dev){	info("CAMERA INTERFACE REGS");	ov511_dump_reg_range(dev, 0x10, 0x1f);	info("DRAM INTERFACE REGS");	ov511_dump_reg_range(dev, 0x20, 0x23);	info("ISO FIFO REGS");	ov511_dump_reg_range(dev, 0x30, 0x31);	info("PIO REGS");	ov511_dump_reg_range(dev, 0x38, 0x39);	ov511_dump_reg_range(dev, 0x3e, 0x3e);	info("I2C REGS");	ov511_dump_reg_range(dev, 0x40, 0x49);	info("SYSTEM CONTROL REGS");	ov511_dump_reg_range(dev, 0x50, 0x55);	ov511_dump_reg_range(dev, 0x5e, 0x5f);	info("OmniCE REGS");	ov511_dump_reg_range(dev, 0x70, 0x79);	/* NOTE: Quantization tables are not readable. You will get the value	 * in reg. 0x79 for every table register */	ov511_dump_reg_range(dev, 0x80, 0x9f);	ov511_dump_reg_range(dev, 0xa0, 0xbf);}#endif/********************************************************************** * * Kernel I2C Interface * **********************************************************************//* For as-yet unimplemented I2C interface */static void call_i2c_clients(struct usb_ov511 *ov511, unsigned int cmd,		 void *arg){	/* Do nothing */}/*****************************************************************************/static int ov511_reset(struct usb_ov511 *ov511, unsigned char reset_type){	int rc;			/* Setting bit 0 not allowed on 518/518Plus */	if (ov511->bridge == BRG_OV518 ||	    ov511->bridge == BRG_OV518PLUS)		reset_type &= 0xfe;	PDEBUG(4, "Reset: type=0x%X", reset_type);	rc = ov511_reg_write(ov511->dev, OV511_REG_SYSTEM_RESET, reset_type);	rc = ov511_reg_write(ov511->dev, OV511_REG_SYSTEM_RESET, 0);	if (rc < 0)		err("reset: command failed");	return rc;}/* Temporarily stops OV511 from functioning. Must do this before changing * registers while the camera is streaming */static inline int ov511_stop(struct usb_ov511 *ov511){	PDEBUG(4, "stopping");	ov511->stopped = 1;		if (ov511->bridge == BRG_OV518 ||	    ov511->bridge == BRG_OV518PLUS)		return (ov511_reg_write(ov511->dev, OV511_REG_SYSTEM_RESET,					0x3a));	else		return (ov511_reg_write(ov511->dev, OV511_REG_SYSTEM_RESET,					0x3d));}/* Restarts OV511 after ov511_stop() is called. Has no effect if it is not * actually stopped (for performance). */static inline int ov511_restart(struct usb_ov511 *ov511){	if (ov511->stopped) {		PDEBUG(4, "restarting");		ov511->stopped = 0;			/* Reinitialize the stream */		if (ov511->bridge == BRG_OV518 ||		    ov511->bridge == BRG_OV518PLUS)			ov511_reg_write(ov511->dev, 0x2f, 0x80);		return (ov511_reg_write(ov511->dev, OV511_REG_SYSTEM_RESET,					0x00));	}	return 0;}/* Resets the hardware snapshot button */static void ov51x_clear_snapshot(struct usb_ov511 *ov511){	if (ov511->bridge == BRG_OV511 || ov511->bridge == BRG_OV511PLUS) {		ov511_reg_write(ov511->dev, OV511_REG_SYSTEM_SNAPSHOT, 0x01);		ov511_reg_write(ov511->dev, OV511_REG_SYSTEM_SNAPSHOT, 0x03);		ov511_reg_write(ov511->dev, OV511_REG_SYSTEM_SNAPSHOT, 0x01);	} else if (ov511->bridge == BRG_OV518 ||		   ov511->bridge == BRG_OV518PLUS) {		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 *ov511){	int ret, status = 0;	if (ov511->bridge == BRG_OV511 || ov511->bridge == BRG_OV511PLUS) {		ret = ov511_reg_read(ov511->dev, OV511_REG_SYSTEM_SNAPSHOT);		if (ret < 0) {			err("Error checking snspshot status (%d)", ret);		} else if (ret & 0x08) {			status = 1;		}	} else if (ov511->bridge == BRG_OV518 ||		   ov511->bridge == BRG_OV518PLUS) {		warn("snapshot check not supported yet on OV518(+)");	} else {		err("check snap: invalid bridge type");	}	return status;}/* Sets I2C read and write slave IDs. Returns <0 for error */

⌨️ 快捷键说明

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