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

📄 omapcamera_sensor_if.c

📁 Linux Kernel 2.6.9 for OMAP1710
💻 C
📖 第 1 页 / 共 3 页
字号:
	if (probe) {		err = ov9640_detect(sensor);		if (err < 0) {			i2c_detach_client(client);			client->adapter = NULL;			return 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;}/* Convert a Video for Linux fourcc pixelformat to an enum pixel_format value. */static enum pixel_formatov9640_find_format(unsigned long pixelformat){	switch (pixelformat) {		case V4L2_PIX_FMT_YUYV:		case V4L2_PIX_FMT_UYVY:		default:			return YUV;		case V4L2_PIX_FMT_RGB565:		case V4L2_PIX_FMT_RGB565X:			return RGB565;		case V4L2_PIX_FMT_RGB555:		case V4L2_PIX_FMT_RGB555X:			return RGB555;	}}/* 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 voidov9640_try_fmt(struct v4l2_pix_format *pix){	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;	}}/* Given the image capture format in cam->pix, the nominal frame period in  * cam->nominal_timeperframe, and the frequency of the camera interface  * functional clock (cam->mclk), calculate the required xclk frequency  * (cam->xclk) and the actual frame period (cam->cparm.timeperframe). * xclk is obtained by dividing mclk with a divisor in the range 1 to 30. * The nominal xclk input frequency of the OV9640 is 24MHz, maximum  * frequency is 48MHz, and minimum frequency is 10MHz. */static voidomap24xxcam_sensor_timeperframe(struct omap24xxcam_device *cam){	unsigned long tgt_xclk;			/* target xclk */	unsigned long tgt_fpm;			/* target frames per minute */	unsigned long divisor;	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 ((cam->nominal_timeperframe.numerator == 0) 		|| (cam->nominal_timeperframe.denominator == 0))	{		/* supply a default nominal_timeperframe of 15 fps */		cam->nominal_timeperframe.numerator = 1;		cam->nominal_timeperframe.denominator = 15;	}	tgt_fpm = (cam->nominal_timeperframe.denominator*60)		/ cam->nominal_timeperframe.numerator;	tgt_xclk = 24000000;	isize = ov9640_find_size(cam->pix.width, cam->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;	}	if (tgt_xclk > cam->mclk)		tgt_xclk = cam->mclk;	divisor = cam->mclk/tgt_xclk;	if (tgt_xclk*divisor < cam->mclk)		divisor += 1;	if (divisor > 30)		divisor = 30;	cam->xclk = cam->mclk/divisor;	cam->cparm.timeperframe = cam->nominal_timeperframe;	ov9640_clkrc(isize, cam->xclk, &cam->cparm.timeperframe);}/* Given a capture format in cam->pix, the frame period in  * cam->cparm.timeperframe, and the xclk frequency in cam->xclk, set the  * capture format of the OV9640 sensor.  The actual frame period will be  * returned in cam->cparm.timeperframe. */static intcamera_sensor_configure(struct omap24xxcam_device *cam){	struct ov9640_sensor *sensor = (struct ov9640_sensor *) cam->sensor;	struct i2c_client *client = &sensor->client;	enum image_size isize;	enum pixel_format pfmt;	int err;	isize = ov9640_find_size(cam->pix.width, cam->pix.height);	pfmt = ov9640_find_format(cam->pix.pixelformat);		err = ov9640_configure(client, isize, pfmt, cam->xclk, 		&cam->cparm.timeperframe);	return err;}/* Implement sensor-specific ioctls.  For any ioctls we don't handle here we  * return -ENOIOCTLCMD, which indicates that the generic camera interface ioctl  * routine should provide a default handler. */static intomap24xxcam_sensor_ioctl(struct omap24xxcam_fh *fh, unsigned long cmd, void *arg){	switch (cmd) {		case VIDIOC_ENUM_FMT:		{			struct v4l2_fmtdesc *fmt = (struct v4l2_fmtdesc *) arg;			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;		}		case VIDIOC_TRY_FMT:		{			struct v4l2_format *f = (struct v4l2_format *) arg;			switch (f->type) {				case V4L2_BUF_TYPE_VIDEO_CAPTURE:					ov9640_try_fmt(&f->fmt.pix);					break;				default:					/* Let the camera interface ioctl 					 * handler deal with all other cases.					 */					return -ENOIOCTLCMD;			}			return 0;		}		default:			return -ENOIOCTLCMD;	}}/* Prepare for the driver to exit. * Balances omap24xxcam_sensor_init(). * This function must set cam->sensor to NULL to indicate that the sensor  * and its associated data structures have been de-initialized. */static voidomap24xxcam_sensor_exit(struct omap24xxcam_device *cam){	struct ov9640_sensor *sensor = (struct ov9640_sensor *) cam->sensor;	if (sensor) {#ifndef CONFIG_OMAP24XX_VIRTIO		ov9640_powerdown(cam);#endif		cam->sensor = NULL;	}}/* 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 cam->pix.  The capture format is not actually programmed  * into the OV9640 sensor by this routine. * This function must set cam->sensor to a non-NULL value to indicate that  * initialization is successful.  cam->sensor must be set to NULL to indicate  * failure. */static voidcamera_sensor_init(struct omap24xxcam_device *cam){	struct ov9640_sensor *sensor = &ov9640;	struct i2c_driver *driver = &sensor->driver;	struct v4l2_pix_format *pix = &cam->pix;	int err;	memset(sensor, 0, sizeof(*sensor));	/* power-up the sensor */#ifndef CONFIG_OMAP24XX_VIRTIO	ov9640_powerup(cam);#endif	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 "%s: Failed to register OV9640 I2C client.\n", 			cam->vfd->name);		return;	}	if (!sensor->client.adapter) {		printk(KERN_WARNING 			"%s: Failed to detect OV9640 sensor chip.\n",			cam->vfd->name);	}	else {		printk(KERN_INFO 			"%s: OV9640 sensor chip version 0x%02x detected\n", 			cam->vfd->name, 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;	ov9640_try_fmt(pix);	cam->sensor = sensor;}struct camera_sensor camera_sensor_if = {	version : 0x01,	init: camera_sensor_init,	timeperframe: omap24xxcam_sensor_timeperframe,	configure: camera_sensor_configure,	exit : omap24xxcam_sensor_exit, 	try_format: ov9640_try_fmt,	ioctl: omap24xxcam_sensor_ioctl,	power_on: ov9640_powerup,	power_off: ov9640_powerdown,	};#endif	/* ifdef CAMERA_OV9640 */

⌨️ 快捷键说明

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