目前在移植android下面的camera 现在大部分工作已经做完,想写一下自己的移植心得。。。。
首先要把一个型号的camera的移植到android的4.0上面,我认为应该要了解以下几点:
1:camera的硬件接口 2:camera的datashe一定要好好看看
3:要开始你的代码之旅了 在android4.0的kernel下面添加您的驱动
4:对于一些特效和效果会涉及到上层代码的修改 这里我也会说明一下。
第一:说明camera的硬件接口
我想大家看见这样的camera接口,应该是很熟悉的了,呵呵 下面我就说说比较关键的几点:
1:是camera的上电时序 我的camera的上电时序的接口是在cpu的S5PV210_GPH2(2):GPH2(2)口是来控制camera的上电的时序的 请看下图
主要是来控制3.3v的上电 下面是我的上电时序的代码 不过这个也要看camera的datasheet才会知道的
gpio_direction_output(S5PV210_GPH2(2), 1);
msleep(20);
gpio_direction_output(S5PV210_GPH2(2), 0);
msleep(500);
2:来看看第8个管教(PWDN)网络标号是:CAM_PD/GPJ4_4 有些人肯定会问为何要关注这个管教呐,呵呵 这个管脚是比较重要的哦
对于不同的camera 对这个管脚的高低电平是有要求的哦 一定要好好看看camera的datasheet。
以gc0308 为例在初始化的时候是要拉低的 gpio_direction_output(S5PV210_GPJ4(4), 0);
3:再来看看CAM_CLKOUT 这个管脚 这个是cpu提供的时钟 根据您的设置 我的设置是 24mhz 刚开始调试的时候 时钟老是出不来,我还以为是配置和其他的问题 最后发现是自己的cpu的管教没有配置好 呵呵 最低级的错误啊 代码的路径是:arch/arm/mach-s5pv210 里面的setup-fimc0.c文件 主要代码是
void s3c_fimc0_cfg_gpio(struct platform_device *pdev)
{
int i = 0;
/* CAM A port(b0010) : PCLK, VSYNC, HREF, DATA[0-4] */
for (i = 0; i < 8; i++) {
s3c_gpio_cfgpin(S5PV210_GPE0(i), S3C_GPIO_SFN(2));
s3c_gpio_setpull(S5PV210_GPE0(i), S3C_GPIO_PULL_NONE);
}
/* CAM A port(b0010) : DATA[5-7], CLKOUT(MIPI CAM also), FIELD */
for (i = 0; i < 5; i++) { //主要是这个
s3c_gpio_cfgpin(S5PV210_GPE1(i), S3C_GPIO_SFN(2));//把GPIO_E1配置为clk的输出模式
s3c_gpio_setpull(S5PV210_GPE1(i), S3C_GPIO_PULL_NONE);
}
。。。。。
4:有关camera的架构和流程我这里就不多说了 有兴趣的朋友可以看看我的另两篇博文
S5PC100平台上Linux Camera驱动开发详解(一)
S5PC100平台上Linux Camera驱动开发详解(二)
这两篇博文对camera的架构有详细的讲解
开始说说对kenel里面的camera的配置吧
arch/arm/mach-s5pv210 里面的 mach-smdkv210.c有一段关于camera的配置 是这样的
static struct ut2055_platform_data ut2055_plat = {
.default_width = 640,
.default_height = 480,
.pixelformat = V4L2_PIX_FMT_YUYV,
.freq = 24000000, //48000000, // what1
.is_mipi = 0,
};
static struct i2c_board_info ut2055_i2c_info = {
I2C_BOARD_INFO("UT2055", 0x22 >> 1),
.platform_data = &ut2055_plat,
};
static struct s3c_platform_camera ut2055 = {
.id = CAMERA_PAR_A,
.type = CAM_TYPE_ITU,
.fmt = ITU_601_YCBCR422_8BIT,
.order422 = CAM_ORDER422_8BIT_YCBYCR,// hi253,hi704
// .order422 = CAM_ORDER422_8BIT_CBYCRY,// hm2055,gc0308
.i2c_busnum = 1,
.info = &ut2055_i2c_info,
.pixelformat = V4L2_PIX_FMT_YUYV,
.srclk_name = "mout_mpll",
.clk_name = "sclk_cam1",
.clk_rate = 24000000, //48000000, /* 24MHz */
.line_length = 1600, /* 640*480 */
/* default resol for preview kind of thing */
.width = 640,
.height = 480,
.window = {
.left = 0,
.top = 0,
.width = 640,
.height = 480,
},
/* Polarity */
.inv_pclk = 0,
.inv_vsync = 1,
.inv_href = 0,
.inv_hsync = 0,
.initialized = 0,
.cam_power = ut_cam0_power,
};
static struct s3c_platform_fimc fimc_plat_lsi = {
.srclk_name = "mout_mpll",
.clk_name = "sclk_fimc",
.lclk_name = "fimc",
.clk_rate = 166750000,
.default_cam = CAMERA_PAR_A,
.camera = {
&ut2055,
&ut2055,
},
.hw_ver = 0x43,
};
有人会问为何我配置两次ut2055 呵呵 应为我的是单双都支持的camera 如果上面胆码配置一个的话 点击后置camera会报错的哦
这个配置对于我的hi703 和hi253 和hm2055 以及gc0308 的配置是全部支持的 唯一的差别是order422的格式不一样 这个我已经在代码上有标志了 大家注意哦
5::主要的核心代码:drivers/media/video 里面需要添加 ut2055.c 和 ut2055.h
由于代码量比较大 这里我就不贴出来了
6:drivers/media/video/samsung/fimc 这个路径的两个文件也是很重要的
比如:
fimc_capture.c 这个文件 的一个函数 比如:
int fimc_enum_input(struct file *file, void *fh, struct v4l2_input *inp)
{
struct fimc_global *fimc = get_fimc_dev();
struct fimc_control *ctrl = ((struct fimc_prv_data *)fh)->ctrl;
fimc_dbg("%s: index %d\n", __func__, inp->index);
if (inp->index < 0 || inp->index >= FIMC_MAXCAMS) {
return -EINVAL;
}
gCameraId = inp->index;//这句话得目的是获取camera的id 也就是上层传先来的是camear 0 或是 camera 1 这样就知道你打开的是前置或是后置了,在ut2055.c里面就好区分了。
if (!fimc->camera_isvalid[inp->index])
{
printk(" ::::fimc_enum_input erro:\n"); //如果你的camera是双的话 没有在第4歩的fimc_plat_lsi 里面的camera 的数组有两个&ut2055,的话打开camera 1 的时候 通常是前置camera 会进入这个错误的。
return -EINVAL;
}
strcpy(inp->name, fimc->camera[inp->index].info->type);
inp->type = V4L2_INPUT_TYPE_CAMERA;
return 0;
}
fimc_regs.c这个文件 的一个函数 比如:
extern int camera_Ycbcr_type; //这个变量是在ut2055.c文件里面又定义 和赋值 比如我检测到的camera是hi253,hi704 哪就是给camera_Ycbcr_type = 1;hm2055 gc0308 的是0 ,不同的camera的配置不一样的,在前面我说过了。
int fimc_hwset_camera_source(struct fimc_control *ctrl)
{
struct s3c_platform_camera *cam = ctrl->cam;
u32 cfg = 0;
/* for now, we support only ITU601 8 bit mode */
if (camera_Ycbcr_type)
cam->order422 = CAM_ORDER422_8BIT_YCBYCR;
else
cam->order422 = CAM_ORDER422_8BIT_CBYCRY;
/* for now, we support only ITU601 8 bit mode */
cfg |= S3C_CISRCFMT_ITU601_8BIT;
cfg |= cam->order422;
if (cam->type == CAM_TYPE_ITU)
cfg |= cam->fmt;
cfg |= S3C_CISRCFMT_SOURCEHSIZE(cam->width);
cfg |= S3C_CISRCFMT_SOURCEVSIZE(cam->height);
writel(cfg, ctrl->regs + S3C_CISRCFMT);
return 0;
}
7:还有一个文件是不可少的:
include/media路径里面的是:ut2055_platform.h
/*
* 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.
*/
struct ut2055_platform_data {
unsigned int default_width;
unsigned int default_height;
unsigned int pixelformat;
int freq; /* MCLK in KHz */
/* This SoC supports Parallel & CSI-2 */
int is_mipi;
};
这个文件要在
arch/arm/mach-s5pv210 里面的 mach-smdkv210.c文件里面包含 #include <media/ut2055_platform.h>
基本上在kernel里面的调试说完了 下一篇我说说在上层的一些调试吧:
在android 4.0 上面移植camera的一些心得 包括 单双camera 型号 hi253 gc0308 hi704 hm2055 ut2055 上层代码的调试