本文针对于linux3.0.8的内核 其他内核也差不多。
第一从fae那里拿到驱动源码,放到/kernel/drivers/media/video下。然后再Kconfig和Makefile添加相应的代码。
2.在kernel/include/media/下添加gc2035_platform.h头文件,可以仿照里面有现成的写。
3.在/kernel/arch/arm/mach-s5pv210/mach-mini210.c添加如下代码:
#ifdef CONFIG_VIDEO_GC2035
#define GC2035_PWR_EN S5PV210_MP05(1)
#define GC2035_RESET S5PV210_GPE1(4)
#define GC2035_PWR_DOWN_B S5PV210_MP05(0)
#define GC2035_FLED_EN S5PV210_MP05(2)
#define GC2035_FLED_MODE S5PV210_MP05(3)
#define GC2035_CAM_AF S5PV210_GPC0(4)
#define GC2035_PWR_DOWN S5PV210_MP04(7)
static void gc2035_pwr_first(void)
{
int err;
unsigned int tempvalue=0;
printk("%s\n",__func__);
err = gpio_request(GC2035_PWR_DOWN, "MP04_7");
if (err)
printk(KERN_ERR "#### failed to get GC2035_PWR_DOWN(MP04_7) for gc2035 CAM\n");
err = gpio_request(GC2035_PWR_DOWN_B, "MP05_0");
if (err)
printk(KERN_ERR "#### failed to get GC2035_PWR_DOWN_B(MP05_0) for gc2035 CAM\n");
err = gpio_request(GC2035_PWR_EN, "MP05_1");
if (err)
printk(KERN_ERR "#### failed to get GC2035_PWR_EN(MP05_1) for gc2035 CAM\n");
err = gpio_request(GC2035_RESET, "GPE1_4");
if (err)
printk(KERN_ERR "#### failed to get GC2035_RESET(GPE1_4) for gc2035 CAM\n");
gpio_direction_output(GC2035_PWR_DOWN_B, 1);
gpio_direction_output(GC2035_PWR_DOWN, 0);
gpio_direction_output(GC2035_RESET, 0);
mdelay(1);
s3c_gpio_setpull(GC2035_PWR_EN, S3C_GPIO_PULL_NONE);
gpio_direction_output(GC2035_PWR_EN, 1);
mdelay(100);
gpio_direction_output(GC2035_RESET, 1);
gpio_free(GC2035_PWR_DOWN);
gpio_free(GC2035_PWR_DOWN_B);
gpio_free(GC2035_PWR_EN);
gpio_free(GC2035_RESET);
mdelay(100);
}
static void gc2035_pwr_en(int enabled)
{
int err;
unsigned int tempvalue=0;
printk("%s\n",__func__);
err = gpio_request(GC2035_PWR_EN, "MP05_1");
if (err)
printk(KERN_ERR "#### failed to get(GPG1) for gc2035 CAM\n");
s3c_gpio_setpull(GC2035_PWR_EN, S3C_GPIO_PULL_NONE);
gpio_direction_output(GC2035_PWR_EN, enabled);
gpio_free(GC2035_PWR_EN);
mdelay(100);
}
static void gc2035_reset(void)
{
int err;
printk("%s\n",__func__);
err = gpio_request(GC2035_RESET, "GPE1");
if (err)
printk(KERN_ERR "#### failed to get(GPE1) for gc2035 CAM\n");
s3c_gpio_setpull(GC2035_RESET, S3C_GPIO_PULL_NONE);
gpio_direction_output(GC2035_RESET, 1);
mdelay(5);
gpio_direction_output(GC2035_RESET, 0);
mdelay(10);
gpio_direction_output(GC2035_RESET, 1);
gpio_free(GC2035_RESET);
}
static void gc2035_pwr_down(int enabled)
{
int err;
printk("%s\n",__func__);
err = gpio_request(GC2035_PWR_DOWN, "GPG1");
if (err)
printk(KERN_ERR "#### failed to reset(GPG1) for gc2035 CAM\n");
s3c_gpio_setpull(GC2035_PWR_DOWN, S3C_GPIO_PULL_NONE);
gpio_direction_output(GC2035_PWR_DOWN, enabled);
gpio_free(GC2035_PWR_DOWN);
}
static void gc2035_fled_en(int enabled)
{
int err;
printk("%s\n",__func__);
err = gpio_request(GC2035_FLED_EN, "GPG1");
if (err)
printk(KERN_ERR "#### failed to get(GPG1) for gc2035 CAM\n");
s3c_gpio_setpull(GC2035_FLED_EN, S3C_GPIO_PULL_NONE);
gpio_direction_output(GC2035_FLED_EN, enabled);
gpio_free(GC2035_FLED_EN);
}
static void gc2035_fled_mode(int mode)
{
int err;
printk("%s\n",__func__);
err = gpio_request(GC2035_FLED_MODE, "GPG1");
if (err)
printk(KERN_ERR "#### failed to get(GPG1) for gc2035 CAM\n");
s3c_gpio_setpull(GC2035_FLED_MODE, S3C_GPIO_PULL_NONE);
gpio_direction_output(GC2035_FLED_MODE, mode);
gpio_free(GC2035_FLED_MODE);
}
static void gc2035_cam_af(int enabled)
{
int err;
printk("%s\n",__func__);
err = gpio_request(GC2035_CAM_AF, "GPC0");
if (err)
printk(KERN_ERR "#### failed to get(GPC0) for gc2035 CAM\n");
s3c_gpio_setpull(GC2035_CAM_AF, S3C_GPIO_PULL_NONE);
gpio_direction_output(GC2035_CAM_AF, enabled);
gpio_free(GC2035_CAM_AF);
}
static int gc2035_pwr(int enabled)
{
printk("%s\n",__func__);
gc2035_reset();
gc2035_pwr_down(1);
gc2035_pwr_en(1);
gc2035_pwr_down(0);
gc2035_fled_en(0);
gc2035_cam_af(1);
return 0;
}
static struct gc2035_platform_data gc2035_plat = {
.pwr_en = gc2035_pwr_en,
.reset = gc2035_reset,
.pwr_down = gc2035_pwr_down,
.fled_en = gc2035_fled_en,
.fled_mode = gc2035_fled_mode,
.cam_af = gc2035_cam_af,
.default_width = 640,
.default_height = 480,
.pixelformat = V4L2_PIX_FMT_UYVY,
.freq = 24000000,
.is_mipi = 0,
};
static struct i2c_board_info gc2035_i2c_info = {
I2C_BOARD_INFO("gc2035", GC2035_I2C_ADDR),
.platform_data = &gc2035_plat,
};
static struct s3c_platform_camera gc2035 = {
#ifdef CAM_ITU_CH_A
.id = CAMERA_PAR_A,
#else
.id = CAMERA_PAR_B,
#endif
.type = CAM_TYPE_ITU,
.fmt = ITU_601_YCBCR422_8BIT,
.order422 = CAM_ORDER422_8BIT_YCBYCR,
.i2c_busnum = 1,
.info = &gc2035_i2c_info,
.pixelformat = V4L2_PIX_FMT_UYVY,
//.srclk_name = "mout_mpll",
.srclk_name = "xusbxti",
.clk_name = "sclk_cam0",
.clk_rate = 24000000,
.line_length = 1920,
.width = 640,
.height = 480,
.window = {
.left = 0,
.top = 0,
.width = 640,
.height = 480,
},
/* Polarity */
.inv_pclk = 0,
.inv_vsync = 0,
.inv_href = 0,
.inv_hsync = 0,
.initialized = 0,
.cam_power = gc2035_pwr,
};
#endif
};
/* Interface setting */
static struct s3c_platform_fimc fimc_plat_lsi = {
.srclk_name = "mout_mpll",
.clk_name = "sclk_fimc",
.lclk_name = "sclk_fimc_lclk",
.clk_rate = 166750000,
#if defined(CONFIG_VIDEO_S5K4EA)
.default_cam = CAMERA_CSI_C,
#else
#ifdef CAM_ITU_CH_A
.default_cam = CAMERA_PAR_A,
#else
.default_cam = CAMERA_PAR_B,
#endif
#endif
.camera = {
#ifdef CONFIG_VIDEO_GC2035
&gc2035,
#endif
},
.hw_ver = 0x43,
};
这里是上电时序和添加i2c从设备地址。
调试时用示波器检测信号。
一般会碰到收不到sensorID,这就是i2c没信号。那就是i2c管脚不对。重新检测电路,用万用表看是否通路。
第一从fae那里拿到驱动源码,放到/kernel/drivers/media/video下。然后再Kconfig和Makefile添加相应的代码。
2.在kernel/include/media/下添加gc2035_platform.h头文件,可以仿照里面有现成的写。
3.在/kernel/arch/arm/mach-s5pv210/mach-mini210.c添加如下代码:
#ifdef CONFIG_VIDEO_GC2035
#define GC2035_PWR_EN S5PV210_MP05(1)
#define GC2035_RESET S5PV210_GPE1(4)
#define GC2035_PWR_DOWN_B S5PV210_MP05(0)
#define GC2035_FLED_EN S5PV210_MP05(2)
#define GC2035_FLED_MODE S5PV210_MP05(3)
#define GC2035_CAM_AF S5PV210_GPC0(4)
#define GC2035_PWR_DOWN S5PV210_MP04(7)
static void gc2035_pwr_first(void)
{
int err;
unsigned int tempvalue=0;
printk("%s\n",__func__);
err = gpio_request(GC2035_PWR_DOWN, "MP04_7");
if (err)
printk(KERN_ERR "#### failed to get GC2035_PWR_DOWN(MP04_7) for gc2035 CAM\n");
err = gpio_request(GC2035_PWR_DOWN_B, "MP05_0");
if (err)
printk(KERN_ERR "#### failed to get GC2035_PWR_DOWN_B(MP05_0) for gc2035 CAM\n");
err = gpio_request(GC2035_PWR_EN, "MP05_1");
if (err)
printk(KERN_ERR "#### failed to get GC2035_PWR_EN(MP05_1) for gc2035 CAM\n");
err = gpio_request(GC2035_RESET, "GPE1_4");
if (err)
printk(KERN_ERR "#### failed to get GC2035_RESET(GPE1_4) for gc2035 CAM\n");
gpio_direction_output(GC2035_PWR_DOWN_B, 1);
gpio_direction_output(GC2035_PWR_DOWN, 0);
gpio_direction_output(GC2035_RESET, 0);
mdelay(1);
s3c_gpio_setpull(GC2035_PWR_EN, S3C_GPIO_PULL_NONE);
gpio_direction_output(GC2035_PWR_EN, 1);
mdelay(100);
gpio_direction_output(GC2035_RESET, 1);
gpio_free(GC2035_PWR_DOWN);
gpio_free(GC2035_PWR_DOWN_B);
gpio_free(GC2035_PWR_EN);
gpio_free(GC2035_RESET);
mdelay(100);
}
static void gc2035_pwr_en(int enabled)
{
int err;
unsigned int tempvalue=0;
printk("%s\n",__func__);
err = gpio_request(GC2035_PWR_EN, "MP05_1");
if (err)
printk(KERN_ERR "#### failed to get(GPG1) for gc2035 CAM\n");
s3c_gpio_setpull(GC2035_PWR_EN, S3C_GPIO_PULL_NONE);
gpio_direction_output(GC2035_PWR_EN, enabled);
gpio_free(GC2035_PWR_EN);
mdelay(100);
}
static void gc2035_reset(void)
{
int err;
printk("%s\n",__func__);
err = gpio_request(GC2035_RESET, "GPE1");
if (err)
printk(KERN_ERR "#### failed to get(GPE1) for gc2035 CAM\n");
s3c_gpio_setpull(GC2035_RESET, S3C_GPIO_PULL_NONE);
gpio_direction_output(GC2035_RESET, 1);
mdelay(5);
gpio_direction_output(GC2035_RESET, 0);
mdelay(10);
gpio_direction_output(GC2035_RESET, 1);
gpio_free(GC2035_RESET);
}
static void gc2035_pwr_down(int enabled)
{
int err;
printk("%s\n",__func__);
err = gpio_request(GC2035_PWR_DOWN, "GPG1");
if (err)
printk(KERN_ERR "#### failed to reset(GPG1) for gc2035 CAM\n");
s3c_gpio_setpull(GC2035_PWR_DOWN, S3C_GPIO_PULL_NONE);
gpio_direction_output(GC2035_PWR_DOWN, enabled);
gpio_free(GC2035_PWR_DOWN);
}
static void gc2035_fled_en(int enabled)
{
int err;
printk("%s\n",__func__);
err = gpio_request(GC2035_FLED_EN, "GPG1");
if (err)
printk(KERN_ERR "#### failed to get(GPG1) for gc2035 CAM\n");
s3c_gpio_setpull(GC2035_FLED_EN, S3C_GPIO_PULL_NONE);
gpio_direction_output(GC2035_FLED_EN, enabled);
gpio_free(GC2035_FLED_EN);
}
static void gc2035_fled_mode(int mode)
{
int err;
printk("%s\n",__func__);
err = gpio_request(GC2035_FLED_MODE, "GPG1");
if (err)
printk(KERN_ERR "#### failed to get(GPG1) for gc2035 CAM\n");
s3c_gpio_setpull(GC2035_FLED_MODE, S3C_GPIO_PULL_NONE);
gpio_direction_output(GC2035_FLED_MODE, mode);
gpio_free(GC2035_FLED_MODE);
}
static void gc2035_cam_af(int enabled)
{
int err;
printk("%s\n",__func__);
err = gpio_request(GC2035_CAM_AF, "GPC0");
if (err)
printk(KERN_ERR "#### failed to get(GPC0) for gc2035 CAM\n");
s3c_gpio_setpull(GC2035_CAM_AF, S3C_GPIO_PULL_NONE);
gpio_direction_output(GC2035_CAM_AF, enabled);
gpio_free(GC2035_CAM_AF);
}
static int gc2035_pwr(int enabled)
{
printk("%s\n",__func__);
gc2035_reset();
gc2035_pwr_down(1);
gc2035_pwr_en(1);
gc2035_pwr_down(0);
gc2035_fled_en(0);
gc2035_cam_af(1);
return 0;
}
static struct gc2035_platform_data gc2035_plat = {
.pwr_en = gc2035_pwr_en,
.reset = gc2035_reset,
.pwr_down = gc2035_pwr_down,
.fled_en = gc2035_fled_en,
.fled_mode = gc2035_fled_mode,
.cam_af = gc2035_cam_af,
.default_width = 640,
.default_height = 480,
.pixelformat = V4L2_PIX_FMT_UYVY,
.freq = 24000000,
.is_mipi = 0,
};
static struct i2c_board_info gc2035_i2c_info = {
I2C_BOARD_INFO("gc2035", GC2035_I2C_ADDR),
.platform_data = &gc2035_plat,
};
static struct s3c_platform_camera gc2035 = {
#ifdef CAM_ITU_CH_A
.id = CAMERA_PAR_A,
#else
.id = CAMERA_PAR_B,
#endif
.type = CAM_TYPE_ITU,
.fmt = ITU_601_YCBCR422_8BIT,
.order422 = CAM_ORDER422_8BIT_YCBYCR,
.i2c_busnum = 1,
.info = &gc2035_i2c_info,
.pixelformat = V4L2_PIX_FMT_UYVY,
//.srclk_name = "mout_mpll",
.srclk_name = "xusbxti",
.clk_name = "sclk_cam0",
.clk_rate = 24000000,
.line_length = 1920,
.width = 640,
.height = 480,
.window = {
.left = 0,
.top = 0,
.width = 640,
.height = 480,
},
/* Polarity */
.inv_pclk = 0,
.inv_vsync = 0,
.inv_href = 0,
.inv_hsync = 0,
.initialized = 0,
.cam_power = gc2035_pwr,
};
#endif
};
/* Interface setting */
static struct s3c_platform_fimc fimc_plat_lsi = {
.srclk_name = "mout_mpll",
.clk_name = "sclk_fimc",
.lclk_name = "sclk_fimc_lclk",
.clk_rate = 166750000,
#if defined(CONFIG_VIDEO_S5K4EA)
.default_cam = CAMERA_CSI_C,
#else
#ifdef CAM_ITU_CH_A
.default_cam = CAMERA_PAR_A,
#else
.default_cam = CAMERA_PAR_B,
#endif
#endif
.camera = {
#ifdef CONFIG_VIDEO_GC2035
&gc2035,
#endif
},
.hw_ver = 0x43,
};
这里是上电时序和添加i2c从设备地址。
调试时用示波器检测信号。
一般会碰到收不到sensorID,这就是i2c没信号。那就是i2c管脚不对。重新检测电路,用万用表看是否通路。