此文是在camera bringup时接触到的有关camera的上电大概流程,所涉及的代码皆为kernel的开源代码。
mt6853-master\drivers\misc\mediatek\imgsensor\src\common\v1_1\imgsensor.c
初始化
module_init(imgsensor_init);
static int __init imgsensor_init(void)
{
PK_DBG("[camerahw_probe] start\n");
//注册一个平台驱动gimgsensor_platform_driver
if (platform_driver_register(&gimgsensor_platform_driver)) {
PK_PR_ERR("failed to register CAMERA_HW driver\n");
return -ENODEV;
}
return 0;
}
static struct platform_driver gimgsensor_platform_driver = {
.probe = imgsensor_probe,
.remove = imgsensor_remove,
.suspend = imgsensor_suspend,
.resume = imgsensor_resume,
.driver = {
.name = "image_sensor",
.owner = THIS_MODULE,
//与设备树匹配
.of_match_table = gimgsensor_of_device_id,
}
};
static const struct of_device_id gimgsensor_of_device_id[] = {
{.compatible = "mediatek,imgsensor",},
{}
};
mt6853-master\arch\arm64\boot\dts\mediatek\mt6853.dts
与此设备树中字符串进行匹配
kd_camera_hw1:kd_camera_hw1@1a004000 {
compatible = "mediatek,imgsensor";
};
mt6853-master\arch\arm64\boot\dts\mediatek\cust_mt6853_camera.dtsi
kd_camera_hw1也与此camera设备树中字符串匹配上:
&kd_camera_hw1 {
inctrl-names = "default",//与pinctrl-0对应
"cam0_rst0", //与pinctrl-1对应
"cam0_rst1",//与pinctrl-2对应
…
pinctrl-0 = <&camera_pins_default>;
pinctrl-1 = <&camera_pins_cam0_rst_0>;
pinctrl-2 = <&camera_pins_cam0_rst_1>;
…
//根据电路原理图,此处cam0的iovdd上电方式为regulator mt6359
// mt6853-master\arch\arm64\boot\dts\mediatek\mt6359.dtsi
mt_pmic_vcamio_ldo_reg: ldo_vcamio {
regulator-name = "vcamio";
regulator-min-microvolt = <1700000>;
regulator-max-microvolt = <1900000>;
regulator-enable-ramp-delay = <1920>;
};
cam0_vcamio-supply = <&mt_pmic_vcamio_ldo_reg>;
…
}
&pio {
//与pinctrl-1对应,根据电路原理图填写此处的GPIO上电引脚
camera_pins_cam0_rst_0: cam0@0 {
pins_cmd_dat {
pinmux = <__HCT_GPIO_CAMERA_CMRST_PINMUX__>;
slew-rate = <1>;
output-low;
};
};
…
}
匹配一致调用probe函数
imgsensor_hw_init(phw);
mt6853-master\drivers\misc\mediatek\imgsensor\src\common\v1_1\imgsensor_hw.c
进行引脚的初始化等操作
//遍历camera
enum IMGSENSOR_SENSOR_IDX {
IMGSENSOR_SENSOR_IDX_MIN_NUM = 0,
IMGSENSOR_SENSOR_IDX_MAIN = IMGSENSOR_SENSOR_IDX_MIN_NUM,
IMGSENSOR_SENSOR_IDX_SUB,
IMGSENSOR_SENSOR_IDX_MAIN2,
IMGSENSOR_SENSOR_IDX_SUB2,
IMGSENSOR_SENSOR_IDX_MAIN3,
IMGSENSOR_SENSOR_IDX_SUB3,
IMGSENSOR_SENSOR_IDX_MAIN4,
IMGSENSOR_SENSOR_IDX_SUB4,
IMGSENSOR_SENSOR_IDX_MAIN5,
IMGSENSOR_SENSOR_IDX_SUB5,
IMGSENSOR_SENSOR_IDX_MAIN6,
IMGSENSOR_SENSOR_IDX_SUB6,
IMGSENSOR_SENSOR_IDX_MAX_NUM,
IMGSENSOR_SENSOR_IDX_NONE,
};
//初始化各camera的上电方式并与cust_mt6853_camera.dtsi中
// kd_camera_hw1的enable_sensor匹配上
//初始化imgsensor_custom_config,regulator/gpio/mclk init
(phw->pdev[i]->init)( phw->pdev[i]->pinstance, &phw->common);
pcust_pwr_cfg = imgsensor_custom_config;
mt6853-master\drivers\misc\mediatek\imgsensor\src\mt6853\camera_hw\imgsensor_cfg_table.c
struct IMGSENSOR_HW_CFG imgsensor_custom_config[] = {
{
IMGSENSOR_SENSOR_IDX_MAIN,
IMGSENSOR_I2C_DEV_0,
{
{IMGSENSOR_HW_PIN_MCLK, IMGSENSOR_HW_ID_MCLK},
{IMGSENSOR_HW_PIN_AVDD, IMGSENSOR_HW_ID_GPIO},
{IMGSENSOR_HW_PIN_DOVDD, IMGSENSOR_HW_ID_REGULATOR},
{IMGSENSOR_HW_PIN_DVDD, IMGSENSOR_HW_ID_GPIO},
{IMGSENSOR_HW_PIN_PDN, IMGSENSOR_HW_ID_GPIO},
{IMGSENSOR_HW_PIN_RST, IMGSENSOR_HW_ID_GPIO},
{IMGSENSOR_HW_PIN_NONE, IMGSENSOR_HW_ID_NONE},
},
},
};
imgsensor_i2c_create();
imgsensor_init_sensor_list();
//初始化读取gimgsensor_sensor_list
static void imgsensor_init_sensor_list(void)
{
struct IMGSENSOR_SENSOR_LIST *psensor_list = gimgsensor_sensor_list;
while (psensor_list->id && i < MAX_NUM_OF_SUPPORT_SENSOR) {
pimgsensor->psensor_list[i] = psensor_list;
i++;
psensor_list++;
}
}
mt6853-master\drivers\misc\mediatek\imgsensor\src\common\v1_1\ imgsensor_sensor_list.c
struct IMGSENSOR_SENSOR_LIST gimgsensor_sensor_list[MAX_NUM_OF_SUPPORT_SENSOR] = {
#if defined(IMX582_MIPI_RAW)
{IMX582_SENSOR_ID, SENSOR_DRVNAME_IMX582_MIPI_RAW, IMX582_MIPI_RAW_SensorInit},
#endif
};
接下来具体的对硬件的操作
mt6853-master\drivers\misc\mediatek\imgsensor\src\common\v1_1\imgsensor.c
//上层操作硬件的具体接口
imgsensor_ioctl();
//根据上层携带下来的指令信息,选择不同的指令
case KDIMGSENSORIOC_X_FEATURECONCTROL:
i4RetValue = adopt_CAMERA_HW_FeatureControl(pBuff);
//继续进行判断,进入上电流程
case SENSOR_FEATURE_SET_DRIVER:
imgsensor_set_driver(psensor);
//上下电流程
imgsensor_check_is_alive(psensor);
(1)imgsensor_hw_power()//上电
err = imgsensor_hw_power(&pgimgsensor->hw,
psensor,
psensor_inst->psensor_name,
IMGSENSOR_HW_POWER_STATUS_ON/*根据这个变量决定是上电还是下电,此处ON是上电*/);
imgsensor_hw_power_sequence(
phw,
sensor_idx,
pwr_status,
platform_power_sequence,
str_index);
imgsensor_hw_power_sequence(
phw,
sensor_idx,
pwr_status,
sensor_power_sequence,
curr_sensor_name);
mt6853-master\drivers\misc\mediatek\imgsensor\src\mt6853\camera_hw\ imgsensor_cfg_table.c
struct IMGSENSOR_HW_POWER_SEQ platform_power_sequence[] = {
#ifdef MIPI_SWITCH
{
PLATFORM_POWER_SEQ_NAME,
{
{
IMGSENSOR_HW_PIN_MIPI_SWITCH_EN,
IMGSENSOR_HW_PIN_STATE_LEVEL_0,
0,
IMGSENSOR_HW_PIN_STATE_LEVEL_HIGH,
0
},
{
IMGSENSOR_HW_PIN_MIPI_SWITCH_SEL,
IMGSENSOR_HW_PIN_STATE_LEVEL_0,
0,
IMGSENSOR_HW_PIN_STATE_LEVEL_0,
0
},
},
IMGSENSOR_SENSOR_IDX_SUB,
},
};
struct IMGSENSOR_HW_POWER_SEQ sensor_power_sequence[] = {
#if defined(IMX586_MIPI_RAW)
{
SENSOR_DRVNAME_IMX586_MIPI_RAW,
{
{RST, Vol_Low, 1},
{AVDD, Vol_2800, 0},
{AFVDD, Vol_2800, 0},
{DVDD, Vol_1100, 0},
{DOVDD, Vol_1800, 1},
{SensorMCLK, Vol_High, 1},
{RST, Vol_High, 3}
},
},
};
mt6853-master\drivers\misc\mediatek\imgsensor\src\common\v1_1\imgsensor_hw.c
//开始真正具体的上下电操作
imgsensor_hw_power_sequence()
//遍历sensor的上电时序set进行上电,gpio/regualtor set
pdev->**set**(pdev->pinstance,
sensor_idx,
ppwr_info->pin/*引脚*/, ppwr_info->pin_state_on/*电压*/);
mdelay(ppwr_info->pin_on_delay/*延时*/);
(2) imgsensor_sensor_feature_control(…SENSOR_FEATURE_CHECK_SENSOR_ID…)//获取sensor id
mt6853-master\drivers\misc\mediatek\imgsensor\src\common\v1_1\imx586_mipi_raw\imx586mipiraw_Sensor.c
//获取sensor id,合法id不包括sensorID == 0 || sensorID == 0xFFFFFFFF
get_imgsensor_id(feature_return_para_32);
static kal_uint32 get_imgsensor_id(UINT32 *sensor_id)
{
kal_uint8 i = 0;
kal_uint8 retry = 2;
/*sensor have two i2c address 0x34 & 0x20,
*we should detect the module used i2c address
*/
while (imgsensor_info.i2c_addr_table[i] != 0xff) {
spin_lock(&imgsensor_drv_lock);
imgsensor.i2c_write_id = imgsensor_info.i2c_addr_table[i];
spin_unlock(&imgsensor_drv_lock);
do {
*sensor_id = ((read_cmos_sensor_8(0x0016) << 8)
| read_cmos_sensor_8(0x0017));
pr_debug(
"read_0x0000=0x%x, 0x0001=0x%x,0x0000_0001=0x%x\n",
read_cmos_sensor_8(0x0016),
read_cmos_sensor_8(0x0017),
read_cmos_sensor(0x0000));
if (*sensor_id == imgsensor_info.sensor_id) {
pr_debug("i2c write id: 0x%x, sensor id: 0x%x\n",
imgsensor.i2c_write_id, *sensor_id);
read_sensor_Cali();
return ERROR_NONE;
}
pr_debug("Read sensor id fail, id: 0x%x\n",
imgsensor.i2c_write_id);
retry--;
} while (retry > 0);
i++;
retry = 2;
}
if (*sensor_id != imgsensor_info.sensor_id) {
/*if Sensor ID is not correct,
*Must set *sensor_id to 0xFFFFFFFF
*/
*sensor_id = 0xFFFFFFFF;
return ERROR_SENSOR_CONNECT_FAIL;
}
return ERROR_NONE;
}
(3)imgsensor_hw_power()//下电
imgsensor_hw_power(&pimgsensor->hw,
psensor,
IMGSENSOR_HW_POWER_STATUS_OFF/*下电*/);