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

📄 sensor_ov9640.c

📁 Linux Kernel 2.6.9 for OMAP1710
💻 C
📖 第 1 页 / 共 3 页
字号:
	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.		 */		return -ENODEV;	}	return ver;}/* This function registers an I2C client via i2c_attach_client() for an OV9640  * sensor device.  If 'probe' is non-zero, then the I2C client is only  * registered if the device can be detected.  If 'probe' is zero, then no  * device detection is attempted and the I2C client is always registered. * Returns zero if an I2C client is successfully registered, or non-zero  * otherwise. */static int ov9640_i2c_attach_client(struct i2c_adapter *adap, int addr, int probe){	struct ov9640_sensor *sensor = &ov9640;	struct i2c_client *client = &sensor->client;	int err;	if (client->adapter)		return -EBUSY;	/* our client is already attached */	client->addr = addr;	client->flags = I2C_CLIENT_ALLOW_USE;	client->driver = &sensor->driver;	client->adapter = adap;	err = i2c_attach_client(client);	if (err) {		client->adapter = NULL;		return err;	}	if (probe) {		err = ov9640_detect(client);		if (err < 0) {			i2c_detach_client(client);			client->adapter = NULL;			return err;		}		sensor->ver = err;	}	return 0;}/* This function is called by i2c_del_adapter() and i2c_del_driver()  * if the adapter or driver with which this I2C client is associated is  * removed.  This function unregisters the client via i2c_detach_client(). * Returns zero if the client is successfully detached, or non-zero  * otherwise. */static int ov9640_i2c_detach_client(struct i2c_client *client){	int err;	if (!client->adapter)		return -ENODEV;	/* our client isn't attached */	err = i2c_detach_client(client);	client->adapter = NULL;	return err;}/* This function will be called for each registered I2C bus adapter when our  * I2C driver is registered via i2c_add_driver().  It will also be called  * whenever a new I2C adapter is registered after our I2C driver is registered. * This function probes the specified I2C bus adapter to determine if an  * OV9640 sensor device is present.  If a device is detected, an I2C client  * is registered for it via ov9640_i2c_attach_client().  Note that we can't use  * the standard i2c_probe() function to look for the sensor because the OMAP  * I2C controller doesn't support probing. * Returns zero if an OV9640 device is detected and an I2C client successfully  * registered for it, or non-zero otherwise. */static int ov9640_i2c_probe_adapter(struct i2c_adapter *adap){	return ov9640_i2c_attach_client(adap, OV9640_I2C_ADDR, 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 enum image_sizeov9640_find_size(unsigned int width, unsigned int height){	enum image_size isize;	unsigned long pixels = width*height;	for (isize = QQCIF; isize < SXGA; isize++) {		if (ov9640_sizes[isize + 1].height*			ov9640_sizes[isize + 1].width > pixels)		{			return isize;		}	}	return SXGA;}/* --------------------------------------------------------------------- * Following are sensor interface functions implemented by  * OV9640 sensor driver. They are nanmed ov9640sensor_<name> */static intov9640sensor_power_on(void *priv){	return ov9640_powerup();}static intov9640sensor_power_off(void *priv){	return ov9640_powerdown();}static intov9640sensor_query_control(struct v4l2_queryctrl *qc, void *priv){	int i;	i = find_vctrl (qc->id);	if (i == -EINVAL) {		qc->flags = V4L2_CTRL_FLAG_DISABLED;		return 0;	}	if (i < 0)		return -EINVAL;	*qc = control[i].qc;	return 0;}static intov9640sensor_get_control(struct v4l2_control *vc, void *priv){	struct ov9640_sensor *sensor = (struct ov9640_sensor *) priv;	struct i2c_client *client = &sensor->client;	int i, val;	struct vcontrol * lvc;		i = find_vctrl(vc->id);	if (i < 0)		return -EINVAL;	lvc = &control[i];		if (ov9640_read_reg_mask(client, lvc->reg, (u8 *)&val, lvc->mask))		return -EIO;			val = val >> lvc->start_bit;		if (val >= 0) {		vc->value = lvc->current_value = val;		return 0;	} else		return val;}static intov9640sensor_set_control(struct v4l2_control *vc, void *priv){	struct ov9640_sensor *sensor = (struct ov9640_sensor *) priv;	struct i2c_client *client = &sensor->client;	struct vcontrol *lvc;	int val = vc->value;	int i;	i = find_vctrl(vc->id);	if (i < 0)		return -EINVAL;	lvc = &control[i];	val = val << lvc->start_bit;	if (ov9640_write_reg_mask(client, lvc->reg, (u8 *)&val, (u8)lvc->mask))		return -EIO;	val = val>> lvc->start_bit;	if (val >= 0) {		lvc->current_value = val;		return 0;	} else		return val;}/* Implement the VIDIOC_ENUM_FMT ioctl for the CAPTURE buffer type. */static intov9640sensor_enum_pixformat(struct v4l2_fmtdesc *fmt, void *priv){	int index = fmt->index;	enum v4l2_buf_type type = fmt->type;	memset(fmt, 0, sizeof(*fmt));	fmt->index = index;	fmt->type = type;	switch (fmt->type) {		case V4L2_BUF_TYPE_VIDEO_CAPTURE:		if (index >= NUM_CAPTURE_FORMATS)			return -EINVAL;		break;		case V4L2_BUF_TYPE_VIDEO_OVERLAY:		if (index >= NUM_OVERLAY_FORMATS)			return -EINVAL;		break;		default:			return -EINVAL;	}	fmt->flags = ov9640_formats[index].flags;	strlcpy(fmt->description, ov9640_formats[index].description, sizeof(fmt->description));	fmt->pixelformat = ov9640_formats[index].pixelformat;	return 0;}/* Implement the VIDIOC_TRY_FMT ioctl for the CAPTURE buffer type.  This  * ioctl is used to negotiate the image capture size and pixel format  * without actually making it take effect. */static intov9640sensor_try_format(struct v4l2_pix_format *pix, void *priv){	enum image_size isize;	int ifmt;	isize = ov9640_find_size(pix->width, pix->height);	pix->width = ov9640_sizes[isize].width;	pix->height = ov9640_sizes[isize].height;	for (ifmt = 0; ifmt < NUM_CAPTURE_FORMATS; ifmt++) {		if (pix->pixelformat == ov9640_formats[ifmt].pixelformat)			break;	}	if (ifmt == NUM_CAPTURE_FORMATS)		ifmt = 0;	pix->pixelformat = ov9640_formats[ifmt].pixelformat;	pix->field = V4L2_FIELD_NONE;	pix->bytesperline = pix->width*2;	pix->sizeimage = pix->bytesperline*pix->height;	pix->priv = 0;	switch (pix->pixelformat) {		case V4L2_PIX_FMT_YUYV:		case V4L2_PIX_FMT_UYVY:		default:			pix->colorspace = V4L2_COLORSPACE_JPEG;			break;		case V4L2_PIX_FMT_RGB565:		case V4L2_PIX_FMT_RGB565X:		case V4L2_PIX_FMT_RGB555:		case V4L2_PIX_FMT_RGB555X:			pix->colorspace = V4L2_COLORSPACE_SRGB;			break;	}	return 0;}/* Given the image capture format in pix, the nominal frame period in  * timeperframe, calculate the required xclk frequency  * The nominal xclk input frequency of the OV9640 is 24MHz, maximum  * frequency is 48MHz, and minimum frequency is 10MHz. */static unsigned longov9640sensor_calc_xclk(struct v4l2_pix_format *pix,			struct v4l2_fract *timeperframe, void *priv){	unsigned long tgt_xclk;			/* target xclk */	unsigned long tgt_fpm;			/* target frames per minute */ 	enum image_size isize;	/* We use arbitrary rules to select the xclk frequency.  If the 	 * capture size is VGA and the frame rate is greater than 900 	 * frames per minute, or if the capture size is SXGA and the 	 * frame rate is greater than 450 frames per minutes, then the 	 * xclk frequency will be set to 48MHz.  Otherwise, the xclk 	 * frequency will be set to 24MHz.  If the mclk frequency is such that 	 * the target xclk frequency is not achievable, then xclk will be set 	 * as close as to the target as possible.	 */	if ((timeperframe->numerator == 0) 		|| (timeperframe->denominator == 0))	{		/* supply a default nominal_timeperframe of 15 fps */		timeperframe->numerator = 1;		timeperframe->denominator = 15;	}	tgt_fpm = (timeperframe->denominator*60)		/ timeperframe->numerator;	tgt_xclk = 24000000;	isize = ov9640_find_size(pix->width, pix->height);	switch (isize) {		case SXGA:			if (tgt_fpm > 450)				tgt_xclk = 48000000;			break;		case VGA:			if (tgt_fpm > 900)				tgt_xclk = 48000000;			break;		default:			break;	}	return tgt_xclk;}/* Given a capture format in pix, the frame period in timeperframe, and * the xclk frequency, set the capture format of the OV9640 sensor. * The actual frame period will be returned in timeperframe. */static intov9640sensor_configure(struct v4l2_pix_format *pix, unsigned long xclk,			struct v4l2_fract *timeperframe, void *priv){	struct ov9640_sensor *sensor = (struct ov9640_sensor *) priv;  	enum pixel_format pfmt = YUV;	switch (pix->pixelformat) {		case V4L2_PIX_FMT_RGB565:		case V4L2_PIX_FMT_RGB565X:			pfmt = RGB565;			break;		case V4L2_PIX_FMT_RGB555:		case V4L2_PIX_FMT_RGB555X:			pfmt = RGB555;			break;		case V4L2_PIX_FMT_YUYV:		case V4L2_PIX_FMT_UYVY:		default:			pfmt = YUV; 	}	return ov9640_configure(&sensor->client,				ov9640_find_size(pix->width, pix->height),				pfmt, xclk, timeperframe);}/* Prepare for the driver to exit. * Balances ov9640sensor_init(). * This function must de-initialize the sensor and its associated data  * structures. */static intov9640sensor_cleanup(void *priv){	struct ov9640_sensor *sensor = (struct ov9640_sensor *) priv;	if (sensor) {		i2c_del_driver(&sensor->driver);		ov9640_powerdown(); 	}	return 0;}/* Initialize the OV9640 sensor. * This routine allocates and initializes the data structure for the sensor,  * powers up the sensor, registers the I2C driver, and sets a default image  * capture format in pix.  The capture format is not actually programmed  * into the OV9640 sensor by this routine. * This function must return a non-NULL value to indicate that  * initialization is successful. */static void *ov9640sensor_init(struct v4l2_pix_format *pix){	struct ov9640_sensor *sensor = &ov9640;	struct i2c_driver *driver = &sensor->driver; 	int err;	memset(sensor, 0, sizeof(*sensor)); 	/* power-up the sensor */	if (ov9640_powerup())		return NULL;	driver->owner = THIS_MODULE;	strlcpy(driver->name, "OV9640 I2C driver", sizeof(driver->name));	driver->id = I2C_DRIVERID_EXP0;	driver->flags = I2C_DF_NOTIFY;	driver->attach_adapter = ov9640_i2c_probe_adapter;	driver->detach_client = ov9640_i2c_detach_client;	err = i2c_add_driver(driver);	if (err) {		printk(KERN_ERR "Failed to register OV9640 I2C client.\n");		return NULL;	}	if (!sensor->client.adapter) {		printk(KERN_WARNING 			"Failed to detect OV9640 sensor chip.\n");		return NULL;	}	else {		printk(KERN_INFO 			"OV9640 sensor chip version 0x%02x detected\n", sensor->ver);	}	/* Make the default capture format QCIF RGB565 */	pix->width = ov9640_sizes[QCIF].width;	pix->height = ov9640_sizes[QCIF].height;	pix->pixelformat = V4L2_PIX_FMT_RGB565;	ov9640sensor_try_format(pix, NULL);	return (void *)sensor;}struct camera_sensor camera_sensor_if = {	version: 	0x01,	name:		"OV9640",	init: 		ov9640sensor_init,	cleanup:	ov9640sensor_cleanup,	power_on:	ov9640sensor_power_on,	power_off:	ov9640sensor_power_off, 	enum_pixformat:	ov9640sensor_enum_pixformat,	try_format:	ov9640sensor_try_format,	calc_xclk:	ov9640sensor_calc_xclk,	configure:	ov9640sensor_configure,	query_control:	ov9640sensor_query_control, 	get_control:	ov9640sensor_get_control, 	set_control:	ov9640sensor_set_control,};void print_ov9640_regs(void *priv){	struct ov9640_sensor *sensor = (struct ov9640_sensor *) priv;	u8 reg, val;	for (reg=0x00; reg <=0x8A; reg++)		if (ov9640_read_reg(&sensor->client,reg,&val))			printk("error reading %x\n", reg);		else			printk("reg %x = %x\n", reg, val);	 }#endif	/* ifdef CAMERA_OV9640 */

⌨️ 快捷键说明

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