📄 ov9653.c
字号:
/* extdrv/peripheral/dc/ov9653.c
*
*
* Copyright (c) 2006 Hisilicon Co., Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program.
*
*
* History:
* 04-Apr-2006 create this file
*
*/
#include <linux/string.h>
#include <linux/slab.h>
#include <linux/module.h>
#include <linux/config.h>
#include <linux/errno.h>
#include <linux/miscdevice.h>
#include <linux/fcntl.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/proc_fs.h>
#include <linux/workqueue.h>
#include <asm/uaccess.h>
#include <asm/system.h>
#include <asm/io.h>
#include "ov9653.h"
#include "gpio_i2c.h"
/* ov9653 i2c slaver address micro-definition. */
#define I2C_OV9653 0x60
#define DC_COM1 0x4
#define DC_COM2 0x9
#define DC_CLKRC 0x11
#define DC_COM7 0x12
#define DC_COM10 0x15
#define DC_MVFP 0x1E
#define DC_COM11 0x3B
#define DC_COM15 0x40
#define DC_PID 0x0A
#define DC_VER 0x0B
static int out_mode = 0;
/*
* ov9653's output format set routine.
*
* @param mode: ov9653's output format
*
* @return value:0-- set success; 1-- set error.
*
*/
static unsigned int dc_mode_set(dc_output_set mode)
{
switch(mode)
{
case DC_MODE_CCIR656:
gpio_i2c_write(I2C_OV9653, DC_COM1, 0x40);
break;
case DC_MODE_VGA:
gpio_i2c_write(I2C_OV9653, DC_COM7, 0x40);
break;
case DC_MODE_CIF:
gpio_i2c_write(I2C_OV9653, DC_COM7, 0x20);
break;
case DC_MODE_QVGA:
gpio_i2c_write(I2C_OV9653, DC_COM7, 0x10);
break;
case DC_MODE_QCIF:
gpio_i2c_write(I2C_OV9653, DC_COM7, 0x08);
break;
case DC_MODE_QQVGA:
gpio_i2c_write(I2C_OV9653, DC_COM7, 0x10);
gpio_i2c_write(I2C_OV9653, DC_COM1, 0x20);
break;
case DC_MODE_QQCIF:
gpio_i2c_write(I2C_OV9653, DC_COM7, 0x08);
gpio_i2c_write(I2C_OV9653, DC_COM1, 0x20);
break;
case DC_MODE_RGB:
gpio_i2c_write(I2C_OV9653, DC_COM7, 0x04);
gpio_i2c_write(I2C_OV9653, DC_COM15, 0x00);
break;
case DC_MODE_RGB565:
gpio_i2c_write(I2C_OV9653, DC_COM7, 0x04);
gpio_i2c_write(I2C_OV9653, DC_COM15, 0x10);
break;
case DC_MODE_RGB555:
gpio_i2c_write(I2C_OV9653, DC_COM7, 0x04);
gpio_i2c_write(I2C_OV9653, DC_COM15, 0x30);
break;
case DC_MODE_RGBRAW:
gpio_i2c_write(I2C_OV9653, DC_COM7, 0x05);
break;
default:
return 1;
}
return 0;
}
/*
* ov9653's output format get routine.
*
* @return value: mode of ov9653's output format
*
*/
static unsigned int dc_mode_get(void)
{
unsigned int regvalue,regvalue1,reg_mode = DC_MODE_CCIR656;
regvalue = gpio_sccb_read(I2C_OV9653, DC_COM1);
if((regvalue & 0x40) == 0x40)
{
reg_mode = DC_MODE_CCIR656;
return reg_mode;
}
regvalue = gpio_sccb_read(I2C_OV9653, DC_COM7);
if((regvalue & 0x40) == 0x40)
{
reg_mode = DC_MODE_VGA;
return reg_mode;
}
else if((regvalue & 0x20) == 0x20)
{
reg_mode = DC_MODE_CIF;
return reg_mode;
}
else if((regvalue & 0x10) == 0x10)
{
reg_mode = DC_MODE_QVGA;
return reg_mode;
}
else if((regvalue & 0x08) == 0x08)
{
reg_mode = DC_MODE_QCIF;
return reg_mode;
}
else if((regvalue & 0x05) == 0x05)
{
reg_mode = DC_MODE_RGBRAW;
return reg_mode;
}
else if(regvalue == 0x0)
{
reg_mode = DC_MODE_SXGA;
return reg_mode;
}
regvalue1 = gpio_sccb_read(I2C_OV9653, DC_COM1);
if(((regvalue & 0x10) == 0x10) && ((regvalue1 & 0x20) == 0x20))
{
reg_mode = DC_MODE_QQVGA;
return reg_mode;
}
else if(((regvalue & 0x08) == 0x08) && ((regvalue1 & 0x20) == 0x20))
{
reg_mode = DC_MODE_QQCIF;
return reg_mode;
}
regvalue1 = gpio_sccb_read(I2C_OV9653, DC_COM15);
if(((regvalue & 0x04) == 0x04) && (regvalue1 == 0x00))
{
reg_mode = DC_MODE_RGB;
return reg_mode;
}
else if(((regvalue & 0x04) == 0x04) && ((regvalue1 & 0x10) == 0x10))
{
reg_mode = DC_MODE_RGB565;
return reg_mode;
}
else if(((regvalue & 0x04) == 0x04) && ((regvalue1 & 0x30) == 0x30))
{
reg_mode = DC_MODE_RGB555;
return reg_mode;
}
return reg_mode;
}
/*
* ov9653's output drive capability set routine.
*
* @param zoom: ov9653's output drive capability value
*
* @return value:0-- set success; 1-- set error.
*
*/
static unsigned int dc_zoom_set(dc_output_zoom zoom)
{
switch(zoom)
{
case DC_ZOOM_1X:
gpio_i2c_write(I2C_OV9653, DC_COM2, 0x0);
break;
case DC_ZOOM_2X:
gpio_i2c_write(I2C_OV9653, DC_COM2, 0x1);
break;
case DC_ZOOM_4X:
gpio_i2c_write(I2C_OV9653, DC_COM2, 0x3);
break;
default:
return 1;
}
return 0;
}
/*
* ov9653's output drive capability get routine.
*
* @return value: ov9653's output drive capability value
*
*/
static unsigned int dc_zoom_get(void)
{
unsigned int regvalue,reg_zoom = DC_ZOOM_1X;
regvalue = gpio_sccb_read(I2C_OV9653, DC_COM2);
if(regvalue == 0)
{
reg_zoom = DC_ZOOM_1X;
}
else if((regvalue & 0x01) == 0x01)
{
reg_zoom = DC_ZOOM_2X;
}
else if((regvalue & 0x03) == 0x03)
{
reg_zoom = DC_ZOOM_4X;
}
return reg_zoom;
}
/*
* ov9653's mirror image set routine.
*
* @param mirror: ov9653's mirror image enable or disable
*
* @return value:0-- set success; 1-- set error.
*
*/
static unsigned int dc_mirror_set(dc_output_mirror mirror)
{
switch(mirror)
{
case DC_MIRROR_DISABLE:
gpio_i2c_write(I2C_OV9653, DC_MVFP, 0x0);
break;
case DC_MIRROR_ENABLE:
gpio_i2c_write(I2C_OV9653, DC_MVFP, 0x20);
break;
default:
return 1;
}
return 0;
}
/*
* ov9653's mirror image get routine.
*
* @return value: ov9653's mirror image enable or disable
*
*/
static unsigned int dc_mirror_get(void)
{
unsigned int regvalue,reg_mirror = DC_MIRROR_DISABLE;
regvalue = gpio_sccb_read(I2C_OV9653, DC_MVFP);
if(regvalue == 0)
{
reg_mirror = DC_MIRROR_DISABLE;
}
else if((regvalue & 0x20) == 0x20)
{
reg_mirror = DC_MIRROR_ENABLE;
}
return reg_mirror;
}
/*
* ov9653's night mode set routine.
*
* @param nightmode: ov9653's night mode value
*
* @return value:0-- set success; 1-- set error.
*
*/
static unsigned int dc_nightmode_set(dc_output_nightmode nightmode)
{
switch(nightmode)
{
case DC_NIGHTMODE_DISABLE:
gpio_i2c_write(I2C_OV9653, DC_COM11, 0x00);
break;
case DC_NIGHTMODE_NORMAL:
gpio_i2c_write(I2C_OV9653, DC_COM11, 0x80);
break;
case DC_NIGHTMODE_HALFFRAME:
gpio_i2c_write(I2C_OV9653, DC_COM11, 0xa0);
break;
case DC_NIGHTMODE_QUARTFRAME:
gpio_i2c_write(I2C_OV9653, DC_COM11, 0xc0);
break;
case DC_NIGHTMODE_OCTFRAME:
gpio_i2c_write(I2C_OV9653, DC_COM11, 0xe0);
break;
default:
return 1;
}
return 0;
}
/*
* ov9653's night mode get routine.
*
* @return value: ov9653's night mode
*
*/
static unsigned int dc_nightmode_get(void)
{
unsigned int regvalue,reg_nightmode = DC_NIGHTMODE_DISABLE;
regvalue = gpio_sccb_read(I2C_OV9653, DC_COM11);
if(regvalue == 0)
{
reg_nightmode = DC_NIGHTMODE_DISABLE;
}
else if((regvalue & 0x80) == 0x80)
{
reg_nightmode = DC_NIGHTMODE_NORMAL;
}
else if((regvalue & 0xa0) == 0xa0)
{
reg_nightmode = DC_NIGHTMODE_HALFFRAME;
}
else if((regvalue & 0xc0) == 0xc0)
{
reg_nightmode = DC_NIGHTMODE_QUARTFRAME;
}
else if((regvalue & 0xe0) == 0xe0)
{
reg_nightmode = DC_NIGHTMODE_OCTFRAME;
}
return reg_nightmode;
}
/*
* ov9653's sync set routine.
*
* @param href_or_hsync: set pin definition
* @param pclk_mode: PCLK output option
* @param pclk_reverse: PCLK reverse
* @param href_reverse: HREF reserse
* @param vsync_neg: VSYNC negative
* @param hsync_neg: HSYNC negative
*
* @return value:0-- set success; 1-- set error.
*
*/
static unsigned int dc_syncset
(
dc_horizontal_mode href_or_hsync,
dc_pclk_mode pclk_mode,
dc_pclk_rev pclk_reverse,
dc_href_rev href_reverse,
dc_vsync_neg vsync_neg,
dc_hsync_neg hsync_neg
)
{
unsigned char reg = 0;
if(href_or_hsync == DC_HSYNC)
reg |= 0x40;
else if(href_or_hsync == DC_HREF)
reg |= 0x00;
else
return 1;
if(pclk_mode == DC_PCLK_DISABLE)
reg |= 0x20;
else if(pclk_mode == DC_PCLK_ENABLE)
reg |= 0x00;
else
return 1;
if(pclk_reverse == DC_PCLK_REVERSE)
reg |= 0x10;
else if(pclk_reverse == DC_PCLK_NORMAL)
reg |= 0x00;
else
return 1;
if(href_reverse == DC_HREF_REVERSE)
reg |= 0x08;
else if(href_reverse == DC_HREF_NORMAL)
reg |= 0x00;
else
return 1;
if(vsync_neg == DC_VSYNC_NEGATIVE)
reg |= 0x02;
else if(vsync_neg == DC_VSYNC_NORMAL)
reg |= 0x00;
else
return 1;
if(hsync_neg == DC_HSYNC_NEGATIVE)
reg |= 0x01;
else if(hsync_neg == DC_HSYNC_NORMAL)
reg |= 0x00;
else
return 1;
gpio_i2c_write(I2C_OV9653, DC_COM10, reg);
return 0;
}
/*
* ov9653's sync get routine.
*
* @return value: ov9653's sync value
*
*/
static struct dc_sync_mode * dc_syncget(void)
{
struct dc_sync_mode *pmode = kmalloc(sizeof(struct dc_sync_mode), GFP_KERNEL);
unsigned int regvalue;
regvalue = gpio_sccb_read(I2C_OV9653, DC_COM10);
if((regvalue & 0x40) == 0x40)
{
pmode->href_or_hsync = DC_HSYNC;
}
else if((regvalue & 0x40) == 0x00)
{
pmode->href_or_hsync = DC_HREF;
}
if((regvalue & 0x20) == 0x20)
{
pmode->pclk_mode = DC_PCLK_DISABLE;
}
else if((regvalue & 0x20) == 0x00)
{
pmode->pclk_mode = DC_PCLK_DISABLE;
}
if((regvalue & 0x10) == 0x10)
{
pmode->pclk_reverse = DC_PCLK_REVERSE;
}
else if((regvalue & 0x10) == 0x00)
{
pmode->pclk_reverse = DC_PCLK_NORMAL;
}
if((regvalue & 0x08) == 0x08)
{
pmode->href_reverse = DC_HREF_REVERSE;
}
else if((regvalue & 0x08) == 0x00)
{
pmode->href_reverse = DC_HREF_NORMAL;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -