Camera 驅動 Bringup

和你一起終身學習,這裏是程序員 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", "cam_vdig";
        qcom,cam-vreg-min-voltage = <1780000 0 0>;
        qcom,cam-vreg-max-voltage = <1950000 0 0>;
        qcom,cam-vreg-op-mode = <105000 0 0>;
        qcom,gpio-no-mux = <0>;
        pinctrl-names = "cam_default", "cam_suspend";
        pinctrl-0 = <&cam_sensor_mclk1_active &cam_sensor_front_active>;
        pinctrl-1 = <&cam_sensor_mclk1_suspend &cam_sensor_front_suspend>;
        gpios = <&tlmm 33 0>, <&tlmm 47 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_MCLK2", "CAM_RESET2";
        qcom,sensor-position = <1>;         // 1:前置   0:後置
        qcom,sensor-mode = <1>;             // 1 -> front camera 2D
        qcom,cci-master = <1>;              // I2C 1
        status = "ok";
        clocks = <&clock_mmss MCLK1_CLK_SRC>, <&clock_mmss MMSS_CAMSS_MCLK1_CLK>;
        clock-names = "cam_src_clk", "cam_clk";
        qcom,clock-rates = <24000000 0>;
    };
}

1.3.2 Camera 供電DTS配置(avdd/dovdd/dvdd/vaf)

Camera 供電配置要根據具體的硬件來配置,
如果走的是 pm 電源則配置如cam_vio-supply = <&pm660_l11>;
如果走的是具體GPIO供電,則要做如下配置 ,調用時配置如cam_vana-supply = <&cam_avdd_gpio_regulator>;
各GPIO 供電配置如下:

@ \kernel\msm-4.4\arch\arm\boot\dts\qcom\sdm660-camera-sensor-mtp.dtsi
&soc {
    cam_avdd_gpio_regulator: cam_avdd_fixed_regulator {
        compatible = "regulator-fixed";
        regulator-name = "cam_avdd_gpio_regulator";
        regulator-min-microvolt = <3600000>;
        regulator-max-microvolt = <3600000>;
        enable-active-high;
        gpio = <&tlmm 51 0>;            // 使用 CPU的 GPIO 51 ,供電 3.6v
        vin-supply = <&pm660l_bob>;
    };
    
    cam_dovdd_gpio_regulator: cam_dovdd_fixed_regulator {
        compatible = "regulator-fixed";
        regulator-name = "cam_dovdd_gpio_regulator";
        regulator-min-microvolt = <3600000>;
        regulator-max-microvolt = <3600000>;
        enable-active-high;
        gpio = <&tlmm 0 0>;             // 使用 CPU的 GPIO 0 ,供電 3.6v
        vin-supply = <&pm660l_bob>;
    };

    cam_dvdd_gpio_regulator: cam_dvdd_fixed_regulator {
        compatible = "regulator-fixed";
        regulator-name = "cam_dvdd_gpio_regulator";
        regulator-min-microvolt = <3600000>;
        regulator-max-microvolt = <3600000>;
        enable-active-high;
        gpio = <&pm660l_gpios 3 0>;         // 使用 PM660L的 gpio 3 ,供電 3.6v
        vin-supply = <&pm660l_bob>;
    };

    cam_rear_dvdd_gpio_regulator: cam_rear_dvdd_fixed_regulator {
        compatible = "regulator-fixed";
        regulator-name = "cam_rear_dvdd_gpio_regulator";
        regulator-min-microvolt = <3600000>;
        regulator-max-microvolt = <3600000>;
        enable-active-high;
        gpio = <&pm660l_gpios 4 0>;         // 使用 PM660L的 gpio 4 ,供電 3.6v
        vin-supply = <&pm660l_bob>;
    };

    cam_vaf_gpio_regulator:cam_vaf_fixed_regulator {
        compatible = "regulator-fixed";
        regulator-name = "cam_vaf_gpio_regulator";
        regulator-min-microvolt = <3600000>;
        regulator-max-microvolt = <3600000>;
        enable-active-high;
        gpio = <&tlmm 50 0>;                // 使用 CPU的 gpio 50 ,供電 3.6v
        vin-supply = <&pm660l_bob>;
    };
};

1.3.3 Camera 閃光燈DTS配置

