diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile index 4766765424fd..ae67bb3e23f9 100644 --- a/arch/arm/boot/dts/Makefile +++ b/arch/arm/boot/dts/Makefile @@ -1238,6 +1238,7 @@ dtb-$(CONFIG_ARCH_ROCKCHIP) += \ rk3506g-iotest-v10.dtb \ rk3506g-iotest-v10-pdm.dtb \ rk3506g-test1-v10-audio.dtb \ + rk3528-demo4-ddr4-v10.dtb \ rk3528-evb1-ddr4-v10.dtb \ rk3528-evb2-ddr3-v10.dtb \ rk3528-evb3-lp4x-v10.dtb \ diff --git a/arch/arm/boot/dts/rk3502.dtsi b/arch/arm/boot/dts/rk3502.dtsi index 1ad8c6d72918..7670de472f32 100644 --- a/arch/arm/boot/dts/rk3502.dtsi +++ b/arch/arm/boot/dts/rk3502.dtsi @@ -142,10 +142,13 @@ pvtpll_core: pvtpll-core@ff840000 { compatible = "rockchip,rk3506-core-pvtpll", "syscon"; reg = <0xff840000 0x100>; + clocks = <&cru ARMCLK>; #clock-cells = <0>; clock-output-names = "clk_core_pvtpll"; assigned-clocks = <&pvtpll_core>; assigned-clock-rates = <1200000000>; + nvmem-cells = <&cpu_opp_info>, <&specification_serial_number>; + nvmem-cell-names = "opp-info", "specification_serial_number"; }; sai0_fs: sai0-fs { @@ -213,23 +216,28 @@ compatible = "operating-points-v2"; opp-shared; - nvmem-cells = <&cpu_leakage>; - nvmem-cell-names = "leakage"; + mbist-vmin = <850000 900000 975000>; + nvmem-cells = <&cpu_leakage>, <&cpu_opp_info>, <&cpu_mbist_vmin>, <&cpu_pvtpll>, + <&specification_serial_number>; + nvmem-cell-names = "leakage", "opp-info", "mbist-vmin", "pvtm", + "specification_serial_number"; rockchip,temp-freq-table = < 85000 1008000 100000 600000 >; + rockchip,supported-hw; rockchip,pvtm-voltage-sel = < - 0 1584 0 - 1585 1619 1 - 1620 1654 2 - 1655 1689 3 - 1690 1724 4 - 1725 1759 5 - 1760 1794 6 - 1795 9999 7 + 0 1520 0 + 1521 1584 1 + 1585 1648 2 + 1649 1712 3 + 1713 1776 4 + 1777 1840 5 + 1841 1904 6 + 1905 1968 7 + 1969 9999 8 >; rockchip,pvtm-pvtpll; rockchip,pvtm-offset = <0x18>; @@ -242,70 +250,152 @@ rockchip,grf = <&pvtpll_core>; rockchip,temp-hysteresis = <5000>; rockchip,low-temp = <10000>; - rockchip,low-temp-min-volt = <900000>; + rockchip,low-temp-min-volt = <950000>; opp-600000000 { + opp-supported-hw = <0xf9 0xffff>; opp-hz = /bits/ 64 <600000000>; - opp-microvolt = <850000 850000 1000000>; + opp-microvolt = <850000 850000 1100000>; + opp-microvolt-L0 = <900000 900000 1100000>; + opp-microvolt-L1 = <900000 900000 1100000>; + opp-microvolt-L2 = <875000 875000 1100000>; clock-latency-ns = <40000>; opp-suspend; }; opp-800000000 { + opp-supported-hw = <0xf9 0xffff>; opp-hz = /bits/ 64 <800000000>; - opp-microvolt = <850000 850000 1000000>; + opp-microvolt = <850000 850000 1100000>; + opp-microvolt-L0 = <900000 900000 1100000>; + opp-microvolt-L1 = <900000 900000 1100000>; + opp-microvolt-L2 = <875000 875000 1100000>; clock-latency-ns = <40000>; }; opp-1008000000 { + opp-supported-hw = <0xf9 0xffff>; opp-hz = /bits/ 64 <1008000000>; - opp-microvolt = <850000 850000 1000000>; - opp-microvolt-L0 = <875000 875000 1000000>; + opp-microvolt = <850000 850000 1100000>; + opp-microvolt-L0 = <900000 900000 1100000>; + opp-microvolt-L1 = <900000 900000 1100000>; + opp-microvolt-L2 = <875000 875000 1100000>; clock-latency-ns = <40000>; }; opp-1200000000 { + opp-supported-hw = <0xf9 0xffff>; opp-hz = /bits/ 64 <1200000000>; - opp-microvolt = <850000 850000 1000000>; - opp-microvolt-L0 = <875000 875000 1000000>; + opp-microvolt = <900000 900000 1100000>; clock-latency-ns = <40000>; }; opp-1296000000 { + opp-supported-hw = <0xf9 0xffff>; opp-hz = /bits/ 64 <1296000000>; - opp-microvolt = <900000 900000 1000000>; - opp-microvolt-L0 = <900000 900000 1000000>; - opp-microvolt-L1 = <887500 887500 1000000>; - opp-microvolt-L2 = <875000 875000 1000000>; - opp-microvolt-L3 = <862500 862500 1000000>; - opp-microvolt-L4 = <850000 850000 1000000>; - opp-microvolt-L5 = <850000 850000 1000000>; - opp-microvolt-L6 = <850000 850000 1000000>; - opp-microvolt-L7 = <850000 850000 1000000>; + opp-microvolt = <900000 900000 1100000>; + opp-microvolt-L0 = <950000 950000 1100000>; + opp-microvolt-L1 = <925000 925000 1100000>; clock-latency-ns = <40000>; }; opp-1416000000 { + opp-supported-hw = <0xf9 0xffff>; opp-hz = /bits/ 64 <1416000000>; - opp-microvolt = <937500 937500 1000000>; - opp-microvolt-L0 = <937500 937500 1000000>; - opp-microvolt-L1 = <925000 925000 1000000>; - opp-microvolt-L2 = <912500 912500 1000000>; - opp-microvolt-L3 = <900000 900000 1000000>; - opp-microvolt-L4 = <887500 887500 1000000>; - opp-microvolt-L5 = <875000 875000 1000000>; - opp-microvolt-L6 = <862500 862500 1000000>; - opp-microvolt-L7 = <850000 850000 1000000>; + opp-microvolt = <900000 900000 1100000>; + opp-microvolt-L0 = <1000000 1000000 1100000>; + opp-microvolt-L1 = <975000 975000 1100000>; + opp-microvolt-L2 = <950000 950000 1100000>; + opp-microvolt-L3 = <925000 925000 1100000>; clock-latency-ns = <40000>; }; opp-1512000000 { + opp-supported-hw = <0xf9 0xffff>; opp-hz = /bits/ 64 <1512000000>; - opp-microvolt = <975000 975000 1000000>; - opp-microvolt-L0 = <975000 975000 1000000>; - opp-microvolt-L1 = <962500 962500 1000000>; - opp-microvolt-L2 = <950000 950000 1000000>; - opp-microvolt-L3 = <937500 937500 1000000>; - opp-microvolt-L4 = <925000 925000 1000000>; - opp-microvolt-L5 = <912500 912000 1000000>; - opp-microvolt-L6 = <900000 900000 1000000>; - opp-microvolt-L7 = <887500 887500 1000000>; + opp-microvolt = <900000 900000 1100000>; + opp-microvolt-L0 = <1050000 1050000 1100000>; + opp-microvolt-L1 = <1025000 1025000 1100000>; + opp-microvolt-L2 = <1000000 1000000 1100000>; + opp-microvolt-L3 = <975000 975000 1100000>; + opp-microvolt-L4 = <950000 950000 1100000>; + opp-microvolt-L5 = <925000 925000 1100000>; clock-latency-ns = <40000>; }; + opp-1608000000 { + opp-supported-hw = <0xf9 0xffff>; + opp-hz = /bits/ 64 <1608000000>; + opp-microvolt = <950000 950000 1100000>; + opp-microvolt-L0 = <1100000 1100000 1100000>; + opp-microvolt-L1 = <1075000 1075000 1100000>; + opp-microvolt-L2 = <1050000 1050000 1100000>; + opp-microvolt-L3 = <1025000 1025000 1100000>; + opp-microvolt-L4 = <1000000 1000000 1100000>; + opp-microvolt-L5 = <975000 975000 1100000>; + clock-latency-ns = <40000>; + }; + + /* RK3506J cpu OPPs */ + opp-j-600000000 { + opp-supported-hw = <0x04 0xffff>; + opp-hz = /bits/ 64 <600000000>; + opp-microvolt = <900000 900000 1050000>; + clock-latency-ns = <40000>; + opp-suspend; + }; + opp-j-800000000 { + opp-supported-hw = <0x04 0xffff>; + opp-hz = /bits/ 64 <800000000>; + opp-microvolt = <900000 900000 1050000>; + clock-latency-ns = <40000>; + }; + opp-j-1008000000 { + opp-supported-hw = <0x04 0xffff>; + opp-hz = /bits/ 64 <1008000000>; + opp-microvolt = <900000 900000 1050000>; + clock-latency-ns = <40000>; + }; + opp-j-1200000000 { + opp-supported-hw = <0x04 0xffff>; + opp-hz = /bits/ 64 <1200000000>; + opp-microvolt = <900000 900000 1050000>; + clock-latency-ns = <40000>; + }; + /* + * The Max frequency is 1200MHz in default normal mode. + * The Max frequency is 1512MHz in overdrive mode, + * but under the overdrive mode for a long time, + * the chipset may shorten the lifetime, especially in high + * temperature condition. Disable overdrive opps by default + * and you can enable them in dts file. + */ + cpu_opp_j_od_1296000000: opp-j-od-1296000000 { + opp-supported-hw = <0x04 0xffff>; + opp-hz = /bits/ 64 <1296000000>; + opp-microvolt = <925000 925000 1050000>; + opp-microvolt-L0 = <950000 950000 1050000>; + opp-microvolt-L1 = <950000 950000 1050000>; + clock-latency-ns = <40000>; + status = "disabled"; + }; + cpu_opp_j_od_1416000000: opp-j-od-1416000000 { + opp-supported-hw = <0x04 0xffff>; + opp-hz = /bits/ 64 <1416000000>; + opp-microvolt = <925000 925000 1050000>; + opp-microvolt-L0 = <1000000 1000000 1050000>; + opp-microvolt-L1 = <1000000 1000000 1050000>; + opp-microvolt-L2 = <975000 975000 1050000>; + opp-microvolt-L3 = <950000 950000 1050000>; + clock-latency-ns = <40000>; + status = "disabled"; + }; + cpu_opp_j_od_1512000000: opp-j-od-1512000000 { + opp-supported-hw = <0xf9 0xffff>; + opp-hz = /bits/ 64 <1512000000>; + opp-microvolt = <925000 925000 1050000>; + opp-microvolt-L0 = <1050000 1050000 1050000>; + opp-microvolt-L1 = <1050000 1050000 1050000>; + opp-microvolt-L2 = <1025000 1025000 1050000>; + opp-microvolt-L3 = <1000000 1000000 1050000>; + opp-microvolt-L4 = <975000 975000 1050000>; + opp-microvolt-L5 = <950000 950000 1050000>; + clock-latency-ns = <40000>; + status = "disabled"; + }; }; arm_pmu: arm-pmu { @@ -1085,6 +1175,10 @@ reg = <0x05 0x1>; bits = <3 3>; }; + specification_serial_number: specification-serial-number@8 { + reg = <0x08 0x1>; + bits = <0 5>; + }; otp_id: id@a { reg = <0x0a 0x10>; }; @@ -1101,6 +1195,16 @@ reg = <0x21 0x1>; bits = <0 2>; }; + cpu_opp_info: cpu-opp-info@24 { + reg = <0x24 0x6>; + }; + cpu_pvtpll: cpu-pvtpll@30 { + reg = <0x30 0x2>; + }; + cpu_mbist_vmin: mbist-vmin@33 { + reg = <0x33 0x1>; + bits = <0 4>; + }; }; audio_codec: audio-codec@ff4f8000 { diff --git a/arch/arm/boot/dts/rk3506-pinctrl.dtsi b/arch/arm/boot/dts/rk3506-pinctrl.dtsi index 0da9f08b27f1..7f6c6b89a24c 100644 --- a/arch/arm/boot/dts/rk3506-pinctrl.dtsi +++ b/arch/arm/boot/dts/rk3506-pinctrl.dtsi @@ -101,7 +101,7 @@ dsmc_clk_pins: dsmc-clk-pins { rockchip,pins = /* dsmc_clkn */ - <1 RK_PA1 2 &pcfg_pull_up>, + <1 RK_PA1 2 &pcfg_pull_up_drv_level_3>, /* dsmc_resetn */ <1 RK_PC0 2 &pcfg_pull_up>; }; @@ -123,7 +123,7 @@ dsmc_bus16_pins: dsmc-bus16-pins { rockchip,pins = /* dsmc_clkp */ - <1 RK_PA0 2 &pcfg_pull_down>, + <1 RK_PA0 2 &pcfg_pull_down_drv_level_3>, /* dsmc_d0 */ <1 RK_PA3 2 &pcfg_pull_down>, /* dsmc_d1 */ diff --git a/arch/arm/boot/dts/rk3528-demo4-ddr4-v10.dts b/arch/arm/boot/dts/rk3528-demo4-ddr4-v10.dts new file mode 100644 index 000000000000..78674a2c197e --- /dev/null +++ b/arch/arm/boot/dts/rk3528-demo4-ddr4-v10.dts @@ -0,0 +1,7 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright (c) 2024 Rockchip Electronics Co., Ltd. + * + */ + +#include "arm64/rockchip/rk3528-demo4-ddr4-v10.dts" diff --git a/arch/arm64/boot/dts/rockchip/px30-evb-ddr3-v10.dtsi b/arch/arm64/boot/dts/rockchip/px30-evb-ddr3-v10.dtsi index c733ca4b32c8..8ef7171c11b5 100644 --- a/arch/arm64/boot/dts/rockchip/px30-evb-ddr3-v10.dtsi +++ b/arch/arm64/boot/dts/rockchip/px30-evb-ddr3-v10.dtsi @@ -483,13 +483,13 @@ }; }; - vcc5v0_host: SWITCH_REG2 { + vcc5v0_host: SWITCH_REG1 { regulator-always-on; regulator-boot-on; regulator-name = "vcc5v0_host"; }; - vcc3v3_lcd: SWITCH_REG1 { + vcc3v3_lcd: SWITCH_REG2 { regulator-boot-on; regulator-name = "vcc3v3_lcd"; }; diff --git a/arch/arm64/boot/dts/rockchip/rk3328-evb.dts b/arch/arm64/boot/dts/rockchip/rk3328-evb.dts index 4e26244e112b..e2729fc3d483 100644 --- a/arch/arm64/boot/dts/rockchip/rk3328-evb.dts +++ b/arch/arm64/boot/dts/rockchip/rk3328-evb.dts @@ -138,6 +138,10 @@ }; }; +&analog_sound { + status = "okay"; +}; + &avsd { status = "okay"; }; @@ -232,6 +236,10 @@ status = "okay"; }; +&hdmi_sound { + status = "okay"; +}; + &hdmiphy { status = "okay"; }; diff --git a/arch/arm64/boot/dts/rockchip/rk3528-evb1-ddr4-v10.dtsi b/arch/arm64/boot/dts/rockchip/rk3528-evb1-ddr4-v10.dtsi index 822d6145d3e6..c3c340968ddd 100644 --- a/arch/arm64/boot/dts/rockchip/rk3528-evb1-ddr4-v10.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3528-evb1-ddr4-v10.dtsi @@ -17,7 +17,9 @@ compatible = "mmc-pwrseq-simple"; pinctrl-names = "default"; pinctrl-0 = <&wifi_enable_h &clkm1_32k_out>; + post-power-on-delay-ms = <200>; reset-gpios = <&gpio1 RK_PA6 GPIO_ACTIVE_LOW>; + status = "okay"; }; wireless_bluetooth: wireless-bluetooth { diff --git a/arch/arm64/boot/dts/rockchip/rk3576-vehicle-evb-v20-maxim-max96712-dcphy0-dummy.dtsi b/arch/arm64/boot/dts/rockchip/rk3576-vehicle-evb-v20-maxim-max96712-dcphy0-dummy.dtsi new file mode 100644 index 000000000000..7236bdab4d9d --- /dev/null +++ b/arch/arm64/boot/dts/rockchip/rk3576-vehicle-evb-v20-maxim-max96712-dcphy0-dummy.dtsi @@ -0,0 +1,709 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright (c) 2024 Rockchip Electronics Co., Ltd. + * + */ +#include + +/ { + max96712_dcphy0_osc: max96712-dcphy0-oscillator { + compatible = "fixed-clock"; + #clock-cells = <1>; + clock-frequency = <25000000>; + clock-output-names = "max96712-dcphy0-osc"; + }; + + max96712_dcphy0_vcc1v2: max96712-dcphy0-vcc1v2 { + compatible = "regulator-fixed"; + regulator-name = "max96712_dcphy0_vcc1v2"; + regulator-boot-on; + regulator-always-on; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1200000>; + startup-delay-us = <850>; + vin-supply = <&vcc_2v0_pldo_s3>; + }; + + max96712_dcphy0_vcc1v8: max96712-dcphy0-vcc1v8 { + compatible = "regulator-fixed"; + regulator-name = "max96712_dcphy0_vcc1v8"; + regulator-boot-on; + regulator-always-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + startup-delay-us = <200>; + vin-supply = <&vcc_2v0_pldo_s3>; + }; + + max96712_dcphy0_pwdn_regulator: max96712-dcphy0-pwdn-regulator { + compatible = "regulator-fixed"; + regulator-name = "max96712_dcphy0_pwdn"; + gpio = <&gpio2 RK_PA0 GPIO_ACTIVE_HIGH>; + pinctrl-names = "default"; + pinctrl-0 = <&max96712_dcphy0_pwdn>; + enable-active-high; + startup-delay-us = <10000>; + off-on-delay-us = <5000>; + }; + + max96712_dcphy0_poc_regulator: max96712-dcphy0-poc-regulator { + compatible = "regulator-fixed"; + regulator-name = "max96712_dcphy0_poc"; + gpio = <&i2c7_nca9539_gpio 2 GPIO_ACTIVE_HIGH>; + enable-active-high; + startup-delay-us = <10000>; + off-on-delay-us = <5000>; + vin-supply = <&dcphy0_vcc12v_buck1>; + }; +}; + +&csi2_dcphy0 { + status = "okay"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + port@0 { + reg = <0>; + #address-cells = <1>; + #size-cells = <0>; + + mipi_dcphy0_in_max96712: endpoint@1 { + reg = <1>; + remote-endpoint = <&max96712_dcphy0_out>; + data-lanes = <1 2 3 4>; + }; + }; + port@1 { + reg = <1>; + #address-cells = <1>; + #size-cells = <0>; + + csidcphy0_out: endpoint@0 { + reg = <0>; + remote-endpoint = <&mipi0_csi2_input>; + }; + }; + }; +}; + +&i2c7 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&i2c7m1_xfer>; + + max96712_dcphy0: max96712@29 { + compatible = "maxim4c,max96712"; + status = "okay"; + reg = <0x29>; + clock-names = "xvclk"; + clocks = <&max96712_dcphy0_osc 0>; + pinctrl-names = "default"; + pinctrl-0 = <&max96712_dcphy0_errb>, <&max96712_dcphy0_lock>; + power-domains = <&power RK3576_PD_VI>; + rockchip,grf = <&sys_grf>; + vcc1v2-supply = <&max96712_dcphy0_vcc1v2>; + vcc1v8-supply = <&max96712_dcphy0_vcc1v8>; + pwdn-supply = <&max96712_dcphy0_pwdn_regulator>; + lock-gpios = <&gpio2 RK_PA2 GPIO_ACTIVE_HIGH>; + + rockchip,camera-module-index = <0>; + rockchip,camera-module-facing = "back"; + rockchip,camera-module-name = "default"; + rockchip,camera-module-lens-name = "default"; + + port { + max96712_dcphy0_out: endpoint { + remote-endpoint = <&mipi_dcphy0_in_max96712>; + data-lanes = <1 2 3 4>; + }; + }; + + /* support mode config start */ + support-mode-config { + status = "okay"; + + bus-format = ; + sensor-width = <1920>; + sensor-height = <1440>; + max-fps-numerator = <10000>; + max-fps-denominator = <300000>; + bpp = <16>; + link-freq-idx = <20>; + }; + /* support mode config end */ + + /* serdes local device start */ + serdes-local-device { + status = "okay"; + + /* GMSL LINK config start */ + gmsl-links { + status = "okay"; + + link-vdd-ldo1-en = <1>; + link-vdd-ldo2-en = <1>; + + // Link A: link-id = 0 + gmsl-link-config-0 { + status = "okay"; + link-id = <0>; // Link ID: 0/1/2/3 + + link-type = <1>; // 0: GMSL1, 1: GMSL2 + link-rx-rate = <1>; // 0: 3GBPS, 1: 6GBPS + link-tx-rate = <0>; // 0: default for 187.5MBPS + + link-remote-cam = <&max96712_dcphy0_cam0>; // remote camera + + link-init-sequence { + seq-item-size = <5>; // reg-addr-len + reg-val-len * 2 + 1 + reg-addr-len = <2>; // 1: 8bits, 2: 16bits + reg-val-len = <1>; // 1: 8bits, 2: 16bits, 3: 24bits + + // reg_addr reg_val val_mask delay + init-sequence = [ + 14 D1 03 00 00 // VGAHiGain + 14 45 00 00 00 // Disable SSC + ]; + }; + }; + + // Link B: link-id = 1 + gmsl-link-config-1 { + status = "okay"; + link-id = <1>; // Link ID: 0/1/2/3 + + link-type = <1>; // 0: GMSL1, 1: GMSL2 + link-rx-rate = <1>; // 0: 3GBPS, 1: 6GBPS + link-tx-rate = <0>; // 0: default for 187.5MBPS + + link-remote-cam = <&max96712_dcphy0_cam1>; // remote camera + + link-init-sequence { + seq-item-size = <5>; // reg-addr-len + reg-val-len * 2 + 1 + reg-addr-len = <2>; // 1: 8bits, 2: 16bits + reg-val-len = <1>; // 1: 8bits, 2: 16bits, 3: 24bits + + // reg_addr reg_val val_mask delay + init-sequence = [ + 15 D1 03 00 00 // VGAHiGain + 15 45 00 00 00 // Disable SSC + ]; + }; + }; + + // Link C: link-id = 2 + gmsl-link-config-2 { + status = "okay"; + link-id = <2>; // Link ID: 0/1/2/3 + + link-type = <1>; // 0: GMSL1, 1: GMSL2 + link-rx-rate = <1>; // 0: 3GBPS, 1: 6GBPS + link-tx-rate = <0>; // 0: default for 187.5MBPS + + link-remote-cam = <&max96712_dcphy0_cam2>; // remote camera + + link-init-sequence { + seq-item-size = <5>; // reg-addr-len + reg-val-len * 2 + 1 + reg-addr-len = <2>; // 1: 8bits, 2: 16bits + reg-val-len = <1>; // 1: 8bits, 2: 16bits, 3: 24bits + + // reg_addr reg_val val_mask delay + init-sequence = [ + 16 D1 03 00 00 // VGAHiGain + 16 45 00 00 00 // Disable SSC + ]; + }; + }; + + // Link D: link-id = 3 + gmsl-link-config-3 { + status = "okay"; + link-id = <3>; // Link ID: 0/1/2/3 + + link-type = <1>; // 0: GMSL1, 1: GMSL2 + link-rx-rate = <1>; // 0: 3GBPS, 1: 6GBPS + link-tx-rate = <0>; // 0: default for 187.5MBPS + + link-remote-cam = <&max96712_dcphy0_cam3>; // remote camera + + link-init-sequence { + seq-item-size = <5>; // reg-addr-len + reg-val-len * 2 + 1 + reg-addr-len = <2>; // 1: 8bits, 2: 16bits + reg-val-len = <1>; // 1: 8bits, 2: 16bits, 3: 24bits + + // reg_addr reg_val val_mask delay + init-sequence = [ + 17 D1 03 00 00 // VGAHiGain + 17 45 00 00 00 // Disable SSC + ]; + }; + }; + }; + /* GMSL LINK config end */ + + /* VIDEO PIPE config start */ + video-pipes { + status = "okay"; + + // Video Pipe 0 + video-pipe-config-0 { + status = "okay"; + pipe-id = <0>; // Video Pipe ID: 0/1/2/3/4/5/6/7 + + pipe-idx = <2>; // Video Pipe X/Y/Z/U: 0/1/2/3 + link-idx = <0>; // Link A/B/C/D: 0/1/2/3 + + pipe-init-sequence { + seq-item-size = <5>; // reg-addr-len + reg-val-len * 2 + 1 + reg-addr-len = <2>; // 1: 8bits, 2: 16bits + reg-val-len = <1>; // 1: 8bits, 2: 16bits, 3: 24bits + + // reg_addr reg_val val_mask delay + init-sequence = [ + // Send YUV422, FS, and FE from Video Pipe 0 to Controller 1 + 09 0B 07 00 00 // Enable 0/1/2 SRC/DST Mappings + 09 2D 15 00 00 // SRC/DST 0/1/2 -> CSI2 Controller 1; + // For the following MSB 2 bits = VC, LSB 6 bits = DT + 09 0D 1e 00 00 // SRC0 VC = 0, DT = YUV422 8bit + 09 0E 1e 00 00 // DST0 VC = 0, DT = YUV422 8bit + 09 0F 00 00 00 // SRC1 VC = 0, DT = Frame Start + 09 10 00 00 00 // DST1 VC = 0, DT = Frame Start + 09 11 01 00 00 // SRC2 VC = 0, DT = Frame End + 09 12 01 00 00 // DST2 VC = 0, DT = Frame End + ]; + }; + }; + + // Video Pipe 1 + video-pipe-config-1 { + status = "okay"; + pipe-id = <1>; // Video Pipe 1: pipe-id = 1 + + pipe-idx = <2>; // Video Pipe X/Y/Z/U: 0/1/2/3 + link-idx = <1>; // Link A/B/C/D: 0/1/2/3 + + pipe-init-sequence { + seq-item-size = <5>; // reg-addr-len + reg-val-len * 2 + 1 + reg-addr-len = <2>; // 1: 8bits, 2: 16bits + reg-val-len = <1>; // 1: 8bits, 2: 16bits, 3: 24bits + + // reg_addr reg_val val_mask delay + init-sequence = [ + // Send YUV422, FS, and FE from Video Pipe 1 to Controller 1 + 09 4B 07 00 00 // Enable 0/1/2 SRC/DST Mappings + 09 6D 15 00 00 // SRC/DST 0/1/2 -> CSI2 Controller 1; + // For the following MSB 2 bits = VC, LSB 6 bits = DT + 09 4D 1e 00 00 // SRC0 VC = 0, DT = YUV422 8bit + 09 4E 5e 00 00 // DST0 VC = 1, DT = YUV422 8bit + 09 4F 00 00 00 // SRC1 VC = 0, DT = Frame Start + 09 50 40 00 00 // DST1 VC = 1, DT = Frame Start + 09 51 01 00 00 // SRC2 VC = 0, DT = Frame End + 09 52 41 00 00 // DST2 VC = 1, DT = Frame End + ]; + }; + }; + + // Video Pipe 2 + video-pipe-config-2 { + status = "okay"; + pipe-id = <2>; // Video Pipe ID: 0/1/2/3/4/5/6/7 + + pipe-idx = <2>; // Video Pipe X/Y/Z/U: 0/1/2/3 + link-idx = <2>; // Link A/B/C/D: 0/1/2/3 + + pipe-init-sequence { + seq-item-size = <5>; // reg-addr-len + reg-val-len * 2 + 1 + reg-addr-len = <2>; // 1: 8bits, 2: 16bits + reg-val-len = <1>; // 1: 8bits, 2: 16bits, 3: 24bits + + // reg_addr reg_val val_mask delay + init-sequence = [ + // Send YUV422, FS, and FE from Video Pipe 2 to Controller 1 + 09 8B 07 00 00 // Enable 0/1/2 SRC/DST Mappings + 09 AD 15 00 00 // SRC/DST 0/1/2 -> CSI2 Controller 1; + // For the following MSB 2 bits = VC, LSB 6 bits = DT + 09 8D 1e 00 00 // SRC0 VC = 0, DT = YUV422 8bit + 09 8E 9e 00 00 // DST0 VC = 2, DT = YUV422 8bit + 09 8F 00 00 00 // SRC1 VC = 0, DT = Frame Start + 09 90 80 00 00 // DST1 VC = 2, DT = Frame Start + 09 91 01 00 00 // SRC2 VC = 0, DT = Frame End + 09 92 81 00 00 // DST2 VC = 2, DT = Frame End + ]; + }; + }; + + // Video Pipe 3 + video-pipe-config-3 { + status = "okay"; + pipe-id = <3>; // Video Pipe ID: 0/1/2/3/4/5/6/7 + + pipe-idx = <2>; // Video Pipe X/Y/Z/U: 0/1/2/3 + link-idx = <3>; // Link A/B/C/D: 0/1/2/3 + + pipe-init-sequence { + seq-item-size = <5>; // reg-addr-len + reg-val-len * 2 + 1 + reg-addr-len = <2>; // 1: 8bits, 2: 16bits + reg-val-len = <1>; // 1: 8bits, 2: 16bits, 3: 24bits + + // reg_addr reg_val val_mask delay + init-sequence = [ + // Send YUV422, FS, and FE from Video Pipe 3 to Controller 1 + 09 CB 07 00 00 // Enable 0/1/2 SRC/DST Mappings + 09 ED 15 00 00 // SRC/DST 0/1/2 -> CSI2 Controller 1; + // For the following MSB 2 bits = VC, LSB 6 bits = DT + 09 CD 1e 00 00 // SRC0 VC = 0, DT = YUV422 8bit + 09 CE de 00 00 // DST0 VC = 3, DT = YUV422 8bit + 09 CF 00 00 00 // SRC1 VC = 0, DT = Frame Start + 09 D0 c0 00 00 // DST1 VC = 3, DT = Frame Start + 09 D1 01 00 00 // SRC2 VC = 0, DT = Frame End + 09 D2 c1 00 00 // DST2 VC = 3, DT = Frame End + ]; + }; + }; + }; + /* VIDEO PIPE config end */ + + /* MIPI TXPHY config start */ + mipi-txphys { + status = "okay"; + + phy-mode = <0>; // 0: 4Lanes, 1: 2Lanes + phy-force-clock-out = <1>; // 1: default for force clock out + phy-force-clk0-en = <1>; // provide MIPI clock: 0 = PHY1, 1 = PHY0 + phy-force-clk3-en = <0>; // provide MIPI clock: 0 = PHY2, 1 = PHY3 + + // MIPI TXPHY A: phy-id = 0 + mipi-txphy-config-0 { + status = "okay"; + phy-id = <0>; // MIPI TXPHY ID: 0/1/2/3 + + phy-type = <0>; // 0: DPHY, 1: CPHY + auto-deskew = <0x80>; + data-lane-num = <4>; + data-lane-map = <0x4>; + vc-ext-en = <0>; + }; + + // MIPI TXPHY B: phy-id = 1 + mipi-txphy-config-1 { + status = "okay"; + phy-id = <1>; // MIPI TXPHY ID: 0/1/2/3 + + phy-type = <0>; // 0: DPHY, 1: CPHY + auto-deskew = <0x80>; + data-lane-num = <4>; + data-lane-map = <0xe>; + vc-ext-en = <0>; + }; + }; + /* MIPI TXPHY config end */ + + /* local device extra init sequence */ + extra-init-sequence { + status = "disabled"; + + seq-item-size = <5>; // reg-addr-len + reg-val-len * 2 + 1 + reg-addr-len = <2>; // 1: 8bits, 2: 16bits + reg-val-len = <1>; // 1: 8bits, 2: 16bits, 3: 24bits + + // reg_addr reg_val val_mask delay + init-sequence = [ + // common init sequence such as fsync / gpio and so on + ]; + }; + }; + /* serdes local device end */ + + /* i2c-mux start */ + i2c-mux { + #address-cells = <1>; + #size-cells = <0>; + + i2c@0 { + #address-cells = <1>; + #size-cells = <0>; + reg = <0>; + + // Note: Serializer node defined before camera node + max96712_dcphy0_ser0: max96717@51 { + compatible = "maxim,ser,max96717"; + reg = <0x51>; + + ser-i2c-addr-def = <0x40>; + + ser-init-sequence { + seq-item-size = <5>; // reg-addr-len + reg-val-len * 2 + 1 + reg-addr-len = <2>; // 1: 8bits, 2: 16bits + reg-val-len = <1>; // 1: 8bits, 2: 16bits, 3: 24bits + + // reg_addr reg_val val_mask delay + init-sequence = [ + 03 02 10 00 00 + 14 17 00 00 00 + 14 32 7f 00 00 + ]; + }; + }; + + max96712_dcphy0_cam0: dummy@31 { + compatible = "maxim,dummy,sensor"; + reg = <0x31>; + + cam-i2c-addr-def = <0x30>; + + cam-remote-ser = <&max96712_dcphy0_ser0>; // remote serializer + + poc-supply = <&max96712_dcphy0_poc_regulator>; + + rockchip,camera-module-index = <0>; + rockchip,camera-module-facing = "back"; + rockchip,camera-module-name = "default"; + rockchip,camera-module-lens-name = "default"; + + /* port config start */ + port { + max96712_dcphy0_cam0_out: endpoint { + data-lanes = <1 2 3 4>; + }; + }; + /* port config end */ + }; + }; + + i2c@1 { + #address-cells = <1>; + #size-cells = <0>; + reg = <1>; + + // Note: Serializer node defined before camera node + max96712_dcphy0_ser1: max96717@52 { + compatible = "maxim,ser,max96717"; + reg = <0x52>; + + ser-i2c-addr-def = <0x40>; + + ser-init-sequence { + seq-item-size = <5>; // reg-addr-len + reg-val-len * 2 + 1 + reg-addr-len = <2>; // 1: 8bits, 2: 16bits + reg-val-len = <1>; // 1: 8bits, 2: 16bits, 3: 24bits + + // reg_addr reg_val val_mask delay + init-sequence = [ + 03 02 10 00 00 + 14 17 00 00 00 + 14 32 7f 00 00 + ]; + }; + }; + + max96712_dcphy0_cam1: dummy@32 { + compatible = "maxim,dummy,sensor"; + reg = <0x32>; + + cam-i2c-addr-def = <0x30>; + + cam-remote-ser = <&max96712_dcphy0_ser1>; // remote serializer + + poc-supply = <&max96712_dcphy0_poc_regulator>; + + rockchip,camera-module-index = <1>; + rockchip,camera-module-facing = "back"; + rockchip,camera-module-name = "default"; + rockchip,camera-module-lens-name = "default"; + + /* port config start */ + port { + max96712_dcphy0_cam1_out: endpoint { + data-lanes = <1 2 3 4>; + }; + }; + /* port config end */ + }; + }; + + i2c@2 { + #address-cells = <1>; + #size-cells = <0>; + reg = <2>; + + // Note: Serializer node defined before camera node + max96712_dcphy0_ser2: max96717@53 { + compatible = "maxim,ser,max96717"; + reg = <0x53>; + + ser-i2c-addr-def = <0x40>; + + ser-init-sequence { + seq-item-size = <5>; // reg-addr-len + reg-val-len * 2 + 1 + reg-addr-len = <2>; // 1: 8bits, 2: 16bits + reg-val-len = <1>; // 1: 8bits, 2: 16bits, 3: 24bits + + // reg_addr reg_val val_mask delay + init-sequence = [ + 03 02 10 00 00 + 14 17 00 00 00 + 14 32 7f 00 00 + ]; + }; + }; + + max96712_dcphy0_cam2: dummy@33 { + compatible = "maxim,dummy,sensor"; + reg = <0x33>; + + cam-i2c-addr-def = <0x30>; + + cam-remote-ser = <&max96712_dcphy0_ser2>; // remote serializer + + poc-supply = <&max96712_dcphy0_poc_regulator>; + + rockchip,camera-module-index = <2>; + rockchip,camera-module-facing = "back"; + rockchip,camera-module-name = "default"; + rockchip,camera-module-lens-name = "default"; + + /* port config start */ + port { + max96712_dcphy0_cam2_out: endpoint { + data-lanes = <1 2 3 4>; + }; + }; + /* port config end */ + }; + }; + + i2c@3 { + #address-cells = <1>; + #size-cells = <0>; + reg = <3>; + + // Note: Serializer node defined before camera node + max96712_dcphy0_ser3: max96717@54 { + compatible = "maxim,ser,max96717"; + reg = <0x54>; + + ser-i2c-addr-def = <0x40>; + + ser-init-sequence { + seq-item-size = <5>; // reg-addr-len + reg-val-len * 2 + 1 + reg-addr-len = <2>; // 1: 8bits, 2: 16bits + reg-val-len = <1>; // 1: 8bits, 2: 16bits, 3: 24bits + + // reg_addr reg_val val_mask delay + init-sequence = [ + 03 02 10 00 00 + 14 17 00 00 00 + 14 32 7f 00 00 + ]; + }; + }; + + max96712_dcphy0_cam3: dummy@34 { + compatible = "maxim,dummy,sensor"; + reg = <0x34>; + + cam-i2c-addr-def = <0x30>; + + cam-remote-ser = <&max96712_dcphy0_ser3>; // remote serializer + + poc-supply = <&max96712_dcphy0_poc_regulator>; + + rockchip,camera-module-index = <3>; + rockchip,camera-module-facing = "back"; + rockchip,camera-module-name = "default"; + rockchip,camera-module-lens-name = "default"; + + /* port config start */ + port { + max96712_dcphy0_cam3_out: endpoint { + data-lanes = <1 2 3 4>; + }; + }; + /* port config end */ + }; + }; + }; + /* i2c-mux end */ + }; +}; + +&mipi0_csi2 { + status = "okay"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + #address-cells = <1>; + #size-cells = <0>; + + mipi0_csi2_input: endpoint@1 { + reg = <1>; + remote-endpoint = <&csidcphy0_out>; + }; + }; + + port@1 { + reg = <1>; + #address-cells = <1>; + #size-cells = <0>; + + mipi0_csi2_output: endpoint@0 { + reg = <0>; + remote-endpoint = <&cif_mipi0_in>; + }; + }; + }; +}; + +&rkcif_mipi_lvds { + status = "okay"; + /* parameters for do cif reset detecting: + * index0: monitor mode, + 0 for idle, + 1 for continue, + 2 for trigger, + 3 for hotplug (for nextchip) + * index1: the frame id to start timer, + min is 2 + * index2: frame num of monitoring cycle + * index3: err time for keep monitoring + after finding out err (ms) + * index4: csi2 err reference val for resetting + */ + rockchip,cif-monitor = <3 2 1 1000 5>; + + port { + cif_mipi0_in: endpoint { + remote-endpoint = <&mipi0_csi2_output>; + }; + }; +}; + +&rkcif { + status = "okay"; + rockchip,android-usb-camerahal-enable; +}; + +&rkcif_mmu { + status = "okay"; +}; + +&pinctrl { + max96712-dcphy0 { + max96712_dcphy0_pwdn: max96712-dcphy0-pwdn { + rockchip,pins = <2 RK_PA0 RK_FUNC_GPIO &pcfg_output_low>; + }; + + max96712_dcphy0_errb: max96712-dcphy0-errb { + rockchip,pins = <2 RK_PA1 RK_FUNC_GPIO &pcfg_pull_none_smt>; + }; + + max96712_dcphy0_lock: max96712-dcphy0-lock { + rockchip,pins = <2 RK_PA2 RK_FUNC_GPIO &pcfg_pull_none_smt>; + }; + }; +}; diff --git a/arch/arm64/boot/dts/rockchip/rk3576-vehicle-evb-v20-maxim-max96712-dcphy0-isx021.dtsi b/arch/arm64/boot/dts/rockchip/rk3576-vehicle-evb-v20-maxim-max96712-dcphy0-isx021.dtsi new file mode 100644 index 000000000000..8efc11645df5 --- /dev/null +++ b/arch/arm64/boot/dts/rockchip/rk3576-vehicle-evb-v20-maxim-max96712-dcphy0-isx021.dtsi @@ -0,0 +1,721 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright (c) 2024 Rockchip Electronics Co., Ltd. + * + */ +#include + +/ { + max96712_dcphy0_osc: max96712-dcphy0-oscillator { + compatible = "fixed-clock"; + #clock-cells = <1>; + clock-frequency = <25000000>; + clock-output-names = "max96712-dcphy0-osc"; + }; + + max96712_dcphy0_vcc1v2: max96712-dcphy0-vcc1v2 { + compatible = "regulator-fixed"; + regulator-name = "max96712_dcphy0_vcc1v2"; + regulator-boot-on; + regulator-always-on; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1200000>; + startup-delay-us = <850>; + vin-supply = <&vcc_2v0_pldo_s3>; + }; + + max96712_dcphy0_vcc1v8: max96712-dcphy0-vcc1v8 { + compatible = "regulator-fixed"; + regulator-name = "max96712_dcphy0_vcc1v8"; + regulator-boot-on; + regulator-always-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + startup-delay-us = <200>; + vin-supply = <&vcc_2v0_pldo_s3>; + }; + + max96712_dcphy0_pwdn_regulator: max96712-dcphy0-pwdn-regulator { + compatible = "regulator-fixed"; + regulator-name = "max96712_dcphy0_pwdn"; + gpio = <&gpio2 RK_PA0 GPIO_ACTIVE_HIGH>; + pinctrl-names = "default"; + pinctrl-0 = <&max96712_dcphy0_pwdn>; + enable-active-high; + startup-delay-us = <10000>; + off-on-delay-us = <5000>; + }; + + max96712_dcphy0_poc_regulator: max96712-dcphy0-poc-regulator { + compatible = "regulator-fixed"; + regulator-name = "max96712_dcphy0_poc"; + gpio = <&i2c7_nca9539_gpio 2 GPIO_ACTIVE_HIGH>; + enable-active-high; + startup-delay-us = <10000>; + off-on-delay-us = <5000>; + vin-supply = <&dcphy0_vcc12v_buck1>; + }; +}; + +&csi2_dcphy0 { + status = "okay"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + port@0 { + reg = <0>; + #address-cells = <1>; + #size-cells = <0>; + + mipi_dcphy0_in_max96712: endpoint@1 { + reg = <1>; + remote-endpoint = <&max96712_dcphy0_out>; + data-lanes = <1 2 3 4>; + }; + }; + port@1 { + reg = <1>; + #address-cells = <1>; + #size-cells = <0>; + + csidcphy0_out: endpoint@0 { + reg = <0>; + remote-endpoint = <&mipi0_csi2_input>; + }; + }; + }; +}; + +&i2c7 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&i2c7m1_xfer>; + + max96712_dcphy0: max96712@29 { + compatible = "maxim4c,max96712"; + status = "okay"; + reg = <0x29>; + clock-names = "xvclk"; + clocks = <&max96712_dcphy0_osc 0>; + pinctrl-names = "default"; + pinctrl-0 = <&max96712_dcphy0_errb>, <&max96712_dcphy0_lock>; + power-domains = <&power RK3576_PD_VI>; + rockchip,grf = <&sys_grf>; + vcc1v2-supply = <&max96712_dcphy0_vcc1v2>; + vcc1v8-supply = <&max96712_dcphy0_vcc1v8>; + pwdn-supply = <&max96712_dcphy0_pwdn_regulator>; + lock-gpios = <&gpio2 RK_PA2 GPIO_ACTIVE_HIGH>; + + rockchip,camera-module-index = <0>; + rockchip,camera-module-facing = "back"; + rockchip,camera-module-name = "default"; + rockchip,camera-module-lens-name = "default"; + + port { + max96712_dcphy0_out: endpoint { + remote-endpoint = <&mipi_dcphy0_in_max96712>; + data-lanes = <1 2 3 4>; + }; + }; + + /* support mode config start */ + support-mode-config { + status = "okay"; + + bus-format = ; + sensor-width = <1920>; + sensor-height = <1281>; + crop-rect = <0 1 1920 1280>; // [ left, top, width, height ] + max-fps-numerator = <10000>; + max-fps-denominator = <300000>; + bpp = <16>; + link-freq-idx = <20>; + }; + /* support mode config end */ + + /* serdes local device start */ + serdes-local-device { + status = "okay"; + + /* GMSL LINK config start */ + gmsl-links { + status = "okay"; + + link-vdd-ldo1-en = <1>; + link-vdd-ldo2-en = <1>; + + // Link A: link-id = 0 + gmsl-link-config-0 { + status = "okay"; + link-id = <0>; // Link ID: 0/1/2/3 + + link-type = <1>; // 0: GMSL1, 1: GMSL2 + link-rx-rate = <0>; // 0: 3GBPS, 1: 6GBPS + link-tx-rate = <0>; // 0: default for 187.5MBPS + + link-remote-cam = <&max96712_dcphy0_cam0>; // remote camera + + link-init-sequence { + seq-item-size = <5>; // reg-addr-len + reg-val-len * 2 + 1 + reg-addr-len = <2>; // 1: 8bits, 2: 16bits + reg-val-len = <1>; // 1: 8bits, 2: 16bits, 3: 24bits + + // reg_addr reg_val val_mask delay + init-sequence = [ + 14 D1 03 00 00 // VGAHiGain + 14 45 00 00 00 // Disable SSC + ]; + }; + }; + + // Link B: link-id = 1 + gmsl-link-config-1 { + status = "okay"; + link-id = <1>; // Link ID: 0/1/2/3 + + link-type = <1>; // 0: GMSL1, 1: GMSL2 + link-rx-rate = <0>; // 0: 3GBPS, 1: 6GBPS + link-tx-rate = <0>; // 0: default for 187.5MBPS + + link-remote-cam = <&max96712_dcphy0_cam1>; // remote camera + + link-init-sequence { + seq-item-size = <5>; // reg-addr-len + reg-val-len * 2 + 1 + reg-addr-len = <2>; // 1: 8bits, 2: 16bits + reg-val-len = <1>; // 1: 8bits, 2: 16bits, 3: 24bits + + // reg_addr reg_val val_mask delay + init-sequence = [ + 15 D1 03 00 00 // VGAHiGain + 15 45 00 00 00 // Disable SSC + ]; + }; + }; + + // Link C: link-id = 2 + gmsl-link-config-2 { + status = "okay"; + link-id = <2>; // Link ID: 0/1/2/3 + + link-type = <1>; // 0: GMSL1, 1: GMSL2 + link-rx-rate = <0>; // 0: 3GBPS, 1: 6GBPS + link-tx-rate = <0>; // 0: default for 187.5MBPS + + link-remote-cam = <&max96712_dcphy0_cam2>; // remote camera + + link-init-sequence { + seq-item-size = <5>; // reg-addr-len + reg-val-len * 2 + 1 + reg-addr-len = <2>; // 1: 8bits, 2: 16bits + reg-val-len = <1>; // 1: 8bits, 2: 16bits, 3: 24bits + + // reg_addr reg_val val_mask delay + init-sequence = [ + 16 D1 03 00 00 // VGAHiGain + 16 45 00 00 00 // Disable SSC + ]; + }; + }; + + // Link D: link-id = 3 + gmsl-link-config-3 { + status = "okay"; + link-id = <3>; // Link ID: 0/1/2/3 + + link-type = <1>; // 0: GMSL1, 1: GMSL2 + link-rx-rate = <0>; // 0: 3GBPS, 1: 6GBPS + link-tx-rate = <0>; // 0: default for 187.5MBPS + + link-remote-cam = <&max96712_dcphy0_cam3>; // remote camera + + link-init-sequence { + seq-item-size = <5>; // reg-addr-len + reg-val-len * 2 + 1 + reg-addr-len = <2>; // 1: 8bits, 2: 16bits + reg-val-len = <1>; // 1: 8bits, 2: 16bits, 3: 24bits + + // reg_addr reg_val val_mask delay + init-sequence = [ + 17 D1 03 00 00 // VGAHiGain + 17 45 00 00 00 // Disable SSC + ]; + }; + }; + }; + /* GMSL LINK config end */ + + /* VIDEO PIPE config start */ + video-pipes { + status = "okay"; + + // Video Pipe 0 + video-pipe-config-0 { + status = "okay"; + pipe-id = <0>; // Video Pipe ID: 0/1/2/3/4/5/6/7 + + pipe-idx = <2>; // Video Pipe X/Y/Z/U: 0/1/2/3 + link-idx = <0>; // Link A/B/C/D: 0/1/2/3 + + pipe-init-sequence { + seq-item-size = <5>; // reg-addr-len + reg-val-len * 2 + 1 + reg-addr-len = <2>; // 1: 8bits, 2: 16bits + reg-val-len = <1>; // 1: 8bits, 2: 16bits, 3: 24bits + + // reg_addr reg_val val_mask delay + init-sequence = [ + // Send YUV422, FS, and FE from Video Pipe 0 to Controller 1 + 09 0B 07 00 00 // Enable 0/1/2 SRC/DST Mappings + 09 2D 15 00 00 // SRC/DST 0/1/2 -> CSI2 Controller 1; + // For the following MSB 2 bits = VC, LSB 6 bits = DT + 09 0D 1e 00 00 // SRC0 VC = 0, DT = YUV422 8bit + 09 0E 1e 00 00 // DST0 VC = 0, DT = YUV422 8bit + 09 0F 00 00 00 // SRC1 VC = 0, DT = Frame Start + 09 10 00 00 00 // DST1 VC = 0, DT = Frame Start + 09 11 01 00 00 // SRC2 VC = 0, DT = Frame End + 09 12 01 00 00 // DST2 VC = 0, DT = Frame End + ]; + }; + }; + + // Video Pipe 1 + video-pipe-config-1 { + status = "okay"; + pipe-id = <1>; // Video Pipe 1: pipe-id = 1 + + pipe-idx = <2>; // Video Pipe X/Y/Z/U: 0/1/2/3 + link-idx = <1>; // Link A/B/C/D: 0/1/2/3 + + pipe-init-sequence { + seq-item-size = <5>; // reg-addr-len + reg-val-len * 2 + 1 + reg-addr-len = <2>; // 1: 8bits, 2: 16bits + reg-val-len = <1>; // 1: 8bits, 2: 16bits, 3: 24bits + + // reg_addr reg_val val_mask delay + init-sequence = [ + // Send YUV422, FS, and FE from Video Pipe 1 to Controller 1 + 09 4B 07 00 00 // Enable 0/1/2 SRC/DST Mappings + 09 6D 15 00 00 // SRC/DST 0/1/2 -> CSI2 Controller 1; + // For the following MSB 2 bits = VC, LSB 6 bits = DT + 09 4D 1e 00 00 // SRC0 VC = 0, DT = YUV422 8bit + 09 4E 5e 00 00 // DST0 VC = 1, DT = YUV422 8bit + 09 4F 00 00 00 // SRC1 VC = 0, DT = Frame Start + 09 50 40 00 00 // DST1 VC = 1, DT = Frame Start + 09 51 01 00 00 // SRC2 VC = 0, DT = Frame End + 09 52 41 00 00 // DST2 VC = 1, DT = Frame End + ]; + }; + }; + + // Video Pipe 2 + video-pipe-config-2 { + status = "okay"; + pipe-id = <2>; // Video Pipe ID: 0/1/2/3/4/5/6/7 + + pipe-idx = <2>; // Video Pipe X/Y/Z/U: 0/1/2/3 + link-idx = <2>; // Link A/B/C/D: 0/1/2/3 + + pipe-init-sequence { + seq-item-size = <5>; // reg-addr-len + reg-val-len * 2 + 1 + reg-addr-len = <2>; // 1: 8bits, 2: 16bits + reg-val-len = <1>; // 1: 8bits, 2: 16bits, 3: 24bits + + // reg_addr reg_val val_mask delay + init-sequence = [ + // Send YUV422, FS, and FE from Video Pipe 2 to Controller 1 + 09 8B 07 00 00 // Enable 0/1/2 SRC/DST Mappings + 09 AD 15 00 00 // SRC/DST 0/1/2 -> CSI2 Controller 1; + // For the following MSB 2 bits = VC, LSB 6 bits = DT + 09 8D 1e 00 00 // SRC0 VC = 0, DT = YUV422 8bit + 09 8E 9e 00 00 // DST0 VC = 2, DT = YUV422 8bit + 09 8F 00 00 00 // SRC1 VC = 0, DT = Frame Start + 09 90 80 00 00 // DST1 VC = 2, DT = Frame Start + 09 91 01 00 00 // SRC2 VC = 0, DT = Frame End + 09 92 81 00 00 // DST2 VC = 2, DT = Frame End + ]; + }; + }; + + // Video Pipe 3 + video-pipe-config-3 { + status = "okay"; + pipe-id = <3>; // Video Pipe ID: 0/1/2/3/4/5/6/7 + + pipe-idx = <2>; // Video Pipe X/Y/Z/U: 0/1/2/3 + link-idx = <3>; // Link A/B/C/D: 0/1/2/3 + + pipe-init-sequence { + seq-item-size = <5>; // reg-addr-len + reg-val-len * 2 + 1 + reg-addr-len = <2>; // 1: 8bits, 2: 16bits + reg-val-len = <1>; // 1: 8bits, 2: 16bits, 3: 24bits + + // reg_addr reg_val val_mask delay + init-sequence = [ + // Send YUV422, FS, and FE from Video Pipe 3 to Controller 1 + 09 CB 07 00 00 // Enable 0/1/2 SRC/DST Mappings + 09 ED 15 00 00 // SRC/DST 0/1/2 -> CSI2 Controller 1; + // For the following MSB 2 bits = VC, LSB 6 bits = DT + 09 CD 1e 00 00 // SRC0 VC = 0, DT = YUV422 8bit + 09 CE de 00 00 // DST0 VC = 3, DT = YUV422 8bit + 09 CF 00 00 00 // SRC1 VC = 0, DT = Frame Start + 09 D0 c0 00 00 // DST1 VC = 3, DT = Frame Start + 09 D1 01 00 00 // SRC2 VC = 0, DT = Frame End + 09 D2 c1 00 00 // DST2 VC = 3, DT = Frame End + ]; + }; + }; + }; + /* VIDEO PIPE config end */ + + /* MIPI TXPHY config start */ + mipi-txphys { + status = "okay"; + + phy-mode = <0>; // 0: 4Lanes, 1: 2Lanes + phy-force-clock-out = <1>; // 1: default for force clock out + phy-force-clk0-en = <1>; // provide MIPI clock: 0 = PHY1, 1 = PHY0 + phy-force-clk3-en = <0>; // provide MIPI clock: 0 = PHY2, 1 = PHY3 + + // MIPI TXPHY A: phy-id = 0 + mipi-txphy-config-0 { + status = "okay"; + phy-id = <0>; // MIPI TXPHY ID: 0/1/2/3 + + phy-type = <0>; // 0: DPHY, 1: CPHY + auto-deskew = <0x80>; + data-lane-num = <4>; + data-lane-map = <0x4>; + vc-ext-en = <0>; + }; + + // MIPI TXPHY B: phy-id = 1 + mipi-txphy-config-1 { + status = "okay"; + phy-id = <1>; // MIPI TXPHY ID: 0/1/2/3 + + phy-type = <0>; // 0: DPHY, 1: CPHY + auto-deskew = <0x80>; + data-lane-num = <4>; + data-lane-map = <0xe>; + vc-ext-en = <0>; + }; + }; + /* MIPI TXPHY config end */ + + /* local device extra init sequence */ + extra-init-sequence { + status = "okay"; + + seq-item-size = <5>; // reg-addr-len + reg-val-len * 2 + 1 + reg-addr-len = <2>; // 1: 8bits, 2: 16bits + reg-val-len = <1>; // 1: 8bits, 2: 16bits, 3: 24bits + + // reg_addr reg_val val_mask delay + init-sequence = [ + // common init sequence such as fsync / gpio and so on + 04 A2 00 00 00 // Master link Video 0 for frame sync generation + 04 AA 00 00 00 // Disable Vsync-Fsync overlap window + 04 AB 00 00 00 // Disable Vsync-Fsync overlap window + 04 A8 00 00 00 // FRM_DIFF_ERR_THR_L + 04 A9 00 00 00 // FRM_DIFF_ERR_THR_H + 04 A7 0c 00 00 // FSYNC_PERIOD_H, Set FSYNC period to 25M/30 clock cycles. PCLK = 25MHz. Sync freq = 30Hz + 04 A6 bf 00 00 // FSYNC_PERIOD_M + 04 A5 35 00 00 // FSYNC_PERIOD_L + 04 AF c0 00 00 // FSYNC is GMSL2 type, use osc for fsync + 04 B1 40 00 00 // FSYNC_TX_ID: set 8 to match MFP8 on serializer side + 04 A0 04 00 00 // MFP2, VS not gen internally, GPIO not used to gen fsync, manual mode + ]; + }; + }; + /* serdes local device end */ + + /* i2c-mux start */ + i2c-mux { + #address-cells = <1>; + #size-cells = <0>; + + i2c@0 { + #address-cells = <1>; + #size-cells = <0>; + reg = <0>; + + // Note: Serializer node defined before camera node + max96712_dcphy0_ser0: max96717@51 { + compatible = "maxim,ser,max96717f"; + reg = <0x51>; + + ser-i2c-addr-def = <0x40>; + + ser-init-sequence { + seq-item-size = <5>; // reg-addr-len + reg-val-len * 2 + 1 + reg-addr-len = <2>; // 1: 8bits, 2: 16bits + reg-val-len = <1>; // 1: 8bits, 2: 16bits, 3: 24bits + + // reg_addr reg_val val_mask delay + init-sequence = [ + 03 02 10 00 00 + 14 17 00 00 00 + 14 32 7f 00 00 + ]; + }; + }; + + max96712_dcphy0_cam0: isx021@31 { + compatible = "maxim,dummy,sensor"; + reg = <0x31>; + + cam-i2c-addr-def = <0x30>; + + cam-remote-ser = <&max96712_dcphy0_ser0>; // remote serializer + + poc-supply = <&max96712_dcphy0_poc_regulator>; + + rockchip,camera-module-index = <0>; + rockchip,camera-module-facing = "back"; + rockchip,camera-module-name = "default"; + rockchip,camera-module-lens-name = "default"; + + /* port config start */ + port { + max96712_dcphy0_cam0_out: endpoint { + data-lanes = <1 2 3 4>; + }; + }; + /* port config end */ + }; + }; + + i2c@1 { + #address-cells = <1>; + #size-cells = <0>; + reg = <1>; + + // Note: Serializer node defined before camera node + max96712_dcphy0_ser1: max96717@52 { + compatible = "maxim,ser,max96717f"; + reg = <0x52>; + + ser-i2c-addr-def = <0x40>; + + ser-init-sequence { + seq-item-size = <5>; // reg-addr-len + reg-val-len * 2 + 1 + reg-addr-len = <2>; // 1: 8bits, 2: 16bits + reg-val-len = <1>; // 1: 8bits, 2: 16bits, 3: 24bits + + // reg_addr reg_val val_mask delay + init-sequence = [ + 03 02 10 00 00 + 14 17 00 00 00 + 14 32 7f 00 00 + ]; + }; + }; + + max96712_dcphy0_cam1: isx021@32 { + compatible = "maxim,dummy,sensor"; + reg = <0x32>; + + cam-i2c-addr-def = <0x30>; + + cam-remote-ser = <&max96712_dcphy0_ser1>; // remote serializer + + poc-supply = <&max96712_dcphy0_poc_regulator>; + + rockchip,camera-module-index = <1>; + rockchip,camera-module-facing = "back"; + rockchip,camera-module-name = "default"; + rockchip,camera-module-lens-name = "default"; + + /* port config start */ + port { + max96712_dcphy0_cam1_out: endpoint { + data-lanes = <1 2 3 4>; + }; + }; + /* port config end */ + }; + }; + + i2c@2 { + #address-cells = <1>; + #size-cells = <0>; + reg = <2>; + + // Note: Serializer node defined before camera node + max96712_dcphy0_ser2: max96717@53 { + compatible = "maxim,ser,max96717f"; + reg = <0x53>; + + ser-i2c-addr-def = <0x40>; + + ser-init-sequence { + seq-item-size = <5>; // reg-addr-len + reg-val-len * 2 + 1 + reg-addr-len = <2>; // 1: 8bits, 2: 16bits + reg-val-len = <1>; // 1: 8bits, 2: 16bits, 3: 24bits + + // reg_addr reg_val val_mask delay + init-sequence = [ + 03 02 10 00 00 + 14 17 00 00 00 + 14 32 7f 00 00 + ]; + }; + }; + + max96712_dcphy0_cam2: isx021@33 { + compatible = "maxim,dummy,sensor"; + reg = <0x33>; + + cam-i2c-addr-def = <0x30>; + + cam-remote-ser = <&max96712_dcphy0_ser2>; // remote serializer + + poc-supply = <&max96712_dcphy0_poc_regulator>; + + rockchip,camera-module-index = <2>; + rockchip,camera-module-facing = "back"; + rockchip,camera-module-name = "default"; + rockchip,camera-module-lens-name = "default"; + + /* port config start */ + port { + max96712_dcphy0_cam2_out: endpoint { + data-lanes = <1 2 3 4>; + }; + }; + /* port config end */ + }; + }; + + i2c@3 { + #address-cells = <1>; + #size-cells = <0>; + reg = <3>; + + // Note: Serializer node defined before camera node + max96712_dcphy0_ser3: max96717@54 { + compatible = "maxim,ser,max96717f"; + reg = <0x54>; + + ser-i2c-addr-def = <0x40>; + + ser-init-sequence { + seq-item-size = <5>; // reg-addr-len + reg-val-len * 2 + 1 + reg-addr-len = <2>; // 1: 8bits, 2: 16bits + reg-val-len = <1>; // 1: 8bits, 2: 16bits, 3: 24bits + + // reg_addr reg_val val_mask delay + init-sequence = [ + 03 02 10 00 00 + 14 17 00 00 00 + 14 32 7f 00 00 + ]; + }; + }; + + max96712_dcphy0_cam3: isx021@34 { + compatible = "maxim,dummy,sensor"; + reg = <0x34>; + + cam-i2c-addr-def = <0x30>; + + cam-remote-ser = <&max96712_dcphy0_ser3>; // remote serializer + + poc-supply = <&max96712_dcphy0_poc_regulator>; + + rockchip,camera-module-index = <3>; + rockchip,camera-module-facing = "back"; + rockchip,camera-module-name = "default"; + rockchip,camera-module-lens-name = "default"; + + /* port config start */ + port { + max96712_dcphy0_cam3_out: endpoint { + data-lanes = <1 2 3 4>; + }; + }; + /* port config end */ + }; + }; + }; + /* i2c-mux end */ + }; +}; + +&mipi0_csi2 { + status = "okay"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + #address-cells = <1>; + #size-cells = <0>; + + mipi0_csi2_input: endpoint@1 { + reg = <1>; + remote-endpoint = <&csidcphy0_out>; + }; + }; + + port@1 { + reg = <1>; + #address-cells = <1>; + #size-cells = <0>; + + mipi0_csi2_output: endpoint@0 { + reg = <0>; + remote-endpoint = <&cif_mipi0_in>; + }; + }; + }; +}; + +&rkcif_mipi_lvds { + status = "okay"; + /* parameters for do cif reset detecting: + * index0: monitor mode, + 0 for idle, + 1 for continue, + 2 for trigger, + 3 for hotplug (for nextchip) + * index1: the frame id to start timer, + min is 2 + * index2: frame num of monitoring cycle + * index3: err time for keep monitoring + after finding out err (ms) + * index4: csi2 err reference val for resetting + */ + rockchip,cif-monitor = <3 2 1 1000 5>; + + port { + cif_mipi0_in: endpoint { + remote-endpoint = <&mipi0_csi2_output>; + }; + }; +}; + +&rkcif { + status = "okay"; + rockchip,android-usb-camerahal-enable; +}; + +&rkcif_mmu { + status = "okay"; +}; + +&pinctrl { + max96712-dcphy0 { + max96712_dcphy0_pwdn: max96712-dcphy0-pwdn { + rockchip,pins = <2 RK_PA0 RK_FUNC_GPIO &pcfg_output_low>; + }; + + max96712_dcphy0_errb: max96712-dcphy0-errb { + rockchip,pins = <2 RK_PA1 RK_FUNC_GPIO &pcfg_pull_none_smt>; + }; + + max96712_dcphy0_lock: max96712-dcphy0-lock { + rockchip,pins = <2 RK_PA2 RK_FUNC_GPIO &pcfg_pull_none_smt>; + }; + }; +}; diff --git a/arch/arm64/boot/dts/rockchip/rk3576-vehicle-evb-v20-maxim-max96712-dphy0-dummy.dtsi b/arch/arm64/boot/dts/rockchip/rk3576-vehicle-evb-v20-maxim-max96712-dphy0-dummy.dtsi new file mode 100644 index 000000000000..eda4f66d6f51 --- /dev/null +++ b/arch/arm64/boot/dts/rockchip/rk3576-vehicle-evb-v20-maxim-max96712-dphy0-dummy.dtsi @@ -0,0 +1,713 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright (c) 2024 Rockchip Electronics Co., Ltd. + * + */ +#include + +/ { + max96712_dphy0_osc: max96712-dphy0-oscillator { + compatible = "fixed-clock"; + #clock-cells = <1>; + clock-frequency = <25000000>; + clock-output-names = "max96712-dphy0-osc"; + }; + + max96712_dphy0_vcc1v2: max96712-dphy0-vcc1v2 { + compatible = "regulator-fixed"; + regulator-name = "max96712_dphy0_vcc1v2"; + regulator-boot-on; + regulator-always-on; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1200000>; + startup-delay-us = <850>; + vin-supply = <&vcc_2v0_pldo_s3>; + }; + + max96712_dphy0_vcc1v8: max96712-dphy0-vcc1v8 { + compatible = "regulator-fixed"; + regulator-name = "max96712_dphy0_vcc1v8"; + regulator-boot-on; + regulator-always-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + startup-delay-us = <200>; + vin-supply = <&vcc_2v0_pldo_s3>; + }; + + max96712_dphy0_pwdn_regulator: max96712-dphy0-pwdn-regulator { + compatible = "regulator-fixed"; + regulator-name = "max96712_dphy0_pwdn"; + gpio = <&gpio2 RK_PA3 GPIO_ACTIVE_HIGH>; + pinctrl-names = "default"; + pinctrl-0 = <&max96712_dphy0_pwdn>; + enable-active-high; + startup-delay-us = <10000>; + off-on-delay-us = <5000>; + }; + + max96712_dphy0_poc_regulator: max96712-dphy0-poc0-regulator { + compatible = "regulator-fixed"; + regulator-name = "max96712_dphy0_poc"; + gpio = <&i2c7_nca9539_gpio 15 GPIO_ACTIVE_HIGH>; + enable-active-high; + startup-delay-us = <10000>; + off-on-delay-us = <5000>; + vin-supply = <&dphy0_vcc12v_buck1>; + }; +}; + +&csi2_dphy0_hw { + status = "okay"; +}; + +&csi2_dphy0 { + status = "okay"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + port@0 { + reg = <0>; + #address-cells = <1>; + #size-cells = <0>; + + mipi_dphy0_in_max96712: endpoint@1 { + reg = <1>; + remote-endpoint = <&max96712_dphy0_out>; + data-lanes = <1 2 3 4>; + }; + }; + port@1 { + reg = <1>; + #address-cells = <1>; + #size-cells = <0>; + + csidphy0_out: endpoint@0 { + reg = <0>; + remote-endpoint = <&mipi1_csi2_input>; + }; + }; + }; +}; + +&i2c7 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&i2c7m1_xfer>; + + max96712_dphy0: max96712@29 { + compatible = "maxim4c,max96712"; + status = "okay"; + reg = <0x29>; + clock-names = "xvclk"; + clocks = <&max96712_dphy0_osc 0>; + pinctrl-names = "default"; + pinctrl-0 = <&max96712_dphy0_errb>, <&max96712_dphy0_lock>; + power-domains = <&power RK3576_PD_VI>; + rockchip,grf = <&sys_grf>; + vcc1v2-supply = <&max96712_dphy0_vcc1v2>; + vcc1v8-supply = <&max96712_dphy0_vcc1v8>; + pwdn-supply = <&max96712_dphy0_pwdn_regulator>; + lock-gpios = <&gpio2 RK_PA5 GPIO_ACTIVE_HIGH>; + + rockchip,camera-module-index = <0>; + rockchip,camera-module-facing = "back"; + rockchip,camera-module-name = "default"; + rockchip,camera-module-lens-name = "default"; + + port { + max96712_dphy0_out: endpoint { + remote-endpoint = <&mipi_dphy0_in_max96712>; + data-lanes = <1 2 3 4>; + }; + }; + + /* support mode config start */ + support-mode-config { + status = "okay"; + + bus-format = ; + sensor-width = <1920>; + sensor-height = <1440>; + max-fps-numerator = <10000>; + max-fps-denominator = <300000>; + bpp = <16>; + link-freq-idx = <20>; + }; + /* support mode config end */ + + /* serdes local device start */ + serdes-local-device { + status = "okay"; + + /* GMSL LINK config start */ + gmsl-links { + status = "okay"; + + link-vdd-ldo1-en = <1>; + link-vdd-ldo2-en = <1>; + + // Link A: link-id = 0 + gmsl-link-config-0 { + status = "okay"; + link-id = <0>; // Link ID: 0/1/2/3 + + link-type = <1>; // 0: GMSL1, 1: GMSL2 + link-rx-rate = <1>; // 0: 3GBPS, 1: 6GBPS + link-tx-rate = <0>; // 0: default for 187.5MBPS + + link-remote-cam = <&max96712_dphy0_cam0>; // remote camera + + link-init-sequence { + seq-item-size = <5>; // reg-addr-len + reg-val-len * 2 + 1 + reg-addr-len = <2>; // 1: 8bits, 2: 16bits + reg-val-len = <1>; // 1: 8bits, 2: 16bits, 3: 24bits + + // reg_addr reg_val val_mask delay + init-sequence = [ + 14 D1 03 00 00 // VGAHiGain + 14 45 00 00 00 // Disable SSC + ]; + }; + }; + + // Link B: link-id = 1 + gmsl-link-config-1 { + status = "okay"; + link-id = <1>; // Link ID: 0/1/2/3 + + link-type = <1>; // 0: GMSL1, 1: GMSL2 + link-rx-rate = <1>; // 0: 3GBPS, 1: 6GBPS + link-tx-rate = <0>; // 0: default for 187.5MBPS + + link-remote-cam = <&max96712_dphy0_cam1>; // remote camera + + link-init-sequence { + seq-item-size = <5>; // reg-addr-len + reg-val-len * 2 + 1 + reg-addr-len = <2>; // 1: 8bits, 2: 16bits + reg-val-len = <1>; // 1: 8bits, 2: 16bits, 3: 24bits + + // reg_addr reg_val val_mask delay + init-sequence = [ + 15 D1 03 00 00 // VGAHiGain + 15 45 00 00 00 // Disable SSC + ]; + }; + }; + + // Link C: link-id = 2 + gmsl-link-config-2 { + status = "okay"; + link-id = <2>; // Link ID: 0/1/2/3 + + link-type = <1>; // 0: GMSL1, 1: GMSL2 + link-rx-rate = <1>; // 0: 3GBPS, 1: 6GBPS + link-tx-rate = <0>; // 0: default for 187.5MBPS + + link-remote-cam = <&max96712_dphy0_cam2>; // remote camera + + link-init-sequence { + seq-item-size = <5>; // reg-addr-len + reg-val-len * 2 + 1 + reg-addr-len = <2>; // 1: 8bits, 2: 16bits + reg-val-len = <1>; // 1: 8bits, 2: 16bits, 3: 24bits + + // reg_addr reg_val val_mask delay + init-sequence = [ + 16 D1 03 00 00 // VGAHiGain + 16 45 00 00 00 // Disable SSC + ]; + }; + }; + + // Link D: link-id = 3 + gmsl-link-config-3 { + status = "okay"; + link-id = <3>; // Link ID: 0/1/2/3 + + link-type = <1>; // 0: GMSL1, 1: GMSL2 + link-rx-rate = <1>; // 0: 3GBPS, 1: 6GBPS + link-tx-rate = <0>; // 0: default for 187.5MBPS + + link-remote-cam = <&max96712_dphy0_cam3>; // remote camera + + link-init-sequence { + seq-item-size = <5>; // reg-addr-len + reg-val-len * 2 + 1 + reg-addr-len = <2>; // 1: 8bits, 2: 16bits + reg-val-len = <1>; // 1: 8bits, 2: 16bits, 3: 24bits + + // reg_addr reg_val val_mask delay + init-sequence = [ + 17 D1 03 00 00 // VGAHiGain + 17 45 00 00 00 // Disable SSC + ]; + }; + }; + }; + /* GMSL LINK config end */ + + /* VIDEO PIPE config start */ + video-pipes { + status = "okay"; + + // Video Pipe 0 + video-pipe-config-0 { + status = "okay"; + pipe-id = <0>; // Video Pipe ID: 0/1/2/3/4/5/6/7 + + pipe-idx = <2>; // Video Pipe X/Y/Z/U: 0/1/2/3 + link-idx = <0>; // Link A/B/C/D: 0/1/2/3 + + pipe-init-sequence { + seq-item-size = <5>; // reg-addr-len + reg-val-len * 2 + 1 + reg-addr-len = <2>; // 1: 8bits, 2: 16bits + reg-val-len = <1>; // 1: 8bits, 2: 16bits, 3: 24bits + + // reg_addr reg_val val_mask delay + init-sequence = [ + // Send YUV422, FS, and FE from Video Pipe 0 to Controller 1 + 09 0B 07 00 00 // Enable 0/1/2 SRC/DST Mappings + 09 2D 15 00 00 // SRC/DST 0/1/2 -> CSI2 Controller 1; + // For the following MSB 2 bits = VC, LSB 6 bits = DT + 09 0D 1e 00 00 // SRC0 VC = 0, DT = YUV422 8bit + 09 0E 1e 00 00 // DST0 VC = 0, DT = YUV422 8bit + 09 0F 00 00 00 // SRC1 VC = 0, DT = Frame Start + 09 10 00 00 00 // DST1 VC = 0, DT = Frame Start + 09 11 01 00 00 // SRC2 VC = 0, DT = Frame End + 09 12 01 00 00 // DST2 VC = 0, DT = Frame End + ]; + }; + }; + + // Video Pipe 1 + video-pipe-config-1 { + status = "okay"; + pipe-id = <1>; // Video Pipe 1: pipe-id = 1 + + pipe-idx = <2>; // Video Pipe X/Y/Z/U: 0/1/2/3 + link-idx = <1>; // Link A/B/C/D: 0/1/2/3 + + pipe-init-sequence { + seq-item-size = <5>; // reg-addr-len + reg-val-len * 2 + 1 + reg-addr-len = <2>; // 1: 8bits, 2: 16bits + reg-val-len = <1>; // 1: 8bits, 2: 16bits, 3: 24bits + + // reg_addr reg_val val_mask delay + init-sequence = [ + // Send YUV422, FS, and FE from Video Pipe 1 to Controller 1 + 09 4B 07 00 00 // Enable 0/1/2 SRC/DST Mappings + 09 6D 15 00 00 // SRC/DST 0/1/2 -> CSI2 Controller 1; + // For the following MSB 2 bits = VC, LSB 6 bits = DT + 09 4D 1e 00 00 // SRC0 VC = 0, DT = YUV422 8bit + 09 4E 5e 00 00 // DST0 VC = 1, DT = YUV422 8bit + 09 4F 00 00 00 // SRC1 VC = 0, DT = Frame Start + 09 50 40 00 00 // DST1 VC = 1, DT = Frame Start + 09 51 01 00 00 // SRC2 VC = 0, DT = Frame End + 09 52 41 00 00 // DST2 VC = 1, DT = Frame End + ]; + }; + }; + + // Video Pipe 2 + video-pipe-config-2 { + status = "okay"; + pipe-id = <2>; // Video Pipe ID: 0/1/2/3/4/5/6/7 + + pipe-idx = <2>; // Video Pipe X/Y/Z/U: 0/1/2/3 + link-idx = <2>; // Link A/B/C/D: 0/1/2/3 + + pipe-init-sequence { + seq-item-size = <5>; // reg-addr-len + reg-val-len * 2 + 1 + reg-addr-len = <2>; // 1: 8bits, 2: 16bits + reg-val-len = <1>; // 1: 8bits, 2: 16bits, 3: 24bits + + // reg_addr reg_val val_mask delay + init-sequence = [ + // Send YUV422, FS, and FE from Video Pipe 2 to Controller 1 + 09 8B 07 00 00 // Enable 0/1/2 SRC/DST Mappings + 09 AD 15 00 00 // SRC/DST 0/1/2 -> CSI2 Controller 1; + // For the following MSB 2 bits = VC, LSB 6 bits = DT + 09 8D 1e 00 00 // SRC0 VC = 0, DT = YUV422 8bit + 09 8E 9e 00 00 // DST0 VC = 2, DT = YUV422 8bit + 09 8F 00 00 00 // SRC1 VC = 0, DT = Frame Start + 09 90 80 00 00 // DST1 VC = 2, DT = Frame Start + 09 91 01 00 00 // SRC2 VC = 0, DT = Frame End + 09 92 81 00 00 // DST2 VC = 2, DT = Frame End + ]; + }; + }; + + // Video Pipe 3 + video-pipe-config-3 { + status = "okay"; + pipe-id = <3>; // Video Pipe ID: 0/1/2/3/4/5/6/7 + + pipe-idx = <2>; // Video Pipe X/Y/Z/U: 0/1/2/3 + link-idx = <3>; // Link A/B/C/D: 0/1/2/3 + + pipe-init-sequence { + seq-item-size = <5>; // reg-addr-len + reg-val-len * 2 + 1 + reg-addr-len = <2>; // 1: 8bits, 2: 16bits + reg-val-len = <1>; // 1: 8bits, 2: 16bits, 3: 24bits + + // reg_addr reg_val val_mask delay + init-sequence = [ + // Send YUV422, FS, and FE from Video Pipe 3 to Controller 1 + 09 CB 07 00 00 // Enable 0/1/2 SRC/DST Mappings + 09 ED 15 00 00 // SRC/DST 0/1/2 -> CSI2 Controller 1; + // For the following MSB 2 bits = VC, LSB 6 bits = DT + 09 CD 1e 00 00 // SRC0 VC = 0, DT = YUV422 8bit + 09 CE de 00 00 // DST0 VC = 3, DT = YUV422 8bit + 09 CF 00 00 00 // SRC1 VC = 0, DT = Frame Start + 09 D0 c0 00 00 // DST1 VC = 3, DT = Frame Start + 09 D1 01 00 00 // SRC2 VC = 0, DT = Frame End + 09 D2 c1 00 00 // DST2 VC = 3, DT = Frame End + ]; + }; + }; + }; + /* VIDEO PIPE config end */ + + /* MIPI TXPHY config start */ + mipi-txphys { + status = "okay"; + + phy-mode = <0>; // 0: 4Lanes, 1: 2Lanes + phy-force-clock-out = <1>; // 1: default for force clock out + phy-force-clk0-en = <1>; // provide MIPI clock: 0 = PHY1, 1 = PHY0 + phy-force-clk3-en = <0>; // provide MIPI clock: 0 = PHY2, 1 = PHY3 + + // MIPI TXPHY A: phy-id = 0 + mipi-txphy-config-0 { + status = "okay"; + phy-id = <0>; // MIPI TXPHY ID: 0/1/2/3 + + phy-type = <0>; // 0: DPHY, 1: CPHY + auto-deskew = <0x80>; + data-lane-num = <4>; + data-lane-map = <0x4>; + vc-ext-en = <0>; + }; + + // MIPI TXPHY B: phy-id = 1 + mipi-txphy-config-1 { + status = "okay"; + phy-id = <1>; // MIPI TXPHY ID: 0/1/2/3 + + phy-type = <0>; // 0: DPHY, 1: CPHY + auto-deskew = <0x80>; + data-lane-num = <4>; + data-lane-map = <0xe>; + vc-ext-en = <0>; + }; + }; + /* MIPI TXPHY config end */ + + /* local device extra init sequence */ + extra-init-sequence { + status = "disabled"; + + seq-item-size = <5>; // reg-addr-len + reg-val-len * 2 + 1 + reg-addr-len = <2>; // 1: 8bits, 2: 16bits + reg-val-len = <1>; // 1: 8bits, 2: 16bits, 3: 24bits + + // reg_addr reg_val val_mask delay + init-sequence = [ + // common init sequence such as fsync / gpio and so on + ]; + }; + }; + /* serdes local device end */ + + /* i2c-mux start */ + i2c-mux { + #address-cells = <1>; + #size-cells = <0>; + + i2c@0 { + #address-cells = <1>; + #size-cells = <0>; + reg = <0>; + + // Note: Serializer node defined before camera node + max96712_dphy0_ser0: max96717@51 { + compatible = "maxim,ser,max96717"; + reg = <0x51>; + + ser-i2c-addr-def = <0x40>; + + ser-init-sequence { + seq-item-size = <5>; // reg-addr-len + reg-val-len * 2 + 1 + reg-addr-len = <2>; // 1: 8bits, 2: 16bits + reg-val-len = <1>; // 1: 8bits, 2: 16bits, 3: 24bits + + // reg_addr reg_val val_mask delay + init-sequence = [ + 03 02 10 00 00 + 14 17 00 00 00 + 14 32 7f 00 00 + ]; + }; + }; + + max96712_dphy0_cam0: dummy@31 { + compatible = "maxim,dummy,sensor"; + reg = <0x31>; + + cam-i2c-addr-def = <0x30>; + + cam-remote-ser = <&max96712_dphy0_ser0>; // remote serializer + + poc-supply = <&max96712_dphy0_poc_regulator>; + + rockchip,camera-module-index = <0>; + rockchip,camera-module-facing = "back"; + rockchip,camera-module-name = "default"; + rockchip,camera-module-lens-name = "default"; + + /* port config start */ + port { + max96712_dphy0_cam0_out: endpoint { + data-lanes = <1 2 3 4>; + }; + }; + /* port config end */ + }; + }; + + i2c@1 { + #address-cells = <1>; + #size-cells = <0>; + reg = <1>; + + // Note: Serializer node defined before camera node + max96712_dphy0_ser1: max96717@52 { + compatible = "maxim,ser,max96717"; + reg = <0x52>; + + ser-i2c-addr-def = <0x40>; + + ser-init-sequence { + seq-item-size = <5>; // reg-addr-len + reg-val-len * 2 + 1 + reg-addr-len = <2>; // 1: 8bits, 2: 16bits + reg-val-len = <1>; // 1: 8bits, 2: 16bits, 3: 24bits + + // reg_addr reg_val val_mask delay + init-sequence = [ + 03 02 10 00 00 + 14 17 00 00 00 + 14 32 7f 00 00 + ]; + }; + }; + + max96712_dphy0_cam1: dummy@32 { + compatible = "maxim,dummy,sensor"; + reg = <0x32>; + + cam-i2c-addr-def = <0x30>; + + cam-remote-ser = <&max96712_dphy0_ser1>; // remote serializer + + poc-supply = <&max96712_dphy0_poc_regulator>; + + rockchip,camera-module-index = <1>; + rockchip,camera-module-facing = "back"; + rockchip,camera-module-name = "default"; + rockchip,camera-module-lens-name = "default"; + + /* port config start */ + port { + max96712_dphy0_cam1_out: endpoint { + data-lanes = <1 2 3 4>; + }; + }; + /* port config end */ + }; + }; + + i2c@2 { + #address-cells = <1>; + #size-cells = <0>; + reg = <2>; + + // Note: Serializer node defined before camera node + max96712_dphy0_ser2: max96717@53 { + compatible = "maxim,ser,max96717"; + reg = <0x53>; + + ser-i2c-addr-def = <0x40>; + + ser-init-sequence { + seq-item-size = <5>; // reg-addr-len + reg-val-len * 2 + 1 + reg-addr-len = <2>; // 1: 8bits, 2: 16bits + reg-val-len = <1>; // 1: 8bits, 2: 16bits, 3: 24bits + + // reg_addr reg_val val_mask delay + init-sequence = [ + 03 02 10 00 00 + 14 17 00 00 00 + 14 32 7f 00 00 + ]; + }; + }; + + max96712_dphy0_cam2: dummy@33 { + compatible = "maxim,dummy,sensor"; + reg = <0x33>; + + cam-i2c-addr-def = <0x30>; + + cam-remote-ser = <&max96712_dphy0_ser2>; // remote serializer + + poc-supply = <&max96712_dphy0_poc_regulator>; + + rockchip,camera-module-index = <2>; + rockchip,camera-module-facing = "back"; + rockchip,camera-module-name = "default"; + rockchip,camera-module-lens-name = "default"; + + /* port config start */ + port { + max96712_dphy0_cam2_out: endpoint { + data-lanes = <1 2 3 4>; + }; + }; + /* port config end */ + }; + }; + + i2c@3 { + #address-cells = <1>; + #size-cells = <0>; + reg = <3>; + + // Note: Serializer node defined before camera node + max96712_dphy0_ser3: max96717@54 { + compatible = "maxim,ser,max96717"; + reg = <0x54>; + + ser-i2c-addr-def = <0x40>; + + ser-init-sequence { + seq-item-size = <5>; // reg-addr-len + reg-val-len * 2 + 1 + reg-addr-len = <2>; // 1: 8bits, 2: 16bits + reg-val-len = <1>; // 1: 8bits, 2: 16bits, 3: 24bits + + // reg_addr reg_val val_mask delay + init-sequence = [ + 03 02 10 00 00 + 14 17 00 00 00 + 14 32 7f 00 00 + ]; + }; + }; + + max96712_dphy0_cam3: dummy@34 { + compatible = "maxim,dummy,sensor"; + reg = <0x34>; + + cam-i2c-addr-def = <0x30>; + + cam-remote-ser = <&max96712_dphy0_ser3>; // remote serializer + + poc-supply = <&max96712_dphy0_poc_regulator>; + + rockchip,camera-module-index = <3>; + rockchip,camera-module-facing = "back"; + rockchip,camera-module-name = "default"; + rockchip,camera-module-lens-name = "default"; + + /* port config start */ + port { + max96712_dphy0_cam3_out: endpoint { + data-lanes = <1 2 3 4>; + }; + }; + /* port config end */ + }; + }; + }; + /* i2c-mux end */ + }; +}; + +&mipi1_csi2 { + status = "okay"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + #address-cells = <1>; + #size-cells = <0>; + + mipi1_csi2_input: endpoint@1 { + reg = <1>; + remote-endpoint = <&csidphy0_out>; + }; + }; + + port@1 { + reg = <1>; + #address-cells = <1>; + #size-cells = <0>; + + mipi1_csi2_output: endpoint@0 { + reg = <0>; + remote-endpoint = <&cif_mipi1_in>; + }; + }; + }; +}; + +&rkcif_mipi_lvds1 { + status = "okay"; + /* parameters for do cif reset detecting: + * index0: monitor mode, + 0 for idle, + 1 for continue, + 2 for trigger, + 3 for hotplug (for nextchip) + * index1: the frame id to start timer, + min is 2 + * index2: frame num of monitoring cycle + * index3: err time for keep monitoring + after finding out err (ms) + * index4: csi2 err reference val for resetting + */ + rockchip,cif-monitor = <3 2 1 1000 5>; + + port { + cif_mipi1_in: endpoint { + remote-endpoint = <&mipi1_csi2_output>; + }; + }; +}; + +&rkcif { + status = "okay"; + rockchip,android-usb-camerahal-enable; +}; + +&rkcif_mmu { + status = "okay"; +}; + +&pinctrl { + max96712-dphy0 { + max96712_dphy0_pwdn: max96712-dphy0-pwdn { + rockchip,pins = <2 RK_PA3 RK_FUNC_GPIO &pcfg_output_low>; + }; + + max96712_dphy0_errb: max96712-dphy0-errb { + rockchip,pins = <2 RK_PA4 RK_FUNC_GPIO &pcfg_pull_none_smt>; + }; + + max96712_dphy0_lock: max96712-dphy0-lock { + rockchip,pins = <2 RK_PA5 RK_FUNC_GPIO &pcfg_pull_none_smt>; + }; + }; +}; diff --git a/arch/arm64/boot/dts/rockchip/rk3576-vehicle-evb-v20-maxim-max96712-dphy3-dummy.dtsi b/arch/arm64/boot/dts/rockchip/rk3576-vehicle-evb-v20-maxim-max96712-dphy3-dummy.dtsi new file mode 100644 index 000000000000..dec61218dca6 --- /dev/null +++ b/arch/arm64/boot/dts/rockchip/rk3576-vehicle-evb-v20-maxim-max96712-dphy3-dummy.dtsi @@ -0,0 +1,713 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright (c) 2024 Rockchip Electronics Co., Ltd. + * + */ +#include + +/ { + max96712_dphy3_osc: max96712-dphy3-oscillator { + compatible = "fixed-clock"; + #clock-cells = <1>; + clock-frequency = <25000000>; + clock-output-names = "max96712-dphy3-osc"; + }; + + max96712_dphy3_vcc1v2: max96712-dphy3-vcc1v2 { + compatible = "regulator-fixed"; + regulator-name = "max96712_dphy3_vcc1v2"; + regulator-boot-on; + regulator-always-on; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1200000>; + startup-delay-us = <850>; + vin-supply = <&vcc_2v0_pldo_s3>; + }; + + max96712_dphy3_vcc1v8: max96712-dphy3-vcc1v8 { + compatible = "regulator-fixed"; + regulator-name = "max96712_dphy3_vcc1v8"; + regulator-boot-on; + regulator-always-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + startup-delay-us = <200>; + vin-supply = <&vcc_2v0_pldo_s3>; + }; + + max96712_dphy3_pwdn_regulator: max96712-dphy3-pwdn-regulator { + compatible = "regulator-fixed"; + regulator-name = "max96712_dphy3_pwdn"; + gpio = <&gpio4 RK_PC0 GPIO_ACTIVE_HIGH>; + pinctrl-names = "default"; + pinctrl-0 = <&max96712_dphy3_pwdn>; + enable-active-high; + startup-delay-us = <10000>; + off-on-delay-us = <5000>; + }; + + max96712_dphy3_poc_regulator: max96712-dphy3-poc-regulator { + compatible = "regulator-fixed"; + regulator-name = "max96712_dphy3_poc"; + gpio = <&gpio4 RK_PC3 GPIO_ACTIVE_HIGH>; + enable-active-high; + startup-delay-us = <10000>; + off-on-delay-us = <5000>; + vin-supply = <&dphy3_vcc12v_buck1>; + }; +}; + +&csi2_dphy1_hw { + status = "okay"; +}; + +&csi2_dphy3 { + status = "okay"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + port@0 { + reg = <0>; + #address-cells = <1>; + #size-cells = <0>; + + mipi_dphy3_in_max96712: endpoint@1 { + reg = <1>; + remote-endpoint = <&max96712_dphy3_out>; + data-lanes = <1 2 3 4>; + }; + }; + port@1 { + reg = <1>; + #address-cells = <1>; + #size-cells = <0>; + + csidphy3_out: endpoint@0 { + reg = <0>; + remote-endpoint = <&mipi3_csi2_input>; + }; + }; + }; +}; + +&i2c8 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&i2c8m2_xfer>; + + max96712_dphy3: max96712@29 { + compatible = "maxim4c,max96712"; + status = "okay"; + reg = <0x29>; + clock-names = "xvclk"; + clocks = <&max96712_dphy3_osc 0>; + pinctrl-names = "default"; + pinctrl-0 = <&max96712_dphy3_errb>, <&max96712_dphy3_lock>; + power-domains = <&power RK3576_PD_VI>; + rockchip,grf = <&sys_grf>; + vcc1v2-supply = <&max96712_dphy3_vcc1v2>; + vcc1v8-supply = <&max96712_dphy3_vcc1v8>; + pwdn-supply = <&max96712_dphy3_pwdn_regulator>; + lock-gpios = <&gpio4 RK_PC2 GPIO_ACTIVE_HIGH>; + + rockchip,camera-module-index = <0>; + rockchip,camera-module-facing = "back"; + rockchip,camera-module-name = "default"; + rockchip,camera-module-lens-name = "default"; + + port { + max96712_dphy3_out: endpoint { + remote-endpoint = <&mipi_dphy3_in_max96712>; + data-lanes = <1 2 3 4>; + }; + }; + + /* support mode config start */ + support-mode-config { + status = "okay"; + + bus-format = ; + sensor-width = <1920>; + sensor-height = <1440>; + max-fps-numerator = <10000>; + max-fps-denominator = <300000>; + bpp = <16>; + link-freq-idx = <20>; + }; + /* support mode config end */ + + /* serdes local device start */ + serdes-local-device { + status = "okay"; + + /* GMSL LINK config start */ + gmsl-links { + status = "okay"; + + link-vdd-ldo1-en = <1>; + link-vdd-ldo2-en = <1>; + + // Link A: link-id = 0 + gmsl-link-config-0 { + status = "okay"; + link-id = <0>; // Link ID: 0/1/2/3 + + link-type = <1>; // 0: GMSL1, 1: GMSL2 + link-rx-rate = <1>; // 0: 3GBPS, 1: 6GBPS + link-tx-rate = <0>; // 0: default for 187.5MBPS + + link-remote-cam = <&max96712_dphy3_cam0>; // remote camera + + link-init-sequence { + seq-item-size = <5>; // reg-addr-len + reg-val-len * 2 + 1 + reg-addr-len = <2>; // 1: 8bits, 2: 16bits + reg-val-len = <1>; // 1: 8bits, 2: 16bits, 3: 24bits + + // reg_addr reg_val val_mask delay + init-sequence = [ + 14 D1 03 00 00 // VGAHiGain + 14 45 00 00 00 // Disable SSC + ]; + }; + }; + + // Link B: link-id = 1 + gmsl-link-config-1 { + status = "okay"; + link-id = <1>; // Link ID: 0/1/2/3 + + link-type = <1>; // 0: GMSL1, 1: GMSL2 + link-rx-rate = <1>; // 0: 3GBPS, 1: 6GBPS + link-tx-rate = <0>; // 0: default for 187.5MBPS + + link-remote-cam = <&max96712_dphy3_cam1>; // remote camera + + link-init-sequence { + seq-item-size = <5>; // reg-addr-len + reg-val-len * 2 + 1 + reg-addr-len = <2>; // 1: 8bits, 2: 16bits + reg-val-len = <1>; // 1: 8bits, 2: 16bits, 3: 24bits + + // reg_addr reg_val val_mask delay + init-sequence = [ + 15 D1 03 00 00 // VGAHiGain + 15 45 00 00 00 // Disable SSC + ]; + }; + }; + + // Link C: link-id = 2 + gmsl-link-config-2 { + status = "okay"; + link-id = <2>; // Link ID: 0/1/2/3 + + link-type = <1>; // 0: GMSL1, 1: GMSL2 + link-rx-rate = <1>; // 0: 3GBPS, 1: 6GBPS + link-tx-rate = <0>; // 0: default for 187.5MBPS + + link-remote-cam = <&max96712_dphy3_cam2>; // remote camera + + link-init-sequence { + seq-item-size = <5>; // reg-addr-len + reg-val-len * 2 + 1 + reg-addr-len = <2>; // 1: 8bits, 2: 16bits + reg-val-len = <1>; // 1: 8bits, 2: 16bits, 3: 24bits + + // reg_addr reg_val val_mask delay + init-sequence = [ + 16 D1 03 00 00 // VGAHiGain + 16 45 00 00 00 // Disable SSC + ]; + }; + }; + + // Link D: link-id = 3 + gmsl-link-config-3 { + status = "okay"; + link-id = <3>; // Link ID: 0/1/2/3 + + link-type = <1>; // 0: GMSL1, 1: GMSL2 + link-rx-rate = <1>; // 0: 3GBPS, 1: 6GBPS + link-tx-rate = <0>; // 0: default for 187.5MBPS + + link-remote-cam = <&max96712_dphy3_cam3>; // remote camera + + link-init-sequence { + seq-item-size = <5>; // reg-addr-len + reg-val-len * 2 + 1 + reg-addr-len = <2>; // 1: 8bits, 2: 16bits + reg-val-len = <1>; // 1: 8bits, 2: 16bits, 3: 24bits + + // reg_addr reg_val val_mask delay + init-sequence = [ + 17 D1 03 00 00 // VGAHiGain + 17 45 00 00 00 // Disable SSC + ]; + }; + }; + }; + /* GMSL LINK config end */ + + /* VIDEO PIPE config start */ + video-pipes { + status = "okay"; + + // Video Pipe 0 + video-pipe-config-0 { + status = "okay"; + pipe-id = <0>; // Video Pipe ID: 0/1/2/3/4/5/6/7 + + pipe-idx = <2>; // Video Pipe X/Y/Z/U: 0/1/2/3 + link-idx = <0>; // Link A/B/C/D: 0/1/2/3 + + pipe-init-sequence { + seq-item-size = <5>; // reg-addr-len + reg-val-len * 2 + 1 + reg-addr-len = <2>; // 1: 8bits, 2: 16bits + reg-val-len = <1>; // 1: 8bits, 2: 16bits, 3: 24bits + + // reg_addr reg_val val_mask delay + init-sequence = [ + // Send YUV422, FS, and FE from Video Pipe 0 to Controller 1 + 09 0B 07 00 00 // Enable 0/1/2 SRC/DST Mappings + 09 2D 15 00 00 // SRC/DST 0/1/2 -> CSI2 Controller 1; + // For the following MSB 2 bits = VC, LSB 6 bits = DT + 09 0D 1e 00 00 // SRC0 VC = 0, DT = YUV422 8bit + 09 0E 1e 00 00 // DST0 VC = 0, DT = YUV422 8bit + 09 0F 00 00 00 // SRC1 VC = 0, DT = Frame Start + 09 10 00 00 00 // DST1 VC = 0, DT = Frame Start + 09 11 01 00 00 // SRC2 VC = 0, DT = Frame End + 09 12 01 00 00 // DST2 VC = 0, DT = Frame End + ]; + }; + }; + + // Video Pipe 1 + video-pipe-config-1 { + status = "okay"; + pipe-id = <1>; // Video Pipe 1: pipe-id = 1 + + pipe-idx = <2>; // Video Pipe X/Y/Z/U: 0/1/2/3 + link-idx = <1>; // Link A/B/C/D: 0/1/2/3 + + pipe-init-sequence { + seq-item-size = <5>; // reg-addr-len + reg-val-len * 2 + 1 + reg-addr-len = <2>; // 1: 8bits, 2: 16bits + reg-val-len = <1>; // 1: 8bits, 2: 16bits, 3: 24bits + + // reg_addr reg_val val_mask delay + init-sequence = [ + // Send YUV422, FS, and FE from Video Pipe 1 to Controller 1 + 09 4B 07 00 00 // Enable 0/1/2 SRC/DST Mappings + 09 6D 15 00 00 // SRC/DST 0/1/2 -> CSI2 Controller 1; + // For the following MSB 2 bits = VC, LSB 6 bits = DT + 09 4D 1e 00 00 // SRC0 VC = 0, DT = YUV422 8bit + 09 4E 5e 00 00 // DST0 VC = 1, DT = YUV422 8bit + 09 4F 00 00 00 // SRC1 VC = 0, DT = Frame Start + 09 50 40 00 00 // DST1 VC = 1, DT = Frame Start + 09 51 01 00 00 // SRC2 VC = 0, DT = Frame End + 09 52 41 00 00 // DST2 VC = 1, DT = Frame End + ]; + }; + }; + + // Video Pipe 2 + video-pipe-config-2 { + status = "okay"; + pipe-id = <2>; // Video Pipe ID: 0/1/2/3/4/5/6/7 + + pipe-idx = <2>; // Video Pipe X/Y/Z/U: 0/1/2/3 + link-idx = <2>; // Link A/B/C/D: 0/1/2/3 + + pipe-init-sequence { + seq-item-size = <5>; // reg-addr-len + reg-val-len * 2 + 1 + reg-addr-len = <2>; // 1: 8bits, 2: 16bits + reg-val-len = <1>; // 1: 8bits, 2: 16bits, 3: 24bits + + // reg_addr reg_val val_mask delay + init-sequence = [ + // Send YUV422, FS, and FE from Video Pipe 2 to Controller 1 + 09 8B 07 00 00 // Enable 0/1/2 SRC/DST Mappings + 09 AD 15 00 00 // SRC/DST 0/1/2 -> CSI2 Controller 1; + // For the following MSB 2 bits = VC, LSB 6 bits = DT + 09 8D 1e 00 00 // SRC0 VC = 0, DT = YUV422 8bit + 09 8E 9e 00 00 // DST0 VC = 2, DT = YUV422 8bit + 09 8F 00 00 00 // SRC1 VC = 0, DT = Frame Start + 09 90 80 00 00 // DST1 VC = 2, DT = Frame Start + 09 91 01 00 00 // SRC2 VC = 0, DT = Frame End + 09 92 81 00 00 // DST2 VC = 2, DT = Frame End + ]; + }; + }; + + // Video Pipe 3 + video-pipe-config-3 { + status = "okay"; + pipe-id = <3>; // Video Pipe ID: 0/1/2/3/4/5/6/7 + + pipe-idx = <2>; // Video Pipe X/Y/Z/U: 0/1/2/3 + link-idx = <3>; // Link A/B/C/D: 0/1/2/3 + + pipe-init-sequence { + seq-item-size = <5>; // reg-addr-len + reg-val-len * 2 + 1 + reg-addr-len = <2>; // 1: 8bits, 2: 16bits + reg-val-len = <1>; // 1: 8bits, 2: 16bits, 3: 24bits + + // reg_addr reg_val val_mask delay + init-sequence = [ + // Send YUV422, FS, and FE from Video Pipe 3 to Controller 1 + 09 CB 07 00 00 // Enable 0/1/2 SRC/DST Mappings + 09 ED 15 00 00 // SRC/DST 0/1/2 -> CSI2 Controller 1; + // For the following MSB 2 bits = VC, LSB 6 bits = DT + 09 CD 1e 00 00 // SRC0 VC = 0, DT = YUV422 8bit + 09 CE de 00 00 // DST0 VC = 3, DT = YUV422 8bit + 09 CF 00 00 00 // SRC1 VC = 0, DT = Frame Start + 09 D0 c0 00 00 // DST1 VC = 3, DT = Frame Start + 09 D1 01 00 00 // SRC2 VC = 0, DT = Frame End + 09 D2 c1 00 00 // DST2 VC = 3, DT = Frame End + ]; + }; + }; + }; + /* VIDEO PIPE config end */ + + /* MIPI TXPHY config start */ + mipi-txphys { + status = "okay"; + + phy-mode = <0>; // 0: 4Lanes, 1: 2Lanes + phy-force-clock-out = <1>; // 1: default for force clock out + phy-force-clk0-en = <1>; // provide MIPI clock: 0 = PHY1, 1 = PHY0 + phy-force-clk3-en = <0>; // provide MIPI clock: 0 = PHY2, 1 = PHY3 + + // MIPI TXPHY A: phy-id = 0 + mipi-txphy-config-0 { + status = "okay"; + phy-id = <0>; // MIPI TXPHY ID: 0/1/2/3 + + phy-type = <0>; // 0: DPHY, 1: CPHY + auto-deskew = <0x80>; + data-lane-num = <4>; + data-lane-map = <0x4>; + vc-ext-en = <0>; + }; + + // MIPI TXPHY B: phy-id = 1 + mipi-txphy-config-1 { + status = "okay"; + phy-id = <1>; // MIPI TXPHY ID: 0/1/2/3 + + phy-type = <0>; // 0: DPHY, 1: CPHY + auto-deskew = <0x80>; + data-lane-num = <4>; + data-lane-map = <0xe>; + vc-ext-en = <0>; + }; + }; + /* MIPI TXPHY config end */ + + /* local device extra init sequence */ + extra-init-sequence { + status = "disabled"; + + seq-item-size = <5>; // reg-addr-len + reg-val-len * 2 + 1 + reg-addr-len = <2>; // 1: 8bits, 2: 16bits + reg-val-len = <1>; // 1: 8bits, 2: 16bits, 3: 24bits + + // reg_addr reg_val val_mask delay + init-sequence = [ + // common init sequence such as fsync / gpio and so on + ]; + }; + }; + /* serdes local device end */ + + /* i2c-mux start */ + i2c-mux { + #address-cells = <1>; + #size-cells = <0>; + + i2c@0 { + #address-cells = <1>; + #size-cells = <0>; + reg = <0>; + + // Note: Serializer node defined before camera node + max96712_dphy3_ser0: max96717@51 { + compatible = "maxim,ser,max96717"; + reg = <0x51>; + + ser-i2c-addr-def = <0x40>; + + ser-init-sequence { + seq-item-size = <5>; // reg-addr-len + reg-val-len * 2 + 1 + reg-addr-len = <2>; // 1: 8bits, 2: 16bits + reg-val-len = <1>; // 1: 8bits, 2: 16bits, 3: 24bits + + // reg_addr reg_val val_mask delay + init-sequence = [ + 03 02 10 00 00 + 14 17 00 00 00 + 14 32 7f 00 00 + ]; + }; + }; + + max96712_dphy3_cam0: dummy@31 { + compatible = "maxim,dummy,sensor"; + reg = <0x31>; + + cam-i2c-addr-def = <0x30>; + + cam-remote-ser = <&max96712_dphy3_ser0>; // remote serializer + + poc-supply = <&max96712_dphy3_poc_regulator>; + + rockchip,camera-module-index = <0>; + rockchip,camera-module-facing = "back"; + rockchip,camera-module-name = "default"; + rockchip,camera-module-lens-name = "default"; + + /* port config start */ + port { + max96712_dphy3_cam0_out: endpoint { + data-lanes = <1 2 3 4>; + }; + }; + /* port config end */ + }; + }; + + i2c@1 { + #address-cells = <1>; + #size-cells = <0>; + reg = <1>; + + // Note: Serializer node defined before camera node + max96712_dphy3_ser1: max96717@52 { + compatible = "maxim,ser,max96717"; + reg = <0x52>; + + ser-i2c-addr-def = <0x40>; + + ser-init-sequence { + seq-item-size = <5>; // reg-addr-len + reg-val-len * 2 + 1 + reg-addr-len = <2>; // 1: 8bits, 2: 16bits + reg-val-len = <1>; // 1: 8bits, 2: 16bits, 3: 24bits + + // reg_addr reg_val val_mask delay + init-sequence = [ + 03 02 10 00 00 + 14 17 00 00 00 + 14 32 7f 00 00 + ]; + }; + }; + + max96712_dphy3_cam1: dummy@32 { + compatible = "maxim,dummy,sensor"; + reg = <0x32>; + + cam-i2c-addr-def = <0x30>; + + cam-remote-ser = <&max96712_dphy3_ser1>; // remote serializer + + poc-supply = <&max96712_dphy3_poc_regulator>; + + rockchip,camera-module-index = <1>; + rockchip,camera-module-facing = "back"; + rockchip,camera-module-name = "default"; + rockchip,camera-module-lens-name = "default"; + + /* port config start */ + port { + max96712_dphy3_cam1_out: endpoint { + data-lanes = <1 2 3 4>; + }; + }; + /* port config end */ + }; + }; + + i2c@2 { + #address-cells = <1>; + #size-cells = <0>; + reg = <2>; + + // Note: Serializer node defined before camera node + max96712_dphy3_ser2: max96717@53 { + compatible = "maxim,ser,max96717"; + reg = <0x53>; + + ser-i2c-addr-def = <0x40>; + + ser-init-sequence { + seq-item-size = <5>; // reg-addr-len + reg-val-len * 2 + 1 + reg-addr-len = <2>; // 1: 8bits, 2: 16bits + reg-val-len = <1>; // 1: 8bits, 2: 16bits, 3: 24bits + + // reg_addr reg_val val_mask delay + init-sequence = [ + 03 02 10 00 00 + 14 17 00 00 00 + 14 32 7f 00 00 + ]; + }; + }; + + max96712_dphy3_cam2: dummy@33 { + compatible = "maxim,dummy,sensor"; + reg = <0x33>; + + cam-i2c-addr-def = <0x30>; + + cam-remote-ser = <&max96712_dphy3_ser2>; // remote serializer + + poc-supply = <&max96712_dphy3_poc_regulator>; + + rockchip,camera-module-index = <2>; + rockchip,camera-module-facing = "back"; + rockchip,camera-module-name = "default"; + rockchip,camera-module-lens-name = "default"; + + /* port config start */ + port { + max96712_dphy3_cam2_out: endpoint { + data-lanes = <1 2 3 4>; + }; + }; + /* port config end */ + }; + }; + + i2c@3 { + #address-cells = <1>; + #size-cells = <0>; + reg = <3>; + + // Note: Serializer node defined before camera node + max96712_dphy3_ser3: max96717@54 { + compatible = "maxim,ser,max96717"; + reg = <0x54>; + + ser-i2c-addr-def = <0x40>; + + ser-init-sequence { + seq-item-size = <5>; // reg-addr-len + reg-val-len * 2 + 1 + reg-addr-len = <2>; // 1: 8bits, 2: 16bits + reg-val-len = <1>; // 1: 8bits, 2: 16bits, 3: 24bits + + // reg_addr reg_val val_mask delay + init-sequence = [ + 03 02 10 00 00 + 14 17 00 00 00 + 14 32 7f 00 00 + ]; + }; + }; + + max96712_dphy3_cam3: dummy@34 { + compatible = "maxim,dummy,sensor"; + reg = <0x34>; + + cam-i2c-addr-def = <0x30>; + + cam-remote-ser = <&max96712_dphy3_ser3>; // remote serializer + + poc-supply = <&max96712_dphy3_poc_regulator>; + + rockchip,camera-module-index = <3>; + rockchip,camera-module-facing = "back"; + rockchip,camera-module-name = "default"; + rockchip,camera-module-lens-name = "default"; + + /* port config start */ + port { + max96712_dphy3_cam3_out: endpoint { + data-lanes = <1 2 3 4>; + }; + }; + /* port config end */ + }; + }; + }; + /* i2c-mux end */ + }; +}; + +&mipi3_csi2 { + status = "okay"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + #address-cells = <1>; + #size-cells = <0>; + + mipi3_csi2_input: endpoint@1 { + reg = <1>; + remote-endpoint = <&csidphy3_out>; + }; + }; + + port@1 { + reg = <1>; + #address-cells = <1>; + #size-cells = <0>; + + mipi3_csi2_output: endpoint@0 { + reg = <0>; + remote-endpoint = <&cif_mipi3_in>; + }; + }; + }; +}; + +&rkcif_mipi_lvds3 { + status = "okay"; + /* parameters for do cif reset detecting: + * index0: monitor mode, + 0 for idle, + 1 for continue, + 2 for trigger, + 3 for hotplug (for nextchip) + * index1: the frame id to start timer, + min is 2 + * index2: frame num of monitoring cycle + * index3: err time for keep monitoring + after finding out err (ms) + * index4: csi2 err reference val for resetting + */ + rockchip,cif-monitor = <3 2 1 1000 5>; + + port { + cif_mipi3_in: endpoint { + remote-endpoint = <&mipi3_csi2_output>; + }; + }; +}; + +&rkcif { + status = "okay"; + rockchip,android-usb-camerahal-enable; +}; + +&rkcif_mmu { + status = "okay"; +}; + +&pinctrl { + max96712-dphy3 { + max96712_dphy3_pwdn: max96712-dphy3-pwdn { + rockchip,pins = <4 RK_PC0 RK_FUNC_GPIO &pcfg_output_low>; + }; + + max96712_dphy3_errb: max96712-dphy3-errb { + rockchip,pins = <4 RK_PC1 RK_FUNC_GPIO &pcfg_pull_none_smt>; + }; + + max96712_dphy3_lock: max96712-dphy3-lock { + rockchip,pins = <4 RK_PC2 RK_FUNC_GPIO &pcfg_pull_none_smt>; + }; + }; +}; diff --git a/arch/arm64/boot/dts/rockchip/rk3576-vehicle-evb-v20-maxim-max96712-dphy3-isx021.dtsi b/arch/arm64/boot/dts/rockchip/rk3576-vehicle-evb-v20-maxim-max96712-dphy3-isx021.dtsi new file mode 100644 index 000000000000..a47c1c72e3dd --- /dev/null +++ b/arch/arm64/boot/dts/rockchip/rk3576-vehicle-evb-v20-maxim-max96712-dphy3-isx021.dtsi @@ -0,0 +1,725 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright (c) 2024 Rockchip Electronics Co., Ltd. + * + */ +#include + +/ { + max96712_dphy3_osc: max96712-dphy3-oscillator { + compatible = "fixed-clock"; + #clock-cells = <1>; + clock-frequency = <25000000>; + clock-output-names = "max96712-dphy3-osc"; + }; + + max96712_dphy3_vcc1v2: max96712-dphy3-vcc1v2 { + compatible = "regulator-fixed"; + regulator-name = "max96712_dphy3_vcc1v2"; + regulator-boot-on; + regulator-always-on; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1200000>; + startup-delay-us = <850>; + vin-supply = <&vcc_2v0_pldo_s3>; + }; + + max96712_dphy3_vcc1v8: max96712-dphy3-vcc1v8 { + compatible = "regulator-fixed"; + regulator-name = "max96712_dphy3_vcc1v8"; + regulator-boot-on; + regulator-always-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + startup-delay-us = <200>; + vin-supply = <&vcc_2v0_pldo_s3>; + }; + + max96712_dphy3_pwdn_regulator: max96712-dphy3-pwdn-regulator { + compatible = "regulator-fixed"; + regulator-name = "max96712_dphy3_pwdn"; + gpio = <&gpio4 RK_PC0 GPIO_ACTIVE_HIGH>; + pinctrl-names = "default"; + pinctrl-0 = <&max96712_dphy3_pwdn>; + enable-active-high; + startup-delay-us = <10000>; + off-on-delay-us = <5000>; + }; + + max96712_dphy3_poc_regulator: max96712-dphy3-poc-regulator { + compatible = "regulator-fixed"; + regulator-name = "max96712_dphy3_poc"; + gpio = <&gpio4 RK_PC3 GPIO_ACTIVE_HIGH>; + enable-active-high; + startup-delay-us = <10000>; + off-on-delay-us = <5000>; + vin-supply = <&dphy3_vcc12v_buck1>; + }; +}; + +&csi2_dphy1_hw { + status = "okay"; +}; + +&csi2_dphy3 { + status = "okay"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + port@0 { + reg = <0>; + #address-cells = <1>; + #size-cells = <0>; + + mipi_dphy3_in_max96712: endpoint@1 { + reg = <1>; + remote-endpoint = <&max96712_dphy3_out>; + data-lanes = <1 2 3 4>; + }; + }; + port@1 { + reg = <1>; + #address-cells = <1>; + #size-cells = <0>; + + csidphy3_out: endpoint@0 { + reg = <0>; + remote-endpoint = <&mipi3_csi2_input>; + }; + }; + }; +}; + +&i2c8 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&i2c8m2_xfer>; + + max96712_dphy3: max96712@29 { + compatible = "maxim4c,max96712"; + status = "okay"; + reg = <0x29>; + clock-names = "xvclk"; + clocks = <&max96712_dphy3_osc 0>; + pinctrl-names = "default"; + pinctrl-0 = <&max96712_dphy3_errb>, <&max96712_dphy3_lock>; + power-domains = <&power RK3576_PD_VI>; + rockchip,grf = <&sys_grf>; + vcc1v2-supply = <&max96712_dphy3_vcc1v2>; + vcc1v8-supply = <&max96712_dphy3_vcc1v8>; + pwdn-supply = <&max96712_dphy3_pwdn_regulator>; + lock-gpios = <&gpio4 RK_PC2 GPIO_ACTIVE_HIGH>; + + rockchip,camera-module-index = <0>; + rockchip,camera-module-facing = "back"; + rockchip,camera-module-name = "default"; + rockchip,camera-module-lens-name = "default"; + + port { + max96712_dphy3_out: endpoint { + remote-endpoint = <&mipi_dphy3_in_max96712>; + data-lanes = <1 2 3 4>; + }; + }; + + /* support mode config start */ + support-mode-config { + status = "okay"; + + bus-format = ; + sensor-width = <1920>; + sensor-height = <1281>; + crop-rect = <0 1 1920 1280>; // [ left, top, width, height ] + max-fps-numerator = <10000>; + max-fps-denominator = <300000>; + bpp = <16>; + link-freq-idx = <20>; + }; + /* support mode config end */ + + /* serdes local device start */ + serdes-local-device { + status = "okay"; + + /* GMSL LINK config start */ + gmsl-links { + status = "okay"; + + link-vdd-ldo1-en = <1>; + link-vdd-ldo2-en = <1>; + + // Link A: link-id = 0 + gmsl-link-config-0 { + status = "okay"; + link-id = <0>; // Link ID: 0/1/2/3 + + link-type = <1>; // 0: GMSL1, 1: GMSL2 + link-rx-rate = <0>; // 0: 3GBPS, 1: 6GBPS + link-tx-rate = <0>; // 0: default for 187.5MBPS + + link-remote-cam = <&max96712_dphy3_cam0>; // remote camera + + link-init-sequence { + seq-item-size = <5>; // reg-addr-len + reg-val-len * 2 + 1 + reg-addr-len = <2>; // 1: 8bits, 2: 16bits + reg-val-len = <1>; // 1: 8bits, 2: 16bits, 3: 24bits + + // reg_addr reg_val val_mask delay + init-sequence = [ + 14 D1 03 00 00 // VGAHiGain + 14 45 00 00 00 // Disable SSC + ]; + }; + }; + + // Link B: link-id = 1 + gmsl-link-config-1 { + status = "okay"; + link-id = <1>; // Link ID: 0/1/2/3 + + link-type = <1>; // 0: GMSL1, 1: GMSL2 + link-rx-rate = <0>; // 0: 3GBPS, 1: 6GBPS + link-tx-rate = <0>; // 0: default for 187.5MBPS + + link-remote-cam = <&max96712_dphy3_cam1>; // remote camera + + link-init-sequence { + seq-item-size = <5>; // reg-addr-len + reg-val-len * 2 + 1 + reg-addr-len = <2>; // 1: 8bits, 2: 16bits + reg-val-len = <1>; // 1: 8bits, 2: 16bits, 3: 24bits + + // reg_addr reg_val val_mask delay + init-sequence = [ + 15 D1 03 00 00 // VGAHiGain + 15 45 00 00 00 // Disable SSC + ]; + }; + }; + + // Link C: link-id = 2 + gmsl-link-config-2 { + status = "okay"; + link-id = <2>; // Link ID: 0/1/2/3 + + link-type = <1>; // 0: GMSL1, 1: GMSL2 + link-rx-rate = <0>; // 0: 3GBPS, 1: 6GBPS + link-tx-rate = <0>; // 0: default for 187.5MBPS + + link-remote-cam = <&max96712_dphy3_cam2>; // remote camera + + link-init-sequence { + seq-item-size = <5>; // reg-addr-len + reg-val-len * 2 + 1 + reg-addr-len = <2>; // 1: 8bits, 2: 16bits + reg-val-len = <1>; // 1: 8bits, 2: 16bits, 3: 24bits + + // reg_addr reg_val val_mask delay + init-sequence = [ + 16 D1 03 00 00 // VGAHiGain + 16 45 00 00 00 // Disable SSC + ]; + }; + }; + + // Link D: link-id = 3 + gmsl-link-config-3 { + status = "okay"; + link-id = <3>; // Link ID: 0/1/2/3 + + link-type = <1>; // 0: GMSL1, 1: GMSL2 + link-rx-rate = <0>; // 0: 3GBPS, 1: 6GBPS + link-tx-rate = <0>; // 0: default for 187.5MBPS + + link-remote-cam = <&max96712_dphy3_cam3>; // remote camera + + link-init-sequence { + seq-item-size = <5>; // reg-addr-len + reg-val-len * 2 + 1 + reg-addr-len = <2>; // 1: 8bits, 2: 16bits + reg-val-len = <1>; // 1: 8bits, 2: 16bits, 3: 24bits + + // reg_addr reg_val val_mask delay + init-sequence = [ + 17 D1 03 00 00 // VGAHiGain + 17 45 00 00 00 // Disable SSC + ]; + }; + }; + }; + /* GMSL LINK config end */ + + /* VIDEO PIPE config start */ + video-pipes { + status = "okay"; + + // Video Pipe 0 + video-pipe-config-0 { + status = "okay"; + pipe-id = <0>; // Video Pipe ID: 0/1/2/3/4/5/6/7 + + pipe-idx = <2>; // Video Pipe X/Y/Z/U: 0/1/2/3 + link-idx = <0>; // Link A/B/C/D: 0/1/2/3 + + pipe-init-sequence { + seq-item-size = <5>; // reg-addr-len + reg-val-len * 2 + 1 + reg-addr-len = <2>; // 1: 8bits, 2: 16bits + reg-val-len = <1>; // 1: 8bits, 2: 16bits, 3: 24bits + + // reg_addr reg_val val_mask delay + init-sequence = [ + // Send YUV422, FS, and FE from Video Pipe 0 to Controller 1 + 09 0B 07 00 00 // Enable 0/1/2 SRC/DST Mappings + 09 2D 15 00 00 // SRC/DST 0/1/2 -> CSI2 Controller 1; + // For the following MSB 2 bits = VC, LSB 6 bits = DT + 09 0D 1e 00 00 // SRC0 VC = 0, DT = YUV422 8bit + 09 0E 1e 00 00 // DST0 VC = 0, DT = YUV422 8bit + 09 0F 00 00 00 // SRC1 VC = 0, DT = Frame Start + 09 10 00 00 00 // DST1 VC = 0, DT = Frame Start + 09 11 01 00 00 // SRC2 VC = 0, DT = Frame End + 09 12 01 00 00 // DST2 VC = 0, DT = Frame End + ]; + }; + }; + + // Video Pipe 1 + video-pipe-config-1 { + status = "okay"; + pipe-id = <1>; // Video Pipe 1: pipe-id = 1 + + pipe-idx = <2>; // Video Pipe X/Y/Z/U: 0/1/2/3 + link-idx = <1>; // Link A/B/C/D: 0/1/2/3 + + pipe-init-sequence { + seq-item-size = <5>; // reg-addr-len + reg-val-len * 2 + 1 + reg-addr-len = <2>; // 1: 8bits, 2: 16bits + reg-val-len = <1>; // 1: 8bits, 2: 16bits, 3: 24bits + + // reg_addr reg_val val_mask delay + init-sequence = [ + // Send YUV422, FS, and FE from Video Pipe 1 to Controller 1 + 09 4B 07 00 00 // Enable 0/1/2 SRC/DST Mappings + 09 6D 15 00 00 // SRC/DST 0/1/2 -> CSI2 Controller 1; + // For the following MSB 2 bits = VC, LSB 6 bits = DT + 09 4D 1e 00 00 // SRC0 VC = 0, DT = YUV422 8bit + 09 4E 5e 00 00 // DST0 VC = 1, DT = YUV422 8bit + 09 4F 00 00 00 // SRC1 VC = 0, DT = Frame Start + 09 50 40 00 00 // DST1 VC = 1, DT = Frame Start + 09 51 01 00 00 // SRC2 VC = 0, DT = Frame End + 09 52 41 00 00 // DST2 VC = 1, DT = Frame End + ]; + }; + }; + + // Video Pipe 2 + video-pipe-config-2 { + status = "okay"; + pipe-id = <2>; // Video Pipe ID: 0/1/2/3/4/5/6/7 + + pipe-idx = <2>; // Video Pipe X/Y/Z/U: 0/1/2/3 + link-idx = <2>; // Link A/B/C/D: 0/1/2/3 + + pipe-init-sequence { + seq-item-size = <5>; // reg-addr-len + reg-val-len * 2 + 1 + reg-addr-len = <2>; // 1: 8bits, 2: 16bits + reg-val-len = <1>; // 1: 8bits, 2: 16bits, 3: 24bits + + // reg_addr reg_val val_mask delay + init-sequence = [ + // Send YUV422, FS, and FE from Video Pipe 2 to Controller 1 + 09 8B 07 00 00 // Enable 0/1/2 SRC/DST Mappings + 09 AD 15 00 00 // SRC/DST 0/1/2 -> CSI2 Controller 1; + // For the following MSB 2 bits = VC, LSB 6 bits = DT + 09 8D 1e 00 00 // SRC0 VC = 0, DT = YUV422 8bit + 09 8E 9e 00 00 // DST0 VC = 2, DT = YUV422 8bit + 09 8F 00 00 00 // SRC1 VC = 0, DT = Frame Start + 09 90 80 00 00 // DST1 VC = 2, DT = Frame Start + 09 91 01 00 00 // SRC2 VC = 0, DT = Frame End + 09 92 81 00 00 // DST2 VC = 2, DT = Frame End + ]; + }; + }; + + // Video Pipe 3 + video-pipe-config-3 { + status = "okay"; + pipe-id = <3>; // Video Pipe ID: 0/1/2/3/4/5/6/7 + + pipe-idx = <2>; // Video Pipe X/Y/Z/U: 0/1/2/3 + link-idx = <3>; // Link A/B/C/D: 0/1/2/3 + + pipe-init-sequence { + seq-item-size = <5>; // reg-addr-len + reg-val-len * 2 + 1 + reg-addr-len = <2>; // 1: 8bits, 2: 16bits + reg-val-len = <1>; // 1: 8bits, 2: 16bits, 3: 24bits + + // reg_addr reg_val val_mask delay + init-sequence = [ + // Send YUV422, FS, and FE from Video Pipe 3 to Controller 1 + 09 CB 07 00 00 // Enable 0/1/2 SRC/DST Mappings + 09 ED 15 00 00 // SRC/DST 0/1/2 -> CSI2 Controller 1; + // For the following MSB 2 bits = VC, LSB 6 bits = DT + 09 CD 1e 00 00 // SRC0 VC = 0, DT = YUV422 8bit + 09 CE de 00 00 // DST0 VC = 3, DT = YUV422 8bit + 09 CF 00 00 00 // SRC1 VC = 0, DT = Frame Start + 09 D0 c0 00 00 // DST1 VC = 3, DT = Frame Start + 09 D1 01 00 00 // SRC2 VC = 0, DT = Frame End + 09 D2 c1 00 00 // DST2 VC = 3, DT = Frame End + ]; + }; + }; + }; + /* VIDEO PIPE config end */ + + /* MIPI TXPHY config start */ + mipi-txphys { + status = "okay"; + + phy-mode = <0>; // 0: 4Lanes, 1: 2Lanes + phy-force-clock-out = <1>; // 1: default for force clock out + phy-force-clk0-en = <1>; // provide MIPI clock: 0 = PHY1, 1 = PHY0 + phy-force-clk3-en = <0>; // provide MIPI clock: 0 = PHY2, 1 = PHY3 + + // MIPI TXPHY A: phy-id = 0 + mipi-txphy-config-0 { + status = "okay"; + phy-id = <0>; // MIPI TXPHY ID: 0/1/2/3 + + phy-type = <0>; // 0: DPHY, 1: CPHY + auto-deskew = <0x80>; + data-lane-num = <4>; + data-lane-map = <0x4>; + vc-ext-en = <0>; + }; + + // MIPI TXPHY B: phy-id = 1 + mipi-txphy-config-1 { + status = "okay"; + phy-id = <1>; // MIPI TXPHY ID: 0/1/2/3 + + phy-type = <0>; // 0: DPHY, 1: CPHY + auto-deskew = <0x80>; + data-lane-num = <4>; + data-lane-map = <0xe>; + vc-ext-en = <0>; + }; + }; + /* MIPI TXPHY config end */ + + /* local device extra init sequence */ + extra-init-sequence { + status = "okay"; + + seq-item-size = <5>; // reg-addr-len + reg-val-len * 2 + 1 + reg-addr-len = <2>; // 1: 8bits, 2: 16bits + reg-val-len = <1>; // 1: 8bits, 2: 16bits, 3: 24bits + + // reg_addr reg_val val_mask delay + init-sequence = [ + // common init sequence such as fsync / gpio and so on + 04 A2 00 00 00 // Master link Video 0 for frame sync generation + 04 AA 00 00 00 // Disable Vsync-Fsync overlap window + 04 AB 00 00 00 // Disable Vsync-Fsync overlap window + 04 A8 00 00 00 // FRM_DIFF_ERR_THR_L + 04 A9 00 00 00 // FRM_DIFF_ERR_THR_H + 04 A7 0c 00 00 // FSYNC_PERIOD_H, Set FSYNC period to 25M/30 clock cycles. PCLK = 25MHz. Sync freq = 30Hz + 04 A6 bf 00 00 // FSYNC_PERIOD_M + 04 A5 35 00 00 // FSYNC_PERIOD_L + 04 AF c0 00 00 // FSYNC is GMSL2 type, use osc for fsync + 04 B1 40 00 00 // FSYNC_TX_ID: set 8 to match MFP8 on serializer side + 04 A0 04 00 00 // MFP2, VS not gen internally, GPIO not used to gen fsync, manual mode + ]; + }; + }; + /* serdes local device end */ + + /* i2c-mux start */ + i2c-mux { + #address-cells = <1>; + #size-cells = <0>; + + i2c@0 { + #address-cells = <1>; + #size-cells = <0>; + reg = <0>; + + // Note: Serializer node defined before camera node + max96712_dphy3_ser0: max96717@51 { + compatible = "maxim,ser,max96717f"; + reg = <0x51>; + + ser-i2c-addr-def = <0x40>; + + ser-init-sequence { + seq-item-size = <5>; // reg-addr-len + reg-val-len * 2 + 1 + reg-addr-len = <2>; // 1: 8bits, 2: 16bits + reg-val-len = <1>; // 1: 8bits, 2: 16bits, 3: 24bits + + // reg_addr reg_val val_mask delay + init-sequence = [ + 03 02 10 00 00 + 14 17 00 00 00 + 14 32 7f 00 00 + ]; + }; + }; + + max96712_dphy3_cam0: isx021@31 { + compatible = "maxim,dummy,sensor"; + reg = <0x31>; + + cam-i2c-addr-def = <0x30>; + + cam-remote-ser = <&max96712_dphy3_ser0>; // remote serializer + + poc-supply = <&max96712_dphy3_poc_regulator>; + + rockchip,camera-module-index = <0>; + rockchip,camera-module-facing = "back"; + rockchip,camera-module-name = "default"; + rockchip,camera-module-lens-name = "default"; + + /* port config start */ + port { + max96712_dphy3_cam0_out: endpoint { + data-lanes = <1 2 3 4>; + }; + }; + /* port config end */ + }; + }; + + i2c@1 { + #address-cells = <1>; + #size-cells = <0>; + reg = <1>; + + // Note: Serializer node defined before camera node + max96712_dphy3_ser1: max96717@52 { + compatible = "maxim,ser,max96717f"; + reg = <0x52>; + + ser-i2c-addr-def = <0x40>; + + ser-init-sequence { + seq-item-size = <5>; // reg-addr-len + reg-val-len * 2 + 1 + reg-addr-len = <2>; // 1: 8bits, 2: 16bits + reg-val-len = <1>; // 1: 8bits, 2: 16bits, 3: 24bits + + // reg_addr reg_val val_mask delay + init-sequence = [ + 03 02 10 00 00 + 14 17 00 00 00 + 14 32 7f 00 00 + ]; + }; + }; + + max96712_dphy3_cam1: isx021@32 { + compatible = "maxim,dummy,sensor"; + reg = <0x32>; + + cam-i2c-addr-def = <0x30>; + + cam-remote-ser = <&max96712_dphy3_ser1>; // remote serializer + + poc-supply = <&max96712_dphy3_poc_regulator>; + + rockchip,camera-module-index = <1>; + rockchip,camera-module-facing = "back"; + rockchip,camera-module-name = "default"; + rockchip,camera-module-lens-name = "default"; + + /* port config start */ + port { + max96712_dphy3_cam1_out: endpoint { + data-lanes = <1 2 3 4>; + }; + }; + /* port config end */ + }; + }; + + i2c@2 { + #address-cells = <1>; + #size-cells = <0>; + reg = <2>; + + // Note: Serializer node defined before camera node + max96712_dphy3_ser2: max96717@53 { + compatible = "maxim,ser,max96717f"; + reg = <0x53>; + + ser-i2c-addr-def = <0x40>; + + ser-init-sequence { + seq-item-size = <5>; // reg-addr-len + reg-val-len * 2 + 1 + reg-addr-len = <2>; // 1: 8bits, 2: 16bits + reg-val-len = <1>; // 1: 8bits, 2: 16bits, 3: 24bits + + // reg_addr reg_val val_mask delay + init-sequence = [ + 03 02 10 00 00 + 14 17 00 00 00 + 14 32 7f 00 00 + ]; + }; + }; + + max96712_dphy3_cam2: isx021@33 { + compatible = "maxim,dummy,sensor"; + reg = <0x33>; + + cam-i2c-addr-def = <0x30>; + + cam-remote-ser = <&max96712_dphy3_ser2>; // remote serializer + + poc-supply = <&max96712_dphy3_poc_regulator>; + + rockchip,camera-module-index = <2>; + rockchip,camera-module-facing = "back"; + rockchip,camera-module-name = "default"; + rockchip,camera-module-lens-name = "default"; + + /* port config start */ + port { + max96712_dphy3_cam2_out: endpoint { + data-lanes = <1 2 3 4>; + }; + }; + /* port config end */ + }; + }; + + i2c@3 { + #address-cells = <1>; + #size-cells = <0>; + reg = <3>; + + // Note: Serializer node defined before camera node + max96712_dphy3_ser3: max96717@54 { + compatible = "maxim,ser,max96717f"; + reg = <0x54>; + + ser-i2c-addr-def = <0x40>; + + ser-init-sequence { + seq-item-size = <5>; // reg-addr-len + reg-val-len * 2 + 1 + reg-addr-len = <2>; // 1: 8bits, 2: 16bits + reg-val-len = <1>; // 1: 8bits, 2: 16bits, 3: 24bits + + // reg_addr reg_val val_mask delay + init-sequence = [ + 03 02 10 00 00 + 14 17 00 00 00 + 14 32 7f 00 00 + ]; + }; + }; + + max96712_dphy3_cam3: isx021@34 { + compatible = "maxim,dummy,sensor"; + reg = <0x34>; + + cam-i2c-addr-def = <0x30>; + + cam-remote-ser = <&max96712_dphy3_ser3>; // remote serializer + + poc-supply = <&max96712_dphy3_poc_regulator>; + + rockchip,camera-module-index = <3>; + rockchip,camera-module-facing = "back"; + rockchip,camera-module-name = "default"; + rockchip,camera-module-lens-name = "default"; + + /* port config start */ + port { + max96712_dphy3_cam3_out: endpoint { + data-lanes = <1 2 3 4>; + }; + }; + /* port config end */ + }; + }; + }; + /* i2c-mux end */ + }; +}; + +&mipi3_csi2 { + status = "okay"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + #address-cells = <1>; + #size-cells = <0>; + + mipi3_csi2_input: endpoint@1 { + reg = <1>; + remote-endpoint = <&csidphy3_out>; + }; + }; + + port@1 { + reg = <1>; + #address-cells = <1>; + #size-cells = <0>; + + mipi3_csi2_output: endpoint@0 { + reg = <0>; + remote-endpoint = <&cif_mipi3_in>; + }; + }; + }; +}; + +&rkcif_mipi_lvds3 { + status = "okay"; + /* parameters for do cif reset detecting: + * index0: monitor mode, + 0 for idle, + 1 for continue, + 2 for trigger, + 3 for hotplug (for nextchip) + * index1: the frame id to start timer, + min is 2 + * index2: frame num of monitoring cycle + * index3: err time for keep monitoring + after finding out err (ms) + * index4: csi2 err reference val for resetting + */ + rockchip,cif-monitor = <3 2 1 1000 5>; + + port { + cif_mipi3_in: endpoint { + remote-endpoint = <&mipi3_csi2_output>; + }; + }; +}; + +&rkcif { + status = "okay"; + rockchip,android-usb-camerahal-enable; +}; + +&rkcif_mmu { + status = "okay"; +}; + +&pinctrl { + max96712-dphy3 { + max96712_dphy3_pwdn: max96712-dphy3-pwdn { + rockchip,pins = <4 RK_PC0 RK_FUNC_GPIO &pcfg_output_low>; + }; + + max96712_dphy3_errb: max96712-dphy3-errb { + rockchip,pins = <4 RK_PC1 RK_FUNC_GPIO &pcfg_pull_none_smt>; + }; + + max96712_dphy3_lock: max96712-dphy3-lock { + rockchip,pins = <4 RK_PC2 RK_FUNC_GPIO &pcfg_pull_none_smt>; + }; + }; +}; diff --git a/arch/arm64/boot/dts/rockchip/rk3576-vehicle-evb-v20-maxim-max96712-dphy3-sc233at.dtsi b/arch/arm64/boot/dts/rockchip/rk3576-vehicle-evb-v20-maxim-max96712-dphy3-sc233at.dtsi new file mode 100644 index 000000000000..07c74718195b --- /dev/null +++ b/arch/arm64/boot/dts/rockchip/rk3576-vehicle-evb-v20-maxim-max96712-dphy3-sc233at.dtsi @@ -0,0 +1,713 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright (c) 2024 Rockchip Electronics Co., Ltd. + * + */ +#include + +/ { + max96712_dphy3_osc: max96712-dphy3-oscillator { + compatible = "fixed-clock"; + #clock-cells = <1>; + clock-frequency = <25000000>; + clock-output-names = "max96712-dphy3-osc"; + }; + + max96712_dphy3_vcc1v2: max96712-dphy3-vcc1v2 { + compatible = "regulator-fixed"; + regulator-name = "max96712_dphy3_vcc1v2"; + regulator-boot-on; + regulator-always-on; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1200000>; + startup-delay-us = <850>; + vin-supply = <&vcc_2v0_pldo_s3>; + }; + + max96712_dphy3_vcc1v8: max96712-dphy3-vcc1v8 { + compatible = "regulator-fixed"; + regulator-name = "max96712_dphy3_vcc1v8"; + regulator-boot-on; + regulator-always-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + startup-delay-us = <200>; + vin-supply = <&vcc_2v0_pldo_s3>; + }; + + max96712_dphy3_pwdn_regulator: max96712-dphy3-pwdn-regulator { + compatible = "regulator-fixed"; + regulator-name = "max96712_dphy3_pwdn"; + gpio = <&gpio4 RK_PC0 GPIO_ACTIVE_HIGH>; + pinctrl-names = "default"; + pinctrl-0 = <&max96712_dphy3_pwdn>; + enable-active-high; + startup-delay-us = <10000>; + off-on-delay-us = <5000>; + }; + + max96712_dphy3_poc_regulator: max96712-dphy3-poc-regulator { + compatible = "regulator-fixed"; + regulator-name = "max96712_dphy3_poc"; + gpio = <&gpio4 RK_PC3 GPIO_ACTIVE_HIGH>; + enable-active-high; + startup-delay-us = <10000>; + off-on-delay-us = <5000>; + vin-supply = <&dphy3_vcc12v_buck1>; + }; +}; + +&csi2_dphy1_hw { + status = "okay"; +}; + +&csi2_dphy3 { + status = "okay"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + port@0 { + reg = <0>; + #address-cells = <1>; + #size-cells = <0>; + + mipi_dphy3_in_max96712: endpoint@1 { + reg = <1>; + remote-endpoint = <&max96712_dphy3_out>; + data-lanes = <1 2 3 4>; + }; + }; + port@1 { + reg = <1>; + #address-cells = <1>; + #size-cells = <0>; + + csidphy3_out: endpoint@0 { + reg = <0>; + remote-endpoint = <&mipi3_csi2_input>; + }; + }; + }; +}; + +&i2c8 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&i2c8m2_xfer>; + + max96712_dphy3: max96712@29 { + compatible = "maxim4c,max96712"; + status = "okay"; + reg = <0x29>; + clock-names = "xvclk"; + clocks = <&max96712_dphy3_osc 0>; + pinctrl-names = "default"; + pinctrl-0 = <&max96712_dphy3_errb>, <&max96712_dphy3_lock>; + power-domains = <&power RK3576_PD_VI>; + rockchip,grf = <&sys_grf>; + vcc1v2-supply = <&max96712_dphy3_vcc1v2>; + vcc1v8-supply = <&max96712_dphy3_vcc1v8>; + pwdn-supply = <&max96712_dphy3_pwdn_regulator>; + lock-gpios = <&gpio4 RK_PC2 GPIO_ACTIVE_HIGH>; + + rockchip,camera-module-index = <0>; + rockchip,camera-module-facing = "back"; + rockchip,camera-module-name = "default"; + rockchip,camera-module-lens-name = "default"; + + port { + max96712_dphy3_out: endpoint { + remote-endpoint = <&mipi_dphy3_in_max96712>; + data-lanes = <1 2 3 4>; + }; + }; + + /* support mode config start */ + support-mode-config { + status = "okay"; + + bus-format = ; + sensor-width = <1920>; + sensor-height = <1200>; + max-fps-numerator = <10000>; + max-fps-denominator = <300000>; + bpp = <16>; + link-freq-idx = <20>; + }; + /* support mode config end */ + + /* serdes local device start */ + serdes-local-device { + status = "okay"; + + /* GMSL LINK config start */ + gmsl-links { + status = "okay"; + + link-vdd-ldo1-en = <1>; + link-vdd-ldo2-en = <1>; + + // Link A: link-id = 0 + gmsl-link-config-0 { + status = "okay"; + link-id = <0>; // Link ID: 0/1/2/3 + + link-type = <1>; // 0: GMSL1, 1: GMSL2 + link-rx-rate = <0>; // 0: 3GBPS, 1: 6GBPS + link-tx-rate = <0>; // 0: default for 187.5MBPS + + link-remote-cam = <&max96712_dphy3_cam0>; // remote camera + + link-init-sequence { + seq-item-size = <5>; // reg-addr-len + reg-val-len * 2 + 1 + reg-addr-len = <2>; // 1: 8bits, 2: 16bits + reg-val-len = <1>; // 1: 8bits, 2: 16bits, 3: 24bits + + // reg_addr reg_val val_mask delay + init-sequence = [ + 14 D1 03 00 00 // VGAHiGain + 14 45 00 00 00 // Disable SSC + ]; + }; + }; + + // Link B: link-id = 1 + gmsl-link-config-1 { + status = "okay"; + link-id = <1>; // Link ID: 0/1/2/3 + + link-type = <1>; // 0: GMSL1, 1: GMSL2 + link-rx-rate = <0>; // 0: 3GBPS, 1: 6GBPS + link-tx-rate = <0>; // 0: default for 187.5MBPS + + link-remote-cam = <&max96712_dphy3_cam1>; // remote camera + + link-init-sequence { + seq-item-size = <5>; // reg-addr-len + reg-val-len * 2 + 1 + reg-addr-len = <2>; // 1: 8bits, 2: 16bits + reg-val-len = <1>; // 1: 8bits, 2: 16bits, 3: 24bits + + // reg_addr reg_val val_mask delay + init-sequence = [ + 15 D1 03 00 00 // VGAHiGain + 15 45 00 00 00 // Disable SSC + ]; + }; + }; + + // Link C: link-id = 2 + gmsl-link-config-2 { + status = "okay"; + link-id = <2>; // Link ID: 0/1/2/3 + + link-type = <1>; // 0: GMSL1, 1: GMSL2 + link-rx-rate = <0>; // 0: 3GBPS, 1: 6GBPS + link-tx-rate = <0>; // 0: default for 187.5MBPS + + link-remote-cam = <&max96712_dphy3_cam2>; // remote camera + + link-init-sequence { + seq-item-size = <5>; // reg-addr-len + reg-val-len * 2 + 1 + reg-addr-len = <2>; // 1: 8bits, 2: 16bits + reg-val-len = <1>; // 1: 8bits, 2: 16bits, 3: 24bits + + // reg_addr reg_val val_mask delay + init-sequence = [ + 16 D1 03 00 00 // VGAHiGain + 16 45 00 00 00 // Disable SSC + ]; + }; + }; + + // Link D: link-id = 3 + gmsl-link-config-3 { + status = "okay"; + link-id = <3>; // Link ID: 0/1/2/3 + + link-type = <1>; // 0: GMSL1, 1: GMSL2 + link-rx-rate = <0>; // 0: 3GBPS, 1: 6GBPS + link-tx-rate = <0>; // 0: default for 187.5MBPS + + link-remote-cam = <&max96712_dphy3_cam3>; // remote camera + + link-init-sequence { + seq-item-size = <5>; // reg-addr-len + reg-val-len * 2 + 1 + reg-addr-len = <2>; // 1: 8bits, 2: 16bits + reg-val-len = <1>; // 1: 8bits, 2: 16bits, 3: 24bits + + // reg_addr reg_val val_mask delay + init-sequence = [ + 17 D1 03 00 00 // VGAHiGain + 17 45 00 00 00 // Disable SSC + ]; + }; + }; + }; + /* GMSL LINK config end */ + + /* VIDEO PIPE config start */ + video-pipes { + status = "okay"; + + // Video Pipe 0 + video-pipe-config-0 { + status = "okay"; + pipe-id = <0>; // Video Pipe ID: 0/1/2/3/4/5/6/7 + + pipe-idx = <2>; // Video Pipe X/Y/Z/U: 0/1/2/3 + link-idx = <0>; // Link A/B/C/D: 0/1/2/3 + + pipe-init-sequence { + seq-item-size = <5>; // reg-addr-len + reg-val-len * 2 + 1 + reg-addr-len = <2>; // 1: 8bits, 2: 16bits + reg-val-len = <1>; // 1: 8bits, 2: 16bits, 3: 24bits + + // reg_addr reg_val val_mask delay + init-sequence = [ + // Send YUV422, FS, and FE from Video Pipe 0 to Controller 1 + 09 0B 07 00 00 // Enable 0/1/2 SRC/DST Mappings + 09 2D 15 00 00 // SRC/DST 0/1/2 -> CSI2 Controller 1; + // For the following MSB 2 bits = VC, LSB 6 bits = DT + 09 0D 1e 00 00 // SRC0 VC = 0, DT = YUV422 8bit + 09 0E 1e 00 00 // DST0 VC = 0, DT = YUV422 8bit + 09 0F 00 00 00 // SRC1 VC = 0, DT = Frame Start + 09 10 00 00 00 // DST1 VC = 0, DT = Frame Start + 09 11 01 00 00 // SRC2 VC = 0, DT = Frame End + 09 12 01 00 00 // DST2 VC = 0, DT = Frame End + ]; + }; + }; + + // Video Pipe 1 + video-pipe-config-1 { + status = "okay"; + pipe-id = <1>; // Video Pipe 1: pipe-id = 1 + + pipe-idx = <2>; // Video Pipe X/Y/Z/U: 0/1/2/3 + link-idx = <1>; // Link A/B/C/D: 0/1/2/3 + + pipe-init-sequence { + seq-item-size = <5>; // reg-addr-len + reg-val-len * 2 + 1 + reg-addr-len = <2>; // 1: 8bits, 2: 16bits + reg-val-len = <1>; // 1: 8bits, 2: 16bits, 3: 24bits + + // reg_addr reg_val val_mask delay + init-sequence = [ + // Send YUV422, FS, and FE from Video Pipe 1 to Controller 1 + 09 4B 07 00 00 // Enable 0/1/2 SRC/DST Mappings + 09 6D 15 00 00 // SRC/DST 0/1/2 -> CSI2 Controller 1; + // For the following MSB 2 bits = VC, LSB 6 bits = DT + 09 4D 1e 00 00 // SRC0 VC = 0, DT = YUV422 8bit + 09 4E 5e 00 00 // DST0 VC = 1, DT = YUV422 8bit + 09 4F 00 00 00 // SRC1 VC = 0, DT = Frame Start + 09 50 40 00 00 // DST1 VC = 1, DT = Frame Start + 09 51 01 00 00 // SRC2 VC = 0, DT = Frame End + 09 52 41 00 00 // DST2 VC = 1, DT = Frame End + ]; + }; + }; + + // Video Pipe 2 + video-pipe-config-2 { + status = "okay"; + pipe-id = <2>; // Video Pipe ID: 0/1/2/3/4/5/6/7 + + pipe-idx = <2>; // Video Pipe X/Y/Z/U: 0/1/2/3 + link-idx = <2>; // Link A/B/C/D: 0/1/2/3 + + pipe-init-sequence { + seq-item-size = <5>; // reg-addr-len + reg-val-len * 2 + 1 + reg-addr-len = <2>; // 1: 8bits, 2: 16bits + reg-val-len = <1>; // 1: 8bits, 2: 16bits, 3: 24bits + + // reg_addr reg_val val_mask delay + init-sequence = [ + // Send YUV422, FS, and FE from Video Pipe 2 to Controller 1 + 09 8B 07 00 00 // Enable 0/1/2 SRC/DST Mappings + 09 AD 15 00 00 // SRC/DST 0/1/2 -> CSI2 Controller 1; + // For the following MSB 2 bits = VC, LSB 6 bits = DT + 09 8D 1e 00 00 // SRC0 VC = 0, DT = YUV422 8bit + 09 8E 9e 00 00 // DST0 VC = 2, DT = YUV422 8bit + 09 8F 00 00 00 // SRC1 VC = 0, DT = Frame Start + 09 90 80 00 00 // DST1 VC = 2, DT = Frame Start + 09 91 01 00 00 // SRC2 VC = 0, DT = Frame End + 09 92 81 00 00 // DST2 VC = 2, DT = Frame End + ]; + }; + }; + + // Video Pipe 3 + video-pipe-config-3 { + status = "okay"; + pipe-id = <3>; // Video Pipe ID: 0/1/2/3/4/5/6/7 + + pipe-idx = <2>; // Video Pipe X/Y/Z/U: 0/1/2/3 + link-idx = <3>; // Link A/B/C/D: 0/1/2/3 + + pipe-init-sequence { + seq-item-size = <5>; // reg-addr-len + reg-val-len * 2 + 1 + reg-addr-len = <2>; // 1: 8bits, 2: 16bits + reg-val-len = <1>; // 1: 8bits, 2: 16bits, 3: 24bits + + // reg_addr reg_val val_mask delay + init-sequence = [ + // Send YUV422, FS, and FE from Video Pipe 3 to Controller 1 + 09 CB 07 00 00 // Enable 0/1/2 SRC/DST Mappings + 09 ED 15 00 00 // SRC/DST 0/1/2 -> CSI2 Controller 1; + // For the following MSB 2 bits = VC, LSB 6 bits = DT + 09 CD 1e 00 00 // SRC0 VC = 0, DT = YUV422 8bit + 09 CE de 00 00 // DST0 VC = 3, DT = YUV422 8bit + 09 CF 00 00 00 // SRC1 VC = 0, DT = Frame Start + 09 D0 c0 00 00 // DST1 VC = 3, DT = Frame Start + 09 D1 01 00 00 // SRC2 VC = 0, DT = Frame End + 09 D2 c1 00 00 // DST2 VC = 3, DT = Frame End + ]; + }; + }; + }; + /* VIDEO PIPE config end */ + + /* MIPI TXPHY config start */ + mipi-txphys { + status = "okay"; + + phy-mode = <0>; // 0: 4Lanes, 1: 2Lanes + phy-force-clock-out = <1>; // 1: default for force clock out + phy-force-clk0-en = <1>; // provide MIPI clock: 0 = PHY1, 1 = PHY0 + phy-force-clk3-en = <0>; // provide MIPI clock: 0 = PHY2, 1 = PHY3 + + // MIPI TXPHY A: phy-id = 0 + mipi-txphy-config-0 { + status = "okay"; + phy-id = <0>; // MIPI TXPHY ID: 0/1/2/3 + + phy-type = <0>; // 0: DPHY, 1: CPHY + auto-deskew = <0x80>; + data-lane-num = <4>; + data-lane-map = <0x4>; + vc-ext-en = <0>; + }; + + // MIPI TXPHY B: phy-id = 1 + mipi-txphy-config-1 { + status = "okay"; + phy-id = <1>; // MIPI TXPHY ID: 0/1/2/3 + + phy-type = <0>; // 0: DPHY, 1: CPHY + auto-deskew = <0x80>; + data-lane-num = <4>; + data-lane-map = <0xe>; + vc-ext-en = <0>; + }; + }; + /* MIPI TXPHY config end */ + + /* local device extra init sequence */ + extra-init-sequence { + status = "disabled"; + + seq-item-size = <5>; // reg-addr-len + reg-val-len * 2 + 1 + reg-addr-len = <2>; // 1: 8bits, 2: 16bits + reg-val-len = <1>; // 1: 8bits, 2: 16bits, 3: 24bits + + // reg_addr reg_val val_mask delay + init-sequence = [ + // common init sequence such as fsync / gpio and so on + ]; + }; + }; + /* serdes local device end */ + + /* i2c-mux start */ + i2c-mux { + #address-cells = <1>; + #size-cells = <0>; + + i2c@0 { + #address-cells = <1>; + #size-cells = <0>; + reg = <0>; + + // Note: Serializer node defined before camera node + max96712_dphy3_ser0: max96717@51 { + compatible = "maxim,ser,max96717f"; + reg = <0x51>; + + ser-i2c-addr-def = <0x40>; + + ser-init-sequence { + seq-item-size = <5>; // reg-addr-len + reg-val-len * 2 + 1 + reg-addr-len = <2>; // 1: 8bits, 2: 16bits + reg-val-len = <1>; // 1: 8bits, 2: 16bits, 3: 24bits + + // reg_addr reg_val val_mask delay + init-sequence = [ + 03 02 10 00 00 + 14 17 00 00 00 + 14 32 7f 00 00 + ]; + }; + }; + + max96712_dphy3_cam0: sc233at@31 { + compatible = "maxim,dummy,sensor"; + reg = <0x31>; + + cam-i2c-addr-def = <0x30>; + + cam-remote-ser = <&max96712_dphy3_ser0>; // remote serializer + + poc-supply = <&max96712_dphy3_poc_regulator>; + + rockchip,camera-module-index = <0>; + rockchip,camera-module-facing = "back"; + rockchip,camera-module-name = "default"; + rockchip,camera-module-lens-name = "default"; + + /* port config start */ + port { + max96712_dphy3_cam0_out: endpoint { + data-lanes = <1 2 3 4>; + }; + }; + /* port config end */ + }; + }; + + i2c@1 { + #address-cells = <1>; + #size-cells = <0>; + reg = <1>; + + // Note: Serializer node defined before camera node + max96712_dphy3_ser1: max96717@52 { + compatible = "maxim,ser,max96717f"; + reg = <0x52>; + + ser-i2c-addr-def = <0x40>; + + ser-init-sequence { + seq-item-size = <5>; // reg-addr-len + reg-val-len * 2 + 1 + reg-addr-len = <2>; // 1: 8bits, 2: 16bits + reg-val-len = <1>; // 1: 8bits, 2: 16bits, 3: 24bits + + // reg_addr reg_val val_mask delay + init-sequence = [ + 03 02 10 00 00 + 14 17 00 00 00 + 14 32 7f 00 00 + ]; + }; + }; + + max96712_dphy3_cam1: sc233at@32 { + compatible = "maxim,dummy,sensor"; + reg = <0x32>; + + cam-i2c-addr-def = <0x30>; + + cam-remote-ser = <&max96712_dphy3_ser1>; // remote serializer + + poc-supply = <&max96712_dphy3_poc_regulator>; + + rockchip,camera-module-index = <1>; + rockchip,camera-module-facing = "back"; + rockchip,camera-module-name = "default"; + rockchip,camera-module-lens-name = "default"; + + /* port config start */ + port { + max96712_dphy3_cam1_out: endpoint { + data-lanes = <1 2 3 4>; + }; + }; + /* port config end */ + }; + }; + + i2c@2 { + #address-cells = <1>; + #size-cells = <0>; + reg = <2>; + + // Note: Serializer node defined before camera node + max96712_dphy3_ser2: max96717@53 { + compatible = "maxim,ser,max96717f"; + reg = <0x53>; + + ser-i2c-addr-def = <0x40>; + + ser-init-sequence { + seq-item-size = <5>; // reg-addr-len + reg-val-len * 2 + 1 + reg-addr-len = <2>; // 1: 8bits, 2: 16bits + reg-val-len = <1>; // 1: 8bits, 2: 16bits, 3: 24bits + + // reg_addr reg_val val_mask delay + init-sequence = [ + 03 02 10 00 00 + 14 17 00 00 00 + 14 32 7f 00 00 + ]; + }; + }; + + max96712_dphy3_cam2: sc233at@33 { + compatible = "maxim,dummy,sensor"; + reg = <0x33>; + + cam-i2c-addr-def = <0x30>; + + cam-remote-ser = <&max96712_dphy3_ser2>; // remote serializer + + poc-supply = <&max96712_dphy3_poc_regulator>; + + rockchip,camera-module-index = <2>; + rockchip,camera-module-facing = "back"; + rockchip,camera-module-name = "default"; + rockchip,camera-module-lens-name = "default"; + + /* port config start */ + port { + max96712_dphy3_cam2_out: endpoint { + data-lanes = <1 2 3 4>; + }; + }; + /* port config end */ + }; + }; + + i2c@3 { + #address-cells = <1>; + #size-cells = <0>; + reg = <3>; + + // Note: Serializer node defined before camera node + max96712_dphy3_ser3: max96717@54 { + compatible = "maxim,ser,max96717f"; + reg = <0x54>; + + ser-i2c-addr-def = <0x40>; + + ser-init-sequence { + seq-item-size = <5>; // reg-addr-len + reg-val-len * 2 + 1 + reg-addr-len = <2>; // 1: 8bits, 2: 16bits + reg-val-len = <1>; // 1: 8bits, 2: 16bits, 3: 24bits + + // reg_addr reg_val val_mask delay + init-sequence = [ + 03 02 10 00 00 + 14 17 00 00 00 + 14 32 7f 00 00 + ]; + }; + }; + + max96712_dphy3_cam3: sc233at@34 { + compatible = "maxim,dummy,sensor"; + reg = <0x34>; + + cam-i2c-addr-def = <0x30>; + + cam-remote-ser = <&max96712_dphy3_ser3>; // remote serializer + + poc-supply = <&max96712_dphy3_poc_regulator>; + + rockchip,camera-module-index = <3>; + rockchip,camera-module-facing = "back"; + rockchip,camera-module-name = "default"; + rockchip,camera-module-lens-name = "default"; + + /* port config start */ + port { + max96712_dphy3_cam3_out: endpoint { + data-lanes = <1 2 3 4>; + }; + }; + /* port config end */ + }; + }; + }; + /* i2c-mux end */ + }; +}; + +&mipi3_csi2 { + status = "okay"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + #address-cells = <1>; + #size-cells = <0>; + + mipi3_csi2_input: endpoint@1 { + reg = <1>; + remote-endpoint = <&csidphy3_out>; + }; + }; + + port@1 { + reg = <1>; + #address-cells = <1>; + #size-cells = <0>; + + mipi3_csi2_output: endpoint@0 { + reg = <0>; + remote-endpoint = <&cif_mipi3_in>; + }; + }; + }; +}; + +&rkcif_mipi_lvds3 { + status = "okay"; + /* parameters for do cif reset detecting: + * index0: monitor mode, + 0 for idle, + 1 for continue, + 2 for trigger, + 3 for hotplug (for nextchip) + * index1: the frame id to start timer, + min is 2 + * index2: frame num of monitoring cycle + * index3: err time for keep monitoring + after finding out err (ms) + * index4: csi2 err reference val for resetting + */ + rockchip,cif-monitor = <3 2 1 1000 5>; + + port { + cif_mipi3_in: endpoint { + remote-endpoint = <&mipi3_csi2_output>; + }; + }; +}; + +&rkcif { + status = "okay"; + rockchip,android-usb-camerahal-enable; +}; + +&rkcif_mmu { + status = "okay"; +}; + +&pinctrl { + max96712-dphy3 { + max96712_dphy3_pwdn: max96712-dphy3-pwdn { + rockchip,pins = <4 RK_PC0 RK_FUNC_GPIO &pcfg_output_low>; + }; + + max96712_dphy3_errb: max96712-dphy3-errb { + rockchip,pins = <4 RK_PC1 RK_FUNC_GPIO &pcfg_pull_none_smt>; + }; + + max96712_dphy3_lock: max96712-dphy3-lock { + rockchip,pins = <4 RK_PC2 RK_FUNC_GPIO &pcfg_pull_none_smt>; + }; + }; +}; diff --git a/arch/arm64/boot/dts/rockchip/rk3576-vehicle-evb-v20.dts b/arch/arm64/boot/dts/rockchip/rk3576-vehicle-evb-v20.dts index cf790ab86eb9..144b742871ae 100644 --- a/arch/arm64/boot/dts/rockchip/rk3576-vehicle-evb-v20.dts +++ b/arch/arm64/boot/dts/rockchip/rk3576-vehicle-evb-v20.dts @@ -11,6 +11,7 @@ #include "rk3576-vehicle-evb-v20-nca9539-io-expander.dtsi" #include "rk3576-vehicle-evb-v20-serdes-mfd-display-maxim.dtsi" #include "rk3576-vehicle-evb-v20-maxim-max96712-dphy0-isx021.dtsi" +#include "rk3576-vehicle-evb-v20-maxim-max96712-dphy3-sc233at.dtsi" #include "rk3576-android.dtsi" / { diff --git a/arch/arm64/boot/dts/rockchip/rk3588-vehicle-evb-v23.dts b/arch/arm64/boot/dts/rockchip/rk3588-vehicle-evb-v23.dts index ef72a61d3187..775cd3140ca2 100644 --- a/arch/arm64/boot/dts/rockchip/rk3588-vehicle-evb-v23.dts +++ b/arch/arm64/boot/dts/rockchip/rk3588-vehicle-evb-v23.dts @@ -308,7 +308,7 @@ pinctrl-0 = <&uart7m1_rtsn>, <&bt_reset_gpio>, <&bt_wake_gpio>, <&bt_irq_gpio>; pinctrl-1 = <&uart7_gpios>; BT,reset_gpio = <&gpio0 RK_PD6 GPIO_ACTIVE_HIGH>; - BT,wake_gpio = <&gpio0 RK_PC7 GPIO_ACTIVE_HIGH>; + BT,wake_gpio = <&gpio3 RK_PB7 GPIO_ACTIVE_HIGH>; BT,wake_host_irq = <&gpio0 RK_PA4 GPIO_ACTIVE_HIGH>; status = "okay"; }; diff --git a/arch/arm64/configs/px30_linux_defconfig b/arch/arm64/configs/px30_linux_defconfig index 7add331c6fb1..91a21f48a9c4 100644 --- a/arch/arm64/configs/px30_linux_defconfig +++ b/arch/arm64/configs/px30_linux_defconfig @@ -1,3 +1,4 @@ +CONFIG_WERROR=y CONFIG_DEFAULT_HOSTNAME="localhost" CONFIG_SYSVIPC=y CONFIG_NO_HZ=y @@ -16,7 +17,6 @@ CONFIG_USER_NS=y CONFIG_BLK_DEV_INITRD=y CONFIG_CC_OPTIMIZE_FOR_SIZE=y CONFIG_EMBEDDED=y -# CONFIG_COMPAT_BRK is not set CONFIG_PROFILING=y CONFIG_ARCH_ROCKCHIP=y # CONFIG_ARM64_ERRATUM_826319 is not set @@ -40,10 +40,9 @@ CONFIG_PM_ADVANCED_DEBUG=y CONFIG_WQ_POWER_EFFICIENT_DEFAULT=y CONFIG_ENERGY_MODEL=y CONFIG_CPU_IDLE=y -CONFIG_ARM_CPUIDLE=y +CONFIG_ARM_PSCI_CPUIDLE=y CONFIG_CPU_FREQ=y CONFIG_CPU_FREQ_STAT=y -CONFIG_CPU_FREQ_TIMES=y CONFIG_CPU_FREQ_DEFAULT_GOV_INTERACTIVE=y CONFIG_CPU_FREQ_GOV_POWERSAVE=y CONFIG_CPU_FREQ_GOV_USERSPACE=y @@ -51,23 +50,15 @@ CONFIG_CPU_FREQ_GOV_ONDEMAND=y CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y CONFIG_CPUFREQ_DT=y CONFIG_ARM_ROCKCHIP_CPUFREQ=y -CONFIG_ARM_SCMI_PROTOCOL=y -CONFIG_ROCKCHIP_SIP=y -CONFIG_ARM64_CRYPTO=y -CONFIG_CRYPTO_SHA1_ARM64_CE=y -CONFIG_CRYPTO_SHA2_ARM64_CE=y -CONFIG_CRYPTO_GHASH_ARM64_CE=y -CONFIG_CRYPTO_AES_ARM64_CE_CCM=y -CONFIG_CRYPTO_AES_ARM64_CE_BLK=y CONFIG_MODULES=y CONFIG_MODULE_FORCE_LOAD=y CONFIG_MODULE_UNLOAD=y CONFIG_MODULE_FORCE_UNLOAD=y CONFIG_PARTITION_ADVANCED=y +# CONFIG_COMPAT_BRK is not set # CONFIG_COMPACTION is not set CONFIG_DEFAULT_MMAP_MIN_ADDR=32768 CONFIG_CMA=y -CONFIG_ZSMALLOC=y CONFIG_NET=y CONFIG_PACKET=y CONFIG_UNIX=y @@ -103,6 +94,8 @@ CONFIG_DEVTMPFS=y CONFIG_DEVTMPFS_MOUNT=y CONFIG_DEBUG_DEVRES=y CONFIG_CONNECTOR=y +CONFIG_ARM_SCMI_PROTOCOL=y +CONFIG_ROCKCHIP_SIP=y CONFIG_DTC_SYMBOLS=y CONFIG_ZRAM=y CONFIG_BLK_DEV_LOOP=y @@ -218,14 +211,12 @@ CONFIG_REGULATOR_GPIO=y CONFIG_REGULATOR_PWM=y CONFIG_REGULATOR_RK808=y CONFIG_MEDIA_SUPPORT=y -CONFIG_VIDEO_V4L2_SUBDEV_API=y CONFIG_MEDIA_USB_SUPPORT=y CONFIG_USB_VIDEO_CLASS=y # CONFIG_USB_VIDEO_CLASS_INPUT_EVDEV is not set -# CONFIG_USB_GSPCA is not set CONFIG_V4L_PLATFORM_DRIVERS=y -CONFIG_VIDEO_ROCKCHIP_RKISP1=y CONFIG_V4L_MEM2MEM_DRIVERS=y +CONFIG_VIDEO_ROCKCHIP_RKISP1=y CONFIG_VIDEO_OV5695=y # CONFIG_DVB_AU8522_V4L is not set # CONFIG_DVB_TUNER_DIB0070 is not set @@ -273,7 +264,6 @@ CONFIG_UHID=y CONFIG_HID_KENSINGTON=y CONFIG_HID_MULTITOUCH=y CONFIG_USB_HIDDEV=y -CONFIG_I2C_HID=y CONFIG_USB_ANNOUNCE_NEW_DEVICES=y # CONFIG_USB_DEFAULT_PERSIST is not set CONFIG_USB_OTG=y @@ -319,6 +309,10 @@ CONFIG_RTC_CLASS=y CONFIG_RTC_DRV_RK808=y CONFIG_DMADEVICES=y CONFIG_PL330_DMA=y +CONFIG_DMABUF_HEAPS=y +CONFIG_DMABUF_SYSFS_STATS=y +CONFIG_DMABUF_HEAPS_SYSTEM=y +CONFIG_DMABUF_HEAPS_CMA=y CONFIG_STAGING=y CONFIG_COMMON_CLK_RK808=y CONFIG_COMMON_CLK_SCMI=y @@ -338,6 +332,9 @@ CONFIG_FIQ_DEBUGGER=y CONFIG_FIQ_DEBUGGER_NO_SLEEP=y CONFIG_FIQ_DEBUGGER_CONSOLE=y CONFIG_FIQ_DEBUGGER_CONSOLE_DEFAULT_ENABLE=y +CONFIG_FIQ_DEBUGGER_TRUST_ZONE=y +CONFIG_RK_CONSOLE_THREAD=y +CONFIG_ROCKCHIP_DEBUG=y CONFIG_PM_DEVFREQ=y CONFIG_DEVFREQ_GOV_PERFORMANCE=y CONFIG_DEVFREQ_GOV_POWERSAVE=y @@ -357,7 +354,6 @@ CONFIG_PWM_ROCKCHIP=y CONFIG_PHY_ROCKCHIP_CSI2_DPHY=y CONFIG_PHY_ROCKCHIP_INNO_USB2=y CONFIG_PHY_ROCKCHIP_INNO_DSIDPHY=y -CONFIG_ANDROID=y CONFIG_NVMEM_ROCKCHIP_OTP=y CONFIG_RK_HEADSET=y CONFIG_EXT4_FS=y @@ -391,12 +387,17 @@ CONFIG_NLS_ASCII=y CONFIG_NLS_ISO8859_1=y CONFIG_NLS_UTF8=y CONFIG_SECURITYFS=y -CONFIG_CRYPTO_MD5=y -CONFIG_CRYPTO_SHA512=y CONFIG_CRYPTO_TWOFISH=y +CONFIG_CRYPTO_MD5=y +CONFIG_CRYPTO_LZO=y CONFIG_CRYPTO_ANSI_CPRNG=y CONFIG_CRYPTO_USER_API_HASH=y CONFIG_CRYPTO_USER_API_SKCIPHER=y +CONFIG_CRYPTO_GHASH_ARM64_CE=y +CONFIG_CRYPTO_SHA1_ARM64_CE=y +CONFIG_CRYPTO_SHA2_ARM64_CE=y +CONFIG_CRYPTO_AES_ARM64_CE_BLK=y +CONFIG_CRYPTO_AES_ARM64_CE_CCM=y CONFIG_CRC_CCITT=y CONFIG_CRC_T10DIF=y CONFIG_CRC7=y @@ -407,9 +408,10 @@ CONFIG_CRC7=y CONFIG_DMA_CMA=y CONFIG_PRINTK_TIME=y CONFIG_DYNAMIC_DEBUG=y -CONFIG_DEBUG_INFO=y +CONFIG_DEBUG_INFO_DWARF_TOOLCHAIN_DEFAULT=y CONFIG_MAGIC_SYSRQ=y CONFIG_MAGIC_SYSRQ_DEFAULT_ENABLE=0 +# CONFIG_SLUB_DEBUG is not set CONFIG_SOFTLOCKUP_DETECTOR=y CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC=y CONFIG_BOOTPARAM_HUNG_TASK_PANIC=y diff --git a/arch/arm64/mm/fixup_fault.S b/arch/arm64/mm/fixup_fault.S index 0e94564ae68d..2ee99f3f74b0 100644 --- a/arch/arm64/mm/fixup_fault.S +++ b/arch/arm64/mm/fixup_fault.S @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0 */ /* - * Copyright (C) 2023 Rockchip Electronics Co. Ltd. + * Copyright (C) 2023 Rockchip Electronics Co., Ltd. */ .arch armv8-a diff --git a/boot.its b/boot.its index 755005c424b4..648258fde2dc 100644 --- a/boot.its +++ b/boot.its @@ -1,5 +1,5 @@ /* - * Copyright (C) 2021 Rockchip Electronics Co., Ltd + * Copyright (C) 2021 Rockchip Electronics Co., Ltd. * * SPDX-License-Identifier: GPL-2.0 */ diff --git a/drivers/clk/rockchip/clk-pvtpll.c b/drivers/clk/rockchip/clk-pvtpll.c index 7cf4889e5aff..0900b6716a61 100644 --- a/drivers/clk/rockchip/clk-pvtpll.c +++ b/drivers/clk/rockchip/clk-pvtpll.c @@ -8,6 +8,7 @@ #include #include #include +#include #include #include #include @@ -18,6 +19,8 @@ #include #include "clk.h" +#define MHz 1000000 + #define RV1103B_PVTPLL_GCK_CFG 0x20 #define RV1103B_PVTPLL_GCK_LEN 0x24 #define RV1103B_GCK_START BIT(0) @@ -36,6 +39,7 @@ #define RK3506_START BIT(0) #define RK3506_RING_LENGTH_SEL_OFFSET 0 #define RK3506_RING_LENGTH_SEL_MASK 0x7f +#define RK3506_PVTPLL_MAX_LENGTH 0x7f struct rockchip_clock_pvtpll; @@ -44,17 +48,25 @@ struct pvtpll_table { u32 length; u32 length_frac; u32 ring_sel; + u32 volt_sel_thr; }; struct rockchip_clock_pvtpll_info { unsigned int table_size; struct pvtpll_table *table; + unsigned int jm_table_size; + struct pvtpll_table *jm_table; int (*config)(struct rockchip_clock_pvtpll *pvtpll, struct pvtpll_table *table); + int (*pvtpll_volt_sel_adjust)(struct rockchip_clock_pvtpll *pvtpll, + u32 clock_id, + u32 volt_sel); }; struct rockchip_clock_pvtpll { - const struct rockchip_clock_pvtpll_info *info; + struct device *dev; + struct list_head list_head; + struct rockchip_clock_pvtpll_info *info; struct regmap *regmap; struct clk_hw hw; struct clk *main_clk; @@ -63,8 +75,19 @@ struct rockchip_clock_pvtpll { struct clk *pvtpll_out; struct notifier_block pvtpll_nb; unsigned long cur_rate; + u32 pvtpll_clk_id; }; +static LIST_HEAD(rockchip_clock_pvtpll_list); +static DEFINE_MUTEX(pvtpll_list_mutex); + +struct otp_opp_info { + u16 min_freq; + u16 max_freq; + u8 volt; + u8 length; +} __packed; + #define ROCKCHIP_PVTPLL(_rate, _sel, _len) \ { \ .rate = _rate##U, \ @@ -72,6 +95,14 @@ struct rockchip_clock_pvtpll { .length = _len, \ } +#define ROCKCHIP_PVTPLL_VOLT_SEL(_rate, _sel, _len, _volt_sel_thr) \ +{ \ + .rate = _rate##U, \ + .ring_sel = _sel, \ + .length = _len, \ + .volt_sel_thr = _volt_sel_thr, \ +} + static struct pvtpll_table rv1103b_core_pvtpll_table[] = { /* rate_hz, ring_sel, length */ ROCKCHIP_PVTPLL(1608000000, 1, 6), @@ -92,13 +123,25 @@ static struct pvtpll_table rv1103b_npu_pvtpll_table[] = { }; static struct pvtpll_table rk3506_core_pvtpll_table[] = { - /* rate_hz, ring_sel, length */ - ROCKCHIP_PVTPLL(1608000000, 0, 6), - ROCKCHIP_PVTPLL(1512000000, 0, 6), - ROCKCHIP_PVTPLL(1416000000, 0, 6), - ROCKCHIP_PVTPLL(1296000000, 0, 6), - ROCKCHIP_PVTPLL(1200000000, 0, 8), - ROCKCHIP_PVTPLL(1008000000, 0, 15), + /* rate_hz, ring_sel, length, volt_sel_thr */ + ROCKCHIP_PVTPLL_VOLT_SEL(1608000000, 0, 6, 7), + ROCKCHIP_PVTPLL_VOLT_SEL(1512000000, 0, 6, 7), + ROCKCHIP_PVTPLL_VOLT_SEL(1416000000, 0, 6, 5), + ROCKCHIP_PVTPLL_VOLT_SEL(1296000000, 0, 6, 3), + ROCKCHIP_PVTPLL_VOLT_SEL(1200000000, 0, 6, 2), + ROCKCHIP_PVTPLL_VOLT_SEL(1008000000, 0, 10, 4), + ROCKCHIP_PVTPLL_VOLT_SEL(800000000, 0, 18, 4), +}; + +static struct pvtpll_table rk3506j_core_pvtpll_table[] = { + /* rate_hz, ring_sel, length, volt_sel_thr */ + ROCKCHIP_PVTPLL_VOLT_SEL(1608000000, 0, 6, 7), + ROCKCHIP_PVTPLL_VOLT_SEL(1512000000, 0, 7, 7), + ROCKCHIP_PVTPLL_VOLT_SEL(1416000000, 0, 7, 5), + ROCKCHIP_PVTPLL_VOLT_SEL(1296000000, 0, 7, 3), + ROCKCHIP_PVTPLL_VOLT_SEL(1200000000, 0, 7, 2), + ROCKCHIP_PVTPLL_VOLT_SEL(1008000000, 0, 11, 2), + ROCKCHIP_PVTPLL_VOLT_SEL(800000000, 0, 19, 2), }; static struct pvtpll_table @@ -259,6 +302,126 @@ static int clock_pvtpll_regitstor(struct device *dev, pvtpll->pvtpll_out); } +static int rk3506_pvtpll_volt_sel_adjust(struct rockchip_clock_pvtpll *pvtpll, + u32 clock_id, + u32 volt_sel) +{ + struct pvtpll_table *table = pvtpll->info->table; + unsigned int size = pvtpll->info->table_size; + uint32_t delta_len = 0; + int i; + + for (i = 0; i < size; i++) { + if (!table[i].volt_sel_thr) + continue; + if (volt_sel >= table[i].volt_sel_thr) { + delta_len = volt_sel - table[i].volt_sel_thr + 1; + table[i].length += delta_len; + if (table[i].length > RK3506_PVTPLL_MAX_LENGTH) + table[i].length = RK3506_PVTPLL_MAX_LENGTH; + } + } + + return 0; +} + +int rockchip_pvtpll_volt_sel_adjust(u32 clock_id, u32 volt_sel) +{ + struct rockchip_clock_pvtpll *pvtpll; + int ret = -ENODEV; + + mutex_lock(&pvtpll_list_mutex); + list_for_each_entry(pvtpll, &rockchip_clock_pvtpll_list, list_head) { + if ((pvtpll->pvtpll_clk_id == clock_id) && pvtpll->info->pvtpll_volt_sel_adjust) { + ret = pvtpll->info->pvtpll_volt_sel_adjust(pvtpll, clock_id, volt_sel); + break; + } + } + mutex_unlock(&pvtpll_list_mutex); + + return ret; +} +EXPORT_SYMBOL_GPL(rockchip_pvtpll_volt_sel_adjust); + +static int rockchip_pvtpll_get_otp_info(struct device *dev, + struct otp_opp_info *opp_info) +{ + struct nvmem_cell *cell; + void *buf; + size_t len = 0; + + cell = nvmem_cell_get(dev, "opp-info"); + if (IS_ERR(cell)) + return PTR_ERR(cell); + + buf = nvmem_cell_read(cell, &len); + if (IS_ERR(buf)) { + nvmem_cell_put(cell); + return PTR_ERR(buf); + } + if (len != sizeof(*opp_info)) { + kfree(buf); + nvmem_cell_put(cell); + return -EINVAL; + } + + memcpy(opp_info, buf, sizeof(*opp_info)); + kfree(buf); + nvmem_cell_put(cell); + + return 0; +} + +static void rockchip_switch_pvtpll_table(struct device *dev, + struct rockchip_clock_pvtpll *pvtpll) +{ + u8 spec = 0; + + if (!pvtpll->info->jm_table) + return; + + if (!nvmem_cell_read_u8(dev, "specification_serial_number", &spec)) { + /* M = 0xd, J = 0xa */ + if ((spec == 0xd) || (spec == 0xa)) { + pvtpll->info->table = pvtpll->info->jm_table; + pvtpll->info->table_size = pvtpll->info->jm_table_size; + } + } +} + +static void rockchip_adjust_pvtpll_by_otp(struct device *dev, + struct rockchip_clock_pvtpll *pvtpll) +{ + struct otp_opp_info opp_info = { 0 }; + struct pvtpll_table *table = pvtpll->info->table; + unsigned int size = pvtpll->info->table_size; + u32 min_freq, max_freq; + int i; + + if (rockchip_pvtpll_get_otp_info(dev, &opp_info)) + return; + + if (!opp_info.length) + return; + + dev_info(dev, "adjust opp-table by otp: min=%uM, max=%uM, length=%u\n", + opp_info.min_freq, opp_info.max_freq, opp_info.length); + + min_freq = opp_info.min_freq * MHz; + max_freq = opp_info.max_freq * MHz; + + for (i = 0; i < size; i++) { + if (table[i].rate < min_freq) + continue; + if (table[i].rate > max_freq) + continue; + + table[i].length += opp_info.length; + if (table[i].length > RK3506_PVTPLL_MAX_LENGTH) + table[i].length = RK3506_PVTPLL_MAX_LENGTH; + } +} + static const struct rockchip_clock_pvtpll_info rv1103b_core_pvtpll_data = { .config = rv1103b_pvtpll_configs, .table_size = ARRAY_SIZE(rv1103b_core_pvtpll_table), @@ -275,6 +438,9 @@ static const struct rockchip_clock_pvtpll_info rk3506_core_pvtpll_data = { .config = rk3506_pvtpll_configs, .table_size = ARRAY_SIZE(rk3506_core_pvtpll_table), .table = rk3506_core_pvtpll_table, + .jm_table_size = ARRAY_SIZE(rk3506j_core_pvtpll_table), + .jm_table = rk3506j_core_pvtpll_table, + .pvtpll_volt_sel_adjust = rk3506_pvtpll_volt_sel_adjust, }; static const struct of_device_id rockchip_clock_pvtpll_match[] = { @@ -299,13 +465,14 @@ static int rockchip_clock_pvtpll_probe(struct platform_device *pdev) struct device *dev = &pdev->dev; struct device_node *np = pdev->dev.of_node; struct rockchip_clock_pvtpll *pvtpll; + struct of_phandle_args clkspec = { 0 }; int error = 0; pvtpll = devm_kzalloc(dev, sizeof(*pvtpll), GFP_KERNEL); if (!pvtpll) return -ENOMEM; - pvtpll->info = (const struct rockchip_clock_pvtpll_info *)device_get_match_data(&pdev->dev); + pvtpll->info = (struct rockchip_clock_pvtpll_info *)device_get_match_data(&pdev->dev); if (!pvtpll->info) return -EINVAL; @@ -313,15 +480,32 @@ static int rockchip_clock_pvtpll_probe(struct platform_device *pdev) if (IS_ERR(pvtpll->regmap)) return PTR_ERR(pvtpll->regmap); + pvtpll->pvtpll_clk_id = UINT_MAX; + + error = of_parse_phandle_with_args(np, "clocks", "#clock-cells", + 0, &clkspec); + if (!error) { + pvtpll->pvtpll_clk_id = clkspec.args[0]; + of_node_put(clkspec.np); + } + + rockchip_switch_pvtpll_table(dev, pvtpll); + + rockchip_adjust_pvtpll_by_otp(dev, pvtpll); + platform_set_drvdata(pdev, pvtpll); error = clock_pvtpll_regitstor(&pdev->dev, pvtpll); if (error) { - dev_err(&pdev->dev, "failed to register clock: %d\n", - error); + dev_err(&pdev->dev, "failed to register clock: %d\n", error); + return error; } - return error; + mutex_lock(&pvtpll_list_mutex); + list_add(&pvtpll->list_head, &rockchip_clock_pvtpll_list); + mutex_unlock(&pvtpll_list_mutex); + + return 0; } static int rockchip_clock_pvtpll_remove(struct platform_device *pdev) diff --git a/drivers/clk/rockchip/clk.h b/drivers/clk/rockchip/clk.h index 0a25a11c0588..7441b7e604b8 100644 --- a/drivers/clk/rockchip/clk.h +++ b/drivers/clk/rockchip/clk.h @@ -774,6 +774,15 @@ struct clk *rockchip_clk_register_ddrclk(const char *name, int flags, } #endif +#if IS_REACHABLE(CONFIG_ROCKCHIP_CLK_PVTPLL) +int rockchip_pvtpll_volt_sel_adjust(u32 clock_id, u32 volt_sel); +#else +static inline int rockchip_pvtpll_volt_sel_adjust(u32 clock_id, u32 volt_sel) +{ + return -ENODEV; +} +#endif + #define ROCKCHIP_INVERTER_HIWORD_MASK BIT(0) struct clk *rockchip_clk_register_inverter(const char *name, diff --git a/drivers/devfreq/rockchip_dmc.c b/drivers/devfreq/rockchip_dmc.c index c798f9220ed7..3526ebc1ecc7 100644 --- a/drivers/devfreq/rockchip_dmc.c +++ b/drivers/devfreq/rockchip_dmc.c @@ -2,7 +2,7 @@ /* * Rockchip Generic dmc support. * - * Copyright (c) 2021 Rockchip Electronics Co. Ltd. + * Copyright (c) 2021 Rockchip Electronics Co., Ltd. * Author: Finley Xiao */ diff --git a/drivers/devfreq/rockchip_dmc_common.c b/drivers/devfreq/rockchip_dmc_common.c index 7765e7174ce2..9fcf4583812a 100644 --- a/drivers/devfreq/rockchip_dmc_common.c +++ b/drivers/devfreq/rockchip_dmc_common.c @@ -2,7 +2,7 @@ /* * Rockchip dmc common functions. * - * Copyright (c) 2021 Rockchip Electronics Co. Ltd. + * Copyright (c) 2021 Rockchip Electronics Co., Ltd. * Author: Finley Xiao */ diff --git a/drivers/gpio/gpio-aw9110.c b/drivers/gpio/gpio-aw9110.c index ab97726fc7ce..b68bd866b9ff 100644 --- a/drivers/gpio/gpio-aw9110.c +++ b/drivers/gpio/gpio-aw9110.c @@ -2,7 +2,7 @@ /* * Driver for aw9110 I2C GPIO expanders * - * Copyright (c) 2021 Rockchip Electronics Co. Ltd. + * Copyright (c) 2021 Rockchip Electronics Co., Ltd. */ #include #include diff --git a/drivers/gpio/gpio-rockchip.c b/drivers/gpio/gpio-rockchip.c index 4a0c12a2808d..2869a50c16be 100644 --- a/drivers/gpio/gpio-rockchip.c +++ b/drivers/gpio/gpio-rockchip.c @@ -3,7 +3,7 @@ * Copyright (c) 2013 MundoReader S.L. * Author: Heiko Stuebner * - * Copyright (c) 2021 Rockchip Electronics Co. Ltd. + * Copyright (c) 2021 Rockchip Electronics Co., Ltd. */ #include diff --git a/drivers/gpu/arm/bifrost/platform/rk/custom_log.h b/drivers/gpu/arm/bifrost/platform/rk/custom_log.h index 5de70ee13d25..fedfd41bb511 100755 --- a/drivers/gpu/arm/bifrost/platform/rk/custom_log.h +++ b/drivers/gpu/arm/bifrost/platform/rk/custom_log.h @@ -1,5 +1,5 @@ /* - * (C) COPYRIGHT RockChip Limited. All rights reserved. + * (C) COPYRIGHT Rockchip Electronics Co., Ltd. All rights reserved. * * This program is free software and is provided to you under the terms of the * GNU General Public License version 2 as published by the Free Software diff --git a/drivers/gpu/arm/bifrost/platform/rk/mali_kbase_config_rk.c b/drivers/gpu/arm/bifrost/platform/rk/mali_kbase_config_rk.c index cb3f6979bb5d..d20de78ce478 100755 --- a/drivers/gpu/arm/bifrost/platform/rk/mali_kbase_config_rk.c +++ b/drivers/gpu/arm/bifrost/platform/rk/mali_kbase_config_rk.c @@ -1,5 +1,5 @@ /* - * (C) COPYRIGHT RockChip Limited. All rights reserved. + * (C) COPYRIGHT Rockchip Electronics Co., Ltd. All rights reserved. * * This program is free software and is provided to you under the terms of the * GNU General Public License version 2 as published by the Free Software diff --git a/drivers/gpu/arm/mali400/mali/platform/rk/rk.c b/drivers/gpu/arm/mali400/mali/platform/rk/rk.c index edbdf8b5f0f7..7f0e160cb1b4 100644 --- a/drivers/gpu/arm/mali400/mali/platform/rk/rk.c +++ b/drivers/gpu/arm/mali400/mali/platform/rk/rk.c @@ -1,5 +1,5 @@ /* - * (C) COPYRIGHT RockChip Limited. All rights reserved. + * (C) COPYRIGHT Rockchip Electronics Co., Ltd. All rights reserved. * * This program is free software and is provided to you under the terms of the * GNU General Public License version 2 as published by the Free Software diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c b/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c index 83ff85d873a9..8b89e45d2fda 100644 --- a/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c +++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c @@ -738,9 +738,9 @@ void analogix_dp_set_training_pattern(struct analogix_dp_device *dp, case TEST_PATTERN_80BIT: reg = 0x3e0f83e0; analogix_dp_write(dp, ANALOGIX_DP_TEST_80B_PATTERN0, reg); - reg = 0x0f83e0f8; + reg = 0x3e0f83e0; analogix_dp_write(dp, ANALOGIX_DP_TEST_80B_PATTERN1, reg); - reg = 0x0000f83e; + reg = 0x000f83e0; analogix_dp_write(dp, ANALOGIX_DP_TEST_80B_PATTERN2, reg); reg = SCRAMBLING_ENABLE | LINK_QUAL_PATTERN_SET_80BIT; analogix_dp_write(dp, ANALOGIX_DP_TRAINING_PTN_SET, reg); diff --git a/drivers/gpu/drm/rockchip/dw-dp.c b/drivers/gpu/drm/rockchip/dw-dp.c index 94fc6a4987d4..ea9e6335b2d0 100644 --- a/drivers/gpu/drm/rockchip/dw-dp.c +++ b/drivers/gpu/drm/rockchip/dw-dp.c @@ -171,6 +171,9 @@ #define DPTX_AUX_DATA3 0x0b14 #define DPTX_GENERAL_INTERRUPT 0x0d00 +#define VIDEO_FIFO_OVERFLOW_STREAM3 BIT(26) +#define VIDEO_FIFO_OVERFLOW_STREAM2 BIT(20) +#define VIDEO_FIFO_OVERFLOW_STREAM1 BIT(14) #define VIDEO_FIFO_OVERFLOW_STREAM0 BIT(6) #define AUDIO_FIFO_OVERFLOW_STREAM0 BIT(5) #define SDP_EVENT_STREAM0 BIT(4) @@ -2840,7 +2843,6 @@ static irqreturn_t dw_dp_hpd_irq_handler(int irq, void *arg) dp->hotplug.long_hpd = true; dp->hotplug.status = hpd; dp->hotplug.state = GPIO_STATE_PLUG; - schedule_work(&dp->hpd_work); } } else if (dp->hotplug.state == GPIO_STATE_PLUG) { if (!hpd) { @@ -2855,9 +2857,12 @@ static irqreturn_t dw_dp_hpd_irq_handler(int irq, void *arg) dp->hotplug.long_hpd = false; dp->hotplug.status = hpd; dp->hotplug.state = GPIO_STATE_PLUG; - schedule_work(&dp->hpd_work); } } + + if (hpd) + schedule_work(&dp->hpd_work); + mutex_unlock(&dp->irq_lock); @@ -2867,6 +2872,10 @@ static irqreturn_t dw_dp_hpd_irq_handler(int irq, void *arg) static void dw_dp_hpd_init(struct dw_dp *dp) { dp->hotplug.status = dw_dp_detect_no_power(dp); + if (dp->hpd_gpio && dp->hotplug.status) { + dp->hotplug.state = GPIO_STATE_PLUG; + dp->hotplug.long_hpd = true; + } if (dp->hpd_gpio || dp->force_hpd || dp->usbdp_hpd) { regmap_update_bits(dp->regmap, DPTX_CCTL, FORCE_HPD, @@ -2900,6 +2909,14 @@ static void dw_dp_init(struct dw_dp *dp) dw_dp_hpd_init(dp); dw_dp_aux_init(dp); + + regmap_update_bits(dp->regmap, DPTX_GENERAL_INTERRUPT_ENABLE, + VIDEO_FIFO_OVERFLOW_STREAM0 | VIDEO_FIFO_OVERFLOW_STREAM1 | + VIDEO_FIFO_OVERFLOW_STREAM2 | VIDEO_FIFO_OVERFLOW_STREAM3, + FIELD_PREP(VIDEO_FIFO_OVERFLOW_STREAM0, 1) | + FIELD_PREP(VIDEO_FIFO_OVERFLOW_STREAM1, 1) | + FIELD_PREP(VIDEO_FIFO_OVERFLOW_STREAM2, 1) | + FIELD_PREP(VIDEO_FIFO_OVERFLOW_STREAM3, 1)); } static void dw_dp_encoder_enable(struct drm_encoder *encoder) @@ -5084,6 +5101,30 @@ static irqreturn_t dw_dp_irq_handler(int irq, void *data) if (value & HDCP_EVENT) dw_dp_handle_hdcp_event(dp); + if (value & VIDEO_FIFO_OVERFLOW_STREAM0) { + dev_err_ratelimited(dp->dev, "video fifo overflow stream0\n"); + regmap_write(dp->regmap, DPTX_GENERAL_INTERRUPT, + VIDEO_FIFO_OVERFLOW_STREAM0); + } + + if (value & VIDEO_FIFO_OVERFLOW_STREAM1) { + dev_err_ratelimited(dp->dev, "video fifo overflow stream1\n"); + regmap_write(dp->regmap, DPTX_GENERAL_INTERRUPT, + VIDEO_FIFO_OVERFLOW_STREAM1); + } + + if (value & VIDEO_FIFO_OVERFLOW_STREAM2) { + dev_err_ratelimited(dp->dev, "video fifo overflow stream2\n"); + regmap_write(dp->regmap, DPTX_GENERAL_INTERRUPT, + VIDEO_FIFO_OVERFLOW_STREAM2); + } + + if (value & VIDEO_FIFO_OVERFLOW_STREAM3) { + dev_err_ratelimited(dp->dev, "video fifo overflow stream3\n"); + regmap_write(dp->regmap, DPTX_GENERAL_INTERRUPT, + VIDEO_FIFO_OVERFLOW_STREAM3); + } + return IRQ_HANDLED; } diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c index 9598b4624cee..25f3879a46b0 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c @@ -1038,6 +1038,9 @@ static const struct drm_bus_format_enum_list drm_bus_format_enum_list[] = { static DRM_ENUM_NAME_FN(drm_get_bus_format_name, drm_bus_format_enum_list) +static inline void vop2_cfg_done(struct drm_crtc *crtc); +static void vop2_wait_for_fs_by_done_bit_status(struct vop2_video_port *vp); + static inline struct vop2_video_port *to_vop2_video_port(struct drm_crtc *crtc) { struct rockchip_crtc *rockchip_crtc; @@ -1224,7 +1227,12 @@ static void vop2_crtc_output_post_enable(struct drm_crtc *crtc, int intf) else if (intf & VOP_OUTPUT_IF_DP2) VOP_CTRL_SET(vop2, dp2_en, 1); - dev_info(vop2->dev, "vop enable intf:%x\n", intf); + if (output_if_is_dp(intf)) { + vop2_cfg_done(crtc); + vop2_wait_for_fs_by_done_bit_status(vp); + } + + drm_info(vop2, "vop enable intf:%x\n", intf); } static void vop2_crtc_output_pre_disable(struct drm_crtc *crtc, int intf) @@ -1239,7 +1247,12 @@ static void vop2_crtc_output_pre_disable(struct drm_crtc *crtc, int intf) else if (intf & VOP_OUTPUT_IF_DP2) VOP_CTRL_SET(vop2, dp2_en, 0); - dev_info(vop2->dev, "vop disable intf:%x\n", intf); + if (output_if_is_dp(intf)) { + vop2_cfg_done(crtc); + vop2_wait_for_fs_by_done_bit_status(vp); + } + + drm_info(vop2, "vop disable intf:%x\n", intf); } static inline const struct vop2_win_regs *vop2_get_win_regs(struct vop2_win *win, diff --git a/drivers/gpu/drm/rockchip/rockchip_vop2_reg.c b/drivers/gpu/drm/rockchip/rockchip_vop2_reg.c index 1ac78f575389..7fe266b500a0 100644 --- a/drivers/gpu/drm/rockchip/rockchip_vop2_reg.c +++ b/drivers/gpu/drm/rockchip/rockchip_vop2_reg.c @@ -4658,7 +4658,7 @@ static const struct vop2_ctrl rk3576_vop_ctrl = { .version = VOP_REG(RK3568_VERSION_INFO, 0xffff, 16), .lut_dma_en = VOP_REG(RK3568_SYS_AXI_LUT_CTRL, 0x1, 0), .lut_use_axi1 = VOP_REG(RK3568_SYS_AXI_LUT_CTRL, 0x1, 9), - .dsp_vs_t_sel = VOP_REG(RK3576_SYS_PORT_CTRL_IMD, 0x1, 4), + .dsp_vs_t_sel = VOP_REG_MASK(RK3576_SYS_PORT_CTRL_IMD, 0x1, 4), .rkmmu_v2_en = VOP_REG_MASK(RK3576_SYS_MMU_CTRL_IMD, 0x1, 0), .rkmmu_v2_sel_axi = VOP_REG_MASK(RK3576_SYS_MMU_CTRL_IMD, 0x1, 1), diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index 33c370eeef45..99fcf9da2445 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -1872,7 +1872,7 @@ u8 *hid_alloc_report_buf(struct hid_report *report, gfp_t flags) u32 len = hid_report_len(report) + 7; - return kmalloc(len, flags); + return kzalloc(len, flags); } EXPORT_SYMBOL_GPL(hid_alloc_report_buf); diff --git a/drivers/iio/adc/rockchip_saradc.c b/drivers/iio/adc/rockchip_saradc.c index 7bd7ba55007e..69dedaa6fa6f 100644 --- a/drivers/iio/adc/rockchip_saradc.c +++ b/drivers/iio/adc/rockchip_saradc.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-or-later /* * Rockchip Successive Approximation Register (SAR) A/D Converter - * Copyright (C) 2014 ROCKCHIP, Inc. + * Copyright (C) 2014 Rockchip Electronics Co., Ltd. */ #include diff --git a/drivers/iio/light/ucs12cm0.c b/drivers/iio/light/ucs12cm0.c index b32dece65d4e..133e8cfb6bba 100644 --- a/drivers/iio/light/ucs12cm0.c +++ b/drivers/iio/light/ucs12cm0.c @@ -2,7 +2,7 @@ /* * UCS12CM0 illuminance and correlated color temperature sensor * - * Copyright (C) 2022-2025 ROCKCHIP. + * Copyright (C) 2022-2025 Rockchip Electronics Co., Ltd. * Author: Jason Zhang * * IIO driver for UCS12CM0 (7-bit I2C slave address 0x38) diff --git a/drivers/input/touchscreen/gslx680_d708/rockchip_gsl3670.h b/drivers/input/touchscreen/gslx680_d708/rockchip_gsl3670.h index 89b74fe3e23c..56df4062587e 100644 --- a/drivers/input/touchscreen/gslx680_d708/rockchip_gsl3670.h +++ b/drivers/input/touchscreen/gslx680_d708/rockchip_gsl3670.h @@ -1,7 +1,7 @@ /* * drivers/input/touchscreen/gslx680_d708/rockchip_gsl3670.h * - * Copyright (c) 2017 rockchip + * Copyright (c) 2017 Rockchip Electronics Co., Ltd. * * * This program is free software; you can redistribute it and/or modify diff --git a/drivers/input/touchscreen/rochkchip_gslX680_8inch_800x1280_tg806_10.h b/drivers/input/touchscreen/rochkchip_gslX680_8inch_800x1280_tg806_10.h index a8ae94e29111..7d424c1e1c30 100644 --- a/drivers/input/touchscreen/rochkchip_gslX680_8inch_800x1280_tg806_10.h +++ b/drivers/input/touchscreen/rochkchip_gslX680_8inch_800x1280_tg806_10.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0 */ /* - * Copyright (c) 2023 Rockchip Electronics Co. Ltd. + * Copyright (c) 2023 Rockchip Electronics Co., Ltd. * * Author: Wangqiang Guo */ diff --git a/drivers/mailbox/rockchip-mailbox.c b/drivers/mailbox/rockchip-mailbox.c index 783d0fd7563a..4dd6963d82a5 100644 --- a/drivers/mailbox/rockchip-mailbox.c +++ b/drivers/mailbox/rockchip-mailbox.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later /* - * Copyright (c) 2024, Rockchip Electronics Co., Ltd + * Copyright (c) 2024, Rockchip Electronics Co., Ltd. */ #include diff --git a/drivers/mailbox/rockchip-mbox-demo.c b/drivers/mailbox/rockchip-mbox-demo.c index 17a313b7e0ab..b91c55e1ac87 100644 --- a/drivers/mailbox/rockchip-mbox-demo.c +++ b/drivers/mailbox/rockchip-mbox-demo.c @@ -2,7 +2,7 @@ /* * Rockchip MBOX Demo. * - * Copyright (c) 2023 Rockchip Electronics Co. Ltd. + * Copyright (c) 2023 Rockchip Electronics Co., Ltd. * Author: Jiahang Zheng */ diff --git a/drivers/media/common/videobuf2/videobuf2-cma-sg.c b/drivers/media/common/videobuf2/videobuf2-cma-sg.c index 84b447100db0..b2f8340ddb7e 100644 --- a/drivers/media/common/videobuf2/videobuf2-cma-sg.c +++ b/drivers/media/common/videobuf2/videobuf2-cma-sg.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 /* - * Copyright (C) 2022 Rockchip Electronics Co., Ltd + * Copyright (C) 2022 Rockchip Electronics Co., Ltd. * Based on videobuf2-dma-sg.c */ diff --git a/drivers/media/i2c/Kconfig b/drivers/media/i2c/Kconfig index d3c0bc171f65..67a779ea612e 100644 --- a/drivers/media/i2c/Kconfig +++ b/drivers/media/i2c/Kconfig @@ -1050,6 +1050,17 @@ config VIDEO_OS05A20 This is a Video4Linux2 sensor driver for the OmniVision OS05A20 camera. +config VIDEO_OS05L10 + tristate "OmniVision OS05L10 sensor support" + depends on I2C && VIDEO_DEV + depends on MEDIA_CAMERA_SUPPORT + select MEDIA_CONTROLLER + select VIDEO_V4L2_SUBDEV_API + select V4L2_FWNODE + help + This is a Video4Linux2 sensor driver for the OmniVision + OS05L10 camera. + config VIDEO_OS08A20 tristate "OmniVision OS08A20 sensor support" depends on I2C && VIDEO_DEV diff --git a/drivers/media/i2c/Makefile b/drivers/media/i2c/Makefile index 6a293413fb71..12cd075780b4 100644 --- a/drivers/media/i2c/Makefile +++ b/drivers/media/i2c/Makefile @@ -153,6 +153,7 @@ obj-$(CONFIG_VIDEO_OS03B10) += os03b10.o obj-$(CONFIG_VIDEO_OS04A10) += os04a10.o obj-$(CONFIG_VIDEO_OS04D10) += os04d10.o obj-$(CONFIG_VIDEO_OS05A20) += os05a20.o +obj-$(CONFIG_VIDEO_OS05L10) += os05l10.o obj-$(CONFIG_VIDEO_OS08A20) += os08a20.o obj-$(CONFIG_VIDEO_OTP_EEPROM) += otp_eeprom.o obj-$(CONFIG_VIDEO_OV02A10) += ov02a10.o diff --git a/drivers/media/i2c/os05l10.c b/drivers/media/i2c/os05l10.c new file mode 100644 index 000000000000..e0c2f4321d67 --- /dev/null +++ b/drivers/media/i2c/os05l10.c @@ -0,0 +1,1739 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * os05l10 driver + * + * Copyright (C) 2024 Rockchip Electronics Co., Ltd. + * + * V0.0X01.0X00 init sensor driver. + */ +//#define DEBUG +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "otp_eeprom.h" + +#define DRIVER_VERSION KERNEL_VERSION(0, 0x01, 0x00) + +#ifndef V4L2_CID_DIGITAL_GAIN +#define V4L2_CID_DIGITAL_GAIN V4L2_CID_GAIN +#endif + +#define OS05L10_LANES 2 +#define OS05L10_BITS_PER_SAMPLE 10 +#define OS05L10_MIPI_FREQ_420MHZ 420000000U + +/* pixel rate = link frequency * 2 * lanes / BITS_PER_SAMPLE */ +#define OS05L10_PIXEL_RATE 288000000 +#define OS05L10_XVCLK_FREQ 24000000 + +#define CHIP_ID 0x104c +#define OS05L10_REG_CHIP_ID_H 0x00 +#define OS05L10_REG_CHIP_ID_L 0x01 + +#define OS05L10_REG_SET_PAGE 0xfd +#define OS05L10_SET_PAGE_ZERO 0x00 + +#define OS05L10_REG_CTRL_MODE 0xa0 +#define OS05L10_MODE_SW_STANDBY 0x00 +#define OS05L10_MODE_STREAMING 0x01 + +#define OS05L10_REG_EXPOSURE_H 0x03 +#define OS05L10_REG_EXPOSURE_L 0x04 +#define OS05L10_FETCH_HIGH_BYTE_EXP(VAL) (((VAL) >> 8) & 0xFF) /* 8 Bits */ +#define OS05L10_FETCH_LOW_BYTE_EXP(VAL) ((VAL) & 0xFF) /* 8 Bits */ +#define OS05L10_EXPOSURE_MIN 4 +#define OS05L10_EXPOSURE_STEP 1 +#define OS05L10_VTS_MAX 0x1fff + +#define OS05L10_REG_AGAIN_H 0x25 +#define OS05L10_REG_AGAIN_L 0x24 +#define OS05L10_GAIN_MIN 0x10 +#define OS05L10_GAIN_MAX 0x1F8 +#define OS05L10_GAIN_STEP 1 +#define OS05L10_GAIN_DEFAULT 0x20 +#define OS05L10_FETCH_H_BYTE_GAIN(VAL) (((VAL) >> 8) & 0x1) /* 1 Bits */ +#define OS05L10_FETCH_L_BYTE_GAIN(VAL) ((VAL) & 0xFF) /* 8 Bits */ + +#define OS05L10_REG_TRIGGER 0x01 + +#define OS05L10_REG_VTS_H 0x05 +#define OS05L10_REG_VTS_L 0x06 + +#define OS05L10_REG_TEST_PATTERN 0x12 +#define OS05L10_TEST_PATTERN_ENABLE 0x01 +#define OS05L10_TEST_PATTERN_DISABLE 0x0 + +#define OS05L10_FLIP_MIRROR_REG 0x32 +#define MIRROR_BIT_MASK BIT(0) +#define FLIP_BIT_MASK BIT(1) + +#define REG_NULL 0xFF + +#define OF_CAMERA_PINCTRL_STATE_DEFAULT "rockchip,camera_default" +#define OF_CAMERA_PINCTRL_STATE_SLEEP "rockchip,camera_sleep" + +#define OS05L10_NAME "os05l10" +#define OS05L10_MEDIA_BUS_FMT MEDIA_BUS_FMT_SBGGR10_1X10 + +/* use RK_OTP or old mode */ +#define RK_OTP +/* choose 2lane support full 30fps or 15fps */ +#define OS05L10_2LANE_30FPS + +static const char * const os05l10_supply_names[] = { + "dovdd", /* Digital I/O power */ + "dvdd", /* Digital core power */ + "avdd", /* Analog power */ +}; + +#define OS05L10_NUM_SUPPLIES ARRAY_SIZE(os05l10_supply_names) + +struct regval { + u8 addr; + u8 val; +}; + +struct os05l10_mode { + u32 width; + u32 height; + struct v4l2_fract max_fps; + u32 hts_def; + u32 vts_def; + u32 exp_def; + u32 mipi_freq_idx; + const struct regval *global_reg_list; + const struct regval *reg_list; + u32 vc[PAD_MAX]; +}; + +struct os05l10 { + struct i2c_client *client; + struct clk *xvclk; + struct gpio_desc *power_gpio; + struct gpio_desc *reset_gpio; + struct gpio_desc *pwdn_gpio; + struct regulator_bulk_data supplies[OS05L10_NUM_SUPPLIES]; + struct pinctrl *pinctrl; + struct pinctrl_state *pins_default; + struct pinctrl_state *pins_sleep; + struct v4l2_subdev subdev; + struct media_pad pad; + struct v4l2_ctrl_handler ctrl_handler; + struct v4l2_ctrl *exposure; + struct v4l2_ctrl *anal_gain; + struct v4l2_ctrl *digi_gain; + struct v4l2_ctrl *hblank; + struct v4l2_ctrl *vblank; + struct v4l2_ctrl *link_freq; + struct v4l2_ctrl *test_pattern; + struct v4l2_ctrl *h_flip; + struct v4l2_ctrl *v_flip; + struct mutex mutex; + bool streaming; + unsigned int lane_num; + unsigned int cfg_num; + unsigned int pixel_rate; + bool power_on; + const struct os05l10_mode *cur_mode; + u32 module_index; + const char *module_facing; + const char *module_name; + const char *len_name; + u32 Dgain_ratio; + struct otp_info *otp; + struct rkmodule_inf module_inf; + struct rkmodule_awb_cfg awb_cfg; +}; + +#define to_os05l10(sd) container_of(sd, struct os05l10, subdev) + +/* + * Xclk 24Mhz + */ +static const struct regval os05l10_global_regs_2lane[] = { + {REG_NULL, 0x00}, +}; + +/* + * Input clock frequency: 24MHz + * mipi_datarate per lane 840Mbps + * hts = 400*8, vts=1750 + * pclk=168M row_clk=21M + * Image output size: 2880x 1620 + * frame rate = 21M/400/1750 = 30fps + */ +static const struct regval os05l10_2880x1620_regs_2lane[] = { + {0xfd, 0x00}, + {0x20, 0x00}, + {0xfd, 0x00}, + {0x20, 0x2b}, + {0xe7, 0x03}, + {0xe7, 0x00}, + {0xfd, 0x00}, + {0x21, 0x06}, + {0x14, 0x8c}, + {0x18, 0x61}, + {0x19, 0x80}, + {0x1a, 0x06}, + {0x1b, 0x69}, + {0x1c, 0x04}, + {0x1d, 0x02}, + {0xfd, 0x00}, + {0x21, 0x00}, + + {0xfd, 0x0f}, + {0x01, 0xe6}, + {0x07, 0x0f}, + {0x08, 0xf0}, + {0x0f, 0x08}, + {0x15, 0x28}, + {0x16, 0x11}, + {0x20, 0x06}, + {0x2e, 0x1c}, + {0x2f, 0x3d}, + {0x30, 0x77}, + {0x31, 0xe5}, + {0x0b, 0x01}, + {0x13, 0x22}, + {0x14, 0xbc}, + {0x2d, 0x0a}, + {0x17, 0x3e}, + {0x1b, 0xe6}, + {0x1c, 0x99}, + {0x1d, 0x99}, + {0x1e, 0x55}, + {0xfd, 0x01}, + {0x02, 0x00}, + {0x03, 0x02}, + {0x04, 0x04}, + {0x06, 0x5c}, + {0x24, 0x80}, + {0x21, 0x00}, + {0x22, 0x40}, + {0x31, 0x00}, + {0x33, 0x03}, + {0x40, 0x30}, + {0x41, 0x0c}, + {0x43, 0x44}, + {0x44, 0x0b}, + {0x46, 0x01}, + {0x48, 0x08}, + {0x4c, 0x10}, + {0x50, 0x0a}, + {0x51, 0x08}, + {0x52, 0x08}, + {0x53, 0x0a}, + {0x54, 0x00}, + {0x55, 0x00}, + {0x57, 0x92}, + {0x58, 0x00}, + {0x59, 0x05}, + {0x5a, 0x05}, + {0x5b, 0x00}, + {0x5c, 0x0b}, + {0x5e, 0x08}, + {0x66, 0x0d}, + {0x69, 0x0d}, + {0x76, 0x0e}, + {0x7a, 0x00}, + {0x7c, 0x03}, + {0x83, 0x03}, + {0x84, 0x25}, + {0x85, 0x03}, + {0x87, 0x03}, + {0x90, 0x33}, + {0x91, 0x1e}, + {0x92, 0x15}, + {0x93, 0x16}, + {0x94, 0x08}, + {0x95, 0x33}, + {0x9c, 0x03}, + {0x9d, 0x13}, + {0x9e, 0x03}, + {0xa0, 0x13}, + {0xa4, 0x01}, + {0xa5, 0x01}, + {0xa7, 0x01}, + {0xc0, 0x09}, + {0xc1, 0x38}, + {0xc8, 0x1f}, + {0xd7, 0x11}, + {0xd9, 0x1c}, + {0xd8, 0x1f}, + {0xda, 0x2f}, + {0xdb, 0x10}, + {0xdd, 0x1b}, + {0xdc, 0x1e}, + {0xde, 0x2d}, + {0xed, 0x33}, + {0xee, 0x33}, + {0x01, 0x01}, + {0xfd, 0x02}, + {0x9a, 0x33}, + {0x05, 0x01}, + {0x0b, 0x0c}, + {0x0c, 0x0f}, + {0xfd, 0x01}, + {0x01, 0x01}, + {0xfd, 0x04}, + {0x19, 0x3f}, + {0x12, 0x00}, + {0xf3, 0x00}, + {0xfd, 0x07}, + {0x10, 0xf0}, + {0x42, 0x00}, + {0x43, 0x76}, + {0x44, 0x00}, + {0x45, 0x76}, + {0x46, 0x00}, + {0x47, 0x76}, + {0x48, 0x00}, + {0x49, 0x76}, + {0xb3, 0x02}, + {0xb4, 0x20}, + {0xb7, 0x02}, + {0xb8, 0x20}, + {0xc5, 0x3a}, + {0xc9, 0x3a}, + {0xcd, 0x3a}, + {0xc6, 0x2b}, + {0xca, 0x2b}, + {0xce, 0x2b}, + {0xc3, 0x0a}, + {0xc7, 0x0a}, + {0xcb, 0x0a}, + {0xc4, 0x12}, + {0xc8, 0x12}, + {0xcc, 0x12}, + {0xcf, 0x11}, + {0xd3, 0x11}, + {0xd7, 0x11}, + {0xd0, 0x0e}, + {0xd4, 0x0e}, + {0xd8, 0x0e}, + {0xbb, 0x7f}, + {0xd1, 0x0f}, + {0xd5, 0x0f}, + {0xd9, 0x0f}, + {0xd2, 0x0a}, + {0xd6, 0x0a}, + {0xda, 0x0a}, + {0xbc, 0x3f}, + {0xfd, 0x03}, + {0x85, 0x03}, + {0x9d, 0x0f}, + {0xba, 0x06}, + {0xfd, 0x01}, + {0xfd, 0x02}, + {0xa1, 0x04}, + {0xa3, 0x54}, + {0xa5, 0x04}, + {0xa7, 0x40}, + {0xfd, 0x00}, + {0x8e, 0x0b}, + {0x8f, 0x40}, + {0x90, 0x06}, + {0x91, 0x54}, + {0x94, 0x08}, + {0x95, 0x09}, + {0x99, 0x08}, + {0x9c, 0x20}, + {0xa4, 0x0c}, + {0x9d, 0x01}, + {0xa5, 0xff}, + {0xa1, 0x04}, + {0xb7, 0x02}, //mipi clk mode:0x00 continue; 0x02 no continue + + {0xc1, 0xee}, + {0xc5, 0x50}, + {0xc4, 0x01}, + {0xa0, 0x00}, + {0xfd, 0x01}, + {0xfd, 0x01}, + {0x01, 0x31}, + {0xfd, 0x00}, + {0x20, 0x1f}, + {0xfd, 0x01}, + {0xfd, 0x01}, + {REG_NULL, 0x00}, +}; + +static const struct os05l10_mode supported_modes_2lane[] = { + { + .width = 2880, + .height = 1620, + .max_fps = { + .numerator = 10000, + .denominator = 300000, + }, + .exp_def = 0x0600, + .hts_def = 0x0190 * 8, + .vts_def = 0x06d6, + .mipi_freq_idx = 0, + .global_reg_list = os05l10_global_regs_2lane, + .reg_list = os05l10_2880x1620_regs_2lane, + .vc[PAD0] = 0, + }, +}; + +static const struct os05l10_mode *supported_modes; + +static const s64 link_freq_menu_items[] = { + OS05L10_MIPI_FREQ_420MHZ, +}; + +static const char * const os05l10_test_pattern_menu[] = { + "Disabled", + "ColorBar" +}; + +/* Write registers up to 4 at a time */ +static int os05l10_write_reg(struct i2c_client *client, u8 reg, u8 val) +{ + struct i2c_msg msg; + u8 buf[2]; + int ret; + + buf[0] = reg & 0xFF; + buf[1] = val; + + msg.addr = client->addr; + msg.flags = client->flags; + msg.buf = buf; + msg.len = sizeof(buf); + + ret = i2c_transfer(client->adapter, &msg, 1); + if (ret >= 0) + return 0; + + dev_err(&client->dev, + "os05l10 write reg(0x%x val:0x%x) failed !\n", reg, val); + + return ret; +} + +static int os05l10_write_array(struct i2c_client *client, + const struct regval *regs) +{ + u32 i = 0; + int ret = 0; + + for (i = 0; ret == 0 && regs[i].addr != REG_NULL; i++) + ret = os05l10_write_reg(client, regs[i].addr, regs[i].val); + + return ret; +} + +/* Read registers up to 4 at a time */ +static int os05l10_read_reg(struct i2c_client *client, u8 reg, u8 *val) +{ + struct i2c_msg msg[2]; + u8 buf[1]; + int ret; + + buf[0] = reg & 0xFF; + + msg[0].addr = client->addr; + msg[0].flags = client->flags; + msg[0].buf = buf; + msg[0].len = sizeof(buf); + + msg[1].addr = client->addr; + msg[1].flags = client->flags | I2C_M_RD; + msg[1].buf = buf; + msg[1].len = 1; + + ret = i2c_transfer(client->adapter, msg, 2); + if (ret >= 0) { + *val = buf[0]; + return 0; + } + + dev_err(&client->dev, + "os05l10 read reg:0x%x failed !\n", reg); + + return ret; +} + +static int os05l10_get_reso_dist(const struct os05l10_mode *mode, + struct v4l2_mbus_framefmt *framefmt) +{ + return abs(mode->width - framefmt->width) + + abs(mode->height - framefmt->height); +} + +static const struct os05l10_mode * +os05l10_find_best_fit(struct os05l10 *os05l10, + struct v4l2_subdev_format *fmt) +{ + struct v4l2_mbus_framefmt *framefmt = &fmt->format; + int dist; + int cur_best_fit = 0; + int cur_best_fit_dist = -1; + unsigned int i; + + for (i = 0; i < os05l10->cfg_num; i++) { + dist = os05l10_get_reso_dist(&supported_modes[i], framefmt); + if (cur_best_fit_dist == -1 || dist < cur_best_fit_dist) { + cur_best_fit_dist = dist; + cur_best_fit = i; + } + } + + return &supported_modes[cur_best_fit]; +} + +static int os05l10_set_fmt(struct v4l2_subdev *sd, + struct v4l2_subdev_state *sd_state, + struct v4l2_subdev_format *fmt) +{ + struct os05l10 *os05l10 = to_os05l10(sd); + const struct os05l10_mode *mode; + s64 h_blank, vblank_def; + + mutex_lock(&os05l10->mutex); + + mode = os05l10_find_best_fit(os05l10, fmt); + fmt->format.code = OS05L10_MEDIA_BUS_FMT; + fmt->format.width = mode->width; + fmt->format.height = mode->height; + fmt->format.field = V4L2_FIELD_NONE; + if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) { +#ifdef CONFIG_VIDEO_V4L2_SUBDEV_API + *v4l2_subdev_get_try_format(sd, sd_state, fmt->pad) = fmt->format; +#else + mutex_unlock(&os05l10->mutex); + return -ENOTTY; +#endif + } else { + os05l10->cur_mode = mode; + h_blank = mode->hts_def - mode->width; + __v4l2_ctrl_modify_range(os05l10->hblank, h_blank, + h_blank, 1, h_blank); + vblank_def = mode->vts_def - mode->height; + __v4l2_ctrl_modify_range(os05l10->vblank, vblank_def, + OS05L10_VTS_MAX - mode->height, + 1, vblank_def); + __v4l2_ctrl_s_ctrl(os05l10->vblank, vblank_def); + __v4l2_ctrl_s_ctrl(os05l10->link_freq, mode->mipi_freq_idx); + } + + mutex_unlock(&os05l10->mutex); + + return 0; +} + +static int os05l10_get_fmt(struct v4l2_subdev *sd, + struct v4l2_subdev_state *sd_state, + struct v4l2_subdev_format *fmt) +{ + struct os05l10 *os05l10 = to_os05l10(sd); + const struct os05l10_mode *mode = os05l10->cur_mode; + + mutex_lock(&os05l10->mutex); + if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) { +#ifdef CONFIG_VIDEO_V4L2_SUBDEV_API + fmt->format = *v4l2_subdev_get_try_format(sd, sd_state, fmt->pad); +#else + mutex_unlock(&os05l10->mutex); + return -ENOTTY; +#endif + } else { + fmt->format.width = mode->width; + fmt->format.height = mode->height; + fmt->format.code = OS05L10_MEDIA_BUS_FMT; + fmt->format.field = V4L2_FIELD_NONE; + } + mutex_unlock(&os05l10->mutex); + + return 0; +} + +static int os05l10_enum_mbus_code(struct v4l2_subdev *sd, + struct v4l2_subdev_state *sd_state, + struct v4l2_subdev_mbus_code_enum *code) +{ + if (code->index != 0) + return -EINVAL; + code->code = OS05L10_MEDIA_BUS_FMT; + + return 0; +} + +static int os05l10_enum_frame_sizes(struct v4l2_subdev *sd, + struct v4l2_subdev_state *sd_state, + struct v4l2_subdev_frame_size_enum *fse) +{ + struct os05l10 *os05l10 = to_os05l10(sd); + + if (fse->index >= os05l10->cfg_num) + return -EINVAL; + + if (fse->code != OS05L10_MEDIA_BUS_FMT) + return -EINVAL; + + fse->min_width = supported_modes[fse->index].width; + fse->max_width = supported_modes[fse->index].width; + fse->max_height = supported_modes[fse->index].height; + fse->min_height = supported_modes[fse->index].height; + + return 0; +} + +static int os05l10_g_frame_interval(struct v4l2_subdev *sd, + struct v4l2_subdev_frame_interval *fi) +{ + struct os05l10 *os05l10 = to_os05l10(sd); + const struct os05l10_mode *mode = os05l10->cur_mode; + + fi->interval = mode->max_fps; + + return 0; +} + +static void os05l10_get_otp(struct otp_info *otp, + struct rkmodule_inf *inf) +{ + u32 i, j; + u32 w, h; + + /* awb */ + if (otp->awb_data.flag) { + inf->awb.flag = 1; + inf->awb.r_value = otp->awb_data.r_ratio; + inf->awb.b_value = otp->awb_data.b_ratio; + inf->awb.gr_value = otp->awb_data.g_ratio; + inf->awb.gb_value = 0x0; + + inf->awb.golden_r_value = otp->awb_data.r_golden; + inf->awb.golden_b_value = otp->awb_data.b_golden; + inf->awb.golden_gr_value = otp->awb_data.g_golden; + inf->awb.golden_gb_value = 0x0; + } + + /* lsc */ + if (otp->lsc_data.flag) { + inf->lsc.flag = 1; + inf->lsc.width = otp->basic_data.size.width; + inf->lsc.height = otp->basic_data.size.height; + inf->lsc.table_size = otp->lsc_data.table_size; + + for (i = 0; i < 289; i++) { + inf->lsc.lsc_r[i] = (otp->lsc_data.data[i * 2] << 8) | + otp->lsc_data.data[i * 2 + 1]; + inf->lsc.lsc_gr[i] = (otp->lsc_data.data[i * 2 + 578] << 8) | + otp->lsc_data.data[i * 2 + 579]; + inf->lsc.lsc_gb[i] = (otp->lsc_data.data[i * 2 + 1156] << 8) | + otp->lsc_data.data[i * 2 + 1157]; + inf->lsc.lsc_b[i] = (otp->lsc_data.data[i * 2 + 1734] << 8) | + otp->lsc_data.data[i * 2 + 1735]; + } + } + + /* pdaf */ + if (otp->pdaf_data.flag) { + inf->pdaf.flag = 1; + inf->pdaf.gainmap_width = otp->pdaf_data.gainmap_width; + inf->pdaf.gainmap_height = otp->pdaf_data.gainmap_height; + inf->pdaf.pd_offset = otp->pdaf_data.pd_offset; + inf->pdaf.dcc_mode = otp->pdaf_data.dcc_mode; + inf->pdaf.dcc_dir = otp->pdaf_data.dcc_dir; + inf->pdaf.dccmap_width = otp->pdaf_data.dccmap_width; + inf->pdaf.dccmap_height = otp->pdaf_data.dccmap_height; + w = otp->pdaf_data.gainmap_width; + h = otp->pdaf_data.gainmap_height; + for (i = 0; i < h; i++) { + for (j = 0; j < w; j++) { + inf->pdaf.gainmap[i * w + j] = + (otp->pdaf_data.gainmap[(i * w + j) * 2] << 8) | + otp->pdaf_data.gainmap[(i * w + j) * 2 + 1]; + } + } + w = otp->pdaf_data.dccmap_width; + h = otp->pdaf_data.dccmap_height; + for (i = 0; i < h; i++) { + for (j = 0; j < w; j++) { + inf->pdaf.dccmap[i * w + j] = + (otp->pdaf_data.dccmap[(i * w + j) * 2] << 8) | + otp->pdaf_data.dccmap[(i * w + j) * 2 + 1]; + } + } + } + + /* af */ + if (otp->af_data.flag) { + inf->af.flag = 1; + inf->af.dir_cnt = 1; + inf->af.af_otp[0].vcm_start = otp->af_data.af_inf; + inf->af.af_otp[0].vcm_end = otp->af_data.af_macro; + inf->af.af_otp[0].vcm_dir = 0; + } + +} + +static void os05l10_get_module_inf(struct os05l10 *os05l10, + struct rkmodule_inf *inf) +{ + struct otp_info *otp = os05l10->otp; + + strscpy(inf->base.sensor, + OS05L10_NAME, + sizeof(inf->base.sensor)); + strscpy(inf->base.module, + os05l10->module_name, + sizeof(inf->base.module)); + strscpy(inf->base.lens, + os05l10->len_name, + sizeof(inf->base.lens)); + if (otp) + os05l10_get_otp(otp, inf); +} + +static void os05l10_set_module_inf(struct os05l10 *os05l10, + struct rkmodule_awb_cfg *cfg) +{ + mutex_lock(&os05l10->mutex); + memcpy(&os05l10->awb_cfg, cfg, sizeof(*cfg)); + mutex_unlock(&os05l10->mutex); +} + +static int os05l10_get_channel_info(struct os05l10 *os05l10, struct rkmodule_channel_info *ch_info) +{ + if (ch_info->index < PAD0 || ch_info->index >= PAD_MAX) + return -EINVAL; + ch_info->vc = os05l10->cur_mode->vc[ch_info->index]; + ch_info->width = os05l10->cur_mode->width; + ch_info->height = os05l10->cur_mode->height; + ch_info->bus_fmt = OS05L10_MEDIA_BUS_FMT; + return 0; +} + +static long os05l10_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg) +{ + struct os05l10 *os05l10 = to_os05l10(sd); + long ret = 0; + u32 stream = 0; + struct rkmodule_channel_info *ch_info; + + switch (cmd) { + case RKMODULE_GET_MODULE_INFO: + os05l10_get_module_inf(os05l10, (struct rkmodule_inf *)arg); + break; + case RKMODULE_AWB_CFG: + os05l10_set_module_inf(os05l10, (struct rkmodule_awb_cfg *)arg); + break; + case RKMODULE_SET_QUICK_STREAM: + + stream = *((u32 *)arg); + if (stream) { + ret = os05l10_write_reg(os05l10->client, + OS05L10_REG_SET_PAGE, + 0x01); + ret |= os05l10_write_reg(os05l10->client, + OS05L10_REG_CTRL_MODE, + OS05L10_MODE_STREAMING); + } else { + ret = os05l10_write_reg(os05l10->client, + OS05L10_REG_SET_PAGE, + 0x01); + ret |= os05l10_write_reg(os05l10->client, + OS05L10_REG_CTRL_MODE, + OS05L10_MODE_SW_STANDBY); + } + break; + case RKMODULE_GET_CHANNEL_INFO: + ch_info = (struct rkmodule_channel_info *)arg; + ret = os05l10_get_channel_info(os05l10, ch_info); + break; + default: + ret = -ENOTTY; + break; + } + + return ret; +} + +#ifdef CONFIG_COMPAT +static long os05l10_compat_ioctl32(struct v4l2_subdev *sd, + unsigned int cmd, unsigned long arg) +{ + void __user *up = compat_ptr(arg); + struct rkmodule_inf *inf; + struct rkmodule_awb_cfg *cfg; + long ret = 0; + u32 stream = 0; + struct rkmodule_channel_info *ch_info; + + switch (cmd) { + case RKMODULE_GET_MODULE_INFO: + inf = kzalloc(sizeof(*inf), GFP_KERNEL); + if (!inf) { + ret = -ENOMEM; + return ret; + } + + ret = os05l10_ioctl(sd, cmd, inf); + if (!ret) { + ret = copy_to_user(up, inf, sizeof(*inf)); + if (ret) + ret = -EFAULT; + } + kfree(inf); + break; + case RKMODULE_AWB_CFG: + cfg = kzalloc(sizeof(*cfg), GFP_KERNEL); + if (!cfg) { + ret = -ENOMEM; + return ret; + } + + ret = copy_from_user(cfg, up, sizeof(*cfg)); + if (!ret) + ret = os05l10_ioctl(sd, cmd, cfg); + else + ret = -EFAULT; + kfree(cfg); + break; + case RKMODULE_SET_QUICK_STREAM: + ret = copy_from_user(&stream, up, sizeof(u32)); + if (!ret) + ret = os05l10_ioctl(sd, cmd, &stream); + else + ret = -EFAULT; + break; + case RKMODULE_GET_CHANNEL_INFO: + ch_info = kzalloc(sizeof(*ch_info), GFP_KERNEL); + if (!ch_info) { + ret = -ENOMEM; + return ret; + } + + ret = os05l10_ioctl(sd, cmd, ch_info); + if (!ret) { + ret = copy_to_user(up, ch_info, sizeof(*ch_info)); + if (ret) + ret = -EFAULT; + } + kfree(ch_info); + break; + default: + ret = -ENOTTY; + break; + } + + return ret; +} +#endif + +static int __os05l10_start_stream(struct os05l10 *os05l10) +{ + int ret; + + ret = os05l10_write_array(os05l10->client, os05l10->cur_mode->reg_list); + if (ret) + return ret; + + /* In case these controls are set before streaming */ + mutex_unlock(&os05l10->mutex); + ret = v4l2_ctrl_handler_setup(&os05l10->ctrl_handler); + mutex_lock(&os05l10->mutex); + ret |= os05l10_write_reg(os05l10->client, + OS05L10_REG_SET_PAGE, + OS05L10_SET_PAGE_ZERO); + ret |= os05l10_write_reg(os05l10->client, + OS05L10_REG_CTRL_MODE, + OS05L10_MODE_STREAMING); + + return ret; +} + +static int __os05l10_stop_stream(struct os05l10 *os05l10) +{ + int ret; + + ret = os05l10_write_reg(os05l10->client, + OS05L10_REG_SET_PAGE, + OS05L10_SET_PAGE_ZERO); + ret |= os05l10_write_reg(os05l10->client, + OS05L10_REG_CTRL_MODE, + OS05L10_MODE_STREAMING); + + + return ret; +} + +static int os05l10_s_stream(struct v4l2_subdev *sd, int on) +{ + struct os05l10 *os05l10 = to_os05l10(sd); + struct i2c_client *client = os05l10->client; + int ret = 0; + + dev_info(&client->dev, "%s: on: %d, %dx%d@%d\n", __func__, on, + os05l10->cur_mode->width, + os05l10->cur_mode->height, + DIV_ROUND_CLOSEST(os05l10->cur_mode->max_fps.denominator, + os05l10->cur_mode->max_fps.numerator)); + + mutex_lock(&os05l10->mutex); + on = !!on; + if (on == os05l10->streaming) + goto unlock_and_return; + + if (on) { + ret = pm_runtime_get_sync(&client->dev); + if (ret < 0) { + pm_runtime_put_noidle(&client->dev); + goto unlock_and_return; + } + + ret = __os05l10_start_stream(os05l10); + if (ret) { + v4l2_err(sd, "start stream failed while write regs\n"); + pm_runtime_put(&client->dev); + goto unlock_and_return; + } + } else { + __os05l10_stop_stream(os05l10); + pm_runtime_put(&client->dev); + } + + os05l10->streaming = on; + +unlock_and_return: + mutex_unlock(&os05l10->mutex); + + return ret; +} + +static int os05l10_s_power(struct v4l2_subdev *sd, int on) +{ + struct os05l10 *os05l10 = to_os05l10(sd); + struct i2c_client *client = os05l10->client; + const struct os05l10_mode *mode = os05l10->cur_mode; + int ret = 0; + + dev_info(&client->dev, "%s(%d) on(%d)\n", __func__, __LINE__, on); + mutex_lock(&os05l10->mutex); + + /* If the power state is not modified - no work to do. */ + if (os05l10->power_on == !!on) + goto unlock_and_return; + + if (on) { + ret = pm_runtime_get_sync(&client->dev); + if (ret < 0) { + pm_runtime_put_noidle(&client->dev); + goto unlock_and_return; + } + + ret = os05l10_write_array(os05l10->client, mode->global_reg_list); + if (ret) { + v4l2_err(sd, "could not set init registers\n"); + pm_runtime_put_noidle(&client->dev); + goto unlock_and_return; + } + + os05l10->power_on = true; + } else { + pm_runtime_put(&client->dev); + os05l10->power_on = false; + } + +unlock_and_return: + mutex_unlock(&os05l10->mutex); + + return ret; +} + +/* Calculate the delay in us by clock rate and clock cycles */ +static inline u32 os05l10_cal_delay(u32 cycles) +{ + return DIV_ROUND_UP(cycles, OS05L10_XVCLK_FREQ / 1000 / 1000); +} + +static int os05l10_enable_regulators(struct os05l10 *os05l10, + struct regulator_bulk_data *consumers) +{ + int i, j; + int ret = 0; + struct device *dev = &os05l10->client->dev; + int num_consumers = OS05L10_NUM_SUPPLIES; + + for (i = 0; i < num_consumers; i++) { + + ret = regulator_enable(consumers[i].consumer); + if (ret < 0) { + dev_err(dev, "Failed to enable regulator: %s\n", + consumers[i].supply); + goto err; + } + } + return 0; +err: + for (j = 0; j < i; j++) + regulator_disable(consumers[j].consumer); + + return ret; +} + +static int __os05l10_power_on(struct os05l10 *os05l10) +{ + int ret; + struct device *dev = &os05l10->client->dev; + + if (!IS_ERR(os05l10->power_gpio)) + gpiod_set_value_cansleep(os05l10->power_gpio, 1); + + usleep_range(1000, 2000); + + if (!IS_ERR_OR_NULL(os05l10->pins_default)) { + ret = pinctrl_select_state(os05l10->pinctrl, + os05l10->pins_default); + if (ret < 0) + dev_err(dev, "could not set pins\n"); + } + ret = clk_set_rate(os05l10->xvclk, OS05L10_XVCLK_FREQ); + if (ret < 0) + dev_warn(dev, "Failed to set xvclk rate (24MHz)\n"); + if (clk_get_rate(os05l10->xvclk) != OS05L10_XVCLK_FREQ) + dev_warn(dev, "xvclk mismatched, modes are based on 24MHz\n"); + + if (!IS_ERR(os05l10->reset_gpio)) + gpiod_set_value_cansleep(os05l10->reset_gpio, 0); + + ret = os05l10_enable_regulators(os05l10, os05l10->supplies); + if (ret < 0) { + dev_err(dev, "Failed to enable regulators\n"); + goto disable_clk; + } + + ret = clk_prepare_enable(os05l10->xvclk); + if (ret < 0) { + dev_err(dev, "Failed to enable xvclk\n"); + return ret; + } + + usleep_range(1000, 1100); + if (!IS_ERR(os05l10->pwdn_gpio)) + gpiod_set_value_cansleep(os05l10->pwdn_gpio, 1); + + /*delay from dvdd stable to sensor XSHUTDN pull up*/ + usleep_range(5000, 5500); + if (!IS_ERR(os05l10->reset_gpio)) + gpiod_set_value_cansleep(os05l10->reset_gpio, 1); + + /*delay from XSHUTDN pull up to SCCB initialization*/ + usleep_range(8000, 8500); + + return 0; + +disable_clk: + clk_disable_unprepare(os05l10->xvclk); + + return ret; +} + +static void __os05l10_power_off(struct os05l10 *os05l10) +{ + int ret; + + if (!IS_ERR(os05l10->pwdn_gpio)) + gpiod_set_value_cansleep(os05l10->pwdn_gpio, 1); + + if (!IS_ERR(os05l10->reset_gpio)) + gpiod_set_value_cansleep(os05l10->reset_gpio, 1); + + clk_disable_unprepare(os05l10->xvclk); + if (!IS_ERR_OR_NULL(os05l10->pins_sleep)) { + ret = pinctrl_select_state(os05l10->pinctrl, + os05l10->pins_sleep); + if (ret < 0) + dev_dbg(&os05l10->client->dev, "could not set pins\n"); + } + if (!IS_ERR(os05l10->power_gpio)) + gpiod_set_value_cansleep(os05l10->power_gpio, 0); + + regulator_bulk_disable(OS05L10_NUM_SUPPLIES, os05l10->supplies); +} + +static int __maybe_unused os05l10_runtime_resume(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct v4l2_subdev *sd = i2c_get_clientdata(client); + struct os05l10 *os05l10 = to_os05l10(sd); + + return __os05l10_power_on(os05l10); +} + +static int __maybe_unused os05l10_runtime_suspend(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct v4l2_subdev *sd = i2c_get_clientdata(client); + struct os05l10 *os05l10 = to_os05l10(sd); + + __os05l10_power_off(os05l10); + + return 0; +} + +#ifdef CONFIG_VIDEO_V4L2_SUBDEV_API +static int os05l10_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) +{ + struct os05l10 *os05l10 = to_os05l10(sd); + struct v4l2_mbus_framefmt *try_fmt = + v4l2_subdev_get_try_format(sd, fh->state, 0); + const struct os05l10_mode *def_mode = &supported_modes[0]; + + mutex_lock(&os05l10->mutex); + /* Initialize try_fmt */ + try_fmt->width = def_mode->width; + try_fmt->height = def_mode->height; + try_fmt->code = OS05L10_MEDIA_BUS_FMT; + try_fmt->field = V4L2_FIELD_NONE; + + mutex_unlock(&os05l10->mutex); + /* No crop or compose */ + + return 0; +} +#endif + +static int os05l10_enum_frame_interval(struct v4l2_subdev *sd, + struct v4l2_subdev_state *sd_state, + struct v4l2_subdev_frame_interval_enum *fie) +{ + struct os05l10 *os05l10 = to_os05l10(sd); + + if (fie->index >= os05l10->cfg_num) + return -EINVAL; + + fie->code = OS05L10_MEDIA_BUS_FMT; + fie->width = supported_modes[fie->index].width; + fie->height = supported_modes[fie->index].height; + fie->interval = supported_modes[fie->index].max_fps; + return 0; +} + +static int os05l10_g_mbus_config(struct v4l2_subdev *sd, unsigned int pad_id, + struct v4l2_mbus_config *config) +{ + struct os05l10 *sensor = to_os05l10(sd); + struct device *dev = &sensor->client->dev; + + dev_info(dev, "%s(%d) enter!\n", __func__, __LINE__); + + if (2 == sensor->lane_num) { + config->type = V4L2_MBUS_CSI2_DPHY; + config->bus.mipi_csi2.num_data_lanes = sensor->lane_num; + } else { + dev_err(&sensor->client->dev, + "unsupported lane_num(%d)\n", sensor->lane_num); + } + return 0; +} + +static const struct dev_pm_ops os05l10_pm_ops = { + SET_RUNTIME_PM_OPS(os05l10_runtime_suspend, + os05l10_runtime_resume, NULL) +}; + +#ifdef CONFIG_VIDEO_V4L2_SUBDEV_API +static const struct v4l2_subdev_internal_ops os05l10_internal_ops = { + .open = os05l10_open, +}; +#endif + +static const struct v4l2_subdev_core_ops os05l10_core_ops = { + .s_power = os05l10_s_power, + .ioctl = os05l10_ioctl, +#ifdef CONFIG_COMPAT + .compat_ioctl32 = os05l10_compat_ioctl32, +#endif +}; + +static const struct v4l2_subdev_video_ops os05l10_video_ops = { + .s_stream = os05l10_s_stream, + .g_frame_interval = os05l10_g_frame_interval, +}; + +static const struct v4l2_subdev_pad_ops os05l10_pad_ops = { + .enum_mbus_code = os05l10_enum_mbus_code, + .enum_frame_size = os05l10_enum_frame_sizes, + .enum_frame_interval = os05l10_enum_frame_interval, + .get_fmt = os05l10_get_fmt, + .set_fmt = os05l10_set_fmt, + .get_mbus_config = os05l10_g_mbus_config, +}; + +static const struct v4l2_subdev_ops os05l10_subdev_ops = { + .core = &os05l10_core_ops, + .video = &os05l10_video_ops, + .pad = &os05l10_pad_ops, +}; + +static int os05l10_set_exposure_reg(struct os05l10 *os05l10, u32 exposure) +{ + int ret = 0; + u32 cal_shutter = 0; + + cal_shutter = exposure >> 1; + cal_shutter = cal_shutter << 1; + + ret = os05l10_write_reg(os05l10->client, + OS05L10_REG_SET_PAGE, 0x01); + ret |= os05l10_write_reg(os05l10->client, + OS05L10_REG_EXPOSURE_H, + OS05L10_FETCH_HIGH_BYTE_EXP(cal_shutter)); + ret |= os05l10_write_reg(os05l10->client, + OS05L10_REG_EXPOSURE_L, + OS05L10_FETCH_LOW_BYTE_EXP(cal_shutter)); + ret |= os05l10_write_reg(os05l10->client, + OS05L10_REG_TRIGGER, 0x01); + + return ret; +} + +static int os05l10_set_gain_reg(struct os05l10 *os05l10, u32 a_gain) +{ + int ret = 0; + + ret = os05l10_write_reg(os05l10->client, + OS05L10_REG_SET_PAGE, 0x01); + ret |= os05l10_write_reg(os05l10->client, + OS05L10_REG_AGAIN_H, + OS05L10_FETCH_H_BYTE_GAIN(a_gain)); + ret |= os05l10_write_reg(os05l10->client, + OS05L10_REG_AGAIN_L, + OS05L10_FETCH_L_BYTE_GAIN(a_gain)); + ret |= os05l10_write_reg(os05l10->client, + OS05L10_REG_TRIGGER, 0x01); + + return ret; +} + +static int os05l10__enable_test_pattern(struct os05l10 *os05l10, u32 pattern) +{ + u32 ret; + + ret = os05l10_write_reg(os05l10->client, + OS05L10_REG_SET_PAGE, 0x04); + + if (pattern) { + ret |= os05l10_write_reg(os05l10->client, + 0xF3, 0x02); + ret |= os05l10_write_reg(os05l10->client, + OS05L10_REG_TEST_PATTERN, 0x01); + } else { + ret |= os05l10_write_reg(os05l10->client, + 0xF3, 0x00); + ret |= os05l10_write_reg(os05l10->client, + OS05L10_REG_TEST_PATTERN, 0x00); + } + + return ret; +} + +static int os05l10_set_ctrl(struct v4l2_ctrl *ctrl) +{ + struct os05l10 *os05l10 = container_of(ctrl->handler, + struct os05l10, ctrl_handler); + struct i2c_client *client = os05l10->client; + s64 max; + int ret = 0; + s32 temp; + u8 val = 0; + + /* Propagate change of current control to all related controls */ + switch (ctrl->id) { + case V4L2_CID_VBLANK: + /* Update max exposure while meeting expected vblanking */ + max = os05l10->cur_mode->height + ctrl->val - 4; + __v4l2_ctrl_modify_range(os05l10->exposure, + os05l10->exposure->minimum, max, + os05l10->exposure->step, + os05l10->exposure->default_value); + break; + } + + if (!pm_runtime_get_if_in_use(&client->dev)) + return 0; + + switch (ctrl->id) { + case V4L2_CID_EXPOSURE: + /* 4 least significant bits of expsoure are fractional part */ + dev_dbg(&client->dev, "set exposure value 0x%x\n", ctrl->val); + ret = os05l10_set_exposure_reg(os05l10, ctrl->val); + break; + case V4L2_CID_ANALOGUE_GAIN: + dev_dbg(&client->dev, "set analog gain value 0x%x\n", ctrl->val); + ret = os05l10_set_gain_reg(os05l10, ctrl->val); + break; + case V4L2_CID_VBLANK: + dev_dbg(&client->dev, "set vb value 0x%x\n", ctrl->val); + /* VB = VTS - height -38, */ + temp = ctrl->val + os05l10->cur_mode->height - 1620 - 38; + + ret = os05l10_write_reg(os05l10->client, + OS05L10_REG_SET_PAGE, + 0x01); + ret |= os05l10_write_reg(os05l10->client, + OS05L10_REG_VTS_H, + (temp >> 8) & 0xff); + ret |= os05l10_write_reg(os05l10->client, + OS05L10_REG_VTS_L, + temp & 0xff); + ret |= os05l10_write_reg(os05l10->client, + OS05L10_REG_TRIGGER, + 0x01); + break; + case V4L2_CID_TEST_PATTERN: + ret = os05l10__enable_test_pattern(os05l10, ctrl->val); + break; + case V4L2_CID_HFLIP: + dev_info(&client->dev, "set mirror value 0x%x\n", ctrl->val); + + ret = os05l10_write_reg(os05l10->client, + OS05L10_REG_SET_PAGE, + 0x01); + ret |= os05l10_read_reg(client, OS05L10_FLIP_MIRROR_REG, &val); + if (ctrl->val) + val |= MIRROR_BIT_MASK; + else + val &= ~MIRROR_BIT_MASK; + ret |= os05l10_write_reg(os05l10->client, + OS05L10_FLIP_MIRROR_REG, + val); + ret |= os05l10_write_reg(os05l10->client, + OS05L10_REG_TRIGGER, + 0x01); + break; + case V4L2_CID_VFLIP: + dev_info(&client->dev, "set flip value 0x%x\n", ctrl->val); + ret = os05l10_write_reg(os05l10->client, + OS05L10_REG_SET_PAGE, + 0x01); + ret |= os05l10_read_reg(client, OS05L10_FLIP_MIRROR_REG, &val); + if (ctrl->val) + val |= FLIP_BIT_MASK; + else + val &= ~FLIP_BIT_MASK; + ret |= os05l10_write_reg(os05l10->client, + OS05L10_FLIP_MIRROR_REG, + val); + ret |= os05l10_write_reg(os05l10->client, + OS05L10_REG_TRIGGER, + 0x01); + break; + default: + dev_warn(&client->dev, "%s Unhandled id:0x%x, val:0x%x\n", + __func__, ctrl->id, ctrl->val); + break; + } + + pm_runtime_put(&client->dev); + + return ret; +} + +static const struct v4l2_ctrl_ops os05l10_ctrl_ops = { + .s_ctrl = os05l10_set_ctrl, +}; + +static int os05l10_initialize_controls(struct os05l10 *os05l10) +{ + const struct os05l10_mode *mode; + struct v4l2_ctrl_handler *handler; + s64 exposure_max, vblank_def; + u32 h_blank; + int ret; + + handler = &os05l10->ctrl_handler; + mode = os05l10->cur_mode; + ret = v4l2_ctrl_handler_init(handler, 8); + if (ret) + return ret; + handler->lock = &os05l10->mutex; + + os05l10->link_freq = v4l2_ctrl_new_int_menu(handler, NULL, + V4L2_CID_LINK_FREQ, + ARRAY_SIZE(link_freq_menu_items) - 1, 0, + link_freq_menu_items); + v4l2_ctrl_s_ctrl(os05l10->link_freq, mode->mipi_freq_idx); + + v4l2_ctrl_new_std(handler, NULL, V4L2_CID_PIXEL_RATE, + 0, os05l10->pixel_rate, 1, os05l10->pixel_rate); + + h_blank = mode->hts_def - mode->width; + os05l10->hblank = v4l2_ctrl_new_std(handler, NULL, V4L2_CID_HBLANK, + h_blank, h_blank, 1, h_blank); + if (os05l10->hblank) + os05l10->hblank->flags |= V4L2_CTRL_FLAG_READ_ONLY; + + vblank_def = mode->vts_def - mode->height; + os05l10->vblank = v4l2_ctrl_new_std(handler, &os05l10_ctrl_ops, + V4L2_CID_VBLANK, vblank_def, + OS05L10_VTS_MAX - mode->height, + 1, vblank_def); + + exposure_max = mode->vts_def - 4; + os05l10->exposure = v4l2_ctrl_new_std(handler, &os05l10_ctrl_ops, + V4L2_CID_EXPOSURE, OS05L10_EXPOSURE_MIN, + exposure_max, OS05L10_EXPOSURE_STEP, + mode->exp_def); + + os05l10->anal_gain = v4l2_ctrl_new_std(handler, &os05l10_ctrl_ops, + V4L2_CID_ANALOGUE_GAIN, OS05L10_GAIN_MIN, + OS05L10_GAIN_MAX, OS05L10_GAIN_STEP, + OS05L10_GAIN_DEFAULT); + + os05l10->test_pattern = v4l2_ctrl_new_std_menu_items(handler, + &os05l10_ctrl_ops, V4L2_CID_TEST_PATTERN, + ARRAY_SIZE(os05l10_test_pattern_menu) - 1, + 0, 0, os05l10_test_pattern_menu); + + os05l10->h_flip = v4l2_ctrl_new_std(handler, &os05l10_ctrl_ops, + V4L2_CID_HFLIP, 0, 1, 1, 0); + + os05l10->v_flip = v4l2_ctrl_new_std(handler, &os05l10_ctrl_ops, + V4L2_CID_VFLIP, 0, 1, 1, 0); + + if (handler->error) { + ret = handler->error; + dev_err(&os05l10->client->dev, + "Failed to init controls(%d)\n", ret); + goto err_free_handler; + } + + os05l10->subdev.ctrl_handler = handler; + + return 0; + +err_free_handler: + v4l2_ctrl_handler_free(handler); + + return ret; +} + +static int os05l10_check_sensor_id(struct os05l10 *os05l10, + struct i2c_client *client) +{ + struct device *dev = &os05l10->client->dev; + u16 id = 0; + u8 reg_H = 0; + u8 reg_L = 0; + int ret; + + ret = os05l10_read_reg(client, OS05L10_REG_CHIP_ID_H, ®_H); + ret |= os05l10_read_reg(client, OS05L10_REG_CHIP_ID_L, ®_L); + id = ((reg_H << 8) & 0xff00) | (reg_L & 0xff); + if (id != CHIP_ID) { + dev_err(dev, "Unexpected sensor id(%06x), ret(%d)\n", id, ret); + //return -ENODEV; + } + dev_info(dev, "detected ov%04x sensor\n", id); + return 0; +} + +static int os05l10_configure_regulators(struct os05l10 *os05l10) +{ + unsigned int i; + + for (i = 0; i < OS05L10_NUM_SUPPLIES; i++) + os05l10->supplies[i].supply = os05l10_supply_names[i]; + + return devm_regulator_bulk_get(&os05l10->client->dev, + OS05L10_NUM_SUPPLIES, + os05l10->supplies); +} + +static int os05l10_parse_of(struct os05l10 *os05l10) +{ + struct device *dev = &os05l10->client->dev; + struct device_node *endpoint; + struct fwnode_handle *fwnode; + int rval; + unsigned int fps; + + endpoint = of_graph_get_next_endpoint(dev->of_node, NULL); + if (!endpoint) { + dev_err(dev, "Failed to get endpoint\n"); + return -EINVAL; + } + fwnode = of_fwnode_handle(endpoint); + rval = fwnode_property_read_u32_array(fwnode, "data-lanes", NULL, 0); + if (rval <= 0) { + dev_warn(dev, " Get mipi lane num failed!\n"); + return -1; + } + + os05l10->lane_num = rval; + if (2 == os05l10->lane_num) { + os05l10->cur_mode = &supported_modes_2lane[0]; + supported_modes = supported_modes_2lane; + os05l10->cfg_num = ARRAY_SIZE(supported_modes_2lane); + /*pixel rate = link frequency * 2 * lanes / BITS_PER_SAMPLE */ + fps = DIV_ROUND_CLOSEST(os05l10->cur_mode->max_fps.denominator, + os05l10->cur_mode->max_fps.numerator); + os05l10->pixel_rate = os05l10->cur_mode->vts_def * + os05l10->cur_mode->hts_def * fps; + dev_info(dev, "lane_num(%d) pixel_rate(%u)\n", + os05l10->lane_num, os05l10->pixel_rate); + } else { + dev_err(dev, "unsupported lane_num(%d)\n", os05l10->lane_num); + return -1; + } + + return 0; +} + +static int os05l10_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct device *dev = &client->dev; + struct device_node *node = dev->of_node; + struct os05l10 *os05l10; + struct v4l2_subdev *sd; + char facing[2]; + int ret; + struct device_node *eeprom_ctrl_node; + struct i2c_client *eeprom_ctrl_client; + struct v4l2_subdev *eeprom_ctrl; + struct otp_info *otp_ptr; + + dev_info(dev, "driver version: %02x.%02x.%02x", + DRIVER_VERSION >> 16, + (DRIVER_VERSION & 0xff00) >> 8, + DRIVER_VERSION & 0x00ff); + + os05l10 = devm_kzalloc(dev, sizeof(*os05l10), GFP_KERNEL); + if (!os05l10) + return -ENOMEM; + + ret = of_property_read_u32(node, RKMODULE_CAMERA_MODULE_INDEX, + &os05l10->module_index); + ret |= of_property_read_string(node, RKMODULE_CAMERA_MODULE_FACING, + &os05l10->module_facing); + ret |= of_property_read_string(node, RKMODULE_CAMERA_MODULE_NAME, + &os05l10->module_name); + ret |= of_property_read_string(node, RKMODULE_CAMERA_LENS_NAME, + &os05l10->len_name); + if (ret) { + dev_err(dev, "could not get module information!\n"); + return -EINVAL; + } + os05l10->client = client; + + os05l10->xvclk = devm_clk_get(dev, "xvclk"); + if (IS_ERR(os05l10->xvclk)) { + dev_err(dev, "Failed to get xvclk\n"); + return -EINVAL; + } + + os05l10->power_gpio = devm_gpiod_get(dev, "power", GPIOD_OUT_LOW); + if (IS_ERR(os05l10->power_gpio)) + dev_warn(dev, "Failed to get power-gpios, maybe no use\n"); + os05l10->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_LOW); + if (IS_ERR(os05l10->reset_gpio)) + dev_warn(dev, "Failed to get reset-gpios\n"); + + os05l10->pwdn_gpio = devm_gpiod_get(dev, "pwdn", GPIOD_OUT_LOW); + if (IS_ERR(os05l10->pwdn_gpio)) + dev_warn(dev, "Failed to get pwdn-gpios\n"); + + ret = os05l10_configure_regulators(os05l10); + if (ret) { + dev_err(dev, "Failed to get power regulators\n"); + return ret; + } + + ret = os05l10_parse_of(os05l10); + if (ret != 0) + return -EINVAL; + + os05l10->pinctrl = devm_pinctrl_get(dev); + if (!IS_ERR(os05l10->pinctrl)) { + os05l10->pins_default = + pinctrl_lookup_state(os05l10->pinctrl, + OF_CAMERA_PINCTRL_STATE_DEFAULT); + if (IS_ERR(os05l10->pins_default)) + dev_err(dev, "could not get default pinstate\n"); + + os05l10->pins_sleep = + pinctrl_lookup_state(os05l10->pinctrl, + OF_CAMERA_PINCTRL_STATE_SLEEP); + if (IS_ERR(os05l10->pins_sleep)) + dev_err(dev, "could not get sleep pinstate\n"); + } + + mutex_init(&os05l10->mutex); + + sd = &os05l10->subdev; + v4l2_i2c_subdev_init(sd, client, &os05l10_subdev_ops); + ret = os05l10_initialize_controls(os05l10); + if (ret) + goto err_destroy_mutex; + + ret = __os05l10_power_on(os05l10); + if (ret) + goto err_free_handler; + + ret = os05l10_check_sensor_id(os05l10, client); + if (ret) + goto err_power_off; + + eeprom_ctrl_node = of_parse_phandle(node, "eeprom-ctrl", 0); + if (eeprom_ctrl_node) { + eeprom_ctrl_client = + of_find_i2c_device_by_node(eeprom_ctrl_node); + of_node_put(eeprom_ctrl_node); + if (IS_ERR_OR_NULL(eeprom_ctrl_client)) { + dev_err(dev, "can not get node\n"); + goto continue_probe; + } + eeprom_ctrl = i2c_get_clientdata(eeprom_ctrl_client); + if (IS_ERR_OR_NULL(eeprom_ctrl)) { + dev_err(dev, "can not get eeprom i2c client\n"); + } else { + otp_ptr = devm_kzalloc(dev, sizeof(*otp_ptr), GFP_KERNEL); + if (!otp_ptr) + return -ENOMEM; + ret = v4l2_subdev_call(eeprom_ctrl, + core, ioctl, 0, otp_ptr); + if (!ret) { + os05l10->otp = otp_ptr; + } else { + os05l10->otp = NULL; + devm_kfree(dev, otp_ptr); + dev_warn(dev, "can not get otp info, skip!\n"); + } + } + } +continue_probe: + +#ifdef CONFIG_VIDEO_V4L2_SUBDEV_API + sd->internal_ops = &os05l10_internal_ops; + sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE | + V4L2_SUBDEV_FL_HAS_EVENTS; +#endif +#if defined(CONFIG_MEDIA_CONTROLLER) + os05l10->pad.flags = MEDIA_PAD_FL_SOURCE; + sd->entity.function = MEDIA_ENT_F_CAM_SENSOR; + ret = media_entity_pads_init(&sd->entity, 1, &os05l10->pad); + if (ret < 0) + goto err_power_off; +#endif + + memset(facing, 0, sizeof(facing)); + if (strcmp(os05l10->module_facing, "back") == 0) + facing[0] = 'b'; + else + facing[0] = 'f'; + + snprintf(sd->name, sizeof(sd->name), "m%02d_%s_%s %s", + os05l10->module_index, facing, + OS05L10_NAME, dev_name(sd->dev)); + ret = v4l2_async_register_subdev_sensor(sd); + if (ret) { + dev_err(dev, "v4l2 async register subdev failed\n"); + goto err_clean_entity; + } + + pm_runtime_set_active(dev); + pm_runtime_enable(dev); + pm_runtime_idle(dev); + + return 0; + +err_clean_entity: +#if defined(CONFIG_MEDIA_CONTROLLER) + media_entity_cleanup(&sd->entity); +#endif +err_power_off: + __os05l10_power_off(os05l10); +err_free_handler: + v4l2_ctrl_handler_free(&os05l10->ctrl_handler); +err_destroy_mutex: + mutex_destroy(&os05l10->mutex); + + return ret; +} + +static void os05l10_remove(struct i2c_client *client) +{ + struct v4l2_subdev *sd = i2c_get_clientdata(client); + struct os05l10 *os05l10 = to_os05l10(sd); + + v4l2_async_unregister_subdev(sd); +#if defined(CONFIG_MEDIA_CONTROLLER) + media_entity_cleanup(&sd->entity); +#endif + v4l2_ctrl_handler_free(&os05l10->ctrl_handler); + mutex_destroy(&os05l10->mutex); + + pm_runtime_disable(&client->dev); + if (!pm_runtime_status_suspended(&client->dev)) + __os05l10_power_off(os05l10); + pm_runtime_set_suspended(&client->dev); +} + +#if IS_ENABLED(CONFIG_OF) +static const struct of_device_id os05l10_of_match[] = { + { .compatible = "ovti,os05l10" }, + {}, +}; +MODULE_DEVICE_TABLE(of, os05l10_of_match); +#endif + +static const struct i2c_device_id os05l10_match_id[] = { + { "ovti,os05l10", 0}, + { }, +}; + +static struct i2c_driver os05l10_i2c_driver = { + .driver = { + .name = OS05L10_NAME, + .pm = &os05l10_pm_ops, + .of_match_table = of_match_ptr(os05l10_of_match), + }, + .probe = &os05l10_probe, + .remove = &os05l10_remove, + .id_table = os05l10_match_id, +}; + +static int __init sensor_mod_init(void) +{ + return i2c_add_driver(&os05l10_i2c_driver); +} + +static void __exit sensor_mod_exit(void) +{ + i2c_del_driver(&os05l10_i2c_driver); +} + +device_initcall_sync(sensor_mod_init); +module_exit(sensor_mod_exit); + +MODULE_DESCRIPTION("OmniVision os05l10 sensor driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/media/i2c/rk628/rk628_csi_v4l2.c b/drivers/media/i2c/rk628/rk628_csi_v4l2.c index 914cdd2e3c74..540e054547b6 100644 --- a/drivers/media/i2c/rk628/rk628_csi_v4l2.c +++ b/drivers/media/i2c/rk628/rk628_csi_v4l2.c @@ -2617,12 +2617,6 @@ static long rk628_csi_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg) v4l2_info(sd, "user set color range: %d\n", csi->user_color_range); rk628_csi_set_color_range(sd); break; - case RKMODULE_GET_SKIP_FRAME: - if (csi->plat_data->tx_mode == DSI_MODE) - *(int *)arg = CSI_SKIP_FRAME_NORMAL; - else - *(int *)arg = 0; - break; case RK_HDMIRX_CMD_GET_EDID_VERSION: *(int *)arg = csi->edid_version; break; diff --git a/drivers/media/usb/uvc/uvc_driver.c b/drivers/media/usb/uvc/uvc_driver.c index 88eda75089d3..0679b288c10a 100644 --- a/drivers/media/usb/uvc/uvc_driver.c +++ b/drivers/media/usb/uvc/uvc_driver.c @@ -369,7 +369,7 @@ static int uvc_parse_format(struct uvc_device *dev, * Parse the frame descriptors. Only uncompressed, MJPEG and frame * based formats have frame descriptors. */ - while (buflen > 2 && buffer[1] == USB_DT_CS_INTERFACE && + while (ftype && buflen > 2 && buffer[1] == USB_DT_CS_INTERFACE && buffer[2] == ftype) { frame = &format->frame[format->nframes]; if (ftype != UVC_VS_FRAME_FRAME_BASED) diff --git a/drivers/memory/rockchip/dsmc-controller.c b/drivers/memory/rockchip/dsmc-controller.c index d4e85f85cdc9..1dc29ecf599d 100644 --- a/drivers/memory/rockchip/dsmc-controller.c +++ b/drivers/memory/rockchip/dsmc-controller.c @@ -4,6 +4,7 @@ */ #include #include +#include #include #include @@ -110,19 +111,21 @@ static uint32_t cap_2_dev_size(uint32_t cap) static int dsmc_psram_id_detect(struct rockchip_dsmc *dsmc, uint32_t cs) { - uint32_t tmp, i; + uint32_t tmp[DSMC_MAX_SLAVE_NUM], i; int ret = -1; struct dsmc_map *region_map = &dsmc->cs_map[cs].region_map[0]; struct dsmc_config_cs *cfg = &dsmc->cfg.cs_cfg[cs]; - tmp = readl(dsmc->regs + DSMC_MCR(cs)); + for (i = 0; i < DSMC_MAX_SLAVE_NUM; i++) { + tmp[i] = readl(dsmc->regs + DSMC_MCR(i)); - /* config to CR space */ - REG_CLRSETBITS(dsmc, DSMC_MCR(cs), - (MCR_IOWIDTH_MASK << MCR_IOWIDTH_SHIFT) | - (MCR_CRT_MASK << MCR_CRT_SHIFT), - (MCR_IOWIDTH_X8 << MCR_IOWIDTH_SHIFT) | - (MCR_CRT_CR_SPACE << MCR_CRT_SHIFT)); + /* config to CR space */ + REG_CLRSETBITS(dsmc, DSMC_MCR(i), + (MCR_IOWIDTH_MASK << MCR_IOWIDTH_SHIFT) | + (MCR_CRT_MASK << MCR_CRT_SHIFT), + (MCR_IOWIDTH_X8 << MCR_IOWIDTH_SHIFT) | + (MCR_CRT_CR_SPACE << MCR_CRT_SHIFT)); + } if (cfg->protcl == OPI_XCCELA_PSRAM) { uint8_t mid; @@ -157,15 +160,17 @@ static int dsmc_psram_id_detect(struct rockchip_dsmc *dsmc, uint32_t cs) } } - /* config to memory space */ - writel(tmp, dsmc->regs + DSMC_MCR(cs)); + for (i = 0; i < DSMC_MAX_SLAVE_NUM; i++) + /* config to memory space */ + writel(tmp[i], dsmc->regs + DSMC_MCR(i)); return ret; } static void dsmc_psram_bw_detect(struct rockchip_dsmc *dsmc, uint32_t cs) { - uint32_t tmp, col; + uint32_t i; + uint32_t tmp[DSMC_MAX_SLAVE_NUM], col; uint16_t ir0_ir1; struct dsmc_map *region_map = &dsmc->cs_map[cs].region_map[0]; struct dsmc_config_cs *cfg = &dsmc->cfg.cs_cfg[cs]; @@ -177,13 +182,15 @@ static void dsmc_psram_bw_detect(struct rockchip_dsmc *dsmc, uint32_t cs) else cfg->io_width = MCR_IOWIDTH_X8; } else { - tmp = readl(dsmc->regs + DSMC_MCR(cs)); - /* config to CR space */ - REG_CLRSETBITS(dsmc, DSMC_MCR(cs), - (MCR_IOWIDTH_MASK << MCR_IOWIDTH_SHIFT) | - (MCR_CRT_MASK << MCR_CRT_SHIFT), - (MCR_IOWIDTH_X8 << MCR_IOWIDTH_SHIFT) | - (MCR_CRT_CR_SPACE << MCR_CRT_SHIFT)); + for (i = 0; i < DSMC_MAX_SLAVE_NUM; i++) { + tmp[i] = readl(dsmc->regs + DSMC_MCR(i)); + /* config to CR space */ + REG_CLRSETBITS(dsmc, DSMC_MCR(i), + (MCR_IOWIDTH_MASK << MCR_IOWIDTH_SHIFT) | + (MCR_CRT_MASK << MCR_CRT_SHIFT), + (MCR_IOWIDTH_X8 << MCR_IOWIDTH_SHIFT) | + (MCR_CRT_CR_SPACE << MCR_CRT_SHIFT)); + } /* hyper psram get IR0 */ ir0_ir1 = hyper_read_mr(region_map, HYPER_PSRAM_IR0); @@ -195,8 +202,9 @@ static void dsmc_psram_bw_detect(struct rockchip_dsmc *dsmc, uint32_t cs) else cfg->io_width = MCR_IOWIDTH_X8; - /* config to memory space */ - writel(tmp, dsmc->regs + DSMC_MCR(cs)); + for (i = 0; i < DSMC_MAX_SLAVE_NUM; i++) + /* config to memory space */ + writel(tmp[i], dsmc->regs + DSMC_MCR(i)); } cfg->col = col; @@ -206,6 +214,7 @@ static int dsmc_psram_dectect(struct rockchip_dsmc *dsmc, uint32_t cs) { uint32_t i = 0; int ret = -1; + struct device *dev = dsmc->dev; struct dsmc_config_cs *cfg = &dsmc->cfg.cs_cfg[cs]; /* axi read do not response error */ @@ -229,7 +238,7 @@ static int dsmc_psram_dectect(struct rockchip_dsmc *dsmc, uint32_t cs) cfg->protcl = psram_info[i].protcl; cfg->mtr_timing = psram_info[i].mtr_timing; if (!dsmc_psram_id_detect(dsmc, cs)) { - pr_info("DSMC: The cs%d %s PSRAM ID: 0x%x\n", cs, + dev_info(dev, "The cs%d %s PSRAM ID: 0x%x\n", cs, (cfg->protcl == OPI_XCCELA_PSRAM) ? "XCCELA" : "HYPER", psram_info[i].id); ret = 0; @@ -237,7 +246,7 @@ static int dsmc_psram_dectect(struct rockchip_dsmc *dsmc, uint32_t cs) } } if (i == ARRAY_SIZE(psram_info)) { - pr_err("DSMC: Unknown PSRAM device\n"); + dev_err(dev, "Unknown PSRAM device\n"); ret = -1; } else { dsmc_psram_bw_detect(dsmc, cs); @@ -315,6 +324,7 @@ static int dsmc_slv_cmn_rgn_config(struct rockchip_dsmc *dsmc, uint32_t rgn, uint32_t cs) { uint32_t tmp; + struct device *dev = dsmc->dev; struct dsmc_map *region_map = &dsmc->cs_map[cs].region_map[0]; struct dsmc_config_cs *cfg = &dsmc->cfg.cs_cfg[cs]; @@ -324,21 +334,21 @@ static int dsmc_slv_cmn_rgn_config(struct rockchip_dsmc *dsmc, } else if (slv_rgn->dummy_clk_num == 1) { tmp |= slv_rgn->dummy_clk_num << WR_DATA_CYC_EXTENDED_SHIFT; } else { - pr_err("DSMC: lb slave: dummy clk too large\n"); + dev_err(dev, "lb slave: dummy clk too large\n"); return -1; } tmp &= ~(RD_LATENCY_CYC_MASK << RD_LATENCY_CYC_SHIFT); if ((cfg->rd_latency == 1) || (cfg->rd_latency == 2)) { tmp |= cfg->rd_latency << RD_LATENCY_CYC_SHIFT; } else { - pr_err("DSMC: lb slave: read latency value error\n"); + dev_err(dev, "lb slave: read latency value error\n"); return -1; } tmp &= ~(WR_LATENCY_CYC_MASK << WR_LATENCY_CYC_SHIFT); if ((cfg->wr_latency == 1) || (cfg->wr_latency == 2)) { tmp |= cfg->wr_latency << WR_LATENCY_CYC_SHIFT; } else { - pr_err("DSMC: lb slave: write latency value error\n"); + dev_err(dev, "lb slave: write latency value error\n"); return -1; } tmp &= ~(CA_CYC_MASK << CA_CYC_SHIFT); @@ -356,6 +366,7 @@ static int dsmc_slv_cmn_config(struct rockchip_dsmc *dsmc, struct regions_config *slv_rgn, uint32_t cs) { uint32_t tmp; + struct device *dev = dsmc->dev; struct dsmc_map *region_map = &dsmc->cs_map[cs].region_map[0]; struct dsmc_config_cs *cfg = &dsmc->cfg.cs_cfg[cs]; @@ -371,7 +382,7 @@ static int dsmc_slv_cmn_config(struct rockchip_dsmc *dsmc, } else if (slv_rgn->dummy_clk_num == 1) { tmp |= slv_rgn->dummy_clk_num << WR_DATA_CYC_EXTENDED_SHIFT; } else { - pr_err("DSMC: lb slave: dummy clk too large\n"); + dev_err(dev, "lb slave: dummy clk too large\n"); return -1; } @@ -388,18 +399,20 @@ static int dsmc_slv_cmn_config(struct rockchip_dsmc *dsmc, static int dsmc_lb_cmn_config(struct rockchip_dsmc *dsmc, uint32_t cs) { - uint32_t tmp, i; + uint32_t tmp[DSMC_MAX_SLAVE_NUM], i; struct dsmc_config_cs *cfg = &dsmc->cfg.cs_cfg[cs]; struct regions_config *slv_rgn; int ret = 0; - tmp = readl(dsmc->regs + DSMC_MCR(cs)); - /* config to CR space */ - REG_CLRSETBITS(dsmc, DSMC_MCR(cs), - (MCR_IOWIDTH_MASK << MCR_IOWIDTH_SHIFT) | - (MCR_CRT_MASK << MCR_CRT_SHIFT), - (MCR_IOWIDTH_X8 << MCR_IOWIDTH_SHIFT) | - (MCR_CRT_CR_SPACE << MCR_CRT_SHIFT)); + for (i = 0; i < DSMC_MAX_SLAVE_NUM; i++) { + tmp[i] = readl(dsmc->regs + DSMC_MCR(i)); + /* config to CR space */ + REG_CLRSETBITS(dsmc, DSMC_MCR(i), + (MCR_IOWIDTH_MASK << MCR_IOWIDTH_SHIFT) | + (MCR_CRT_MASK << MCR_CRT_SHIFT), + (MCR_IOWIDTH_X8 << MCR_IOWIDTH_SHIFT) | + (MCR_CRT_CR_SPACE << MCR_CRT_SHIFT)); + } for (i = 0; i < DSMC_LB_MAX_RGN; i++) { slv_rgn = &cfg->slv_rgn[i]; @@ -413,8 +426,9 @@ static int dsmc_lb_cmn_config(struct rockchip_dsmc *dsmc, uint32_t cs) slv_rgn = &cfg->slv_rgn[0]; ret = dsmc_slv_cmn_config(dsmc, slv_rgn, cs); - /* config to memory space */ - writel(tmp, dsmc->regs + DSMC_MCR(cs)); + for (i = 0; i < DSMC_MAX_SLAVE_NUM; i++) + /* config to memory space */ + writel(tmp[i], dsmc->regs + DSMC_MCR(i)); for (i = 0; i < DSMC_LB_MAX_RGN; i++) { slv_rgn = &cfg->slv_rgn[i]; @@ -472,17 +486,20 @@ static void dsmc_cfg_latency(uint32_t rd_ltcy, uint32_t wr_ltcy, static int dsmc_psram_cfg(struct rockchip_dsmc *dsmc, uint32_t cs) { - uint32_t latency, mcr, tmp; + uint32_t i; + uint32_t latency, mcr[DSMC_MAX_SLAVE_NUM], tmp; struct dsmc_map *region_map = &dsmc->cs_map[cs].region_map[0]; struct dsmc_config_cs *cs_cfg = &dsmc->cfg.cs_cfg[cs]; - mcr = readl(dsmc->regs + DSMC_MCR(cs)); - /* config to CR space */ - REG_CLRSETBITS(dsmc, DSMC_MCR(cs), - (MCR_IOWIDTH_MASK << MCR_IOWIDTH_SHIFT) | - (MCR_CRT_MASK << MCR_CRT_SHIFT), - (MCR_IOWIDTH_X8 << MCR_IOWIDTH_SHIFT) | - (MCR_CRT_CR_SPACE << MCR_CRT_SHIFT)); + for (i = 0; i < DSMC_MAX_SLAVE_NUM; i++) { + mcr[i] = readl(dsmc->regs + DSMC_MCR(i)); + /* config to CR space */ + REG_CLRSETBITS(dsmc, DSMC_MCR(i), + (MCR_IOWIDTH_MASK << MCR_IOWIDTH_SHIFT) | + (MCR_CRT_MASK << MCR_CRT_SHIFT), + (MCR_IOWIDTH_X8 << MCR_IOWIDTH_SHIFT) | + (MCR_CRT_CR_SPACE << MCR_CRT_SHIFT)); + } if (cs_cfg->protcl == OPI_XCCELA_PSRAM) { /* Xccela psram init */ uint8_t mr_tmp, rbxen; @@ -507,6 +524,9 @@ static int dsmc_psram_cfg(struct rockchip_dsmc *dsmc, uint32_t cs) mr_tmp = (mr_tmp & (~(XCCELA_MR4_WL_MASK << XCCELA_MR4_WL_SHIFT))) | (tmp << XCCELA_MR4_WL_SHIFT); + /* set 0.5x refresh rate allow */ + mr_tmp = (mr_tmp & (~(XCCELA_MR4_REFRESH_MASK << XCCELA_MR4_REFRESH_SHIFT))) | + (XCCELA_MR4_0_5_REFRESH_RATE << XCCELA_MR4_REFRESH_SHIFT); xccela_write_mr(region_map, 4, mr_tmp); @@ -583,8 +603,9 @@ static int dsmc_psram_cfg(struct rockchip_dsmc *dsmc, uint32_t cs) (CR1_CLOCK_TYPE_DIFF_CLK << CR1_CLOCK_TYPE_SHIFT); hyper_write_mr(region_map, HYPER_PSRAM_CR1, cr_tmp); } - /* config to memory space */ - writel(mcr, dsmc->regs + DSMC_MCR(cs)); + for (i = 0; i < DSMC_MAX_SLAVE_NUM; i++) + /* config to memory space */ + writel(mcr[i], dsmc->regs + DSMC_MCR(i)); return 0; } @@ -593,6 +614,7 @@ static int dsmc_psram_cfg(struct rockchip_dsmc *dsmc, uint32_t cs) static int dsmc_psram_init(struct rockchip_dsmc *dsmc, uint32_t cs) { uint32_t latency; + struct device *dev = dsmc->dev; struct dsmc_config_cs *cs_cfg = &dsmc->cfg.cs_cfg[cs]; uint32_t mhz = dsmc->cfg.freq_hz / MHZ; @@ -607,7 +629,7 @@ static int dsmc_psram_init(struct rockchip_dsmc *dsmc, uint32_t cs) } else if (mhz <= 200) { latency = 7; } else { - pr_err("DSMC: PSRAM frequency do not support!\n"); + dev_err(dev, "PSRAM frequency do not support!\n"); return -1; } @@ -646,6 +668,7 @@ static int dsmc_ctrller_cfg_for_psram(struct rockchip_dsmc *dsmc, uint32_t cs) static void dsmc_psram_remodify_timing(struct rockchip_dsmc *dsmc, uint32_t cs) { + uint32_t i; uint32_t max_length = 511, tcmd = 3; uint32_t tcsm, tmp; uint32_t mhz = dsmc->cfg.freq_hz / MHZ; @@ -670,13 +693,16 @@ static void dsmc_psram_remodify_timing(struct rockchip_dsmc *dsmc, uint32_t cs) if (tmp > max_length) tmp = max_length; + for (i = 0; i < DSMC_MAX_SLAVE_NUM; i++) + REG_CLRSETBITS(dsmc, DSMC_MCR(i), + MCR_IOWIDTH_MASK << MCR_IOWIDTH_SHIFT, + cs_cfg->io_width << MCR_IOWIDTH_SHIFT); + REG_CLRSETBITS(dsmc, DSMC_MCR(cs), (MCR_MAXEN_MASK << MCR_MAXEN_SHIFT) | - (MCR_MAXLEN_MASK << MCR_MAXLEN_SHIFT) | - (MCR_IOWIDTH_MASK << MCR_IOWIDTH_SHIFT), + (MCR_MAXLEN_MASK << MCR_MAXLEN_SHIFT), (MCR_MAX_LENGTH_EN << MCR_MAXEN_SHIFT) | - (tmp << MCR_MAXLEN_SHIFT) | - (cs_cfg->io_width << MCR_IOWIDTH_SHIFT)); + (tmp << MCR_MAXLEN_SHIFT)); if (cs_cfg->io_width == MCR_IOWIDTH_X16) tmp = cs_cfg->col - 2; @@ -794,6 +820,7 @@ int rockchip_dsmc_dll_training(struct rockchip_dsmc_device *priv) int dll, dll_step = 10; struct dsmc_config_cs *cfg; struct rockchip_dsmc *dsmc = &priv->dsmc; + struct device *dev = dsmc->dev; int ret; for (cs = 0; cs < DSMC_MAX_SLAVE_NUM; cs++) { @@ -829,11 +856,11 @@ int rockchip_dsmc_dll_training(struct rockchip_dsmc_device *priv) } dll = (dll_max + dll_min) / 2; if ((dll >= 0xff) || (dll <= 0)) { - pr_err("DSMC: cs%d byte%d dll training error(0x%x)\n", + dev_err(dev, "DSMC: cs%d byte%d dll training error(0x%x)\n", cs, byte, dll); return -1; } - pr_info("DSMC: cs%d byte%d dll delay line result 0x%x\n", cs, byte, dll); + dev_info(dev, "cs%d byte%d dll delay line result 0x%x\n", cs, byte, dll); REG_CLRSETBITS(dsmc, DSMC_RDS_DLL_CTL(cs, byte), RDS_DLL0_CTL_RDS_0_CLK_DELAY_NUM_MASK, dll << RDS_DLL0_CTL_RDS_0_CLK_DELAY_NUM_SHIFT); @@ -942,6 +969,7 @@ EXPORT_SYMBOL(rockchip_dsmc_psram_reinit); int rockchip_dsmc_ctrller_init(struct rockchip_dsmc *dsmc, uint32_t cs) { + uint32_t i; struct dsmc_config_cs *cfg = &dsmc->cfg.cs_cfg[cs]; writel(MRGTCR_READ_WRITE_MERGE_EN, @@ -953,17 +981,21 @@ int rockchip_dsmc_ctrller_init(struct rockchip_dsmc *dsmc, uint32_t cs) (cfg->dll_num[1] << RDS_DLL1_CTL_RDS_1_CLK_DELAY_NUM_SHIFT), dsmc->regs + DSMC_RDS_DLL1_CTL(cs)); + /* all io_width should set the same value in diff cs */ + for (i = 0; i < DSMC_MAX_SLAVE_NUM; i++) + REG_CLRSETBITS(dsmc, DSMC_MCR(cs), + MCR_IOWIDTH_MASK << MCR_IOWIDTH_SHIFT, + cfg->io_width << MCR_IOWIDTH_SHIFT); + REG_CLRSETBITS(dsmc, DSMC_MCR(cs), (MCR_ACS_MASK << MCR_ACS_SHIFT) | (MCR_DEVTYPE_MASK << MCR_DEVTYPE_SHIFT) | - (MCR_IOWIDTH_MASK << MCR_IOWIDTH_SHIFT) | (MCR_EXCLUSIVE_DQS_MASK << MCR_EXCLUSIVE_DQS_SHIFT) | (MCR_WRAPSIZE_MASK << MCR_WRAPSIZE_SHIFT) | (MCR_MAXEN_MASK << MCR_MAXEN_SHIFT) | (MCR_MAXLEN_MASK << MCR_MAXLEN_SHIFT), (cfg->acs << MCR_ACS_SHIFT) | (MCR_DEVTYPE_HYPERRAM << MCR_DEVTYPE_SHIFT) | - (cfg->io_width << MCR_IOWIDTH_SHIFT) | (cfg->exclusive_dqs << MCR_EXCLUSIVE_DQS_SHIFT) | (cfg->wrap_size << MCR_WRAPSIZE_SHIFT) | (cfg->max_length_en << MCR_MAXEN_SHIFT) | diff --git a/drivers/memory/rockchip/dsmc-host.c b/drivers/memory/rockchip/dsmc-host.c index b96e012d395d..03e4ff3b3189 100644 --- a/drivers/memory/rockchip/dsmc-host.c +++ b/drivers/memory/rockchip/dsmc-host.c @@ -526,6 +526,7 @@ static int dsmc_write(struct rockchip_dsmc_device *dsmc_dev, uint32_t cs, uint32 static void dsmc_lb_dma_hw_mode_en(struct rockchip_dsmc *dsmc, uint32_t cs) { + struct device *dev = dsmc->dev; struct dsmc_transfer *xfer = &dsmc->xfer; size_t size = xfer->transfer_size; uint32_t burst_byte = xfer->brst_len * xfer->brst_size; @@ -533,7 +534,7 @@ static void dsmc_lb_dma_hw_mode_en(struct rockchip_dsmc *dsmc, uint32_t cs) dma_req_num = size / burst_byte; if (size % burst_byte) { - pr_warn("DSMC: DMA size is unaligned\n"); + dev_warn(dev, "DMA size is unaligned\n"); dma_req_num++; } writel(dma_req_num, dsmc->regs + DSMC_DMA_REQ_NUM(cs)); @@ -683,7 +684,7 @@ static int dsmc_copy_from(struct rockchip_dsmc_device *dsmc_dev, uint32_t cs, ui struct rockchip_dsmc *dsmc = &dsmc_dev->dsmc; if (atomic_read(&dsmc->xfer.state) & (RXDMA | TXDMA)) { - pr_warn("DSMC: copy_from: the transfer is busy!\n"); + dev_warn(dev, "copy_from: the transfer is busy!\n"); return -EBUSY; } @@ -721,7 +722,7 @@ static int dsmc_copy_to(struct rockchip_dsmc_device *dsmc_dev, uint32_t cs, uint struct rockchip_dsmc *dsmc = &dsmc_dev->dsmc; if (atomic_read(&dsmc->xfer.state) & (RXDMA | TXDMA)) { - pr_warn("DSMC: copy_to: the transfer is busy!\n"); + dev_warn(dev, "copy_to: the transfer is busy!\n"); return -EBUSY; } @@ -785,6 +786,29 @@ static void dsmc_data_init(struct rockchip_dsmc *dsmc) } } +static int dsmc_check_mult_psram_cap(struct rockchip_dsmc *dsmc) +{ + uint32_t cs; + uint32_t io_width = 0xffffffff; + struct device *dev = dsmc->dev; + struct dsmc_ctrl_config *cfg = &dsmc->cfg; + + for (cs = 0; cs < DSMC_MAX_SLAVE_NUM; cs++) { + if (cfg->cs_cfg[cs].device_type == DSMC_UNKNOWN_DEVICE) + continue; + if (io_width == 0xffffffff) { + io_width = dsmc->cfg.cs_cfg[cs].io_width; + } else { + if (io_width != dsmc->cfg.cs_cfg[cs].io_width) { + dev_err(dev, "The io width error for mult rank!\n"); + return -1; + } + } + } + + return 0; +} + static void dsmc_reset_ctrl(struct rockchip_dsmc *dsmc) { reset_control_assert(dsmc->areset); @@ -797,6 +821,7 @@ static void dsmc_reset_ctrl(struct rockchip_dsmc *dsmc) static int dsmc_init(struct rockchip_dsmc *dsmc) { uint32_t cs; + struct device *dev = dsmc->dev; struct dsmc_ctrl_config *cfg = &dsmc->cfg; struct dsmc_config_cs *cs_cfg; uint32_t ret = 0; @@ -812,13 +837,18 @@ static int dsmc_init(struct rockchip_dsmc *dsmc) return ret; } } + + ret = dsmc_check_mult_psram_cap(dsmc); + if (ret) + return ret; + dsmc_reset_ctrl(dsmc); for (cs = 0; cs < DSMC_MAX_SLAVE_NUM; cs++) { if (cfg->cs_cfg[cs].device_type == DSMC_UNKNOWN_DEVICE) continue; cs_cfg = &dsmc->cfg.cs_cfg[cs]; - pr_info("DSMC: init cs%d %s device\n", + dev_info(dev, "init cs%d %s device\n", cs, (cs_cfg->device_type == DSMC_LB_DEVICE) ? "LB" : "PSRAM"); rockchip_dsmc_ctrller_init(dsmc, cs); if (cs_cfg->device_type == OPI_XCCELA_PSRAM) diff --git a/drivers/memory/rockchip/dsmc-host.h b/drivers/memory/rockchip/dsmc-host.h index 9e4f7671a594..0c17d7eafd79 100644 --- a/drivers/memory/rockchip/dsmc-host.h +++ b/drivers/memory/rockchip/dsmc-host.h @@ -254,6 +254,9 @@ #define XCCELA_MR4_WL_SHIFT (5) #define XCCELA_MR4_WL_MASK (0x7) +#define XCCELA_MR4_REFRESH_SHIFT (3) +#define XCCELA_MR4_REFRESH_MASK (0x3) +#define XCCELA_MR4_0_5_REFRESH_RATE (0x3) #define XCCELA_MR8_IO_TYPE_SHIFT (6) #define XCCELA_MR8_IO_TYPE_MASK (0x1) diff --git a/drivers/mfd/display-serdes/serdes-bridge.c b/drivers/mfd/display-serdes/serdes-bridge.c index 49f8090429f3..9a6f9bf8aef4 100644 --- a/drivers/mfd/display-serdes/serdes-bridge.c +++ b/drivers/mfd/display-serdes/serdes-bridge.c @@ -7,6 +7,8 @@ * Author: luowei */ +#include + #include "core.h" static struct serdes_bridge *to_serdes_bridge(struct drm_bridge *bridge) @@ -24,7 +26,7 @@ static struct mipi_dsi_device *serdes_attach_dsi(struct serdes_bridge *serdes_br int ret; if (serdes->chip_data->name) - memcpy(&info.type, serdes->chip_data->name, ARRAY_SIZE(info.type)); + strscpy(info.type, serdes->chip_data->name, sizeof(info.type)); SERDES_DBG_MFD("%s: type=%s, name=%s\n", __func__, info.type, serdes->chip_data->name); diff --git a/drivers/misc/rk628/rk628_dsi.c b/drivers/misc/rk628/rk628_dsi.c index ed53a6724568..a2755565ca57 100644 --- a/drivers/misc/rk628/rk628_dsi.c +++ b/drivers/misc/rk628/rk628_dsi.c @@ -1292,7 +1292,11 @@ static void rk628_dsi_bridge_enable(struct rk628 *rk628, static int rk628_dsi_color_bar_show(struct seq_file *s, void *data) { - seq_puts(s, " Enable color bar:\n"); + seq_puts(s, " Enable horizontal color bar:\n"); + seq_puts(s, " example: echo 3 > /sys/kernel/debug/rk628/2-0050/dsi_color_bar\n"); + seq_puts(s, " Enable vertical color bar:\n"); + seq_puts(s, " example: echo 2 > /sys/kernel/debug/rk628/2-0050/dsi_color_bar\n"); + seq_puts(s, " Enable BER pattern (vertical only):\n"); seq_puts(s, " example: echo 1 > /sys/kernel/debug/rk628/2-0050/dsi_color_bar\n"); seq_puts(s, " Disable color bar:\n"); seq_puts(s, " example: echo 0 > /sys/kernel/debug/rk628/2-0050/dsi_color_bar\n"); @@ -1305,6 +1309,29 @@ static int rk628_dsi_color_bar_open(struct inode *inode, struct file *file) return single_open(file, rk628_dsi_color_bar_show, inode->i_private); } +static void rk628_dsi_color_bar(struct rk628 *rk628, struct rk628_dsi *dsi, u8 mode) +{ + switch (mode) { + case 3: // horizontal color bar + dsi_update_bits(rk628, dsi, DSI_VID_MODE_CFG, VPG_ORIENTATION | VPG_MODE | VPG_EN, + VPG_ORIENTATION | 0 | VPG_EN); + break; + case 2: // vertical color bar + dsi_update_bits(rk628, dsi, DSI_VID_MODE_CFG, VPG_ORIENTATION | VPG_MODE | VPG_EN, + 0 | 0 | VPG_EN); + break; + case 1: // BER pattern (vertical only) + dsi_update_bits(rk628, dsi, DSI_VID_MODE_CFG, VPG_ORIENTATION | VPG_MODE | VPG_EN, + 0 | VPG_MODE | VPG_EN); + break; + default: // Disable color bar + dsi_update_bits(rk628, dsi, DSI_VID_MODE_CFG, VPG_ORIENTATION | VPG_MODE | VPG_EN, + 0 | 0 | 0); + dsi_write(rk628, dsi, DSI_PWR_UP, RESET); + dsi_write(rk628, dsi, DSI_PWR_UP, POWER_UP); + } +} + static ssize_t rk628_dsi_color_bar_write(struct file *file, const char __user *ubuf, size_t len, loff_t *offp) { @@ -1316,19 +1343,10 @@ static ssize_t rk628_dsi_color_bar_write(struct file *file, const char __user *u if (kstrtou8_from_user(ubuf, len, 0, &mode)) return -EFAULT; - dsi_update_bits(rk628, dsi, DSI_VID_MODE_CFG, VPG_EN, mode ? VPG_EN : 0); - if (!mode) { - dsi_write(rk628, dsi, DSI_PWR_UP, RESET); - dsi_write(rk628, dsi, DSI_PWR_UP, POWER_UP); - } + rk628_dsi_color_bar(rk628, dsi, mode); - if (dsi->slave) { - dsi_update_bits(rk628, dsi1, DSI_VID_MODE_CFG, VPG_EN, mode ? VPG_EN : 0); - if (!mode) { - dsi_write(rk628, dsi1, DSI_PWR_UP, RESET); - dsi_write(rk628, dsi1, DSI_PWR_UP, POWER_UP); - } - } + if (dsi->slave) + rk628_dsi_color_bar(rk628, dsi1, mode); return len; } diff --git a/drivers/misc/rk628/rk628_dsi.h b/drivers/misc/rk628/rk628_dsi.h index eb6dc7a578bd..668c5e5b9f62 100644 --- a/drivers/misc/rk628/rk628_dsi.h +++ b/drivers/misc/rk628/rk628_dsi.h @@ -43,6 +43,8 @@ #define DSI_MODE_CFG 0x0034 #define CMD_VIDEO_MODE(x) UPDATE(x, 0, 0) #define DSI_VID_MODE_CFG 0x0038 +#define VPG_ORIENTATION BIT(24) +#define VPG_MODE BIT(20) #define VPG_EN BIT(16) #define LP_CMD_EN BIT(15) #define FRAME_BTA_ACK_EN BIT(14) diff --git a/drivers/mmc/host/rk_sdmmc.h b/drivers/mmc/host/rk_sdmmc.h deleted file mode 100755 index cad989246002..000000000000 --- a/drivers/mmc/host/rk_sdmmc.h +++ /dev/null @@ -1,387 +0,0 @@ -/* - * Synopsys DesignWare Multimedia Card Interface driver - * (Based on NXP driver for lpc 31xx) - * - * Copyright (C) 2009 NXP Semiconductors - * Copyright (C) 2009, 2010 Imagination Technologies Ltd. - * - * Copyright (C) 2014 Fuzhou Rockchip Electronics Co.Ltd. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - */ - -#ifndef _DW_MMC_H_ -#define _DW_MMC_H_ -#include "rk_sdmmc_dbg.h" - -#define DW_MMC_240A 0x240a -#define DW_MMC_270A 0x270a - -#define SDMMC_CTRL 0x000 -#define SDMMC_PWREN 0x004 -#define SDMMC_CLKDIV 0x008 -#define SDMMC_CLKSRC 0x00c -#define SDMMC_CLKENA 0x010 -#define SDMMC_TMOUT 0x014 -#define SDMMC_CTYPE 0x018 -#define SDMMC_BLKSIZ 0x01c -#define SDMMC_BYTCNT 0x020 -#define SDMMC_INTMASK 0x024 -#define SDMMC_CMDARG 0x028 -#define SDMMC_CMD 0x02c -#define SDMMC_RESP0 0x030 -#define SDMMC_RESP1 0x034 -#define SDMMC_RESP2 0x038 -#define SDMMC_RESP3 0x03c -#define SDMMC_MINTSTS 0x040 -#define SDMMC_RINTSTS 0x044 -#define SDMMC_STATUS 0x048 -#define SDMMC_FIFOTH 0x04c -#define SDMMC_CDETECT 0x050 -#define SDMMC_WRTPRT 0x054 -#define SDMMC_GPIO 0x058 -#define SDMMC_TCBCNT 0x05c -#define SDMMC_TBBCNT 0x060 -#define SDMMC_DEBNCE 0x064 -#define SDMMC_USRID 0x068 -#define SDMMC_VERID 0x06c -#define SDMMC_HCON 0x070 -#define SDMMC_UHS_REG 0x074 -#define SDMMC_RST_N 0x078 -#define SDMMC_BMOD 0x080 -#define SDMMC_PLDMND 0x084 -#define SDMMC_DBADDR 0x088 -#define SDMMC_IDSTS 0x08c -#define SDMMC_IDINTEN 0x090 -#define SDMMC_DSCADDR 0x094 -#define SDMMC_BUFADDR 0x098 -#define SDMMC_CDTHRCTL 0x100 -#define SDMMC_DATA(x) (x) - - -static const u8 tuning_blk_pattern_4bit[] = { - 0xff, 0x0f, 0xff, 0x00, 0xff, 0xcc, 0xc3, 0xcc, - 0xc3, 0x3c, 0xcc, 0xff, 0xfe, 0xff, 0xfe, 0xef, - 0xff, 0xdf, 0xff, 0xdd, 0xff, 0xfb, 0xff, 0xfb, - 0xbf, 0xff, 0x7f, 0xff, 0x77, 0xf7, 0xbd, 0xef, - 0xff, 0xf0, 0xff, 0xf0, 0x0f, 0xfc, 0xcc, 0x3c, - 0xcc, 0x33, 0xcc, 0xcf, 0xff, 0xef, 0xff, 0xee, - 0xff, 0xfd, 0xff, 0xfd, 0xdf, 0xff, 0xbf, 0xff, - 0xbb, 0xff, 0xf7, 0xff, 0xf7, 0x7f, 0x7b, 0xde, -}; - -static const u8 tuning_blk_pattern_8bit[] = { - 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, - 0xff, 0xff, 0xcc, 0xcc, 0xcc, 0x33, 0xcc, 0xcc, - 0xcc, 0x33, 0x33, 0xcc, 0xcc, 0xcc, 0xff, 0xff, - 0xff, 0xee, 0xff, 0xff, 0xff, 0xee, 0xee, 0xff, - 0xff, 0xff, 0xdd, 0xff, 0xff, 0xff, 0xdd, 0xdd, - 0xff, 0xff, 0xff, 0xbb, 0xff, 0xff, 0xff, 0xbb, - 0xbb, 0xff, 0xff, 0xff, 0x77, 0xff, 0xff, 0xff, - 0x77, 0x77, 0xff, 0x77, 0xbb, 0xdd, 0xee, 0xff, - 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, - 0x00, 0xff, 0xff, 0xcc, 0xcc, 0xcc, 0x33, 0xcc, - 0xcc, 0xcc, 0x33, 0x33, 0xcc, 0xcc, 0xcc, 0xff, - 0xff, 0xff, 0xee, 0xff, 0xff, 0xff, 0xee, 0xee, - 0xff, 0xff, 0xff, 0xdd, 0xff, 0xff, 0xff, 0xdd, - 0xdd, 0xff, 0xff, 0xff, 0xbb, 0xff, 0xff, 0xff, - 0xbb, 0xbb, 0xff, 0xff, 0xff, 0x77, 0xff, 0xff, - 0xff, 0x77, 0x77, 0xff, 0x77, 0xbb, 0xdd, 0xee, -}; - -/* - * Data offset is difference according to Version - * Lower than 2.40a : data register offest is 0x100 - */ -#define DATA_OFFSET 0x100 -#define DATA_240A_OFFSET 0x200 - -/* shift bit field */ -#define _SBF(f, v) ((v) << (f)) - - -struct sdmmc_reg { -u32 addr; -char *name; -}; - -static const struct sdmmc_reg dw_mci_regs[] = { -{ 0x0000, "CTRL" }, -{ 0x0004, "PWREN" }, -{ 0x0008, "CLKDIV" }, -{ 0x000C, "CLKSRC" }, -{ 0x0010, "CLKENA" }, -{ 0x0014, "TMOUT" }, -{ 0x0018, "CTYPE" }, -{ 0x001C, "BLKSIZ" }, -{ 0x0020, "BYTCNT" }, -{ 0x0024, "INTMASK" }, -{ 0x0028, "CMDARG" }, -{ 0x002C, "CMD" }, -{ 0x0030, "RESP0" }, -{ 0x0034, "RESP1" }, -{ 0x0038, "RESP2" }, -{ 0x003C, "RESP3" }, -{ 0x0040, "MINSTS" }, -{ 0x0044, "RINTSTS" }, -{ 0x0048, "STATUS" }, -{ 0x004C, "FIFOTH" }, -{ 0x0050, "CDETECT" }, -{ 0x0054, "WRTPRT" }, -{ 0x0058, "GPIO" }, -{ 0x005C, "TCBCNT" }, -{ 0x0060, "TBBCNT" }, -{ 0x0064, "DEBNCE" }, -{ 0x0068, "USRID" }, -{ 0x006C, "VERID" }, -{ 0x0070, "HCON" }, -{ 0x0074, "UHS_REG" }, -{ 0x0078, "RST_n" }, -{ 0x0080, "BMOD" }, -{ 0x0084, "PLDMND" }, -{ 0x0088, "DBADDR" }, -{ 0x008C, "IDSTS" }, -{ 0x0090, "IDINTEN" }, -{ 0x0094, "DSCADDR" }, -{ 0x0098, "BUFADDR" }, -{ 0x0100, "CARDTHRCTL" }, -{ 0x0104, "BackEndPwr" }, -{ 0, 0 } -}; - - -/* Control register defines */ -#define SDMMC_CTRL_USE_IDMAC BIT(25) -#define SDMMC_CTRL_CEATA_INT_EN BIT(11) -#define SDMMC_CTRL_SEND_AS_CCSD BIT(10) -#define SDMMC_CTRL_SEND_CCSD BIT(9) -#define SDMMC_CTRL_ABRT_READ_DATA BIT(8) -#define SDMMC_CTRL_SEND_IRQ_RESP BIT(7) -#define SDMMC_CTRL_READ_WAIT BIT(6) -#define SDMMC_CTRL_DMA_ENABLE BIT(5) -#define SDMMC_CTRL_INT_ENABLE BIT(4) -#define SDMMC_CTRL_DMA_RESET BIT(2) -#define SDMMC_CTRL_FIFO_RESET BIT(1) -#define SDMMC_CTRL_RESET BIT(0) -/* Clock Enable register defines */ -#define SDMMC_CLKEN_LOW_PWR BIT(16) -#define SDMMC_CLKEN_ENABLE BIT(0) -/* time-out register defines */ -#define SDMMC_TMOUT_DATA(n) _SBF(8, (n)) -#define SDMMC_TMOUT_DATA_MSK 0xFFFFFF00 -#define SDMMC_TMOUT_RESP(n) ((n) & 0xFF) -#define SDMMC_TMOUT_RESP_MSK 0xFF -/* card-type register defines */ -#define SDMMC_CTYPE_8BIT BIT(16) -#define SDMMC_CTYPE_4BIT BIT(0) -#define SDMMC_CTYPE_1BIT 0 -/* Interrupt status & mask register defines */ -#define SDMMC_INT_SDIO(n) BIT(16 + (n)) -#define SDMMC_INT_EBE BIT(15) -#define SDMMC_INT_ACD BIT(14) -#define SDMMC_INT_SBE BIT(13) -#define SDMMC_INT_HLE BIT(12) -#define SDMMC_INT_FRUN BIT(11) -#define SDMMC_INT_HTO BIT(10) -#define SDMMC_INT_VSI SDMMC_INT_HTO -#define SDMMC_INT_DRTO BIT(9) -#define SDMMC_INT_RTO BIT(8) -#define SDMMC_INT_DCRC BIT(7) -#define SDMMC_INT_RCRC BIT(6) -#define SDMMC_INT_RXDR BIT(5) -#define SDMMC_INT_TXDR BIT(4) -#define SDMMC_INT_DATA_OVER BIT(3) -#define SDMMC_INT_CMD_DONE BIT(2) -#define SDMMC_INT_RESP_ERR BIT(1) -#define SDMMC_INT_CD BIT(0) -#define SDMMC_INT_ERROR 0xbfc2 -/* Command register defines */ -#define SDMMC_CMD_START BIT(31) -#define SDMMC_CMD_USE_HOLD_REG BIT(29) -#define SDMMC_CMD_VOLT_SWITCH BIT(28) -#define SDMMC_CMD_BOOT_MODE BIT(27) -#define SDMMC_CMD_DISABLE_BOOT BIT(26) -#define SDMMC_CMD_EXPECT_BOOT_ACK BIT(25) -#define SDMMC_CMD_ENABLE_BOOT BIT(24) -#define SDMMC_CMD_CCS_EXP BIT(23) -#define SDMMC_CMD_CEATA_RD BIT(22) -#define SDMMC_CMD_UPD_CLK BIT(21) -#define SDMMC_CMD_INIT BIT(15) -#define SDMMC_CMD_STOP BIT(14) -#define SDMMC_CMD_PRV_DAT_WAIT BIT(13) -#define SDMMC_CMD_SEND_STOP BIT(12) -#define SDMMC_CMD_STRM_MODE BIT(11) -#define SDMMC_CMD_DAT_WR BIT(10) -#define SDMMC_CMD_DAT_EXP BIT(9) -#define SDMMC_CMD_RESP_CRC BIT(8) -#define SDMMC_CMD_RESP_LONG BIT(7) -#define SDMMC_CMD_RESP_EXP BIT(6) -#define SDMMC_CMD_INDX(n) ((n) & 0x1F) -/* Status register defines */ -#define SDMMC_GET_FCNT(x) (((x)>>17) & 0x1FFF) -#define SDMMC_STAUTS_MC_BUSY BIT(10) -#define SDMMC_STAUTS_DATA_BUSY BIT(9) -#define SDMMC_CMD_FSM_MASK (0x0F << 4) -#define SDMMC_CMD_FSM_IDLE (0x00) -#define SDMMC_STAUTS_FIFO_FULL BIT(3) -#define SDMMC_STAUTS_FIFO_EMPTY BIT(2) - -/* Control SDMMC_UHS_REG defines (base+ 0x74)*/ -#define SDMMC_UHS_DDR_MODE BIT(16) -#define SDMMC_UHS_VOLT_REG_18 BIT(0) - -/* FIFOTH register defines */ -#define SDMMC_SET_FIFOTH(m, r, t) (((m) & 0x7) << 28 | \ - ((r) & 0xFFF) << 16 | \ - ((t) & 0xFFF)) -/* Internal DMAC interrupt defines */ -#define SDMMC_IDMAC_INT_AI BIT(9) -#define SDMMC_IDMAC_INT_NI BIT(8) -#define SDMMC_IDMAC_INT_CES BIT(5) -#define SDMMC_IDMAC_INT_DU BIT(4) -#define SDMMC_IDMAC_INT_FBE BIT(2) -#define SDMMC_IDMAC_INT_RI BIT(1) -#define SDMMC_IDMAC_INT_TI BIT(0) -/* Internal DMAC bus mode bits */ -#define SDMMC_IDMAC_ENABLE BIT(7) -#define SDMMC_IDMAC_FB BIT(1) -#define SDMMC_IDMAC_SWRESET BIT(0) -/* Version ID register define */ -#define SDMMC_GET_VERID(x) ((x) & 0xFFFF) -/* Card read threshold */ -#define SDMMC_SET_RD_THLD(v, x) (((v) & 0xFFF) << 16 | (x)) - -/* Register access macros */ -#define mci_readl(dev, reg) \ - __raw_readl((dev)->regs + SDMMC_##reg) -#define mci_writel(dev, reg, value) \ - __raw_writel((value), (dev)->regs + SDMMC_##reg) -#define mci_readreg(dev, addr) \ - __raw_readl((dev)->regs + addr) -#define mci_writereg(dev, addr, value) \ - __raw_writel((value), (dev)->regs + addr) - - -/* 16-bit FIFO access macros */ -#define mci_readw(dev, reg) \ - __raw_readw((dev)->regs + SDMMC_##reg) -#define mci_writew(dev, reg, value) \ - __raw_writew((value), (dev)->regs + SDMMC_##reg) - -/* 64-bit FIFO access macros */ -#ifdef readq -#define mci_readq(dev, reg) \ - __raw_readq((dev)->regs + SDMMC_##reg) -#define mci_writeq(dev, reg, value) \ - __raw_writeq((value), (dev)->regs + SDMMC_##reg) -#else -/* - * Dummy readq implementation for architectures that don't define it. - * - * We would assume that none of these architectures would configure - * the IP block with a 64bit FIFO width, so this code will never be - * executed on those machines. Defining these macros here keeps the - * rest of the code free from ifdefs. - */ -#define mci_readq(dev, reg) \ - (*(u64 __force *)((dev)->regs + SDMMC_##reg)) -#define mci_writeq(dev, reg, value) \ - (*(u64 __force *)((dev)->regs + SDMMC_##reg) = (value)) -#endif -#ifdef CONFIG_PM -extern int dw_mci_suspend(struct dw_mci *host); -extern int dw_mci_resume(struct dw_mci *host); -#endif -static const struct dw_mci_rst_ops dw_mci_pdrst_ops; - -/** - * struct dw_mci_slot - MMC slot state - * @mmc: The mmc_host representing this slot. - * @host: The MMC controller this slot is using. - * @quirks: Slot-level quirks (DW_MCI_SLOT_QUIRK_XXX) - * @wp_gpio: If gpio_is_valid() we'll use this to read write protect. - * @ctype: Card type for this slot. - * @mrq: mmc_request currently being processed or waiting to be - * processed, or NULL when the slot is idle. - * @queue_node: List node for placing this node in the @queue list of - * &struct dw_mci. - * @clock: Clock rate configured by set_ios(). Protected by host->lock. - * @__clk_old: The last updated clock with reflecting clock divider. - * Keeping track of this helps us to avoid spamming the console - * with CONFIG_MMC_CLKGATE. - * @flags: Random state bits associated with the slot. - * @id: Number of this slot. - * @last_detect_state: Most recently observed card detect state. - */ -struct dw_mci_slot { -struct mmc_host *mmc; -struct dw_mci *host; -int quirks; -int wp_gpio; -int cd_gpio; -int pwr_en_gpio; -u32 ctype; -u32 pre_ctype; - -struct mmc_request *mrq; -struct list_head queue_node; - -unsigned int clock; -unsigned int __clk_old; - -unsigned long flags; -#define DW_MMC_CARD_PRESENT 0 -#define DW_MMC_CARD_NEED_INIT 1 -int id; -int last_detect_state; -}; - -struct dw_mci_tuning_data { - const u8 *blk_pattern; - unsigned int blksz; -}; - -/** - * dw_mci driver data - dw-mshc implementation specific driver data. - * @caps: mmc subsystem specified capabilities of the controller(s). - * @hold_reg_flag: Fixed the value of HOLG_REG - * @init: early implementation specific initialization. - * @setup_clock: implementation specific clock configuration. - * @prepare_command: handle CMD register extensions. - * @set_ios: handle bus specific extensions. - * @parse_dt: parse implementation specific device tree properties. - * - * Provide controller implementation specific extensions. The usage of this - * data structure is fully optional and usage of each member in this structure - * is optional as well. - */ - -struct dw_mci_drv_data { - unsigned long *caps; - unsigned int *hold_reg_flag; - - int (*init)(struct dw_mci *host); - int (*setup_clock)(struct dw_mci *host); - void (*prepare_command)(struct dw_mci *host, u32 *cmdr); - void (*set_ios)(struct dw_mci *host, struct mmc_ios *ios); - int (*parse_dt)(struct dw_mci *host); - int (*execute_tuning)(struct dw_mci_slot *slot, - u32 opcode, - struct dw_mci_tuning_data - *tuning_data); -}; - -/* Variations in Rockchip specific dw-mshc controller */ -enum dw_mci_rockchip_type { -DW_MCI_TYPE_RK3188, -DW_MCI_TYPE_RK3288, -DW_MCI_TYPE_RK3036, -DW_MCI_TYPE_RK312X, -DW_MCI_TYPE_RK3368, -DW_MCI_TYPE_RK3228, -}; - -#endif /* _DW_MMC_H_ */ diff --git a/drivers/mmc/host/rk_sdmmc_ops.h b/drivers/mmc/host/rk_sdmmc_ops.h index 81890ab6a94e..4f68c1a35951 100644 --- a/drivers/mmc/host/rk_sdmmc_ops.h +++ b/drivers/mmc/host/rk_sdmmc_ops.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (C) 2021 Rockchip Inc. + * Copyright (C) 2021 Rockchip Electronics Co., Ltd. */ #ifndef _RK_SDMMC_OPS_H_ diff --git a/drivers/mtd/spi-nor/boya.c b/drivers/mtd/spi-nor/boya.c index 669791e53a04..e94ef4e16bab 100644 --- a/drivers/mtd/spi-nor/boya.c +++ b/drivers/mtd/spi-nor/boya.c @@ -11,6 +11,8 @@ static const struct flash_info boya_parts[] = { { "BY25Q256FSEIG", INFO(0x684919, 0, 64 * 1024, 512) NO_SFDP_FLAGS(SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) FIXUP_FLAGS(SPI_NOR_4B_OPCODES) }, + { "BY25Q64ESSIG", INFO(0x684017, 0, 64 * 1024, 128) + NO_SFDP_FLAGS(SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, }; const struct spi_nor_manufacturer spi_nor_boya = { diff --git a/drivers/mtd/spi-nor/esmt.c b/drivers/mtd/spi-nor/esmt.c index b91b4ba801e3..5d92b77756f2 100644 --- a/drivers/mtd/spi-nor/esmt.c +++ b/drivers/mtd/spi-nor/esmt.c @@ -32,6 +32,9 @@ static const struct flash_info esmt_nor_parts[] = { { "en25qx128a", INFO(0x1c7118, 0, 64 * 1024, 256) NO_SFDP_FLAGS(SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, + { "en25qx64a", INFO(0x1c7117, 0, 64 * 1024, 128) + NO_SFDP_FLAGS(SECT_4K | SPI_NOR_DUAL_READ | + SPI_NOR_QUAD_READ) }, }; const struct spi_nor_manufacturer spi_nor_esmt = { diff --git a/drivers/mtd/spi-nor/puya.c b/drivers/mtd/spi-nor/puya.c index b875702385cd..f1b913c136c8 100644 --- a/drivers/mtd/spi-nor/puya.c +++ b/drivers/mtd/spi-nor/puya.c @@ -26,6 +26,9 @@ static const struct flash_info puya_parts[] = { { "PY25Q128LA", INFO(0x856518, 0, 64 * 1024, 256) NO_SFDP_FLAGS(SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, + { "PY25Q256LC", INFO(0x856519, 0, 64 * 1024, 512) + NO_SFDP_FLAGS(SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) + FIXUP_FLAGS(SPI_NOR_4B_OPCODES) }, }; const struct spi_nor_manufacturer spi_nor_puya = { diff --git a/drivers/nvmem/rockchip-otp.c b/drivers/nvmem/rockchip-otp.c index d5c5d6658f8b..981b78418453 100644 --- a/drivers/nvmem/rockchip-otp.c +++ b/drivers/nvmem/rockchip-otp.c @@ -783,21 +783,17 @@ static const struct rockchip_data rk3528_data = { .reg_read = rk3568_otp_read, }; -static const char * const rk3562_otp_clocks[] = { +static const char * const rk3568_otp_clocks[] = { "usr", "sbpi", "apb", "phy", }; static const struct rockchip_data rk3562_data = { .size = 0x80, - .clocks = rk3562_otp_clocks, - .num_clks = ARRAY_SIZE(rk3562_otp_clocks), + .clocks = rk3568_otp_clocks, + .num_clks = ARRAY_SIZE(rk3568_otp_clocks), .reg_read = rk3568_otp_read, }; -static const char * const rk3568_otp_clocks[] = { - "usr", "sbpi", "apb", "phy", -}; - static const struct rockchip_data rk3568_data = { .size = 0x80, .clocks = rk3568_otp_clocks, @@ -829,14 +825,10 @@ static const struct rockchip_data rk3588_data = { .reg_read = rk3588_otp_read, }; -static const char * const rv1106_otp_clocks[] = { - "usr", "sbpi", "apb", "phy", -}; - static const struct rockchip_data rv1106_data = { .size = 0x80, - .clocks = rv1106_otp_clocks, - .num_clks = ARRAY_SIZE(rv1106_otp_clocks), + .clocks = rk3568_otp_clocks, + .num_clks = ARRAY_SIZE(rk3568_otp_clocks), .reg_read = rk3568_otp_read, }; diff --git a/drivers/phy/rockchip/phy-rockchip-snps-pcie3.c b/drivers/phy/rockchip/phy-rockchip-snps-pcie3.c index a10e23b68115..5841a41a6703 100644 --- a/drivers/phy/rockchip/phy-rockchip-snps-pcie3.c +++ b/drivers/phy/rockchip/phy-rockchip-snps-pcie3.c @@ -276,17 +276,15 @@ static int rockchip_p3phy_probe(struct platform_device *pdev) dev_info(dev, "failed to find rockchip,pipe_grf regmap\n"); ret = device_property_read_u32(dev, "rockchip,pcie30-phymode", &val); - if (!ret) + if (!ret) { priv->pcie30_phymode = val; - else + if (priv->pcie30_phymode > 4) + priv->pcie30_phymode = PHY_MODE_PCIE_AGGREGATION; + regmap_write(priv->phy_grf, RK3588_PCIE3PHY_GRF_CMN_CON0, + (0x7<<16) | priv->pcie30_phymode); + } else { priv->pcie30_phymode = PHY_MODE_PCIE_AGGREGATION; - - /* Select correct pcie30_phymode */ - if (priv->pcie30_phymode > 4) - priv->pcie30_phymode = PHY_MODE_PCIE_AGGREGATION; - - regmap_write(priv->phy_grf, RK3588_PCIE3PHY_GRF_CMN_CON0, - (0x7<<16) | priv->pcie30_phymode); + } /* Set pcie1ln_sel in PHP_GRF_PCIESEL_CON */ if (!IS_ERR(priv->pipe_grf)) { diff --git a/drivers/soc/rockchip/rockchip_opp_select.c b/drivers/soc/rockchip/rockchip_opp_select.c index 549c8b6c5b4f..e7f0644600b4 100644 --- a/drivers/soc/rockchip/rockchip_opp_select.c +++ b/drivers/soc/rockchip/rockchip_opp_select.c @@ -1390,7 +1390,7 @@ static void rockchip_init_pvtpll_table(struct device *dev, res = sip_smc_get_pvtpll_info(PVTPLL_GET_INFO, info->pvtpll_clk_id); if (res.a0) { - info->pvtpll_clk_id = UINT_MAX; + info->pvtpll_smc = false; goto out; } if (!res.a1) @@ -1698,6 +1698,7 @@ int rockchip_init_opp_info(struct device *dev, struct rockchip_opp_info *info, info->process = -EINVAL; info->volt_sel = -EINVAL; info->pvtpll_clk_id = UINT_MAX; + info->pvtpll_smc = true; info->is_runtime_active = true; mutex_init(&info->dvfs_mutex); @@ -2070,6 +2071,10 @@ static int rockchip_pvtpll_set_volt_sel(struct device *dev, if (info->pvtpll_clk_id == UINT_MAX) return 0; + if (!info->pvtpll_smc) + return rockchip_pvtpll_volt_sel_adjust(info->pvtpll_clk_id, + info->volt_sel); + res = sip_smc_pvtpll_config(PVTPLL_VOLT_SEL, info->pvtpll_clk_id, (u32)info->volt_sel, 0, 0, 0, 0); if (res.a0) diff --git a/drivers/video/rockchip/rga3/include/rga_job.h b/drivers/video/rockchip/rga3/include/rga_job.h index bdd9ab9ed74a..28bf35bacc55 100644 --- a/drivers/video/rockchip/rga3/include/rga_job.h +++ b/drivers/video/rockchip/rga3/include/rga_job.h @@ -27,7 +27,7 @@ enum job_flags { void rga_job_scheduler_dump_info(struct rga_scheduler_t *scheduler); void rga_job_next(struct rga_scheduler_t *scheduler); struct rga_job *rga_job_done(struct rga_scheduler_t *scheduler); -struct rga_job *rga_job_commit(struct rga_req *rga_command_base, struct rga_request *request); +int rga_job_commit(struct rga_req *rga_command_base, struct rga_request *request); int rga_job_mpi_commit(struct rga_req *rga_command_base, struct rga_request *request); int rga_job_assign(struct rga_job *job); diff --git a/drivers/video/rockchip/rga3/rga_job.c b/drivers/video/rockchip/rga3/rga_job.c index 2acbb9d9596d..fd254b587fde 100644 --- a/drivers/video/rockchip/rga3/rga_job.c +++ b/drivers/video/rockchip/rga3/rga_job.c @@ -403,7 +403,7 @@ static struct rga_scheduler_t *rga_job_schedule(struct rga_job *job) return scheduler; } -struct rga_job *rga_job_commit(struct rga_req *rga_command_base, struct rga_request *request) +int rga_job_commit(struct rga_req *rga_command_base, struct rga_request *request) { int ret; struct rga_job *job = NULL; @@ -412,7 +412,7 @@ struct rga_job *rga_job_commit(struct rga_req *rga_command_base, struct rga_requ job = rga_job_alloc(rga_command_base); if (!job) { rga_err("failed to alloc rga job!\n"); - return ERR_PTR(-ENOMEM); + return -ENOMEM; } job->use_batch_mode = request->use_batch_mode; @@ -458,7 +458,7 @@ struct rga_job *rga_job_commit(struct rga_req *rga_command_base, struct rga_requ rga_power_disable(scheduler); - return job; + return 0; err_unmap_job_info: rga_mm_unmap_job_info(job); @@ -472,9 +472,9 @@ err_free_cmd_buf: err_free_job: ret = job->ret; - rga_request_release_signal(scheduler, job); + rga_job_free(job); - return ERR_PTR(ret); + return ret; } static bool rga_is_need_current_mm(struct rga_req *req) @@ -908,20 +908,15 @@ static int rga_request_wait(struct rga_request *request) switch (left_time) { case 0: ret = rga_request_timeout_query_state(request); - goto err_request_abort; + break; case -ERESTARTSYS: ret = -ERESTARTSYS; - goto err_request_abort; + break; default: ret = request->ret; break; } - return ret; - -err_request_abort: - rga_request_release_abort(request, ret); - return ret; } @@ -929,7 +924,6 @@ int rga_request_commit(struct rga_request *request) { int ret; int i = 0; - struct rga_job *job; if (DEBUGGER_EN(MSG)) rga_req_log(request, "commit process: %s\n", request->session->pname); @@ -942,12 +936,11 @@ int rga_request_commit(struct rga_request *request) rga_dump_req(request, req); } - job = rga_job_commit(req, request); - if (IS_ERR(job)) { + ret = rga_job_commit(req, request); + if (ret < 0) { rga_req_err(request, "task[%d] job_commit failed.\n", i); - rga_request_release_abort(request, PTR_ERR(job)); - return PTR_ERR(job); + return ret; } } @@ -1220,9 +1213,6 @@ int rga_request_submit(struct rga_request *request) int ret = 0; unsigned long flags; struct dma_fence *release_fence; - struct mm_struct *current_mm; - - current_mm = rga_request_get_current_mm(request); spin_lock_irqsave(&request->lock, flags); @@ -1231,7 +1221,7 @@ int rga_request_submit(struct rga_request *request) rga_req_err(request, "can not re-config when request is running\n"); ret = -EFAULT; - goto err_put_current_mm; + goto err_abort_request; } if (request->task_list == NULL) { @@ -1239,7 +1229,7 @@ int rga_request_submit(struct rga_request *request) rga_req_err(request, "can not find task list\n"); ret = -EINVAL; - goto err_put_current_mm; + goto err_abort_request; } /* Reset */ @@ -1248,7 +1238,6 @@ int rga_request_submit(struct rga_request *request) request->finished_task_count = 0; request->failed_task_count = 0; request->ret = 0; - request->current_mm = current_mm; /* Unlock after ensuring that the current request will not be resubmitted. */ spin_unlock_irqrestore(&request->lock, flags); @@ -1258,8 +1247,10 @@ int rga_request_submit(struct rga_request *request) if (IS_ERR_OR_NULL(release_fence)) { rga_req_err(request, "Can not alloc release fence!\n"); ret = IS_ERR(release_fence) ? PTR_ERR(release_fence) : -EINVAL; - goto err_reset_request; + goto err_abort_request; } + + request->current_mm = rga_request_get_current_mm(request); request->release_fence = release_fence; if (request->acquire_fence_fd > 0) { @@ -1276,16 +1267,22 @@ int rga_request_submit(struct rga_request *request) } else { rga_req_err(request, "Failed to add callback with acquire fence fd[%d]!\n", request->acquire_fence_fd); - goto err_put_release_fence; + + rga_dma_fence_put(request->release_fence); + request->release_fence = NULL; + goto err_put_current_mm; } } + } else { + request->current_mm = rga_request_get_current_mm(request); + request->release_fence = NULL; } request_commit: ret = rga_request_commit(request); if (ret < 0) { rga_req_err(request, "request commit failed!\n"); - goto err_put_release_fence; + goto err_put_current_mm; } export_release_fence_fd: @@ -1293,8 +1290,7 @@ export_release_fence_fd: ret = rga_dma_fence_get_fd(request->release_fence); if (ret < 0) { rga_req_err(request, "Failed to alloc release fence fd!\n"); - rga_request_release_abort(request, ret); - return ret; + goto err_put_current_mm; } request->release_fence_fd = ret; @@ -1302,22 +1298,12 @@ export_release_fence_fd: return 0; -err_put_release_fence: - if (request->release_fence != NULL) { - rga_dma_fence_put(request->release_fence); - request->release_fence = NULL; - } - -err_reset_request: - spin_lock_irqsave(&request->lock, flags); - - request->current_mm = NULL; - request->is_running = false; - - spin_unlock_irqrestore(&request->lock, flags); - err_put_current_mm: - rga_request_put_current_mm(current_mm); + rga_request_put_current_mm(request->current_mm); + request->current_mm = NULL; + +err_abort_request: + rga_request_release_abort(request, ret); return ret; } @@ -1325,7 +1311,6 @@ err_put_current_mm: int rga_request_mpi_submit(struct rga_req *req, struct rga_request *request) { int ret = 0; - struct rga_job *job = NULL; unsigned long flags; struct rga_pending_request_manager *request_manager; @@ -1333,7 +1318,8 @@ int rga_request_mpi_submit(struct rga_req *req, struct rga_request *request) if (request->sync_mode == RGA_BLIT_ASYNC) { rga_req_err(request, "mpi unsupported async mode!\n"); - return -EINVAL; + ret = -EINVAL; + goto err_abort_request; } spin_lock_irqsave(&request->lock, flags); @@ -1341,13 +1327,15 @@ int rga_request_mpi_submit(struct rga_req *req, struct rga_request *request) if (request->is_running) { rga_req_err(request, "can not re-config when request is running"); spin_unlock_irqrestore(&request->lock, flags); - return -EFAULT; + ret = -EFAULT; + goto err_abort_request; } if (request->task_list == NULL) { rga_req_err(request, "can not find task list"); spin_unlock_irqrestore(&request->lock, flags); - return -EINVAL; + ret = -EINVAL; + goto err_abort_request; } /* Reset */ @@ -1367,17 +1355,22 @@ int rga_request_mpi_submit(struct rga_req *req, struct rga_request *request) rga_request_get(request); mutex_unlock(&request_manager->lock); - job = rga_job_commit(req, request); - if (IS_ERR_OR_NULL(job)) { + ret = rga_job_commit(req, request); + if (ret < 0) { rga_req_err(request, "failed to commit job!\n"); - return job ? PTR_ERR(job) : -EFAULT; + goto err_abort_request; } ret = rga_request_wait(request); if (ret < 0) - return ret; + goto err_abort_request; return 0; + +err_abort_request: + rga_request_release_abort(request, ret); + + return ret; } int rga_request_free(struct rga_request *request) diff --git a/include/soc/rockchip/rockchip_opp_select.h b/include/soc/rockchip/rockchip_opp_select.h index f448b3814508..e11c4cccd4bb 100644 --- a/include/soc/rockchip/rockchip_opp_select.h +++ b/include/soc/rockchip/rockchip_opp_select.h @@ -97,6 +97,7 @@ struct pvtpll_opp_table { * @init_freq: Set the initial frequency when init opp table. * @is_rate_volt_checked: Marks if device has checked initial rate and voltage. * @pvtpll_clk_id: Device's clock id. + * @pvtpll_smc: Marks if smc call of pvtpll is available. * @pvtpll_low_temp: Marks if device has low temperature pvtpll config. */ struct rockchip_opp_info { @@ -138,6 +139,7 @@ struct rockchip_opp_info { bool is_rate_volt_checked; u32 pvtpll_clk_id; + bool pvtpll_smc; bool pvtpll_low_temp; }; diff --git a/sound/soc/codecs/dummy-codec.c b/sound/soc/codecs/dummy-codec.c index 2cb3ae65d4f7..57b9e9937399 100644 --- a/sound/soc/codecs/dummy-codec.c +++ b/sound/soc/codecs/dummy-codec.c @@ -50,7 +50,7 @@ struct snd_soc_dai_driver dummy_dai = { .stream_name = "Dummy Playback", .channels_min = 1, .channels_max = 384, - .rates = SNDRV_PCM_RATE_8000_384000, + .rates = SNDRV_PCM_RATE_CONTINUOUS, .formats = (SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | @@ -61,7 +61,7 @@ struct snd_soc_dai_driver dummy_dai = { .stream_name = "Dummy Capture", .channels_min = 1, .channels_max = 384, - .rates = SNDRV_PCM_RATE_8000_384000, + .rates = SNDRV_PCM_RATE_CONTINUOUS, .formats = (SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | diff --git a/sound/soc/rockchip/rockchip_i2s.c b/sound/soc/rockchip/rockchip_i2s.c index 452f713ea7ad..c7ec42d74880 100644 --- a/sound/soc/rockchip/rockchip_i2s.c +++ b/sound/soc/rockchip/rockchip_i2s.c @@ -1054,7 +1054,7 @@ static int rockchip_i2s_init_dai(struct rk_i2s_dev *i2s, struct resource *res, dai->playback.stream_name = "Playback"; dai->playback.channels_min = 2; dai->playback.channels_max = 8; - dai->playback.rates = SNDRV_PCM_RATE_8000_192000; + dai->playback.rates = SNDRV_PCM_RATE_CONTINUOUS; dai->playback.formats = SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | @@ -1076,7 +1076,7 @@ static int rockchip_i2s_init_dai(struct rk_i2s_dev *i2s, struct resource *res, dai->capture.stream_name = "Capture"; dai->capture.channels_min = 2; dai->capture.channels_max = 8; - dai->capture.rates = SNDRV_PCM_RATE_8000_192000; + dai->capture.rates = SNDRV_PCM_RATE_CONTINUOUS; dai->capture.formats = SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | diff --git a/sound/soc/rockchip/rockchip_i2s_tdm.c b/sound/soc/rockchip/rockchip_i2s_tdm.c index 43aaab16c239..260195072ba3 100644 --- a/sound/soc/rockchip/rockchip_i2s_tdm.c +++ b/sound/soc/rockchip/rockchip_i2s_tdm.c @@ -2807,7 +2807,7 @@ static int rockchip_i2s_tdm_init_dai(struct rk_i2s_tdm_dev *i2s_tdm) dai->playback.stream_name = "Playback"; dai->playback.channels_min = 2; dai->playback.channels_max = 64; - dai->playback.rates = SNDRV_PCM_RATE_8000_192000; + dai->playback.rates = SNDRV_PCM_RATE_CONTINUOUS; dai->playback.formats = formats; } @@ -2815,7 +2815,7 @@ static int rockchip_i2s_tdm_init_dai(struct rk_i2s_tdm_dev *i2s_tdm) dai->capture.stream_name = "Capture"; dai->capture.channels_min = 2; dai->capture.channels_max = 64; - dai->capture.rates = SNDRV_PCM_RATE_8000_192000; + dai->capture.rates = SNDRV_PCM_RATE_CONTINUOUS; dai->capture.formats = formats; } diff --git a/sound/soc/rockchip/rockchip_sai.c b/sound/soc/rockchip/rockchip_sai.c index efa377fe23af..077a66e8c761 100644 --- a/sound/soc/rockchip/rockchip_sai.c +++ b/sound/soc/rockchip/rockchip_sai.c @@ -1226,7 +1226,7 @@ static int rockchip_sai_init_dai(struct rk_sai_dev *sai, struct resource *res, dai->playback.stream_name = "Playback"; dai->playback.channels_min = 1; dai->playback.channels_max = 512; - dai->playback.rates = SNDRV_PCM_RATE_8000_384000; + dai->playback.rates = SNDRV_PCM_RATE_CONTINUOUS; dai->playback.formats = SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE | @@ -1242,7 +1242,7 @@ static int rockchip_sai_init_dai(struct rk_sai_dev *sai, struct resource *res, dai->capture.stream_name = "Capture"; dai->capture.channels_min = 1; dai->capture.channels_max = 512; - dai->capture.rates = SNDRV_PCM_RATE_8000_384000; + dai->capture.rates = SNDRV_PCM_RATE_CONTINUOUS; dai->capture.formats = SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE |