由于近期在研究Android的一些视频通话的一些技术,所以很快就发现实现摄像头的驱动成为必须研究的课题。下面是在telechips公司提供的Android SDK中已经包含的GT2005型号sensor的部分驱动代码。虽然已经有了比较完善的驱动代码,但是我TCC8902板子上的GT2005摄像头还是没能preview出图像来,最近一直在试图进行各种方法的调试和分析。最后觉得硬着头皮来好好研究GT2005 camera的driver,我会分几期来进行分析,如果有不正确的地方,非常欢迎指正。
下面的代码是GT2005_2mp.h(GT2005 2百万像素摄像头头文件)
- /*
- * drivers/media/video/tcc83xx/GT2005_2mp.h
- *
- * Register definitions for the GT2005 CameraChip.
- *
- * Author: zzau (zzau@telechips.com)
- *
- * Copyright (C) 2008 Telechips, Inc.
- *
- * This file is licensed under the terms of the GNU General Public License
- * version 2. This program is licensed "as is" without any warranty of any
- * kind, whether express or implied.
- */
- #include <mach/globals.h>
- #include "sensor_if.h"
- #ifndef GT2005_H
- #define GT2005_H
- /* The MT9D112 I2C sensor chip has a fixed slave address of 0x78. */
- #define SENSOR_I2C_ADDR 0x78 //[suting] : 摄像头涉及I2C总线协议
- #define REG_TERM 0x0000 /* terminating list entry for reg */
- #define VAL_TERM 0x0000 /* terminating list entry for val */
- //CLOCK
- #define CKC_CAMERA_MCLK 240000
- #define CKC_CAMERA_MCLK_SRC DIRECTPLL1
- #define CKC_CAMERA_SCLK 480000
- #define CKC_CAMERA_SCLK_SRC DIRECTPLL2
- #define FRAMESKIP_COUNT_FOR_CAPTURE 3
- // ZOOM Setting!!
- #define PRV_W 800
- #define PRV_H 600
- #define PRV_ZOFFX 8
- #define PRV_ZOFFY 6
- #define CAP_W 1600
- #define CAP_H 1200
- #define CAP_ZOFFX 16
- #define CAP_ZOFFY 12
- #define CAM_2XMAX_ZOOM_STEP 25
- #define CAM_CAPCHG_WIDTH 800
- struct sensor_reg { //[suting]: register number and number hold
- unsigned short reg;
- unsigned short val;
- };
- struct capture_size { //[suting] : width and height
- unsigned long width;
- unsigned long height;
- };
- extern struct capture_size sensor_sizes[];
- extern void sensor_init_fnc(SENSOR_FUNC_TYPE *sensor_func);
- #endif /* GT2005_H */
从上面的代码可以看出,GT2005摄像头涉及到了I2C总线协议,因为它在发送命令和接受数据时,都是通过I2C总线的方式来完成的。
上面比较重要的数据结构是:
(1)struct sensor_reg ,它提供的是一个键值对:寄存器号 、 寄存器的值,这样定义的目的是在进行初始化等各种操作时,能够很方便的由寄存器号获得寄存器值,进行I2C总线的读写。
(2)struct capture_size ,它定义了capture后的image的width、heigth。
(3)extern void sensor_init_fnc(SENSOR_FUNC_TYPE *sensor_func);
这个函数用于注册GT2005_2mp.c中实际提供给上层应用程序的接口函数。
SENSOR_FUNC_TYPE类型是在 sensor_if.c/.h中定义的。
下面是GT2005_2mp.c 实现文件
- #include <linux/delay.h>
- #include <asm/system.h>
- #include <mach/hardware.h>
- #include <asm/io.h>
- #include "sensor_if.h"
- #include "cam.h"
- #include "tcc_cam_i2c.h"
- #if defined(CONFIG_ARCH_TCC92X) || defined(CONFIG_ARCH_TCC93XX)
- #include <mach/bsp.h>
- #elif defined(CONFIG_ARCH_TCC79X)
- #include <mach/tcc79x.h>
- #endif
- //省略了一些注释掉的代吗
- //................
- /* Array of image sizes supported by GT2005. These must be ordered from
- * smallest image size to largest.
- */
- struct capture_size sensor_sizes[] = {
- { 1600, 1200 }, /* UXGA */
- { 1280, 960 }, /* SXGA */
- { 1024, 768 }, /* XGA */
- { 800, 600 }, /* SVGA */
- { 640, 480 }, /* VGA */
- { 320, 240 }, /* QVGA */
- { 176, 144 }, /* QCIF */
- };
- /* 上面这个结构主要是用于保存capture size,它每个数据项必须按从小到大来排列,因为在sensor_if.c的sensor_find_size()函数中,需要使用这个struct的定义,根据app给出的capture size,协商出最合适的size */
- /* register initialization tables for sensor */
- /* common sensor register initialization for all image sizes, pixel formats,
- * and frame rates
- */
- /* ....省略,后面是一些寄存器的键值对定义,主要用于寄存器的初始化,指定对应的image size / pixel format / frmae rate ,这些都可以通过GT2005的数据手册获得 */
- /* .....省略,接下来的是一些针对camera的不同属性的寄存器定义,比如:white balance / brightness / special effect等等 */
- static int write_regs(const struct sensor_reg reglist[]) //[suting]: write register list
- {
- int err;
- int err_cnt = 0;
- unsigned char data[132];
- unsigned char bytes;
- const struct sensor_reg *next = reglist;
- while (!((next->reg == REG_TERM) && (next->val == VAL_TERM)))
- {
- if(next->reg == REG_TERM && next->val != VAL_TERM)
- {
- mdelay(next->val*2);
- printk("Sensor init Delay[%d]!!!! /n", next->val);
- next++;
- }
- else
- {
- bytes = 0;
- data[bytes]= next->reg>>8; bytes++;
- data[bytes]= (u8)next->reg&0xff; bytes++;
- data[bytes]= next->val; bytes++;
- err = DDI_I2C_Write(data, 2, bytes-2); //[suting] : DDI_I2C_Write
- if (err)
- {
- err_cnt++;
- if(err_cnt >= 3)
- {
- printk("ERROR: Sensor I2C !!!! /n");
- return err;
- }
- }
- else
- {
- err_cnt = 0;
- next++;
- }
- }
- }
- return 0;
- }
- /* 上面这个函数主要用于写寄存器,它被下面很多的接口函数所调用 */
- static int sensor_open(void)
- {
- int id = 0;
- int id1 = 0;
- sensor_power_disable();
- sensor_delay(10);
- sensor_power_enable();
- sensor_delay(10);
- sensor_powerdown_disable();
- sensor_delay(10);
- sensor_powerdown_enable();
- sensor_delay(10);
- sensor_reset_low();
- sensor_delay(10);
- CIF_Open(); //[suting] : open CIF
- sensor_delay(40);
- sensor_reset_high();
- sensor_delay(15);
- printk("init sensor GT2005 !!!! /n");
- DDI_I2C_Read(0x0000, 2, &id, 1);
- DDI_I2C_Read(0x0001, 2, &id1, 1);
- printk("read sensor ID : %x%x/n", id, id1);
- return write_regs(sensor_reg_common[0]); //[suting]: write_regs for initialization
- }
- static int sensor_close(void)
- {
- CIF_ONOFF(OFF); //[suting] : close CIF
- sensor_reset_low();
- sensor_power_disable();
- sensor_powerdown_disable();
- CIF_Close();
- msleep(5);
- return 0;
- }
- static int sensor_preview(void)
- {
- printk("sensor_preview/r/n");
- return write_regs(sensor_reg_common[1]); //[suting] : write_regs for preview
- }
- static int sensor_capture(void)
- {
- printk("sensor_capture/r/n");
- return write_regs(sensor_reg_common[2]); //[suting] : write_regs for capture
- }
- static int sensor_capturecfg(int width, int height)
- {
- return 0;
- }
- /* 上面就是几个比较有代表性的接口函数 */
- void sensor_init_fnc(SENSOR_FUNC_TYPE *sensor_func) //[suting] just like register callback functions
- {
- sensor_func->Open = sensor_open;
- sensor_func->Close = sensor_close;
- sensor_func->Set_Preview = sensor_preview;
- sensor_func->Set_Capture = sensor_capture;
- sensor_func->Set_CaptureCfg = sensor_capturecfg;
- sensor_func->Set_Zoom = sensor_zoom;
- sensor_func->Set_AF = sensor_autofocus;
- sensor_func->Set_Effect = sensor_effect;
- sensor_func->Set_Flip = sensor_flip;
- sensor_func->Set_ISO = sensor_iso;
- sensor_func->Set_ME = sensor_me;
- sensor_func->Set_WB = sensor_wb;
- sensor_func->Set_Bright = sensor_bright;
- sensor_func->Set_Scene = sensor_scene;
- sensor_func->Check_ESD = sensor_check_esd;
- sensor_func->Check_Luma = sensor_check_luma;
- }
- /* 上面就是注册所有的接口函数 */