@ \kernel\msm-4.4\arch\arm\boot\dts\qcom\sdm660-camera-sensor-mtp.dtsi
&soc {
    led_flash0: qcom,camera-flash@0 {
        cell-index = <0>;                   // 閃光燈配置索引 0
        compatible = "qcom,camera-flash";
        // 如下: 如果兩顆燈的話,則配置對應的兩個供電,如果是一顆燈的主話,則配置一個供電
        qcom,flash-source = <&pm660l_flash0 &pm660l_flash1>;//閃光燈供電配置
        qcom,torch-source = <&pm660l_torch0 &pm660l_torch1>;//手電筒供電配置
        qcom,switch-source = <&pm660l_switch0>;
        status = "ok";
    };

    led_flash1: qcom,camera-flash@1 {
        cell-index = <1>;                   // 閃光燈配置索引 1
        compatible = "qcom,camera-flash";
        qcom,flash-source = <&pm660l_flash2>; //閃光燈供電配置
        qcom,torch-source = <&pm660l_torch2>; //手電筒供電配置
        qcom,switch-source = <&pm660l_switch1>;
        status = "ok";
    };

上述的相關電源配置均在 msm-pm660l.dtsi文件中

@ \kernel\msm-4.4\arch\arm\boot\dts\qcom\msm-pm660l.dtsi

        flash_led: qcom,leds@d300 {
            compatible = "qcom,qpnp-flash-led-v2";
            reg = <0xd300 0x100>;
            label = "flash";
            interrupts = <0x3 0xd3 0x0 IRQ_TYPE_EDGE_RISING>,
                    <0x3 0xd3 0x3 IRQ_TYPE_EDGE_RISING>,
                    <0x3 0xd3 0x4 IRQ_TYPE_EDGE_RISING>;
            interrupt-names = "led-fault-irq",
                    "all-ramp-down-done-irq",
                    "all-ramp-up-done-irq";
            qcom,hdrm-auto-mode;
            qcom,short-circuit-det;
            qcom,open-circuit-det;
            qcom,vph-droop-det;
            qcom,thermal-derate-en;
            qcom,thermal-derate-current = <200 500 1000>;
            qcom,isc-delay = <192>;
            qcom,pmic-revid = <&pm660l_revid>;

            pm660l_flash0: qcom,flash_0 {
                label = "flash";
                qcom,led-name = "led:flash_0";
                qcom,max-current = <1500>;  // 最大電流 1.5A
                qcom,default-led-trigger = "flash0_trigger";
                qcom,id = <0>;              // flash0
                qcom,current-ma = <1000>;   
                qcom,duration-ms = <1280>;
                qcom,ires-ua = <12500>;
                qcom,hdrm-voltage-mv = <325>;
                qcom,hdrm-vol-hi-lo-win-mv = <100>;
            };

            pm660l_flash1: qcom,flash_1 {
                label = "flash";
                qcom,led-name = "led:flash_1";
                qcom,max-current = <1500>;
                qcom,default-led-trigger = "flash1_trigger";
                qcom,id = <1>;
                qcom,current-ma = <1000>;
                qcom,duration-ms = <1280>;
                qcom,ires-ua = <12500>;
                qcom,hdrm-voltage-mv = <325>;
                qcom,hdrm-vol-hi-lo-win-mv = <100>;
            };

            pm660l_flash2: qcom,flash_2 {
                label = "flash";
                qcom,led-name = "led:flash_2";
                qcom,max-current = <750>;
                qcom,default-led-trigger = "flash2_trigger";
                qcom,id = <2>;
                qcom,current-ma = <500>;
                qcom,duration-ms = <1280>;
                qcom,ires-ua = <12500>;
                qcom,hdrm-voltage-mv = <325>;
                qcom,hdrm-vol-hi-lo-win-mv = <100>;
            };
            pm660l_torch0: qcom,torch_0 {
                label = "torch";
                qcom,led-name = "led:torch_0";
                qcom,max-current = <500>;
                qcom,default-led-trigger = "torch0_trigger";
                qcom,id = <0>;
                qcom,current-ma = <300>;
                qcom,ires-ua = <12500>;
                qcom,hdrm-voltage-mv = <325>;
                qcom,hdrm-vol-hi-lo-win-mv = <100>;
            };
            ......
            pm660l_switch0: qcom,led_switch_0 {
                label = "switch";
                qcom,led-name = "led:switch_0";
                qcom,led-mask = <3>;
                qcom,default-led-trigger = "switch0_trigger";
            };
        };

1.3.4 Camera 馬達DTS配置

&cci {
    actuator0: qcom,actuator@0 {
        cell-index = <0>;
        reg = <0x0>;
        compatible = "qcom,actuator";
        qcom,cci-master = <0>;      // 馬達使用的 i2c master , I2C 0
        cam_vaf-supply = <&cam_vaf_gpio_regulator>; // 馬達供電
        qcom,cam-vreg-name = "cam_vaf";
        qcom,cam-vreg-min-voltage = <3300000>;
        qcom,cam-vreg-max-voltage = <3600000>;
        qcom,cam-vreg-op-mode = <100000>;
    };

    actuator1: qcom,actuator@1 {
        cell-index = <1>;
        reg = <0x1>;
        compatible = "qcom,actuator";
        qcom,cci-master = <1>;      // 馬達使用的 i2c master , I2C 1
        cam_vaf-supply = <&cam_vaf_gpio_regulator>;
        qcom,cam-vreg-name = "cam_vaf";
        qcom,cam-vreg-min-voltage = <3300000>;
        qcom,cam-vreg-max-voltage = <3600000>;
        qcom,cam-vreg-op-mode = <100000>;
    };

1.3.5 Camera 光學防抖 OSI DTS配置

ois0: qcom,ois@0 {
        cell-index = <0>;
        reg = <0x0>;
        compatible = "qcom,ois";
        qcom,cci-master = <0>;  // 使用 I2C 0
        gpios = <&tlmm 50 0>;   // GPIO 50
        qcom,gpio-vaf = <0>;
        qcom,gpio-req-tbl-num = <0>;
        qcom,gpio-req-tbl-flags = <0>;
        qcom,gpio-req-tbl-label = "CAM_VAF";
        pinctrl-names = "cam_default", "cam_suspend";
        pinctrl-0 = <&cam_actuator_vaf_active>;
        pinctrl-1 = <&cam_actuator_vaf_suspend>;
        status = "disabled";
    };

1.3.6 Camera eeprom DTS配置

eeprom0: qcom,eeprom@0 {
        cell-index = <0>;
        reg = <0>;
        compatible = "qcom,eeprom";
        cam_vio-supply = <&pm660_l11>;
        cam_vana-supply = <&cam_avdd_gpio_regulator>;
        cam_vdig-supply = <&cam_rear_dvdd_gpio_regulator>;
        cam_vaf-supply = <&pm660l_l8>;
        qcom,cam-vreg-name = "cam_vio", "cam_vana", "cam_vdig", "cam_vaf";
        qcom,cam-vreg-min-voltage = <1780000 0 0 2800000>;
        qcom,cam-vreg-max-voltage = <1950000 0 0 3400000>;
        qcom,cam-vreg-op-mode = <105000 0 0 100000>;
        qcom,gpio-no-mux = <0>;
        pinctrl-names = "cam_default", "cam_suspend";
        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>;
        qcom,sensor-mode = <0>;
        qcom,cci-master = <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>;
    };

1.3.7 Camera PM660L GPIO DTS配置

前面我們使用到了兩個 PM660L 的GPIO:
gpio = <&pm660l_gpios 3 0>;
gpio = <&pm660l_gpios 4 0>;

不同於 CPU的gpio ,其需要作單獨配置,如下:

@\kernel\msm-4.4\arch\arm\boot\dts\qcom\sdm660-camera-sensor-mtp.dtsi
&pm660l_gpios {
    gpio@c300 { /* GPIO4 -CAMERA SENSOR 0 VDIG*/
        qcom,mode = <1>;                /* Output */
        qcom,pull = <5>;                /* No Pull */
        qcom,vin-sel = <0>;             /* VIN1 GPIO_LV */
        qcom,src-sel = <0>;             /* GPIO */
        qcom,invert = <0>;              /* Invert */
        qcom,master-en = <1>;           /* Enable GPIO */
        status = "ok";
    };

    gpio@c200 { /* GPIO3 -CAMERA SENSOR 2 VDIG*/
        qcom,mode = <1>;                /* Output */
        qcom,pull = <5>;                /* No Pull */
        qcom,vin-sel = <0>;             /* VIN1 GPIO_LV */
        qcom,src-sel = <0>;             /* GPIO */
        qcom,invert = <0>;              /* Invert */
        qcom,master-en = <1>;           /* Enable GPIO */
        status = "ok";
    };
};

1.4 sdm660-pinctrl.dtsi

在前面 中,有需要用到的gpio,出於電源管理的需求,需要在 pinctrl 中配置其active 和 suspend 對應的配置:

例如,GPIO 32 和 GPIO 46 以及 GPIO 50
在前邊代碼中,使用配置如下:

gpio 50:
        pinctrl-names = "cam_default", "cam_suspend";
        pinctrl-0 = <&cam_actuator_vaf_active>;
        pinctrl-1 = <&cam_actuator_vaf_suspend>;

GPIO 32 、GPIO 46:
        pinctrl-names = "cam_default", "cam_suspend";
        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>;
@ \kernel\msm-4.4\arch\arm\boot\dts\qcom\sdm660-pinctrl.dtsi
        cam_actuator_vaf_active: cam_actuator_vaf_active {
            /* ACTUATOR POWER */
            mux {
                pins = "gpio50";
                function = "gpio";
            };
            config {
                pins = "gpio50";
                bias-disable; /* No PULL */
                drive-strength = <2>; /* 2 MA */
            };
        };
        cam_actuator_vaf_suspend: cam_actuator_vaf_suspend {
            /* ACTUATOR POWER */
            mux {
                pins = "gpio50";
                function = "gpio";
            };
            config {
                pins = "gpio50";
                bias-pull-down; /* PULL DOWN */
                drive-strength = <2>; /* 2 MA */
            };
        };
        cam_sensor_mclk0_active: cam_sensor_mclk0_active {
            /* MCLK0 */
            mux {
                /* CLK */
                pins = "gpio32";
                function = "cam_mclk";
            };
            config {
                pins = "gpio32";
                bias-disable; /* No PULL */
                drive-strength = <2>; /* 2 MA */
            };
        };
        cam_sensor_mclk0_suspend: cam_sensor_mclk0_suspend {
            /* MCLK0 */
            mux {
                /* CLK */
                pins = "gpio32";
                function = "cam_mclk";
            };
            config {
                pins = "gpio32";
                bias-pull-down; /* PULL DOWN */
                drive-strength = <2>; /* 2 MA */
            };
        };
        cam_sensor_rear_active: cam_sensor_rear_active {
            /* RESET, STANDBY */
            mux {
                pins = "gpio46";
                function = "gpio";
            };
            config {
                pins = "gpio46";
                bias-disable; /* No PULL */
                drive-strength = <2>; /* 2 MA */
            };
        };
        cam_sensor_rear_suspend: cam_sensor_rear_suspend {
            /* RESET, STANDBY */
            mux {
                pins = "gpio46";
                function = "gpio";
            };
            config {
                pins = "gpio46";
                bias-disable; /* No PULL */
                drive-strength = <2>; /* 2 MA */
            };
        };
        cam_sensor_mclk1_active: cam_sensor_mclk1_active {
            /* MCLK1 */
            mux {
                /* CLK */
                pins = "gpio33";
                function = "cam_mclk";
            };
            config {
                pins = "gpio33";
                bias-disable; /* No PULL */
                drive-strength = <2>; /* 2 MA */
            };
        };
        cam_sensor_mclk1_suspend: cam_sensor_mclk1_suspend {
            /* MCLK1 */
            mux {
                /* CLK */
                pins = "gpio33";
                function = "cam_mclk";
            };
            config {
                pins = "gpio33";
                bias-pull-down; /* PULL DOWN */
                drive-strength = <2>; /* 2 MA */
            };
        };
        cam_sensor_rear2_active: cam_sensor_rear2_active {
            /* RESET, STANDBY */
            mux {
                pins = "gpio48";
                function = "gpio";
            };
            config {
                pins = "gpio48";
                bias-disable; /* No PULL */
                drive-strength = <2>; /* 2 MA */
            };
        };
        cam_sensor_rear2_suspend: cam_sensor_rear2_suspend {
            /* RESET, STANDBY */
            mux {
                pins = "gpio48";
                function = "gpio";
            };
            config {
                pins = "gpio48";
                bias-disable; /* No PULL */
                drive-strength = <2>; /* 2 MA */
            };
        };
        cam_sensor_mclk2_active: cam_sensor_mclk2_active {
            /* MCLK1 */
            mux {
                /* CLK */
                pins = "gpio34";
                function = "cam_mclk";
            };
            config {
                pins = "gpio34";
                bias-disable; /* No PULL */
                drive-strength = <2>; /* 2 MA */
            };
        };
        cam_sensor_mclk2_suspend: cam_sensor_mclk2_suspend {
            /* MCLK1 */
            mux {
                /* CLK */
                pins = "gpio34";
                function = "cam_mclk";
            };
            config {
                pins = "gpio34";
                bias-pull-down; /* PULL DOWN */
                drive-strength = <2>; /* 2 MA */
            };
        };
        cam_sensor_front_active: cam_sensor_front_active {
            /* RESET  VANA*/
            mux {
                pins = "gpio47";
                function = "gpio";
            };
            config {
                pins = "gpio47";
                bias-disable; /* No PULL */
                drive-strength = <2>; /* 2 MA */
            };
        };
        cam_sensor_front_suspend: cam_sensor_front_suspend {
            /* RESET */
            mux {
                pins = "gpio47";
                function = "gpio";
            };
            config {
                pins = "gpio47";
                bias-disable; /* No PULL */
                drive-strength = <2>; /* 2 MA */
            };
        };
        cam_sensor_mclk3_active: cam_sensor_mclk3_active {
            /* MCLK3 */
            mux {
                /* CLK */
                pins = "gpio35";
                function = "cam_mclk";
            };
            config {
                pins = "gpio35";
                bias-disable; /* No PULL */
                drive-strength = <2>; /* 2 MA */
            };
        };
        cam_sensor_mclk3_suspend: cam_sensor_mclk3_suspend {
            /* MCLK3 */
            mux {
                /* CLK */
                pins = "gpio35";
                function = "cam_mclk";
            };
            config {
                pins = "gpio35";
                bias-pull-down; /* PULL DOWN */
                drive-strength = <2>; /* 2 MA */
            };
        };
        cam_sensor_front_iris_active: cam_sensor_front_iris_active {
            /* RESET */
            mux {
                pins = "gpio52";
                function = "gpio";
            };
            config {
                pins = "gpio52";
                bias-disable; /* No PULL */
                drive-strength = <2>; /* 2 MA */
            };
        };
        cam_sensor_front_iris_suspend: cam_sensor_front_iris_suspend {
            /* RESET */
            mux {
                pins = "gpio52";
                function = "gpio";
            };
            config {
                pins = "gpio52";
                bias-disable; /* No PULL */
                drive-strength = <2>; /* 2 MA */
            };
        };

至此,Camera 中 dts 相關的配置好上邊這些就ok 了。

2. Kernel Driver 配置

現在比較新的高通代碼中,Kernel 中只需要配置好DTS就可以了,驅動代碼是以庫代碼的形式存放在vendor 目錄中。

而kernel 中的camera 相關的 C 文件是高通默認的通用文件。

@ \kernel\msm-4.4\drivers\media\platform\msm\camera_v2

我們今天重點在移植,這一塊的代碼,後續我講camera 工作流程的時候重點來學習。

二、Vendor 代碼移植

目前高通中,vendor 中包括了,camera、馬達、eeprom、Trunning 效果等庫文件,這些是我們要根據需求移植進來的。

接下來我們慢慢寫的來。

1. Camera Sensor 庫文件代碼移植

以 imx350 sensor 爲例:

@ qcom\proprietary\common\config\device-vendor.mk
@ qcom\proprietary\mm-camera\mm-camera2\media-controller\modules\sensors\config\Android.mk
@ qcom\proprietary\mm-camera\mm-camera2\media-controller\modules\sensors\config\imx350_suny.xml
@ qcom\proprietary\mm-camera\mm-camera2\media-controller\modules\sensors\config\sdm660_camera.xml
@ qcom\proprietary\mm-camera\mm-camera2\media-controller\modules\sensors\libs\imx350\ 
@ qcom\proprietary\mm-camera\mm-camera2\media-controller\modules\sensors\chromatix\0310\chromatix_imx350_sunny\ 

1.1 導入Camera Sensor lib 庫代碼

將 sensor lib庫代碼放入如下目錄:
@\vendor\qcom\proprietary\mm-camera\mm-camera2\media-controller\modules\sensors\sensor\libs\imx350

注意Android.mk中
LOCAL_SRC_FILES:= imx350_lib.c
LOCAL_MODULE := libmmcamera_imx350

需要在 @\vendor\qcom\proprietary\common\config\device-vendor.mk中導入模塊,添加修改如下:
MM_CAMERA += libmmcamera_imx350

2. 導入Camera Chromatix 默認效果參數

將默認的 Chromatix 效果參數放入如下目錄
@\vendor\qcom\proprietary\mm-camera\mm-camera2\media-controller\modules\sensors\chromatix\0310\chromatix_imx350_sunny

其中包括了,3A 及 ISP 的效果參數,後續Camera Turnning 工程師會代碼效果後修以下面的參數。

由於上面每個分別會編譯成多個庫,所以我們要注意每個庫的名字,我們進入每個文件夾的Android.mk 看下:

@ mm-camera2\media-controller\modules\sensors\chromatix\0310\chromatix_imx350_sunny\3A
LOCAL_MODULE           :=  libchromatix_imx350_sunny_default_preview_3a
LOCAL_MODULE           :=  libchromatix_imx350_sunny_default_video_3a
LOCAL_MODULE           :=  libchromatix_imx350_sunny_hfr_120_3a
LOCAL_MODULE           :=  libchromatix_imx350_sunny_hfr_60_3a
LOCAL_MODULE           :=  libchromatix_imx350_sunny_hfr_90_3a 
LOCAL_MODULE           :=  libchromatix_imx350_sunny_zsl_preview_3a
LOCAL_MODULE           :=  libchromatix_imx350_sunny_zsl_video_3a

@ mm-camera2\media-controller\modules\sensors\chromatix\0310\chromatix_imx350_sunny\common
LOCAL_MODULE           :=  libchromatix_imx350_sunny_common

@ mm-camera2\media-controller\modules\sensors\chromatix\0310\chromatix_imx350_sunny\cpp
LOCAL_MODULE           := libchromatix_imx350_sunny_cpp_hfr_120
LOCAL_MODULE           := libchromatix_imx350_sunny_cpp_hfr_60
LOCAL_MODULE           := libchromatix_imx350_sunny_cpp_hfr_90
LOCAL_MODULE           := libchromatix_imx350_sunny_cpp_liveshot
LOCAL_MODULE           := libchromatix_imx350_sunny_cpp_preview
LOCAL_MODULE           := libchromatix_imx350_sunny_cpp_snapshot
LOCAL_MODULE           := libchromatix_imx350_sunny_cpp_video

@ mm-camera2\media-controller\modules\sensors\chromatix\0310\chromatix_imx350_sunny\isp
LOCAL_MODULE           := libchromatix_imx350_sunny_hfr_120
LOCAL_MODULE           := libchromatix_imx350_sunny_hfr_60
LOCAL_MODULE           := libchromatix_imx350_sunny_hfr_90
LOCAL_MODULE           := libchromatix_imx350_sunny_liveshot
LOCAL_MODULE           := libchromatix_imx350_sunny_preview
LOCAL_MODULE           := libchromatix_imx350_sunny_snapshot
LOCAL_MODULE           := libchromatix_imx350_sunny_default_video
LOCAL_MODULE           := libchromatix_imx350_sunny_postproc
LOCAL_MODULE           := libchromatix_imx350_sunny_oz_preview_3a
LOCAL_MODULE           := libchromatix_imx350_sunny_oz_video_3a

@ mm-camera2\media-controller\modules\sensors\chromatix\0310\chromatix_imx350_sunny\postproc
LOCAL_MODULE           := libchromatix_imx350_sunny_postproc

在 @\vendor\qcom\proprietary\common\config\device-vendor.mk中添加如下修改:

MM_CAMERA += libchromatix_imx350_sunny_default_preview_3a
MM_CAMERA += libchromatix_imx350_sunny_default_video_3a
MM_CAMERA += libchromatix_imx350_sunny_hfr_120_3a
MM_CAMERA += libchromatix_imx350_sunny_hfr_60_3a
MM_CAMERA += libchromatix_imx350_sunny_hfr_90_3a
MM_CAMERA += libchromatix_imx350_sunny_zsl_preview_3a
MM_CAMERA += libchromatix_imx350_sunny_zsl_video_3a

MM_CAMERA += libchromatix_imx350_sunny_common

MM_CAMERA += libchromatix_imx350_sunny_cpp_hfr_120
MM_CAMERA += libchromatix_imx350_sunny_cpp_hfr_60
MM_CAMERA += libchromatix_imx350_sunny_cpp_hfr_90
MM_CAMERA += libchromatix_imx350_sunny_cpp_liveshot
MM_CAMERA += libchromatix_imx350_sunny_cpp_preview
MM_CAMERA += libchromatix_imx350_sunny_cpp_snapshot
MM_CAMERA += libchromatix_imx350_sunny_cpp_video

MM_CAMERA += libchromatix_imx350_sunny_hfr_120
MM_CAMERA += libchromatix_imx350_sunny_hfr_60
MM_CAMERA += libchromatix_imx350_sunny_hfr_90
MM_CAMERA += libchromatix_imx350_sunny_liveshot
MM_CAMERA += libchromatix_imx350_sunny_preview
MM_CAMERA += libchromatix_imx350_sunny_snapshot
MM_CAMERA += libchromatix_imx350_sunny_default_video
MM_CAMERA += libchromatix_imx350_sunny_postproc
MM_CAMERA += libchromatix_imx350_sunny_oz_preview_3a
MM_CAMERA += libchromatix_imx350_sunny_oz_video_3a

MM_CAMERA += libchromatix_imx350_sunny_postproc

2.1 chromatix version 0309 和 0310 定義
具體走哪個是由 CHROMATIX_VERSION來控制的,其定義於:

@\vendor\qcom\proprietary\mm-camera\Android.mk

ifeq ($(BUILD_SERVER), true)
  CHROMATIX_VERSION := 0208
else ifeq ($(BUILD_MM_CAMERA2), true)
  ifeq ($(OEM_CHROMATIX_0308), 1)
    CHROMATIX_VERSION := 0308E
  else ifeq ($(call is-board-platform-in-list,sdm660 msm8998),true)
    CHROMATIX_VERSION := 0310
  else
    CHROMATIX_VERSION := 0309
  endif
endif

ifeq ($(OEM_CHROMATIX_0310), 1)
  OEM_CHROMATIX:=true
endif

ifeq ($(OEM_CHROMATIX), true)
  LOCAL_CHROMATIX_PATH := $(LOCAL_PATH)/../mm-camera-ext/mm-camerasdk/sensor/includes/$(CHROMATIX_VERSION)
  LOCAL_EXTEN_ISP_INCLUDES := $(LOCAL_PATH)/../mm-camera-ext/mm-camera2/media-controller/modules/isp2/
  LOCAL_EXTEN_PPROC_INCLUDES := $(LOCAL_PATH)/../mm-camera-ext/mm-camera2/media-controller/modules/pproc-new/cpp/
  LOCAL_EXTEN_CHROMATIX_FILE_PATH := $(LOCAL_PATH)/../mm-camera-ext/mm-camera2/media-controller/modules/sensors/chromatix/$(CHROMATIX_VERSION)
else
  LOCAL_CHROMATIX_PATH := $(LOCAL_PATH)/../mm-camerasdk/sensor/includes/$(CHROMATIX_VERSION)
  LOCAL_EXTEN_CHROMATIX_FILE_PATH := $(LOCAL_PATH)/mm-camera2/media-controller/modules/sensors/chromatix/$(CHROMATIX_VERSION)
endif

3. 修改 Sensor Config XML

@ qcom\proprietary\mm-camera\mm-camera2\media-controller\modules\sensors\config\Android.mk
@ qcom\proprietary\mm-camera\mm-camera2\media-controller\modules\sensors\config\imx350_suny.xml
@ qcom\proprietary\mm-camera\mm-camera2\media-controller\modules\sensors\config\sdm660_camera.xml

3.1 imx350_sunny.xml

@\mm-camera2\media-controller\modules\sensors\configs\imx350_sunny.xml
在該文件中,主要是描述了對應的 chromatix 模塊名字,如下:
可以看出,和前面 chromatix 中的模塊名字一模一樣。

<!--
CommonChromatixInfo:
    CommonChromatixInfo is the information about chromatix needed for various use cases.
    Ex:- Preview, Snapshot, ZSL, HFR, HDR, Video, Liveshot for ISP, CPP,3A and SW PostProc.
    Entries in this node are common for all sensor modes.

ResolutionChromatixInfo:
    ResolutionChromatixInfo is the information about chromatix needed for various use cases.
    Ex:- Preview, Snapshot, ZSL, HFR, HDR, Video, Liveshot for ISP, CPP, 3A and SW PostProc.
    Entries in this node are specific to sensor resolution.

ChromatixName:
    Contains the list of chromatix names for all modules.
    special_mode_mask:
        It is the bit mask for special modes, which is used for  chromatix selection.
        Special modes can be any mode that needs a special chromatix.
        Ex:- scene mode, DZOOM mode, OIS capture mode, flash mode
        This is applicable for CommonChromatixInfo and ResolutionChromatixInfo.
        special_mode_mask="0" means none of the special modes are selected.
    sensor_resolution_index:
        It is the sensor resolution index for which chromatix libraries will be choosen.
        It is applicable only in ResolutionChromatixInfo.

ISPCommon :     Common tuning library name for ISP
ISPPreview :    Preview tuning library name for ISP
ISPSnapshot :   Snapshot tuning library name for ISP
CPPCommon :     Common tuning library name for CPP
CPPPreview :    Preview tuning library name for CPP
CPPSnapshot :   Snapshot tuning library name for CPP
CPPLiveshot :   Liveshot tuning library name for CPP
PostProc :      Tuning library name for postproc module
A3Preview :     Preview tuning library for 3A
A3Video :       Video tuning library for 3A

Order of Resolution Pick:
    Assume the current sensor mode is "r" and special mode mask is "s".
    Chromatix for a module and type is choosen in this order till we find a valid chroamtix file name or else NULL is returned.
    1) From ResolutionChromatixInfo node for which sensor_resolution_index is "r" and special_mode_mask is "s".
    2) From CommonChromatixInfo node for which special_mode_mask is "s".
    3) From ResolutionChromatixInfo node for which sensor_resolution_index is "r" and special_mode_mask is "0".
    4) From CommonChromatixInfo node for which special_mode_mask is "0".
    5) NULL is returned if we dont find in any of the above cases.

