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

📄 omapcamera_sensor_if.c

📁 Linux Kernel 2.6.9 for OMAP1710
💻 C
📖 第 1 页 / 共 3 页
字号:
};const static struct ov9640_reg *	ov9640_reg_init[NUM_PIXEL_FORMATS][NUM_IMAGE_SIZES] ={ { qqcif_yuv, qqvga_yuv, qcif_yuv, qvga_yuv, cif_yuv, vga_yuv, sxga_yuv }, { qqcif_565, qqvga_565, qcif_565, qvga_565, cif_565, vga_565, sxga_565 }, { qqcif_555, qqvga_555, qcif_555, qvga_555, cif_555, vga_555, sxga_555 },};static int ov9640_read_reg(struct i2c_client *client, u8 reg, u8 *val){	int err;	struct i2c_msg msg[1];	unsigned char data[1];	if (!client->adapter)		return -ENODEV;	msg->addr = client->addr;	msg->flags = 0;	msg->len = 1;	msg->buf = data;	*data = reg;	err = i2c_transfer(client->adapter, msg, 1);	if (err >= 0) {		msg->flags = I2C_M_RD;		err = i2c_transfer(client->adapter, msg, 1);	}	if (err >= 0) {		*val = *data;		return 0;	}	return err;}/* Write a value to a register in an OV9640 sensor device. * Returns zero if successful, or non-zero otherwise. */static int ov9640_write_reg(struct i2c_client *client, u8 reg, u8 val){	int err;	struct i2c_msg msg[1];	unsigned char data[2];	if (!client->adapter)		return -ENODEV;		msg->addr = client->addr;	msg->flags = 0;	msg->len = 2;	msg->buf = data;	data[0] = reg;	data[1] = val;	err = i2c_transfer(client->adapter, msg, 1);	if (err >= 0)		return 0;	return err;}/* Initialize a list of OV9640 registers. * The list of registers is terminated by the pair of values  * { OV9640_REG_TERM, OV9640_VAL_TERM }. * Returns zero if successful, or non-zero otherwise. */static int ov9640_write_regs(struct i2c_client *client, const struct ov9640_reg reglist[]){	int err;	const struct ov9640_reg *next = reglist;		while (!((next->reg == OV9640_REG_TERM) 		&& (next->val == OV9640_VAL_TERM)))	{		err = ov9640_write_reg(client, next->reg, next->val);		udelay(100);		if (err)			return err;		next++;	}	return 0;}/* 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(enum image_size isize, unsigned long xclk, struct v4l2_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[isize];	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));}/* Configure the OV9640 for a specified image size, pixel format, and frame  * period.  xclk is the frequency (in Hz) of the xclk input to the OV9640.   * fper is the frame period (in seconds) expressed as a fraction. * Returns zero if successful, or non-zero otherwise. * The actual frame period is returned in fper. */static intov9640_configure(struct i2c_client *client, 	enum image_size isize, 	enum pixel_format pfmt,	unsigned long xclk,	struct v4l2_fract *fper){	int err;	unsigned char clkrc;	/* common register initialization */	err = ov9640_write_regs(client, ov9640_common);	if (err)		return err;	/* configure image size and pixel format */	err = ov9640_write_regs(client, ov9640_reg_init[pfmt][isize]);	if (err)		return err;	/* configure frame rate */	clkrc = ov9640_clkrc(isize, xclk, fper);	err = ov9640_write_reg(client, OV9640_CLKRC, clkrc);	if (err)		return err;	return 0;}/* Write to GPIO EXPA on the H4 board. * The GPIO expanders need an independent I2C client driver. */static intwrite_gpio_expa(u8 val, int add){	struct i2c_adapter *adap;	int err;	struct i2c_msg msg[1];	unsigned char data[1];	adap = i2c_get_adapter(0);	if (!adap)		return -ENODEV;	msg->addr = add;	/* I2C address of GPIO EXPA */	msg->flags = 0;	msg->len = 1;	msg->buf = data;	data[0] = val;	err = i2c_transfer(adap, msg, 1);	if (err >= 0)		return 0;	return err;}/* Read from GPIO EXPA on the H4 board. * The GPIO expanders need an independent I2C client driver. */static intread_gpio_expa(u8 *val, int add){	struct i2c_adapter *adap;	int err;	struct i2c_msg msg[1];	unsigned char data[1];	adap = i2c_get_adapter(0);	if (!adap)		return -ENODEV;	msg->addr = add;	/* I2C address of GPIO EXPA */	msg->flags = I2C_M_RD;	msg->len = 1;	msg->buf = data;	err = i2c_transfer(adap, msg, 1);	*val = data[0];	if (err >= 0)		return 0;	return err;}/* Power-up the OV9640 sensor on the H4 board. * Returns 0 if successful, non-zero otherwise. */static intov9640_powerup(struct omap24xxcam_device *cam){	unsigned char expa;	int err;	/* read current state of GPIO EXPA outputs */	if ((err = read_gpio_expa(&expa, 0x20))) {		printk(KERN_ERR "%s: Error reading GPIO EXPA\n", 			cam->vfd->name);		return err;	}	/* Clear GPIO EXPA P3 (CAMERA_MODULE_EN) to power-up sensor */	if ((err = write_gpio_expa(expa & ~0x08, 0x20))) {		printk(KERN_ERR "%s: Error writing to GPIO EXPA\n", 			cam->vfd->name);		return err;	}	/* read current state of GPIO EXPA outputs */	if ((err = read_gpio_expa(&expa, 0x22))) {		printk(KERN_ERR "%s: Error reading GPIO EXPA\n", 			cam->vfd->name);		return err;	}	/* Clear GPIO EXPA P3 (CAMERA_MODULE_EN) to power-up sensor */	if ((err = write_gpio_expa(expa & ~0x80, 0x22))) {		printk(KERN_ERR "%s: Error writing to GPIO EXPA\n", 			cam->vfd->name);		return err;	}	return 0;}/* Power-down the OV9640 sensor on the H4 board. * Returns 0 if successful, non-zero otherwise. */static intov9640_powerdown(struct omap24xxcam_device *cam){	unsigned char expa;	int err;	/* read current state of GPIO EXPA outputs */	if ((err = read_gpio_expa(&expa, 0x20))) {		printk(KERN_ERR "%s: Error reading GPIO EXPA\n", 			cam->vfd->name);		return err;	}	/* Set GPIO EXPA P3 (CAMERA_MODULE_EN) to power-down sensor */	if ((err = write_gpio_expa(expa | 0x08, 0x20))) {		printk(KERN_ERR "%s: Error writing to GPIO EXPA\n", 			cam->vfd->name);		return err;	}	return 0;}/* Detect if an OV9640 is present, and if so which revision.  * A device is considered to be detected if the manufacturer ID (MIDH and MIDL)  * and the product ID (PID) registers match the expected values.   * Any value of the version ID (VER) register is accepted. * Here are the version numbers we know about: *	0x48 --> OV9640 Revision 1 or OV9640 Revision 2 *	0x49 --> OV9640 Revision 3 * Returns a negative error number if no device is detected, or the  * non-negative value of the version ID register if a device is detected. */static intov9640_detect(struct ov9640_sensor *sensor){	u8 midh, midl, pid, ver;	struct i2c_client *client;	if (!sensor)		return -ENODEV;	client = &sensor->client;	if (ov9640_read_reg(client, OV9640_MIDH, &midh))		return -ENODEV;	if (ov9640_read_reg(client, OV9640_MIDL, &midl))		return -ENODEV;	if (ov9640_read_reg(client, OV9640_PID, &pid))		return -ENODEV;	if (ov9640_read_reg(client, OV9640_VER, &ver))		return -ENODEV;	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;	}	sensor->ver = ver;	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;	}

⌨️ 快捷键说明

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