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

📄 camera_ov9640.c

📁 pxa270下的摄像头mtd91111的驱动
💻 C
📖 第 1 页 / 共 2 页
字号:
		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 ov9640_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 intov9640_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 = ov9640_write_control(lvc, vc->value);	else		val = ov9640_read_control(lvc);		if (val >= 0) {		vc->value = lvc->current_value = val;		return 0;	} else		return val;}static intov9640_set_control(struct v4l2_control *vc){	return ov9640_control(vc, 1);}static intov9640_get_control(struct v4l2_control *vc){	return ov9640_control(vc, 0);}static intov9640_restore_default_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].qc.default_value;		if ((rc = ov9640_set_control(&vc)))			break;	}	return rc;}struct fract {	unsigned long numerator;	unsigned long denominator;};	/* Calculate the internal clock divisor (value of the CLKRC register) of the  * OV9640 given the image size, the frequency (in Hz) of its XCLK input and a  * desired frame period (in seconds).  The frame period 'fper' is expressed as  * a fraction.  The frame period is an input/output parameter. * Returns the value of the OV9640 CLKRC register that will yield the frame  * period returned in 'fper' at the specified xclk frequency.  The  * returned period will be as close to the requested period as possible. */static unsigned charov9640_clkrc(unsigned long xclk, struct fract *fper){	unsigned long fpm, fpm_max;	/* frames per minute */	unsigned long divisor;	const unsigned long divisor_max = 64;	const static unsigned long clks_per_frame[] = 		{ 200000, 400000, 200000, 400000, 400000, 800000, 3200000 };	/*         QQCIF   QQVGA    QCIF    QVGA     CIF     VGA     SXGA	 *actually 199680,400000, 199680, 400000, 399360, 800000, 3200000	 */ 	if (fper->numerator > 0)		fpm = (fper->denominator*60)/fper->numerator;	else		fpm = 0xffffffff;	fpm_max = (xclk*60)/clks_per_frame[this->imgfmt];	if (fpm_max == 0)		fpm_max = 1;	if (fpm > fpm_max)		fpm = fpm_max;	if (fpm == 0)		fpm = 1;	divisor = fpm_max/fpm;	if (divisor > divisor_max)		divisor = divisor_max;	fper->numerator = divisor*60;	fper->denominator = fpm_max;	/* try to reduce the fraction */	while (!(fper->denominator % 5) && !(fper->numerator % 5)) {		fper->numerator /= 5;		fper->denominator /= 5;	}	while (!(fper->denominator % 3) && !(fper->numerator % 3)) {		fper->numerator /= 3;		fper->denominator /= 3;	}	while (!(fper->denominator % 2) && !(fper->numerator % 2)) {		fper->numerator /= 2;		fper->denominator /= 2;	}	if (fper->numerator < fper->denominator) {		if (!(fper->denominator % fper->numerator)) {			fper->denominator /= fper->numerator;			fper->numerator = 1;		}	}	else {		if (!(fper->numerator % fper->denominator)) {			fper->numerator /= fper->denominator;			fper->denominator = 1;		}	}	/* we set bit 7 in CLKRC to enable the digital PLL */	return (0x80 | (divisor - 1));}static inline void cvt_fp_to_fract(struct fract * fper, int fp){	fper->numerator = fp;	fper->denominator = 10000000;}static inline int cvt_fract_to_fp(struct fract * fper){	return (fper->numerator * 10000000) / fper->denominator;}static int ov9640_set_fp(int fp, int xclk, int test){	struct camera_serial_bus * sbus = this->camif->sbus;	struct fract fper;	int retfp;	u8 clkrc;		cvt_fp_to_fract(&fper, fp);	/* configure frame rate */	clkrc = ov9640_clkrc(xclk, &fper);	retfp = cvt_fract_to_fp(&fper);	if (!test) {		int err = sbus->write(OV9640_CLKRC, &clkrc, 1);		if (err)			return err;		current_frame_period = retfp;		current_xclk = xclk;	}	return retfp;}static int ov9640_get_fp(void){	return current_frame_period;}/* * Configure the OV9640 for the current image size, pixel format, and * frame rate. Returns zero if successful, or non-zero otherwise. */static inline intov9640_configure(void){	int err;	/* common register initialization */	err = ov_write_reglist(ov9640_common);	if (err)		return err;	/* configure image size and pixel format */	err = ov_write_reglist(ov9640_reg_init[this->pixfmt][this->imgfmt]);	if (err)		return err;	/* restore the current controls */	err = ov9640_restore_default_controls();	if (err)		return err;	/*	 * and finally set the internal clock to generate the	 * current frame rate for this image format	 */	err = ov9640_set_fp(current_frame_period, current_xclk, 0);	if (err < 0)		return err;	return 0;}/* Convert a Video for Linux pixelformat to an enum pixel_format value. */static intov9640_find_format(struct v4l2_pix_format* fmt){	switch (fmt->pixelformat) {	case V4L2_PIX_FMT_YUYV:	case V4L2_PIX_FMT_UYVY:		return YUV;	case V4L2_PIX_FMT_RGB565:	case V4L2_PIX_FMT_RGB565X:	case V4L2_PIX_FMT_BGR24: /* will have to convert to BGR24 */		return RGB565;	case V4L2_PIX_FMT_RGB555:	case V4L2_PIX_FMT_RGB555X:		return RGB555;	}	return -1;}/* * Find the best match for a requested image capture size.  The best match * is chosen as the nearest match that has the same number or fewer pixels * as the requested size, or the smallest image size if the requested size * has fewer pixels than the smallest image. */static intov9640_find_size(struct v4l2_pix_format* fmt){        int isize;        for (isize = QQCIF; isize < SXGA; isize++) {                if ((mx2ads_image_size[isize].height >= fmt->height) &&		    (mx2ads_image_size[isize].width >= fmt->width)) {			fmt->width = mx2ads_image_size[isize].width;			fmt->height = mx2ads_image_size[isize].height;                        return isize;                }        }	fmt->width = mx2ads_image_size[SXGA].width;	fmt->height = mx2ads_image_size[SXGA].height;        return SXGA;}static int ov9640_setup(struct v4l2_pix_format* fmt){	enum pixel_format pixfmt;	enum image_format imgfmt;	if ((pixfmt = ov9640_find_format(fmt)) < 0)		return -EINVAL;		imgfmt = ov9640_find_size(fmt);	this->imgfmt = imgfmt;	this->pixfmt = pixfmt;	/* configure image size and pixel format */	return ov_write_reglist(ov9640_reg_init[this->pixfmt][this->imgfmt]);}static int ov9640_open(void){	uint16_t reg_val;        /*         * Make standby low (disable standby)         */	CSI_REG_READ(EXP_IO, reg_val);	reg_val &= ~EXP_IO_CSI_CTL0;	CSI_REG_WRITE(EXP_IO, reg_val);	udelay(20);	return 0;}static int ov9640_close(void){	uint16_t reg_val;        /*         * Make standby high (enable standby)         */	CSI_REG_READ(EXP_IO, reg_val);	reg_val |= EXP_IO_CSI_CTL0;	CSI_REG_WRITE(EXP_IO, reg_val);	udelay(20);	return 0;}static int ov9640_init(void){	int i;	for (i=0; i<NUM_CONTROLS; i++)		control[i].current_value = control[i].qc.default_value;		this->imgfmt = QVGA;	this->pixfmt = RGB565;	ov9640_configure();	ov9640_close();	return 0;}static void ov9640_cleanup(void){	ov9640_close();	this->camif->sbus->cleanup();}static int ov9640_detect(void){	struct camera_serial_bus * sbus;	u8 midh, midl, pid, ver;	int rc;		this = &camera_ov9640;	sbus = this->camif->sbus;		sbus->set_devid(CAMERA_OV9640_DEV_ID);	/*	 * Special MDS register (controls CNTL and LEDs)	 */        uint16_t reg_val;        CSI_REG_READ(EXP_IO, reg_val);        /*         * Make standby low (disable standby)         */        reg_val &= ~EXP_IO_CSI_CTL0;        CSI_REG_WRITE(EXP_IO, reg_val);        udelay(20);        /*         * Make reset high (reset sensor)         */        reg_val |= EXP_IO_CSI_CTL1;        CSI_REG_WRITE(EXP_IO, reg_val);        udelay(200);        /*         * Make reset low         */        reg_val &= ~EXP_IO_CSI_CTL1;        CSI_REG_WRITE(EXP_IO, reg_val);        mdelay(15);	if ((rc = sbus->init()) < 0) {		ov9640_cleanup();		return rc;	}	if ((rc = sbus->read(OV9640_MIDH, &midh, 1))) {		ov9640_cleanup();		return rc;	}	if ((rc = sbus->read(OV9640_MIDL, &midl, 1))) {		ov9640_cleanup();		return rc;	}	if ((rc = sbus->read(OV9640_PID, &pid, 1))) {		ov9640_cleanup();		return rc;	}	if ((rc = sbus->read(OV9640_VER, &ver, 1))) {		ov9640_cleanup();		return rc;	}	if ((midh != OV9640_MIDH_MAGIC) 		|| (midl != OV9640_MIDL_MAGIC)		|| (pid != OV9640_PID_MAGIC))	{		/* We didn't read the values we expected, so 		 * this must not be an OV9640.		 */		ov9640_cleanup();		return -ENODEV;	}	return 0;}struct camera camera_ov9640 = {	imgfmt: QVGA,	pixfmt: RGB565,		detect:  ov9640_detect,	init:    ov9640_init,	cleanup: ov9640_cleanup,	open:    ov9640_open,	close:   ov9640_close,	set_format:   ov9640_setup,	set_frame_period: ov9640_set_fp,	get_frame_period: ov9640_get_fp,		query_control: ov9640_query_control,	get_control:   ov9640_get_control,	set_control:   ov9640_set_control,	query_menu:    ov9640_querymenu,};

⌨️ 快捷键说明

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