special_mode_mask values:
    SENSOR_SPECIAL_MODE_NONE = 0,
    SENSOR_SPECIAL_MODE_FLASH = 1,
    SENSOR_SPECIAL_MODE_ZOOM_UPSCALE = 2,
    SENSOR_SPECIAL_MODE_ZOOM_DOWNSCALE = 4,
    SENSOR_SPECIAL_MODE_OIS_CAPTURE = 8,
-->

<ChromatixConfigurationRoot>
  <CommonChromatixInfo>
    <ChromatixName>
      <PostProc>imx350_sunny_postproc</PostProc>
    </ChromatixName>
  </CommonChromatixInfo>
  <ResolutionChromatixInfo>
    <ChromatixName sensor_resolution_index="0">
      <ISPCommon>imx350_sunny_common</ISPCommon>
      <ISPPreview>imx350_sunny_snapshot</ISPPreview>
      <ISPSnapshot>imx350_sunny_snapshot</ISPSnapshot>
      <ISPVideo>imx350_sunny_default_video</ISPVideo>
      <CPPPreview>imx350_sunny_cpp_preview</CPPPreview>
      <CPPSnapshot>imx350_sunny_cpp_snapshot</CPPSnapshot>
      <CPPVideo>imx350_sunny_cpp_video</CPPVideo>
      <CPPLiveshot>imx350_sunny_cpp_liveshot</CPPLiveshot>
      <A3Preview>imx350_sunny_zsl_preview_3a</A3Preview>
      <A3Video>imx350_sunny_zsl_video_3a</A3Video>
    </ChromatixName>
    <ChromatixName sensor_resolution_index="1">
      <ISPCommon>imx350_sunny_common_oz</ISPCommon>
      <ISPPreview>imx350_sunny_oz_preview</ISPPreview>
      <ISPSnapshot>imx350_sunny_oz_snapshot</ISPSnapshot>
      <ISPVideo>imx350_sunny_oz_preview</ISPVideo>
      <CPPPreview>imx350_sunny_cpp_oz_preview</CPPPreview>
      <CPPSnapshot>imx350_sunny_cpp_oz_snapshot</CPPSnapshot>
      <CPPVideo>imx350_sunny_cpp_oz_preview</CPPVideo>
      <CPPLiveshot>imx350_sunny_cpp_liveshot</CPPLiveshot>
      <A3Preview>imx350_sunny_oz_preview_3a</A3Preview>
      <A3Video>imx350_sunny_oz_preview_3a</A3Video>
    </ChromatixName>
    <ChromatixName sensor_resolution_index="2">
      <ISPCommon>imx350_sunny_common_bining</ISPCommon>
      <ISPPreview>imx350_sunny_preview</ISPPreview>
      <ISPSnapshot>imx350_sunny_snapshot</ISPSnapshot>
      <ISPVideo>imx350_sunny_default_video</ISPVideo>
      <CPPPreview>imx350_sunny_cpp_preview</CPPPreview>
      <CPPSnapshot>imx350_sunny_cpp_snapshot</CPPSnapshot>
      <CPPVideo>imx350_sunny_cpp_video</CPPVideo>
      <CPPLiveshot>imx350_sunny_cpp_liveshot</CPPLiveshot>
      <A3Preview>imx350_sunny_default_preview_3a</A3Preview>
      <A3Video>imx350_sunny_default_video_3a</A3Video>
    </ChromatixName>
    <ChromatixName sensor_resolution_index="2" special_mode_mask="SCENE_BOKEH_MODE|">
      <ISPCommon>imx350_sunny_common_bining</ISPCommon>
      <ISPPreview>imx350_sunny_preview_bokeh</ISPPreview>
      <ISPSnapshot>imx350_sunny_preview_bokeh</ISPSnapshot>
      <ISPVideo>imx350_sunny_default_video</ISPVideo>
      <CPPPreview>imx350_sunny_cpp_preview</CPPPreview>
      <CPPSnapshot>imx350_sunny_cpp_snapshot</CPPSnapshot>
      <CPPVideo>imx350_sunny_cpp_video</CPPVideo>
      <CPPLiveshot>imx350_sunny_cpp_liveshot</CPPLiveshot>
      <A3Preview>imx350_sunny_default_preview_3a</A3Preview>
      <A3Video>imx350_sunny_default_video_3a</A3Video>
    </ChromatixName>
    <ChromatixName sensor_resolution_index="3">
      <ISPCommon>imx350_sunny_common</ISPCommon>
      <ISPPreview>imx350_sunny_hfr_90</ISPPreview>
      <ISPSnapshot>imx350_sunny_hfr_90</ISPSnapshot>
      <ISPVideo>imx350_sunny_hfr_90</ISPVideo>
      <CPPPreview>imx350_sunny_cpp_hfr_90</CPPPreview>
      <CPPSnapshot>imx350_sunny_cpp_hfr_90</CPPSnapshot>
      <CPPVideo>imx350_sunny_cpp_hfr_90</CPPVideo>
      <CPPLiveshot>imx350_sunny_cpp_liveshot</CPPLiveshot>
      <A3Preview>imx350_sunny_hfr_90_3a</A3Preview>
      <A3Video>imx350_sunny_hfr_90_3a</A3Video>
    </ChromatixName>
    <ChromatixName sensor_resolution_index="4">
      <ISPCommon>imx350_sunny_common</ISPCommon>
      <ISPPreview>imx350_sunny_hfr_120</ISPPreview>
      <ISPSnapshot>imx350_sunny_hfr_120</ISPSnapshot>
      <ISPVideo>imx350_sunny_hfr_120</ISPVideo>
      <CPPPreview>imx350_sunny_cpp_hfr_120</CPPPreview>
      <CPPSnapshot>imx350_sunny_cpp_hfr_120</CPPSnapshot>
      <CPPVideo>imx350_sunny_cpp_hfr_120</CPPVideo>
      <CPPLiveshot>imx350_sunny_cpp_liveshot</CPPLiveshot>
      <A3Preview>imx350_sunny_hfr_120_3a</A3Preview>
      <A3Video>imx350_sunny_hfr_120_3a</A3Video>
    </ChromatixName>
  </ResolutionChromatixInfo>
