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 + -
显示快捷键?