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

📄 ov511_core.c

📁 支持linux2.6和linux2.4的ov511摄像头驱动源码
💻 C
📖 第 1 页 / 共 5 页
字号:
	rc = reg_r(ov, R51x_I2C_DATA);	if (rc < 0)		goto out;	else		*val = rc;	PDEBUG(5, "(0x%02X) 0x%02X", addr<<1, *val);	/* This is needed to make writes work again */	rc = reg_w(ov, R511_I2C_CTL, 0x05);out:	if (rc < 0)		PDEBUG(5, "I2C read error (%d)", rc);	return rc;}static intov511_i2c_adap_write_byte(struct usb_ov511 *ov,			  unsigned char addr,			  unsigned char subaddr){	int rc, retries;	PDEBUG(5, "(0x%02X) 0x%02X", addr<<1, subaddr);	/* Set slave addresses */		rc = ov51x_i2c_adap_set_slave(ov, addr);	if (rc < 0)		return rc;	/* Two byte write cycle */	for (retries = OV511_I2C_RETRIES; ; ) {		/* Select camera register */		rc = reg_w(ov, R51x_I2C_SADDR_2, subaddr);		if (rc < 0)			goto out;		/* Initiate 2-byte write cycle */		rc = reg_w(ov, R511_I2C_CTL, 0x03);		if (rc < 0)			goto out;		do			rc = reg_r(ov, R511_I2C_CTL);		while (rc > 0 && ((rc&1) == 0)); /* Retry until idle */		if (rc < 0)			goto out;		if ((rc&2) == 0) /* Ack? */			break;		/* I2C abort */		rc = reg_w(ov, R511_I2C_CTL, 0x10);		if (rc < 0)			goto out;		if (--retries < 0) {			PDEBUG(5, "i2c write retries exhausted");			rc = -1;			goto out;		}	}out:	if (rc < 0)		PDEBUG(5, "I2C write error (%d)", rc);	return rc;}static intov511_i2c_adap_read_byte_data(struct usb_ov511 *ov,			      unsigned char addr,			      unsigned char subaddr,			      unsigned char *val){	int rc;	rc = ov511_i2c_adap_write_byte(ov, addr, subaddr);	if (rc < 0)		return rc;	rc = ov511_i2c_adap_read_byte(ov, addr, val);	return rc;}static intov511_i2c_adap_write_byte_data(struct usb_ov511 *ov,			       unsigned char addr,			       unsigned char subaddr,			       unsigned char val){	int rc, retries;	PDEBUG(5, "(0x%02X) 0x%02X:0x%02X", addr<<1, subaddr, val);	/* Set slave addresses */		rc = ov51x_i2c_adap_set_slave(ov, addr);	if (rc < 0)		return rc;	/* Three byte write cycle */	for (retries = OV511_I2C_RETRIES; ; ) {		/* Select camera register */		rc = reg_w(ov, R51x_I2C_SADDR_3, subaddr);		if (rc < 0)			goto out;		/* Write "value" to I2C data port of OV511 */		rc = reg_w(ov, R51x_I2C_DATA, val);		if (rc < 0)			goto out;		/* Initiate 3-byte write cycle */		rc = reg_w(ov, R511_I2C_CTL, 0x01);		if (rc < 0)			goto out;		do			rc = reg_r(ov, R511_I2C_CTL);		while (rc > 0 && ((rc&1) == 0)); /* Retry until idle */		if (rc < 0)			goto out;		if ((rc&2) == 0) /* Ack? */			break;#if 0		/* I2C abort */		reg_w(ov, R511_I2C_CTL, 0x10);#endif		if (--retries < 0) {			PDEBUG(5, "i2c write retries exhausted");			rc = -1;			goto out;		}	}out:	if (rc < 0)		PDEBUG(5, "I2C write error (%d)", rc);	return rc;}/* NOTE: this function always succeeds regardless of whether the sensor is * present and working. */static intov518_i2c_adap_read_byte(struct usb_ov511 *ov,			 unsigned char addr,			 unsigned char *val){	int rc;	/* Set slave addresses */		rc = ov51x_i2c_adap_set_slave(ov, addr);	if (rc < 0)		return rc;	/* Initiate 2-byte read cycle */	rc = reg_w(ov, R518_I2C_CTL, 0x05);	if (rc < 0)		goto out;	rc = reg_r(ov, R51x_I2C_DATA);	if (rc < 0)		goto out;	else		*val = rc;	PDEBUG(5, "(0x%02X) 0x%02X", addr<<1, *val);out:	if (rc < 0)		PDEBUG(5, "I2C read error (%d)", rc);	return rc;}/* NOTE: this function always succeeds regardless of whether the sensor is * present and working. */static intov518_i2c_adap_write_byte(struct usb_ov511 *ov,			  unsigned char addr,			  unsigned char subaddr){	int rc;	PDEBUG(5, "(0x%02X) 0x%02X", addr<<1, subaddr);	/* Set slave addresses */		rc = ov51x_i2c_adap_set_slave(ov, addr);	if (rc < 0)		return rc;	/* Select camera register */	rc = reg_w(ov, R51x_I2C_SADDR_2, subaddr);	if (rc < 0)		goto out;	/* Initiate 2-byte write cycle */	rc = reg_w(ov, R518_I2C_CTL, 0x03);	if (rc < 0)		goto out;out:	if (rc < 0)		PDEBUG(5, "I2C write error (%d)", rc);	return rc;}static intov518_i2c_adap_read_byte_data(struct usb_ov511 *ov,			      unsigned char addr,			      unsigned char subaddr,			      unsigned char *val){	int rc;	rc = ov518_i2c_adap_write_byte(ov, addr, subaddr);	if (rc < 0)		return rc;	rc = ov518_i2c_adap_read_byte(ov, addr, val);	return rc;}/* NOTE: this function always succeeds regardless of whether the sensor is * present and working. */static intov518_i2c_adap_write_byte_data(struct usb_ov511 *ov,			       unsigned char addr,			       unsigned char subaddr,			       unsigned char val){	int rc;	PDEBUG(5, "(0x%02X) 0x%02X:0x%02X", addr<<1, subaddr, val);	/* Set slave addresses */		rc = ov51x_i2c_adap_set_slave(ov, addr);	if (rc < 0)		return rc;	/* Select camera register */	rc = reg_w(ov, R51x_I2C_SADDR_3, subaddr);	if (rc < 0)		goto out;	/* Write "value" to I2C data port of OV511 */	rc = reg_w(ov, R51x_I2C_DATA, val);	if (rc < 0)		goto out;	/* Initiate 3-byte write cycle */	rc = reg_w(ov, R518_I2C_CTL, 0x01);	if (rc < 0)		goto out;out:	if (rc < 0)		PDEBUG(5, "I2C write error (%d)", rc);	return rc;}static intwrite_regvals(struct usb_ov511 *ov, struct regval *regvals){	int rc;	while (regvals->mask != 0) {		rc = reg_w_mask(ov, regvals->reg, regvals->val, regvals->mask);		if (rc < 0)			return rc;		regvals++;	}	return 0;}#ifdef OV511_DEBUGstatic 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/********************************************************************** * * Kernel I2C Interface * **********************************************************************/static intov511_i2c_validate_addr(struct usb_ov511 *ov, u16 addr){	switch (addr) {	case 0x00c2>>1:	/* Tuner */	case 0x0088>>1:	/* Audiochip */		if (ov->tuner_type >= 0)			return 0;		else			goto reject;	case SAA7111A_SID:		return 0;	case OV6xx0_SID:	case OV7xx0_SID:		/* Got to be careful here... tuner gives a false ACK at		 * address 0x00c0>>1 */		if (ov->tuner_type >= 0)			goto reject;		else			return 0;	}reject:	PDEBUG(3, "Rejected slave ID 0x%04X", addr);	return -ENODEV;}static intov518_i2c_validate_addr(struct usb_ov511 *ov, u16 addr){	switch (addr) {	case OV6xx0_SID:	case OV7xx0_SID:		return 0;	default:		PDEBUG(3, "Rejected slave ID 0x%04X", addr);		return -ENODEV;	}}static inline intsensor_cmd(struct usb_ov511 *ov, unsigned int cmd, void *arg){	struct i2c_client *c = ov->sensor_client;	if (ov->sensor == SEN_SAA7111A)		return -EPERM;	/* Non-fatal error */	if (c && c->driver->command)		return c->driver->command(ov->sensor_client, cmd, arg);	else		return -ENODEV;}static voidcall_i2c_clients(struct usb_ov511 *ov, unsigned int cmd, void *arg){#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0)	struct i2c_client *client;	int i;	for (i = 0; i < I2C_CLIENT_MAX; i++) {		client = ov->i2c_adap.clients[i];		/* Sensor_client is not called from here for now, since it		   has different enumeration for cmd  */		if (client == ov->sensor_client)			continue;		if (client && client->driver->command)			client->driver->command(client, cmd, arg);	}#else	i2c_clients_command(&ov->i2c_adap, cmd, arg);#endif}static intov511_smbus_xfer(struct i2c_adapter *adapter, u16 addr, unsigned short flags,		 char read_write, u8 command, int size,		 union i2c_smbus_data *data){	struct usb_ov511 *ov = i2c_get_adapdata(adapter);	int rc;	rc = ov511_i2c_validate_addr(ov, addr);	if (rc < 0)		return rc;	if (size == I2C_SMBUS_QUICK) {		PDEBUG(4, "Got probed at addr 0x%04X", addr);	} else if (size == I2C_SMBUS_BYTE) {		if (read_write == I2C_SMBUS_WRITE) { 			rc = ov511_i2c_adap_write_byte(ov, addr, command);		} else if (read_write == I2C_SMBUS_READ) {			rc = ov511_i2c_adap_read_byte(ov, addr, &data->byte);		}	} else if (size == I2C_SMBUS_BYTE_DATA) {		if (read_write == I2C_SMBUS_WRITE) { 			rc = ov511_i2c_adap_write_byte_data(ov, addr, command,							    data->byte);		} else if (read_write == I2C_SMBUS_READ) {			rc = ov511_i2c_adap_read_byte_data(ov, addr, command,							   &data->byte);		}	} else {		warn("Unsupported I2C transfer mode (%d)", size);		return -EINVAL;	}	/* This works around a bug in the I2C core */	if (rc > 0)		rc = 0;	return rc;}static u32ov511_i2c_func(struct i2c_adapter *adap){	return I2C_FUNC_SMBUS_QUICK	     | I2C_FUNC_SMBUS_BYTE	     | I2C_FUNC_SMBUS_BYTE_DATA;}static intov518_smbus_xfer(struct i2c_adapter *adapter, u16 addr, unsigned short flags,		 char read_write, u8 command, int size,		 union i2c_smbus_data *data){	struct usb_ov511 *ov = i2c_get_adapdata(adapter);	int rc;	/* With OV518 we must be more aggressive about rejecting	 * unknown addresses, since it can't report NAKs. */	rc = ov518_i2c_validate_addr(ov, addr);	if (rc < 0)		return rc;	if (size == I2C_SMBUS_QUICK) {		PDEBUG(4, "Got probed at addr 0x%04X", addr);	} else if (size == I2C_SMBUS_BYTE) {		if (read_write == I2C_SMBUS_WRITE) { 			rc = ov518_i2c_adap_write_byte(ov, addr, command);		} else if (read_write == I2C_SMBUS_READ) {			rc = ov518_i2c_adap_read_byte(ov, addr, &data->byte);		}	} else if (size == I2C_SMBUS_BYTE_DATA) {		if (read_write == I2C_SMBUS_WRITE) { 			rc = ov518_i2c_adap_write_byte_data(ov, addr, command,							    data->byte);		} else if (read_write == I2C_SMBUS_READ) {			rc = ov518_i2c_adap_read_byte_data(ov, addr, command,							   &data->byte);		}	} else {		warn("Unsupported I2C transfer mode (%d)", size);		return -EINVAL;	}	/* This works around a bug in the I2C core */	if (rc > 0)		rc = 0;	return rc;}static u32ov518_i2c_func(struct i2c_adapter *adap){	return I2C_FUNC_SMBUS_QUICK	     | I2C_FUNC_SMBUS_BYTE	     | I2C_FUNC_SMBUS_BYTE_DATA;}

⌨️ 快捷键说明

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