</ChromatixConfigurationRoot>

3.2 sdm660_camera.xml

<!--
CameraModuleConfig :
    This node must be added for each module prosent in the device.
    It contain all information about the module present.
    The number of nodes of CameraModuleConfig indicate number of modules
    to be probed on the device.
    Maximum number of CameraModuleConfig nodes is 10
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

*CameraId : Camera Id is the Slot number in which the mode is plugged. Valid values are 0, 1, 2 and 3.
*SensorName : Name of the sensor present on the module. The sensor library name should be of the form libmmcamera_<SensorName>.so
ActuatorName : Name of the actuator on this module.The actuator library name should be of the form libactuator_<ActuatorName>.so.
                If there is no actuator remove the <ActuatorName> node.
EepromName : Name of the eeprom on this module.
    Eeprom lib name should be of the form libmmcamera_<EepromName>_eeprom.so If there is no eeprom remove the <EepromName> node.
FlashName :
    Name of the flash on this module.
    The flash library name should be of the form libflash_<FlashName>.so. If there is no flash remove the <FlashName> node.
ChromatixName :
    Name of the tuning xml file.
    Tuning file contains the list of chromatix library names. If there is no tuning xml file remove the <ChromatixName> node.
Position :
    Position of the sensor module. Valid values are: BACK, FRONT and BACK_AUX
