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

📄 ov511_core.c

📁 支持linux2.6和linux2.4的ov511摄像头驱动源码
💻 C
📖 第 1 页 / 共 5 页
字号:
static inti2c_attach_inform(struct i2c_client *client){	struct usb_ov511 *ov = i2c_get_adapdata(client->adapter);	int id = client->driver->id;	if (id == I2C_DRIVERID_OVCAMCHIP) {		int rc;		ov->sensor_client = client;		rc = sensor_cmd(ov, OVCAMCHIP_CMD_INITIALIZE, &ov->sensor_mono);		if (rc < 0) {			err("ERROR: Sensor init failed (rc=%d)", rc);			ov->sensor_client = NULL;			return rc;		}		down(&ov->lock);		if (sensor_cmd(ov, OVCAMCHIP_CMD_Q_SUBTYPE, &ov->sensor) < 0)			rc = -EIO;		else if (client->addr == OV7xx0_SID)			rc = ov7xx0_configure(ov);		else if (client->addr == OV6xx0_SID)			rc = ov6xx0_configure(ov);		else			rc = -EINVAL;		up(&ov->lock);		if (rc) {			ov->sensor_client = NULL;			return rc;		}	} else if (id == I2C_DRIVERID_TUNER) {		if (ov->bclass == BCL_OV518 || ov->tuner_type < 0)			return -1;		ov->has_tuner = 1;		call_i2c_clients(ov, TUNER_SET_TYPE, &ov->tuner_type);	} else if (id == I2C_DRIVERID_TDA7313) {		if (ov->bclass == BCL_OV518 || ov->tuner_type < 0)			return -1;		ov->has_audiochip = 1;	} else if (id == I2C_DRIVERID_SAA7111A) {		int arg;		if (ov->bclass == BCL_OV518)			return -1;		down(&ov->lock);		saa7111a_configure(ov);		up(&ov->lock);		arg = 1; call_i2c_clients(ov, DECODER_ENABLE_OUTPUT, &arg);	} else	{		PDEBUG(1, "Rejected client [%s] with [%s]",#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 16)		       client->name, client->driver->name);#else		       client->name, client->driver->driver.name);#endif		return -1;	}	PDEBUG(1, "i2c attach client [%s] with [%s]",#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 16)	       client->name, client->driver->name);#else	       client->name, client->driver->driver.name);#endif	return 0;}static inti2c_detach_inform(struct i2c_client *client){	struct usb_ov511 *ov = i2c_get_adapdata(client->adapter);	if (ov->sensor_client == client)		ov->sensor_client = NULL;	PDEBUG(1, "i2c detach [%s]", client->name);	return 0;}static int ov51x_i2c_control(struct i2c_adapter *adapter, unsigned int cmd,		  unsigned long arg){	return 0;}#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 0)static voidov51x_i2c_inc_use(struct i2c_adapter *adap){	MOD_INC_USE_COUNT;}static voidov51x_i2c_dec_use(struct i2c_adapter *adap){	MOD_DEC_USE_COUNT;}#endifstatic struct i2c_algorithm ov518_i2c_algo = {#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 14)	.name =			"OV518 algorithm",	.id =			I2C_ALGO_SMBUS,#endif	.smbus_xfer =		ov518_smbus_xfer,	.algo_control =		ov51x_i2c_control,	.functionality =	ov518_i2c_func,};static struct i2c_algorithm ov511_i2c_algo = {#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 14)	.name =			"OV511 algorithm",	.id =			I2C_ALGO_SMBUS,#endif	.smbus_xfer =		ov511_smbus_xfer,	.algo_control =		ov51x_i2c_control,	.functionality =	ov511_i2c_func,};static struct i2c_adapter i2c_adap_template = {	.name = 		"(unset)",#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 6)	.class =		I2C_CLASS_CAM_DIGITAL,#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 70)	.class =		I2C_ADAP_CLASS_CAM_DIGITAL,#endif#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 0)	.inc_use =		ov51x_i2c_inc_use,	.dec_use =		ov51x_i2c_dec_use,#else	.owner =		THIS_MODULE,#endif	.client_register =	i2c_attach_inform,	.client_unregister =	i2c_detach_inform,};static intov51x_init_i2c(struct usb_ov511 *ov){	memcpy(&ov->i2c_adap, &i2c_adap_template, sizeof(struct i2c_adapter));	/* Temporary name. We'll set the final one when we know the minor # */	sprintf(ov->i2c_adap.name, "OV51x");	i2c_set_adapdata(&ov->i2c_adap, ov);	// FIXME: Need separate IDs for OV511+/OV518+	if (ov->bclass == BCL_OV518) {		ov->i2c_adap.algo = &ov518_i2c_algo;#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 14)		ov->i2c_adap.id = I2C_ALGO_SMBUS | I2C_HW_SMBUS_OV518;#else		ov->i2c_adap.id = I2C_HW_SMBUS_OV518;#endif	} else {		ov->i2c_adap.algo = &ov511_i2c_algo;#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 14)		ov->i2c_adap.id = I2C_ALGO_SMBUS | I2C_HW_SMBUS_OV511;#else		ov->i2c_adap.id = I2C_HW_SMBUS_OV511;#endif	}	ov->internal_client.adapter = &ov->i2c_adap;	PDEBUG(4, "Registering I2C bus with kernel");	return i2c_add_adapter(&ov->i2c_adap);}/*****************************************************************************//* 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 or unplugged */static intov51x_wait_frames_inactive(struct usb_ov511 *ov){	int rc;	rc = wait_event_interruptible(ov->wq, ov->curframe < 0 || !ov->present);	if (rc)		return rc;	if (ov->present)		return 0;	else		return -ENODEV;}/* Resets the hardware snapshot button */static voidov51x_clear_snapshot(struct usb_ov511 *ov){	if (ov->bclass == BCL_OV511) {		reg_w(ov, R51x_SYS_SNAP, 0x00);		reg_w(ov, R51x_SYS_SNAP, 0x02);		reg_w(ov, R51x_SYS_SNAP, 0x00);	} else if (ov->bclass == BCL_OV518) {		warn("snapshot reset not supported yet on OV518(+)");	} else {		err("clear snap: invalid bridge type");	}}#if defined(CONFIG_VIDEO_PROC_FS)/* 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 intov51x_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;}#endif/* Returns 1 if image streaming needs to be stopped while setting the specified * control, and returns 0 if not */static intsensor_needs_stop(struct usb_ov511 *ov, int cid){	if (!ov->stop_during_set)		return 0;	/* SAA7111A always maintains a stable	 * image, even when setting controls */	if (ov->sensor == SEN_SAA7111A)		return 0;	switch (cid) {	case OVCAMCHIP_CID_CONT:	case OVCAMCHIP_CID_BRIGHT:	case OVCAMCHIP_CID_SAT:	case OVCAMCHIP_CID_HUE:	case OVCAMCHIP_CID_EXP:		 return 1;	}	return 0;}static intsensor_set_control(struct usb_ov511 *ov, int cid, int val){	struct ovcamchip_control ctl;	int rc;	if (sensor_needs_stop(ov, cid))		if (ov51x_stop(ov) < 0)			return -EIO;	ctl.id = cid;	ctl.value = val;	rc = sensor_cmd(ov, OVCAMCHIP_CMD_S_CTRL, &ctl);	if (ov51x_restart(ov) < 0)		return -EIO;	return rc;}static intsensor_get_control(struct usb_ov511 *ov, int cid, int *val){	struct ovcamchip_control ctl;	int rc;	ctl.id = cid;	rc = sensor_cmd(ov, OVCAMCHIP_CMD_G_CTRL, &ctl);	if (rc >= 0)		*val = ctl.value;	return rc;}static intov511_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);			return -EINVAL;		}	} else {		err("Set packet size: Invalid bridge type");		return -EINVAL;	}	PDEBUG(3, "%d, mult=%d, alt=%d", size, mult, alt);	if (reg_w(ov, R51x_FIFO_PSIZE, mult) < 0)		return -EIO;	if (usb_set_interface(ov->dev, ov->iface, alt) < 0) {		err("Set packet size: set interface error");		return -EBUSY;	}	if (ov51x_reset(ov, OV511_RESET_NOREGS) < 0)		return -EIO;	ov->packet_size = size;	if (ov51x_restart(ov) < 0)		return -EIO;	return 0;}/* Note: Unlike the OV511/OV511+, the size argument does NOT include the * optional packet number byte. The actual size *is* stored in ov->packet_size, * though. */static intov518_set_packet_size(struct usb_ov511 *ov, int size){	int alt;	if (ov51x_stop(ov) < 0)		return -EIO;	if (ov->bclass == BCL_OV518) {		if (size == 0) alt = OV518_ALT_SIZE_0;		else if (size == 128) alt = OV518_ALT_SIZE_128;		else if (size == 256) alt = OV518_ALT_SIZE_256;		else if (size == 384) alt = OV518_ALT_SIZE_384;		else if (size == 512) alt = OV518_ALT_SIZE_512;		else if (size == 640) alt = OV518_ALT_SIZE_640;		else if (size == 768) alt = OV518_ALT_SIZE_768;		else if (size == 896) alt = OV518_ALT_SIZE_896;		else {			err("Set packet size: invalid size (%d)", size);			return -EINVAL;		}	} else {		err("Set packet size: Invalid bridge type");		return -EINVAL;	}	PDEBUG(3, "%d, alt=%d", size, alt);	ov->packet_size = size;	if (size > 0) {		/* Program ISO FIFO size reg (packet number isn't included) */		ov518_reg_w32(ov, 0x30, size, 2);		if (ov->packet_numbering)			++ov->packet_size;	}	if (usb_set_interface(ov->dev, ov->iface, alt) < 0) {		err("Set packet size: set interface error");		return -EBUSY;	}	/* Initialize the stream */	if (reg_w(ov, 0x2f, 0x80) < 0)		return -EIO;	if (ov51x_restart(ov) < 0)		return -EIO;	if (ov51x_reset(ov, OV511_RESET_NOREGS) < 0)		return -EIO;	return 0;}/* Upload compression params and quantization tables. Returns 0 for success. */static intov511_init_compression(struct usb_ov511 *ov){	int rc = 0;	if (!ov->compress_inited) {		reg_w(ov, 0x70, phy);		reg_w(ov, 0x71, phuv);		reg_w(ov, 0x72, pvy);		reg_w(ov, 0x73, pvuv);		reg_w(ov, 0x74, qhy);		reg_w(ov, 0x75, qhuv);		reg_w(ov, 0x76, qvy);		reg_w(ov, 0x77, qvuv);		if (ov511_upload_quan_tables(ov) < 0) {			err("Error uploading quantization tables");			rc = -EIO;			goto out;		}	}	ov->compress_inited = 1;out:	return rc;}/* Upload compression params and quantization tables. Returns 0 for success. */static intov518_init_compression(struct usb_ov511 *ov){	int rc = 0;	if (!ov->compress_inited) {		if (ov518_upload_quan_tables(ov) < 0) {			err("Error uploading quantization tables");			rc = -EIO;			goto out;		}	}	ov->compress_inited = 1;out:	return rc;}static intsensor_set_picture(struct usb_ov511 *ov, struct video_picture *p){	int rc;	PDEBUG(4, "sensor_set_picture");	if (ov->has_decoder) {		call_i2c_clients(ov, DECODER_SET_PICTURE, p);		return 0;	}	/* Don't return error if a setting is unsupported, or rest of settings         * will not be performed */	rc = sensor_set_control(ov, OVCAMCHIP_CID_CONT, p->contrast);	if (FATAL_ERROR(rc))		return rc;	rc = sensor_set_control(ov, OVCAMCHIP_CID_BRIGHT, p->brightness);	if (FATAL_ERROR(rc))		return rc;	rc = sensor_set_control(ov, OVCAMCHIP_CID_SAT, p->colour);	if (FATAL_ERROR(rc))		return rc;	rc = sensor_set_control(ov, OVCAMCHIP_CID_HUE, p->hue);	if (FATAL_ERROR(rc))		return rc;	return 0;}

⌨️ 快捷键说明

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