1.有那个一个需求,需要读取mipi摄像头ID
起初,我以为很简单,实际非常复杂;
2.移植原有的逻辑,就是操作I2C函数读取ID寄存器,但是一直失败;
3.然后发现是电源没有打开;然后电源又是在DTS里面配置的
4.配置电源后发现要配置时钟
5.配置时钟后发现还要配置摄像头的上电时序
最后是自己构建了一个lbdrv_data的结构体存储这些数据,然后自己定制的驱动里面实现控制
补丁:
diff --git a/sysdrv/source/kernel/drivers/lonbon/lbdrv/lbdrv_probe.c b/sysdrv/source/kernel/drivers/lonbon/lbdrv/lbdrv_probe.c
old mode 100644
new mode 100755
index 2a2d9689c..b432a6d7d
--- a/sysdrv/source/kernel/drivers/lonbon/lbdrv/lbdrv_probe.c
+++ b/sysdrv/source/kernel/drivers/lonbon/lbdrv/lbdrv_probe.c
@@ -42,19 +42,20 @@
static struct i2c_client *sensor_client;
static struct proc_dir_entry *proc_lbdrv;
+struct lbdrv_data *lbdrv_power_data;^M
static reg_table gc2053_sensor_id_table[] =
{
{0xf0, 0x20},
{0xf1, 0x53},
};
-#if 0
+^M
static reg_table gc4653_sensor_id_table[] =
{
{0x03f0, 0x46},
{0x03f1, 0x53},
};
-
+#if 0^M
static reg_table sc200ai_sensor_id_table[] =
{
{0x3107, 0xCB},
@@ -72,7 +73,7 @@ static reg_table ov2710_sensor_id_table[] =
static const struct sensor_info sensor_list[] = {
/* name | slave addr | reg addr | reg value | reg addr bytes | reg value bytes */
{"gc2053", 0x6e, gc2053_sensor_id_table, ARRAY_SIZE(gc2053_sensor_id_table), 0x01, 0x01,LBDRV_MCLK_72M}, // for galaxycore gc2053
- //{"gc4653", 0x52, gc4653_sensor_id_table, ARRAY_SIZE(gc4653_sensor_id_table), 0x02, 0x01,LBDRV_MCLK_72M}, // for galaxycore gc2053
+ {"gc4653", 0x52, gc4653_sensor_id_table, ARRAY_SIZE(gc4653_sensor_id_table), 0x02, 0x01,LBDRV_MCLK_72M}, // for galaxycore gc4653^M
//{"sc200ai",0x60, sc200ai_sensor_id_table, ARRAY_SIZE(sc200ai_sensor_id_table), 0x02, 0x01,SNR_MCLK_27M}, // for smartsens sc200ai
//{"ov2710", 0x6c, ov2710_sensor_id_table, ARRAY_SIZE(ov2710_sensor_id_table), 0x02, 0x01,SNR_MCLK_24M}, // for omnivision ov2710
};
@@ -95,6 +96,190 @@ static void lbdrv_set_i2c_addr_idle(struct i2c_client *cli)
}
}
+static inline u32 lbdrv_cal_delay(u32 cycles)^M
+{^M
+ return DIV_ROUND_UP(cycles, LBDRV_XVCLK_FREQ / 1000 / 1000);^M
+}^M
+^M
+int lbdrv_power_on_gc2053(void){^M
+ int ret;^M
+ u32 delay_us;^M
+^M
+ ret = clk_set_rate(lbdrv_power_data->xvclk, LBDRV_XVCLK_FREQ);^M
+ if (ret < 0)^M
+ lbdrv_info("Failed to set xvclk rate (24MHz)\n");^M
+ if (clk_get_rate(lbdrv_power_data->xvclk) != LBDRV_XVCLK_FREQ)^M
+ lbdrv_info("xvclk mismatched, modes are based on 24MHz\n");^M
+ ret = clk_prepare_enable(lbdrv_power_data->xvclk);^M
+ if (ret < 0) {^M
+ lbdrv_err("Failed to enable xvclk\n");^M
+ return ret;^M
+ }^M
+^M
+ ret = regulator_bulk_enable(LBDRV_NUM_SUPPLIES, lbdrv_power_data->supplies);^M
+ if (ret < 0) {^M
+ lbdrv_info("Failed to enable regulators\n");^M
+ goto disable_clk;^M
+ }^M
+ if (!IS_ERR(lbdrv_power_data->power_gpio)) {^M
+ gpiod_set_value_cansleep(lbdrv_power_data->power_gpio, 1);^M
+ usleep_range(100, 200);^M
+ }^M
+ if (!IS_ERR(lbdrv_power_data->reset_gpio)) {^M
+ gpiod_set_value_cansleep(lbdrv_power_data->reset_gpio, 1);^M
+ usleep_range(100, 200);^M
+ }^M
+ if (!IS_ERR(lbdrv_power_data->pwdn_gpio))^M
+ gpiod_set_value_cansleep(lbdrv_power_data->pwdn_gpio, 0);^M
+^M
+ if (!IS_ERR(lbdrv_power_data->reset_gpio))^M
+ gpiod_set_value_cansleep(lbdrv_power_data->reset_gpio, 0);^M
+ usleep_range(3000, 6000);^M
+ /* 8192 cycles prior to first SCCB transaction */^M
&