MountAngle :
    Angle at which the sensor is mounted. Valid values are 0, 90, 180, 270 and 360.
    To use default mountangle mentioned in kernel use 360.

CsiInfo : This node contains information about the receiver configuration.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

*CSIDCore : CSID core to receive the data. Valid values are 0, 1, 2 and 3.
*LaneMask : Mask to mention which lane is enabled.
    LaneMask[0] for DL0.
    LaneMask[1] for CLK.
    LaneMask[2] for DL1.
    LaneMask[3] for DL2.
    LaneMask[4] for DL3
*LaneAssign : Number which describes the lane mapping between sensor and PHY.
    LaneAssign[0:3] is sensor lane number connected to data lane 0 of PHY on MSM
    LaneAssign[4:7] is sensor lane number connected to data lane 2 of PHY on MSM
    LaneAssign[8:11] is sensor lane number connected to data lane 3 of PHY on MSM
    LaneAssign[12:15] is sensor lane number connected to data lane 4 of PHY on MSM

    NOTE : Lane 1 is reserved for the clock lane.
        Wiring and setting it to a data lane is prohibited.
ComboMode :
    Flag to enable combo mode.
    This flag is enabled if multiple sensors are using same CSI-PHY receiver

LensInfo : Information of the lens present in the module.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

*FocalLength : FocalLength of the lens in micometers. Distance between the center of curvature to the focal point.
*FNumber : FNumber of the lens.
*TotalFocusDistance : The total distance in meters the lens could focus.
*HorizontalViewAngle : HorizontalViewAngle in degrees
*VerticalViewAngle : VerticalViewAngle in degrees
*MinFocusDistance : Minimum distance in meters the lens could focus.

