ov9640.c

来自「Linux Kernel 2.6.9 for OMAP1710」· C语言 代码 · 共 555 行 · 第 1/2 页

C
555
字号
	{ 0x12, 0x04 }, { 0x3C, 0x40 }, { 0x40, 0x30 },	/* COM7, COM12, COM15 */
	{ 0x04, 0x00 }, { 0x0C, 0x00 }, { 0x0D, 0x40 },	/* COM1, COM3, COM4 */
	{ 0x4F, 0x71 }, { 0x50, 0x3E }, { 0x51, 0x0C },	/* MTX1, MTX2, MTX3 */
	{ 0x52, 0x33 }, { 0x53, 0x72 }, { 0x54, 0x00 },	/* MTX4, MTX5, MTX6 */
	{ 0x55, 0x2B }, { 0x56, 0x66 }, { 0x57, 0xD2 },	/* MTX7, MTX8, MTX9 */
	{ 0x58, 0x65 }, 				/* MTXS */
	{ OV9640_REG_TERM, OV9640_VAL_TERM }
};

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 },
};

extern struct camera_serial_bus_ops camera_i2c_fops;

/* 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(const struct ov9640_reg reglist[])
{
	int err;
	const struct ov9640_reg *next = reglist;
	
	while (!((next->reg == OV9640_REG_TERM) 
		&& (next->val == OV9640_VAL_TERM)))
	{
		udelay (500);
		err = camera_i2c_fops.write (next->reg, next->val);
		/*if (err)
		{
			printk ("\nI2C write failed. Error code = 0x%x", err);
			return err;
		}*/
		next++;
	}
	return 0;
}

/* 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.
 */
int
ov9640_configure(enum image_size isize, 
	enum pixel_format pfmt,
	unsigned char clkrc)
{
	int err;

        /* common register initialization */
        err = ov9640_write_regs(ov9640_common);
        if (err) 
                return err;

	/* configure image size and pixel format */
	err = ov9640_write_regs(ov9640_reg_init[pfmt][isize]);
	if (err) 
		return err;

#if 0
	/* we set bit 7 in CLKRC to enable the digital PLL */
	clkrc = 0x85; 
#endif
	err = camera_i2c_fops.write(OV9640_CLKRC, clkrc);

	if (err)
		return err;

	return 0;
}	

int ov9640_write_mask(u8 reg, u8 value, u8 mask)
{
        unsigned char oldval, newval;
        int rc;

        if (mask == 0xff) {
                newval = value;
        } else {
		/* need to do read - modify - write */
                if ((rc = camera_i2c_fops.read(reg, &oldval)))
                        return rc;

                oldval &= (~mask);              /* Clear the masked bits */
                value &= mask;                  /* Enforce mask on value */
                newval = oldval | value;        /* Set the desired bits */
        }

	/* write the new value to the register */
        if ((rc = camera_i2c_fops.write(reg, newval)))
                return rc;

        if ((rc = camera_i2c_fops.read(reg, &newval)))
                return rc;

        return newval & mask;
}

int ov9640_read_mask(u8 reg, u8 mask)
{
        unsigned char val;
        int rc;

        if ((rc = camera_i2c_fops.read(reg, &val)))
                return rc;

        return val & mask;
}
	
	
/* 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 int
ov9640_detect(void)
{
	u8 midh, midl, pid, ver;

	if (camera_i2c_fops.read(OV9640_MIDH, &midh))
		{
		printk ("\nOV9640_MIDH");

		return -ENODEV;
		}
	if (camera_i2c_fops.read(OV9640_MIDL, &midl))
                {
                printk ("\nOV9640_MIDL");
		return -ENODEV;
		}

	if (camera_i2c_fops.read(OV9640_PID, &pid))
                {
                printk ("\nOV9640_PID");
		return -ENODEV;
		}

	if (camera_i2c_fops.read(OV9640_VER, &ver))
                {
                printk ("\nOV9640_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.
		 */
		printk ("\nMAGIC");
		return -ENODEV;
	}

	return 0;
}

#ifdef CONFIG_MACH_OMAP_H3

/* Write to GPIO EXPA on the H4 board.
 * The GPIO expanders need an independent I2C client driver.
 */
static int
write_gpio_expa(u8 val)
{
	struct i2c_adapter *adap;
	int err;
	struct i2c_msg msg[1];
	unsigned char data[1];

	adap = i2c_get_adapter(0);
	if (!adap) {
		printk(" no device found \n");
		return -ENODEV;
	}
	msg->addr = 0x27; 	/* 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 int
read_gpio_expa(u8 *val)
{
	struct i2c_adapter *adap;
	int err;
	struct i2c_msg msg[1];
	unsigned char data[1];

	adap = i2c_get_adapter(0);
	if (!adap) {	
		printk(" no device found \n");
		return -ENODEV;
	}
	msg->addr = 0x27; 	/* I2C address of GPIO EXPA */
	msg->flags = I2C_M_RD;
	msg->len = 2;
	msg->buf = data;
	err = i2c_transfer(adap, msg, 1);
	*val = data[0];
	if (err >= 0)
		return 0;
	return err;
}

static int
ov9640_powerup(void)
{
	unsigned char expa;
	int err;
	/* read the current state of GPIO EXPA output */
	if (( err = read_gpio_expa(&expa))){
		printk(" Error reading GPIO EXPA \n");
	}
	/* set GPIO EXPA P7 CAMERA_MOD_EN to power-up sensor */
        if ((err = write_gpio_expa(expa | 0x80))) {
		printk(" error writing to GPIO EXPA \n");
	}
	if (( err = read_gpio_expa(&expa))){
		printk(" Error reading GPIO EXPA \n");
	}
	return 0;
}
#endif

int ov9640_init (void)
{
	int err = 0;

#ifdef CONFIG_MACH_OMAP_H3
	/* power up the camera */
	ov9640_powerup();
#endif
	/* initialise the i2c interface */
	camera_i2c_fops.init ();
	
	/* Check whether ov9640 camera is present */
	err = ov9640_detect ();
	if (err) {
		printk ("Omnivision-9640 camera is not found\n");
		return err;
	}

        /* common register initialization */
        err = ov9640_write_regs(ov9640_common);
        if (err)
                return err;

	return 0;
}




⌨️ 快捷键说明

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