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

📄 camera_ov6x30.c

📁 pxa270下的摄像头mtd91111的驱动
💻 C
📖 第 1 页 / 共 2 页
字号:
	};	if (qm->id == V4L2_CID_EXPOSURE) {		if (qm->index < 0 ||		    qm->index >= sizeof(expo_menu)/sizeof(char *))			return -EINVAL;		memcpy(qm->name, expo_menu[qm->index], sizeof(qm->name));		return 0;	}#else	// No menu controls have been defined	return -EINVAL;#endif}static intov6x30_query_control(struct v4l2_queryctrl *qc){	int i;	i = find_vctrl(qc->id);	if (i == -EINVAL) {		qc->flags = V4L2_CTRL_FLAG_DISABLED;		return 0;	}	if (i < 0)		return -EINVAL;	/*  V4L2 filled in category and group, preserve them */	control[i].qc.category = qc->category;	memcpy(control[i].qc.group, qc->group, sizeof(qc->group));	*qc = control[i].qc;	return 0;}static int ov6x30_write_control(struct vcontrol * lvc, u8 value){	struct camera_serial_bus * sbus = this->camif->sbus;	u8 oldval, newval;	u8 reg = lvc->reg;	u8 mask = lvc->mask;	int rc;		value <<= lvc->start_bit;	if (mask == 0xff) {		newval = value;	} else {		if ((rc = sbus->read(reg, &oldval, 1)))			return rc;				oldval &= ~mask;              /* Clear the masked bits */		value &= mask;                /* Enforce mask on value */		newval = oldval | value;      /* Set the desired bits */	}		if ((rc = sbus->write(reg, &newval, 1)))		return rc;	if ((rc = sbus->read(reg, &newval, 1)))		return rc;	return (newval & mask) >> lvc->start_bit;}static int ov6x30_read_control(struct vcontrol * lvc){	struct camera_serial_bus * sbus = this->camif->sbus;	u8 val;	u8 reg = lvc->reg;	u8 mask = lvc->mask;	int rc;		if ((rc = sbus->read(reg, &val, 1)))		return rc;	return (val & mask) >> lvc->start_bit;}static intov6x30_control(struct v4l2_control *vc, int write){	int i, val;	struct vcontrol * lvc;		i = find_vctrl(vc->id);	if (i < 0)		return -EINVAL;	lvc = &control[i];		if (write)		val = ov6x30_write_control(lvc, vc->value);	else		val = ov6x30_read_control(lvc);		if (val >= 0) {		vc->value = lvc->current_value = val;		return 0;	} else		return val;}static intov6x30_set_control(struct v4l2_control *vc){	return ov6x30_control(vc, 1);}static intov6x30_get_control(struct v4l2_control *vc){	return ov6x30_control(vc, 0);}static intov6x30_restore_current_controls(void){	struct v4l2_control vc;	int i, rc=0;		for (i=0; i<NUM_CONTROLS; i++) {		vc.id = control[i].qc.id;		vc.value = control[i].current_value;		if ((rc = ov6x30_set_control(&vc)))			break;	}	return rc;}static intov6x30_save_current_controls(void){	struct v4l2_control vc;	int i, rc=0;		for (i=0; i<NUM_CONTROLS; i++) {		vc.id = control[i].qc.id;		if ((rc = ov6x30_get_control(&vc)))			break;	}	return rc;}#define MIN_FP_24MHZ  245820 // 40.68 fps#define MIN_FP_12MHZ  492410 // 20.31 fps#define MAX_FP_24MHZ  512560 // 19.51 fps#define MAX_FP_12MHZ 1022890 //  9.78 fps#define MIN_FP 250000 // 40 fps#define MAX_FR 40#define MAX_FP 666667 // 15 fps#define MIN_FR 15/* starts at MAX_FP, increments by 0.2 sec (5 Hz) */static struct {	int exclk; // MHz	int regval;} fp_tbl[6] = {	{ 12000000, 165 }, // 15 fps	{ 12000000,   7 }, // 20 fps	{ 24000000, 295 }, // 25 fps	{ 24000000, 167 }, // 30 fps	{ 24000000,  77 }, // 35 fps	{ 24000000,   8 }  // 40 fps};static int ov6x30_set_fp(int fp, int xclk, int test){	int ret;	unsigned int fr_x100, i;		ENTRY();	if (fp < MIN_FP || fp > MAX_FP) {		err("fp out of range: %d\n", fp);		return -EINVAL;	}	if (fp == 333667)		fr_x100 = 30 * 100;	else		fr_x100 = (1000000000 + fp/2) / fp; // desired framerate * 100	if (fr_x100 % 500) {		err("fp must be in intervals of 0.2 sec (5 Hz): %d\n", fp);		return -EINVAL;	}	i = (fr_x100 - MIN_FR*100) / 500;	if (xclk != fp_tbl[i].exclk) {		err("need %d MHz XCLK for fp %d\n", fp_tbl[i].exclk, fp);		return -EINVAL;	}	if (!test) {		struct camera_serial_bus * sbus = this->camif->sbus;		unsigned int regval = fp_tbl[i].regval;				ret = sbus->write_verify(0x2a,					 0x84 | ((regval & (1<<8))?(1<<5):0));		if (ret < 0)			return ret;				ret = sbus->write_verify(0x2b, regval & ~(1<<8));		if (ret < 0)			return ret;				current_frame_period = fp;		current_xclk = xclk;	}	return fp;}static int ov6x30_get_fp(void){	return current_frame_period;}static int ov6x30_set_mode(void){#if 0	int H_start,H_end;	int V_start,V_end;	int width = omap_image_size[this->imgfmt].width;	int height = omap_image_size[this->imgfmt].height;#endif	struct camera_serial_bus * sbus = this->camif->sbus;	int qcif = (this->imgfmt == QCIF);	int ret = 0;	u8 reg14;		if ((ret = sbus->read(0x14, &reg14, 1)))		return ret;	if (qcif)		reg14 |= 0x20;	else		reg14 &= ~0x20;	if ((ret = sbus->write_verify(0x2b, reg14)) < 0)		return ret;#if 0       // FIXME: fix this       // Calculate a centered image within the full CCD grid.	H_start = ((MAXWIDTH - width)/4) + HORZCONST;	H_end = H_start + (width/2);	if (H_start < HORZCONST) {		H_start = HORZCONST; // keep within bounds.		H_end = MAXWIDTH/2;	}		V_start = ((MAXHEIGHT - height)/4) + VERTCONST;	V_end = V_start + (height/2);		if (V_start < VERTCONST) {  // keep within bounds.		V_start = VERTCONST;		V_end = MAXHEIGHT/2;	}	ret = sbus->write_verify(0x17, (u8)H_start);	ret = sbus->write_verify(0x18, (u8)H_end);	ret = sbus->write_verify(0x19, (u8)V_start);	ret = sbus->write_verify(0x1A, (u8)V_end);#endif	return ret;}/* * This camera only supports RGB565 pixel format, but it can * convert to any of the following V4L2 pixel formats. */static intov6x30_find_format(struct v4l2_pix_format* fmt){	switch (fmt->pixelformat) {	case V4L2_PIX_FMT_RGB565:	case V4L2_PIX_FMT_RGB565X:	case V4L2_PIX_FMT_BGR24:		return RGB565;	}	return -1;}// **************************// Routine:// Description://   This the setup that must occur to adjust the//   reg settings as per any new VIDIOC_S_FMT command//   the client may have just performed to the driver.// **************************static int ov6x30_setup(struct v4l2_pix_format* fmt){	enum pixel_format pixfmt;	enum image_format imgfmt;	if ((pixfmt = ov6x30_find_format(fmt)) < 0)		return -EINVAL;	if (fmt->width >= omap_image_size[CIF].width) {		imgfmt = CIF;	} else {		imgfmt = QCIF;	}	fmt->width = omap_image_size[imgfmt].width;	fmt->height = omap_image_size[imgfmt].height;	this->imgfmt = imgfmt;	this->pixfmt = pixfmt;		return ov6x30_set_mode();}static int ov6x30_open(void){	struct camera_serial_bus * sbus = this->camif->sbus;	int i, rc;	for (i=0; i < INIT_REGTBL_SIZE; i++) {		if (init_regtbl[i].no_verify)			sbus->write(init_regtbl[i].reg,				    &init_regtbl[i].val, 1);		else			sbus->write_verify(init_regtbl[i].reg,					   init_regtbl[i].val);				}	if ((rc = ov6x30_set_fp(current_frame_period, current_xclk, 0)) < 0) {		err("failed to set frame period\n");		return rc;	}	if ((rc = ov6x30_set_mode()))		return rc;	return ov6x30_restore_current_controls();}static int ov6x30_close(void){	/*	 * save the current controls so they can be restored on	 * next open.	 */	return ov6x30_save_current_controls();}static int ov6x30_init(void){	int i;	for (i=0; i<NUM_CONTROLS; i++)		control[i].current_value = control[i].qc.default_value;		this->imgfmt = QCIF;	this->pixfmt = RGB565;	return 0;}static void ov6x30_cleanup(void){	// nothing to do}static int ov6x30_detect(void){	struct camera_serial_bus * sbus;	this = &camera_ov6x30;	sbus = this->camif->sbus;		sbus->set_devid(CAMERA_OV6630_DEV_ID);	// Just an arbitrary OmniVision camera command	return sbus->write_verify(0x11, 0x40);}struct camera camera_ov6x30 = {	imgfmt: QCIF,	pixfmt: RGB565,		detect:  ov6x30_detect,	init:    ov6x30_init,	cleanup: ov6x30_cleanup,	open:    ov6x30_open,	close:   ov6x30_close,	set_format:   ov6x30_setup,	set_frame_period: ov6x30_set_fp,	get_frame_period: ov6x30_get_fp,		convert_image: ov6x30_convert_image,	query_control: ov6x30_query_control,	get_control:   ov6x30_get_control,	set_control:   ov6x30_set_control,	query_menu:    ov6x30_querymenu,};

⌨️ 快捷键说明

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