*VARIABLES MARKED WITH ASTRICK (*) ARE MANDATORY.
-->
<CameraConfigurationRoot>
  <CameraModuleConfig>
        <CameraId>0</CameraId>                          // camera id =0,注意和 dts 中 cell-index 一致
        <SensorName>imx362</SensorName>                 // sensor name , 這個名字用來找到對應的 sensor lib 庫,所以不能錯了
        <ActuatorName>ak7374</ActuatorName>             // lens name ,用來找到對應的馬達驅動
        <EepromName>sony_imx362</EepromName>            // eeprom name, 用來找到對應的eeprom驅動
        <ChromatixName>imx362_chromatix</ChromatixName> // chromatix name,用來找到對應的效果文件
        <FlashName>pmic</FlashName>                     // flashlight name, 用來找到 mm-camera2\media-controller\modules\sensors\flash\libs 下面對應的庫
        <ModesSupported>1</ModesSupported>
        <Position>BACK</Position>                       // 後攝
        <MountAngle>90</MountAngle>                     // 旋轉90度,注意和 dts 中配置的一樣
        <CSIInfo>
              <CSIDCore>0</CSIDCore>                    // CS 0
              <LaneMask>0x1F</LaneMask>                 // 4 lane 和 1 clk 同時使能
              <LaneAssign>0x4320</LaneAssign>
              <ComboMode>0</ComboMode>
        </CSIInfo>
        <LensInfo>                                      // 馬達相關的參數,具體看模組 sepc
              <FocalLength>3.94</FocalLength>
              <FNumber>1.9</FNumber>
              <TotalFocusDistance>4.64</TotalFocusDistance>
              <HorizontalViewAngle>70.4</HorizontalViewAngle>
              <VerticalViewAngle>55.7</VerticalViewAngle>
              <MinFocusDistance>0.1</MinFocusDistance>
        </LensInfo>
  </CameraModuleConfig>
        <CameraModuleConfig>
        <CameraId>1</CameraId>                          // camera id =1
        <SensorName>imx350</SensorName>
        <ActuatorName>dw9800</ActuatorName>
        <EepromName>sony_imx350</EepromName>
        <ChromatixName>imx350_chromatix</ChromatixName>
        <ModesSupported>1</ModesSupported>
        <Position>BACK_AUX</Position>                   // 後二攝
        <MountAngle>90</MountAngle>
        <CSIInfo>
              <CSIDCore>1</CSIDCore>                    // CS 1
              <LaneMask>0x1F</LaneMask>
              <LaneAssign>0x4320</LaneAssign>
              <ComboMode>0</ComboMode>
        </CSIInfo>
        <LensInfo>
              <FocalLength>5.3</FocalLength>
              <FNumber>2.6</FNumber>
              <TotalFocusDistance>5.0</TotalFocusDistance>
              <HorizontalViewAngle>51.4</HorizontalViewAngle>
              <VerticalViewAngle>40.0</VerticalViewAngle>
              <MinFocusDistance>0.3</MinFocusDistance>
        </LensInfo>
  </CameraModuleConfig>
  <CameraModuleConfig>
        <CameraId>2</CameraId>                          // camera id =2
        <SensorName>s5k4h7yx</SensorName>
        <EepromName>holitech_s5k4h7yx</EepromName>
        <ChromatixName>s5k4h7yx_chromatix</ChromatixName>
        <ModesSupported>1</ModesSupported>
        <Position>FRONT</Position>                      // 前攝
        <MountAngle>270</MountAngle>                    // 旋轉270度
        <CSIInfo>
              <CSIDCore>2</CSIDCore>                    // CS2
              <LaneMask>0x1F</LaneMask>
              <LaneAssign>0x4320</LaneAssign>
              <ComboMode>0</ComboMode>
        </CSIInfo>
        <LensInfo>                                      // 馬達相關參數
              <FocalLength>2.47</FocalLength>
              <FNumber>2.0</FNumber>
              <TotalFocusDistance>1.9</TotalFocusDistance>
              <HorizontalViewAngle>63.84</HorizontalViewAngle>
              <VerticalViewAngle>47.88</VerticalViewAngle>
              <MinFocusDistance>0.1</MinFocusDistance>
        </LensInfo>
  </CameraModuleConfig>
