和你一起终身学习,这里是程序员Android
经典好文推荐,通过阅读本文,您将收获以下知识点:
一、Kernel 代码移植
二、Vendor 代码移植
三、扩展
一、Kernel 代码移植
1. DTS 文件配置
dts 文件目录:
高通SDM660平台代码中,arm64 与 arm 走的是同一个目录文件,
kernel\msm-4.4\arch\arm64\boot\dts\qcom这个目录其实是 \kernel\msm-4.4\arch\arm\boot\dts\qcom的软链接。
Camera 相关的 dts 文件:
@ kernel\msm-4.4\arch\arm64\boot\dts\qcom\sdm660.dtsi
@ kernel\msm-4.4\arch\arm64\boot\dts\qcom\sdm660-camera.dtsi
@ kernel\msm-4.4\arch\arm64\boot\dts\qcom\sdm660-pinctrl.dtsi
@ kernel\msm-4.4\arch\arm64\boot\dts\qcom\sdm660-camera-sensor-mtp.dtsi
1.1 sdm660.dtsi
在该文件中,主要功能如下:
引入 sdm660-camera.dtsi 文件
配置 camera_focus 和 camera_snapshot 对应的 GPIO 及 上报的 keycode。
@ \kernel\msm-4.4\arch\arm\boot\dts\qcom\sdm660.dtsi
// 1. 引入 sdm660-camera.dtsi
#include "sdm660-camera.dtsi"
// 2. 配置 camera_focus 和 camera_snapshot GPIO 及对应的 keycode。
&soc {
gpio_keys {
status = "okay";
compatible = "gpio-keys";
input-name = "gpio-keys";
pinctrl-names = "tlmm_gpio_key_active","tlmm_gpio_key_suspend";
pinctrl-0 = <&gpio_key_active>;
pinctrl-1 = <&gpio_key_suspend>;
camera_focus {
label = "camera_focus";
gpios = <&tlmm 64 0x1>;
linux,input-type = <1>;
linux,code = <0x210>;
debounce-interval = <15>;
};
camera_snapshot {
label = "camera_snapshot";
gpios = <&tlmm 113 0x1>;
linux,input-type = <1>;
linux,code = <0x2fe>;
debounce-interval = <15>;
};
};
};
1.2 sdm660-camera.dtsi
在 sdm660-camera.dtsi 中主要是配置了平台相关的Camera 底层硬件相关的配置,比如 CSI,CS。
如无特殊需求,一般不会修改此处的代码。
部分代码及对应的解释如下:
各参数解析详见:
@ \kernel\msm-4.4\Documentation\devicetree\bindings\media\video\msm-csid.txt
@ \kernel\msm-4.4\Documentation\devicetree\bindings\media\video\msm-csi-phy.txt
&soc {
qcom,csiphy@c824000 { // CSI 总线映射的寄存器地址
cell-index = <0>; // CSI 硬件总线索引号 0
compatible = "qcom,csiphy-v3.5", "qcom,csiphy"; // compatible = “a厂商,p产品”, “标准bbb类型设备”。
// 那么linux kernel可能首先使用“a厂商,p产品”来匹配适合的driver,
// 如果没有匹配到,那么使用字符串“标准bbb类型设备”来继续寻找适合的driver。
reg = <0xc824000 0x1000>,<0xca00120 0x4>; // 使用的寄存器地址 及 长度
reg-names = "csiphy", "csiphy_clk_mux"; // cisphy 寄存器地址为 0xc824000, 长度为 0x1000
// csiphy_clk_mux 寄存器地址为 0xca00120,长度为 0x4
interrupts = <0 78 0>; // interrupt的格式是<type, interrupt number, trigger type>, 详见《(扩展1) interrupts 中断节点解析》
interrupt-names = "csiphy"; // 中断name,可通过 cat /proc/interrupts 获取
gdscr-supply = <&gdsc_camss_top>;
bimc_smmu-supply = <&gdsc_bimc_smmu>;
qcom,cam-vreg-name = "gdscr", "bimc_smmu"; // voltage regulators 和 name
clocks = <&clock_rpmcc MMSSNOC_AXI_CLK>, // clocks 和 name
<&clock_mmss MMSS_MNOC_AHB_CLK>,
<&clock_mmss MMSS_BIMC_SMMU_AHB_CLK>,
<&clock_mmss MMSS_BIMC_SMMU_AXI_CLK>,
<&clock_mmss MMSS_CAMSS_AHB_CLK>,
<&clock_mmss MMSS_CAMSS_TOP_AHB_CLK>,
<&clock_mmss CSI0_CLK_SRC>,
<&clock_mmss MMSS_CAMSS_CSI0_CLK>,
<&clock_mmss MMSS_CAMSS_CPHY_CSID0_CLK>,
<&clock_mmss CSI0PHYTIMER_CLK_SRC>,
<&clock_mmss MMSS_CAMSS_CSI0PHYTIMER_CLK>,
<&clock_mmss MMSS_CAMSS_ISPIF_AHB_CLK>,
<&clock_mmss CSIPHY_CLK_SRC>,
<&clock_mmss MMSS_CAMSS_CSIPHY0_CLK>,
<&clock_mmss MMSS_CSIPHY_AHB2CRIF_CLK>;
clock-names = "mmssnoc_axi", "mnoc_ahb",
"bmic_smmu_ahb", "bmic_smmu_axi",
"camss_ahb_clk", "camss_top_ahb_clk",
"csi_src_clk", "csi_clk", "cphy_csid_clk",
"csiphy_timer_src_clk", "csiphy_timer_clk",
"camss_ispif_ahb_clk", "csiphy_clk_src", "csiphy_clk",
"csiphy_ahb2crif";
qcom,clock-rates = <0 0 0 0 0 0 310000000 0 0 269333333 0 0 200000000 0 0>; // 上面对应所有clock 的速率
status = "ok";
};
qcom,csiphy@c825000 {
cell-index = <1>; // CSI 硬件总线索引号 1
compatible = "qcom,csiphy-v3.5", "qcom,csiphy";
reg = <0xc825000 0x1000>, <0xca00124 0x4>;
reg-names = "csiphy", "csiphy_clk_mux"; // cisphy 寄存器地址为 0xc825000, 长度为 0x1000
// csiphy_clk_mux 寄存器地址为 0xca00124 ,长度为 0x4
interrupts = <0 79 0>;
interrupt-names = "csiphy";
...... // 此处省略一大段代码,内容和前面 CSI 0 一样,配置clk 及其速率
};
1.3 sdm660-camera-sensor-mtp.dtsi
文件 sdm660-pinctrl.dtsi和 sdm660-camera-sensor-mtp.dtsi是在 sdm660-mtp.dtsi中被包含的。
@ \kernel\msm-4.4\arch\arm\boot\dts\qcom\sdm660-mtp.dtsi
#include "sdm660-pinctrl.dtsi"
#include "sdm660-camera-sensor-mtp.dtsi"
sdm660-camera-sensor-mtp.dtsi是kernel camera 重点要配置的文件
其中包括了 camera 闪光灯的配置,avdd/dovdd/dvdd/vaf 等电压的配置,camera 马达的配置 ,eeprom的配置,camera sensor的配置。
1.3.1 Camera Sensor DTS配置
@ \kernel\msm-4.4\arch\arm\boot\dts\qcom\sdm660-camera-sensor-mtp.dtsi
@ \kernel\msm-4.4\Documentation\devicetree\bindings\media\video\msm-cci.txt
&cci {
qcom,camera@0 {
cell-index = <0>; // Camera索引号 0,此处注意不要重复了
compatible = "qcom,camera";
reg = <0x0>; // 和索引号一样
qcom,csiphy-sd-index = <0>; // 使用 CSI 0,具体根据硬件决定,一般来说, 0:后摄, 1:前摄
qcom,csid-sd-index = <0>; // 使用 CSI 0
qcom,mount-angle = <90>; // Sensor 成像方向与主板的角度,camear旋转角度
qcom,led-flash-src = <&led_flash0>; // 闪光灯,使用 led_flash0
qcom,actuator-src = <&actuator0>; // 马达,使用 actuator0
qcom,ois-src = <&ois0>; // 是否支持 光学防抖
qcom,eeprom-src = <&eeprom1>; // eeprom 1
cam_vio-supply = <&pm660_l11>; // IO voltage IO口电压 VDDIO 数字 IO 电源主要给 I2C 部分供电;
cam_vana-supply = <&cam_avdd_gpio_regulator>; // analog voltage 模拟电压 AVDD 模拟供电,主要给感光区和 ADC 部分供电;
cam_vdig-supply = <&cam_rear_dvdd_gpio_regulator>; // digital voltage 数字电压DVDD 数字供电,主要给 ISP 供电
cam_vaf-supply = <&cam_vaf_gpio_regulator>; // AF voltage Camera 自动对焦马达的供电
cam_v_custom1-supply = <&cam_dovdd_gpio_regulator>;
qcom,cam-vreg-name = "cam_vio", "cam_vana", "cam_vdig", "cam_vaf","cam_v_custom1"; // 供电配置 及对应的 电压,详见下
qcom,cam-vreg-min-voltage = <1780000 0 0 0 0>;
qcom,cam-vreg-max-voltage = <1950000 0 0 0 0>;
qcom,cam-vreg-op-mode = <105000 0 0 0 0>;
qcom,gpio-no-mux = <0>; // 1:表示 gpio mux 不可用 0:表示可用
pinctrl-names = "cam_default", "cam_suspend"; // Camera gpio clk 和 reset gpio 配置
pinctrl-0 = <&cam_sensor_mclk0_active &cam_sensor_rear_active>;
pinctrl-1 = <&cam_sensor_mclk0_suspend &cam_sensor_rear_suspend>;
gpios = <&tlmm 32 0>, <&tlmm 46 0>;
qcom,gpio-reset = <1>;
qcom,gpio-req-tbl-num = <0 1>;
qcom,gpio-req-tbl-flags = <1 0>;
qcom,gpio-req-tbl-label = "CAMIF_MCLK0", "CAM_RESET0";
qcom,sensor-position = <0>; // 1:前置 0:后置
qcom,sensor-mode = <0>;
===>{ @ \kernel\msm-4.4\Documentation\devicetree\bindings\media\video\msm-cci.txt
- qcom,sensor-mode : should contain sensor mode supported
- 0 -> back camera 2D
- 1 -> front camera 2D
- 2 -> back camera 3D
- 3 -> back camera int 3D
}
qcom,cci-master = <0>; // I2C 0
status = "ok";
clocks = <&clock_mmss MCLK0_CLK_SRC>, <&clock_mmss MMSS_CAMSS_MCLK0_CLK>;
clock-names = "cam_src_clk", "cam_clk";
qcom,clock-rates = <24000000 0>; // clock rate in Hz
//- qcom,sensor-type : should contain format of data that sensor streams
// - 0 -> bayer format
// - 1 -> yuv format
};
qcom,camera@1 {
cell-index = <1>; // Camera索引号 1,此处注意不要重复了
compatible = "qcom,camera";
reg = <0x1>;
qcom,csiphy-sd-index = <1>;
qcom,csid-sd-index = <1>;
qcom,mount-angle = <90>;
qcom,actuator-src = <&actuator1>;
qcom,eeprom-src = <&eeprom1>;
cam_vio-supply = <&cam_dovdd_gpio_regulator>;
cam_vana-supply = <&cam_avdd_gpio_regulator>;
cam_vdig-supply = <&cam_rear_dvdd_gpio_regulator>;
cam_vaf-supply = <&cam_vaf_gpio_regulator>;
qcom,cam-vreg-name = "cam_vio", "cam_vana", "cam_vdig", "cam_vaf";
qcom,cam-vreg-min-voltage = <0 0 0 0>;
qcom,cam-vreg-max-voltage = <0 0 0 0>;
qcom,cam-vreg-op-mode = <105000 0 0 0>;
qcom,gpio-no-mux = <0>;
pinctrl-names = "cam_default", "cam_suspend";
pinctrl-0 = <&cam_sensor_mclk2_active &cam_sensor_rear2_active>;
pinctrl-1 = <&cam_sensor_mclk2_suspend &cam_sensor_rear2_suspend>;
gpios = <&tlmm 34 0>, <&tlmm 48 0>;
qcom,gpio-reset = <1>;
qcom,gpio-req-tbl-num = <0 1>;
qcom,gpio-req-tbl-flags = <1 0>;
qcom,gpio-req-tbl-label = "CAMIF_MCLK", "CAM_RESET";
qcom,sensor-position = <0>; // 1:前置 0:后置
qcom,sensor-mode = <0>; // 0 -> back camera 2D
qcom,cci-master = <1>; // I2C 1
status = "ok";
clocks = <&clock_mmss MCLK2_CLK_SRC>, <&clock_mmss MMSS_CAMSS_MCLK2_CLK>;
clock-names = "cam_src_clk", "cam_clk";
qcom,clock-rates = <24000000 0>;
};
qcom,camera@2 {
cell-index = <2>; // Camera索引号 2,此处注意不要重复了
compatible = "qcom,camera";
reg = <0x02>;
qcom,csiphy-sd-index = <2>;
qcom,csid-sd-index = <2>;
qcom,mount-angle = <270>;
//qcom,actuator-src = <&actuator2>; // 前报不需要马达,所以此处不用配置马达 ,同样下面也不用配置 af voltage
qcom,eeprom-src = <&eeprom2>;
cam_vio-supply = <&pm660_l11>;
cam_vana-supply = <&cam_avdd_gpio_regulator>;
cam_vdig-supply = <&cam_dvdd_gpio_regulator>;
qcom,cam-vreg-name = "cam_vio", "cam_vana", "ca