</CameraConfigurationRoot>

3.3 sensors_configs_Android.mk

@\vendor\qcom\proprietary\mm-camera\mm-camera2\media-controller\modules\sensors\configs\Android.mk
在 Android.mk 中,添加 xml 編譯。

ifeq ($(call is-board-platform-in-list, sdm660),true)
include $(CLEAR_VARS)
LOCAL_MODULE:= camera_config.xml
LOCAL_MODULE_CLASS := EXECUTABLES
LOCAL_SRC_FILES := sdm660_camera.xml
LOCAL_MODULE_TAGS := optional
LOCAL_MODULE_PATH := $(TARGET_OUT)/etc/camera
LOCAL_MODULE_OWNER := qti
include $(BUILD_PREBUILT)

include $(CLEAR_VARS)
LOCAL_MODULE:= imx350_sunny.xml
LOCAL_MODULE_CLASS := EXECUTABLES
LOCAL_SRC_FILES := imx350_sunny.xml
LOCAL_MODULE_TAGS := optional
LOCAL_MODULE_PATH := $(TARGET_OUT)/etc/camera
LOCAL_MODULE_OWNER := qti
include $(BUILD_PREBUILT)

4. 導入 Camera AF 馬達lib庫代碼

在前面sdm660_camera.xml中,我們可以看出,
使用了 <ActuatorName>ak7374</ActuatorName>和<ActuatorName>dw9800</ActuatorName>這兩種馬達。

馬達lib庫代碼位於@vendor\qcom\proprietary\mm-camera\mm-camera2\media-controller\modules\sensors\actuator\libs中。

從 Android.mk中可以看出,各模塊名字爲:
LOCAL_MODULE := libactuator_dw9800
LOCAL_MODULE := libactuator_ak7374

導入代碼後,在 @\vendor\qcom\proprietary\common\config\device-vendor.mk
中添加如下代碼,將模塊導入進來:
MM_CAMERA += libactuator_dw9800
MM_CAMERA += libactuator_ak7374

5. 導入 Camera Flashlight 閃光燈lib庫代碼

在前面sdm660_camera.xml中,可以看出flashlight 使用的是默認的 <FlashName>pmic</FlashName>驅動。

代碼位置在 @\vendor\qcom\proprietary\mm-camera\mm-camera2\media-controller\modules\sensors\flash\libs\pmic

在Android.mk中,模塊名字爲:
LOCAL_MODULE := libflash_pmic

導入代碼後,在 @\vendor\qcom\proprietary\common\config\device-vendor.mk中添加如下代碼,將模塊導入進來:
MM_CAMERA += libflash_pmic

6. 導入 Camera Eeprom OTP lib庫代碼

在前面sdm660_camera.xml中,可以看出Eeprom使用的是默認的 <EepromName>sony_imx362</EepromName>和<EepromName>sony_imx350</EepromName>驅動。
代碼位置在 @\vendor\qcom\proprietary\mm-camera\mm-camera2\media-controller\modules\sensors\eeprom\libs\sony_imx350

在Android.mk中,模塊名字爲:
LOCAL_MODULE := libmmcamera_sony_imx350_eeprom

導入代碼後,在 @\vendor\qcom\proprietary\common\config\device-vendor.mk中添加如下代碼,將模塊導入進來:
MM_CAMERA += libmmcamera_sony_imx350_eeprom

好,至此,camera 代碼移植相關的工作就完了,如果這些相關的文件都配置正確的話,
接下來您就可以,編譯下載看下是否正常點亮,及抓log 調試下。

三、擴展

擴展一、 interrupts 中斷節點解析

interrupts = <0 78 0>;

(1)interrupt type

上述代碼中,interrupts 屬性中的第一個0是指 interrupt type。

在Linux系統中,它可以管理4種類型的中斷:

外設中斷(Peripheral interrupt)
根據目標CPU的不同,外設的中斷可以分成PPI(Private Peripheral Interrupt)和SPI(Shared Peripheral Interrupt)。
PPI只能分配給一個確定的processor,而SPI可以由Distributor將中斷分配給一組Processor中的一個進行處理。
外設類型的中斷一般通過一個interrupt request line的硬件信號線連接到中斷控制器,
可能是電平觸發的(Level-sensitive),也可能是邊緣觸發的(Edge-triggered)。

軟件觸發的中斷(SGI,Software-generated interrupt)
軟件可以通過寫GICD_SGIR寄存器來觸發一箇中斷事件,這樣的中斷,可以用於processor之間的通信。
SGI用於processor之間的通信,和外設無關。

虛擬中斷(Virtual interrupt)

Maintenance interrupt

(2)interrupt number

interrupts 屬性中的第二個78是指該外設使用的GIC interrupt ID號。

GIC最大支持1020個HW interrupt ID,具體的ID分配情況如下:

ID0 ~ ID31
ID0 ~ ID31是用於分發到一個特定的process的interrupt。
標識這些interrupt不能僅僅依靠ID,因爲各個interrupt source都用同樣的ID0 ~ ID31來標識,
因此識別這些interrupt需要interrupt ID + CPU interface number。

ID0 ~ ID15用於SGI,SGI是通過寫GICD_SGIR寄存器而觸發的中斷,Distributor通過processor source ID、中斷ID和target processor ID來唯一識別一個SGI
ID16 ~ ID31用於PPI,PPI類型的中斷會送到指定的process上,和其他的process無關。

ID32 ~ ID1019
ID32 ~ ID1019 用於SPI

(3)trigger type

觸發類型包括如下四種:

上升沿觸發
下降沿觸發
高電平觸發
低電平觸發
各自代碼定義如下:

bits[3:0] trigger type and level flags.
 1 = low-to-high edge triggered                         上升沿觸發
 2 = high-to-low edge triggered (invalid for SPIs)      下降沿觸發
 4 = active high level-sensitive                        高電平觸發
 8 = active low level-sensitive (invalid for SPIs)      低電平觸發

而代碼中 interrupts = <0 78 0>;
其中第三個的0 ,說明在DTS中並沒有初始化中斷觸發類型,內核通過request irq申請中斷的時候再來設置中斷觸發類型。

有關interrupt 相關的可以參考網友的文章:
《Linux DTS中和中斷相關屬性的解釋和用法》
《設備樹中中斷節點的創建》

擴展二、 光學防抖 OIS

光學防抖OIS,全稱OpticalImage Stabilization,從字面理解就是穩定的光學圖像。其工作原理是基於陀螺儀檢測並進行位移補償。即通過鏡頭內的陀螺儀偵測手機抖動產生的微小移動,然後將信號傳至CPU處理,CPU會即刻計算需要補償的位移量,再根據計算結果移動相機鏡片組中的懸浮鏡片,以抵消抖動產生的微小位移,從而有效克服因相機振動產生的影像模糊。

光學防抖的用處

提升暗光拍攝品質
夜景拍攝時,往往需要較長的曝光時間,此時快門速度較慢,手抖對於成像的影響就尤其明顯。使用光學防抖後,就可以削弱抖動影響,對各種抖動作相應的補償,有類似於三腳架的功效,能有效提高暗光下照片的質量。

穩定拍攝,提高視頻穩定性
錄製視頻時,錄製者的移動,走動,會帶來畫面跳動。使用光學防抖後,對由此產生的額外抖動作光學補償後,可減少畫面跳動,增強視頻連貫性;同時,光學防抖還能保證每一幀畫面的清晰度,使畫面中的字跡、綠植等紋理部分仍清晰可見。

原文鏈接:https://blog.csdn.net/Ciellee/article/details/105409928

至此,本篇已結束。轉載網絡的文章,小編覺得很優秀,歡迎點擊閱讀原文,支持原創作者,如有侵權,懇請聯繫小編刪除,歡迎您的建議與指正。同時期待您的關注,感謝您的閱讀,謝謝!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章