diff --git a/arch/arm64/boot/dts/rockchip/Makefile b/arch/arm64/boot/dts/rockchip/Makefile index 69076635229d..985c3b3941b7 100644 --- a/arch/arm64/boot/dts/rockchip/Makefile +++ b/arch/arm64/boot/dts/rockchip/Makefile @@ -152,14 +152,18 @@ dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3566-rk817-tablet-rkg11.dtb dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3566-rk817-tablet-v10.dtb dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3567-evb2-lp4x-v10.dtb dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3567-evb2-lp4x-v10-dual-channel-lvds.dtb -dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3567-evb2-lp4x-v10-dual-lvds.dtb +dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3567-evb2-lp4x-v10-one-vp-two-single-channel-lvds.dtb +dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3567-evb2-lp4x-v10-single-channel-lvds.dtb +dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3567-evb2-lp4x-v10-two-vp-two-separate-single-channel-lvds.dtb dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3568-evb1-ddr4-v10.dtb dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3568-evb1-ddr4-v10-dual-camera.dtb -dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3568-evb1-ddr4-v10-dual-lvds.dtb -dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3568-evb1-ddr4-v10-dual-lvds-linux.dtb +dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3568-evb1-ddr4-v10-one-vp-two-single-channel-lvds.dtb +dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3568-evb1-ddr4-v10-one-vp-two-single-channel-lvds-linux.dtb dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3568-evb1-ddr4-v10-linux.dtb dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3568-evb1-ddr4-v10-linux-amp.dtb dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3568-evb1-ddr4-v10-linux-spi-nor.dtb +dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3568-evb1-ddr4-v10-single-channel-lvds.dtb +dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3568-evb1-ddr4-v10-two-vp-two-separate-single-channel-lvds.dtb dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3568-evb2-lp4x-v10.dtb dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3568-evb2-lp4x-v10-bt1120-to-hdmi.dtb dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3568-evb4-lp3-v10.dtb diff --git a/arch/arm64/boot/dts/rockchip/px30.dtsi b/arch/arm64/boot/dts/rockchip/px30.dtsi index 43b2a6ffd942..d2d816ab69ea 100644 --- a/arch/arm64/boot/dts/rockchip/px30.dtsi +++ b/arch/arm64/boot/dts/rockchip/px30.dtsi @@ -1048,6 +1048,7 @@ pwm0: pwm@ff200000 { compatible = "rockchip,px30-pwm", "rockchip,rk3328-pwm"; reg = <0x0 0xff200000 0x0 0x10>; + interrupts = ; clocks = <&cru SCLK_PWM0>, <&cru PCLK_PWM0>; clock-names = "pwm", "pclk"; pinctrl-names = "active"; @@ -1059,6 +1060,7 @@ pwm1: pwm@ff200010 { compatible = "rockchip,px30-pwm", "rockchip,rk3328-pwm"; reg = <0x0 0xff200010 0x0 0x10>; + interrupts = ; clocks = <&cru SCLK_PWM0>, <&cru PCLK_PWM0>; clock-names = "pwm", "pclk"; pinctrl-names = "active"; @@ -1070,6 +1072,7 @@ pwm2: pwm@ff200020 { compatible = "rockchip,px30-pwm", "rockchip,rk3328-pwm"; reg = <0x0 0xff200020 0x0 0x10>; + interrupts = ; clocks = <&cru SCLK_PWM0>, <&cru PCLK_PWM0>; clock-names = "pwm", "pclk"; pinctrl-names = "active"; @@ -1081,6 +1084,8 @@ pwm3: pwm@ff200030 { compatible = "rockchip,px30-pwm", "rockchip,rk3328-pwm"; reg = <0x0 0xff200030 0x0 0x10>; + interrupts = , + ; clocks = <&cru SCLK_PWM0>, <&cru PCLK_PWM0>; clock-names = "pwm", "pclk"; pinctrl-names = "active"; @@ -1092,6 +1097,7 @@ pwm4: pwm@ff208000 { compatible = "rockchip,px30-pwm", "rockchip,rk3328-pwm"; reg = <0x0 0xff208000 0x0 0x10>; + interrupts = ; clocks = <&cru SCLK_PWM1>, <&cru PCLK_PWM1>; clock-names = "pwm", "pclk"; pinctrl-names = "active"; @@ -1103,6 +1109,7 @@ pwm5: pwm@ff208010 { compatible = "rockchip,px30-pwm", "rockchip,rk3328-pwm"; reg = <0x0 0xff208010 0x0 0x10>; + interrupts = ; clocks = <&cru SCLK_PWM1>, <&cru PCLK_PWM1>; clock-names = "pwm", "pclk"; pinctrl-names = "active"; @@ -1114,6 +1121,7 @@ pwm6: pwm@ff208020 { compatible = "rockchip,px30-pwm", "rockchip,rk3328-pwm"; reg = <0x0 0xff208020 0x0 0x10>; + interrupts = ; clocks = <&cru SCLK_PWM1>, <&cru PCLK_PWM1>; clock-names = "pwm", "pclk"; pinctrl-names = "active"; @@ -1125,6 +1133,8 @@ pwm7: pwm@ff208030 { compatible = "rockchip,px30-pwm", "rockchip,rk3328-pwm"; reg = <0x0 0xff208030 0x0 0x10>; + interrupts = , + ; clocks = <&cru SCLK_PWM1>, <&cru PCLK_PWM1>; clock-names = "pwm", "pclk"; pinctrl-names = "active"; diff --git a/arch/arm64/boot/dts/rockchip/rk3562-evb1-lp4x-v10.dtsi b/arch/arm64/boot/dts/rockchip/rk3562-evb1-lp4x-v10.dtsi index 44f2ff713dde..7fdb0557edda 100644 --- a/arch/arm64/boot/dts/rockchip/rk3562-evb1-lp4x-v10.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3562-evb1-lp4x-v10.dtsi @@ -179,18 +179,6 @@ }; }; -&bus_soc { - rockchip,soc-bus-table = <0 0x00a000a8 0x7001>, - <1 0x00a000a8 0x7c39>, - <2 0x00a000a8 0x7c39>, - <3 0x00a000a8 0x7c39>, - <4 0x00a000a5 0xb007>, - <5 0x00a000a8 0x7034>, - <6 0x00a000a8 0x7034>, - <7 0x00a000a8 0x7034>, - <8 0x00a000a8 0x7001>; -}; - &gmac0 { /* Use rgmii-rxid mode to disable rx delay inside Soc */ phy-mode = "rgmii-rxid"; diff --git a/arch/arm64/boot/dts/rockchip/rk3562-rk817-tablet-v10.dts b/arch/arm64/boot/dts/rockchip/rk3562-rk817-tablet-v10.dts index 281b65104b53..4f9edc072df7 100644 --- a/arch/arm64/boot/dts/rockchip/rk3562-rk817-tablet-v10.dts +++ b/arch/arm64/boot/dts/rockchip/rk3562-rk817-tablet-v10.dts @@ -209,18 +209,6 @@ cpu-supply = <&vdd_cpu>; }; -&bus_soc { - rockchip,soc-bus-table = <0 0x00a000a8 0x7001>, - <1 0x00a000a8 0x7c39>, - <2 0x00a000a8 0x7c39>, - <3 0x00a000a8 0x7c39>, - <4 0x00a000a5 0xb007>, - <5 0x00a000a8 0x7034>, - <6 0x00a000a8 0x7034>, - <7 0x00a000a8 0x7034>, - <8 0x00a000a8 0x7001>; -}; - &dfi { status = "okay"; }; diff --git a/arch/arm64/boot/dts/rockchip/rk3562.dtsi b/arch/arm64/boot/dts/rockchip/rk3562.dtsi index a6d904fe01b1..212e4154d4b0 100644 --- a/arch/arm64/boot/dts/rockchip/rk3562.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3562.dtsi @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -361,20 +362,6 @@ interrupt-affinity = <&cpu0>, <&cpu1>, <&cpu2>, <&cpu3>; }; - bus_soc: bus-soc { - compatible = "rockchip,rk3562-bus"; - rockchip,busfreq-policy = "smc"; - rockchip,soc-bus-table = <0 0x00a000a8 0x7001>, - <1 0x00a000a8 0x7c39>, - <2 0x00a000a8 0x7c39>, - <3 0x00a000a8 0x7c39>, - <4 0x00a000a4 0xb007>, - <5 0x00a000a8 0x7034>, - <6 0x00a000a8 0x7034>, - <7 0x00a000a8 0x7034>, - <8 0x00a000a8 0x7001>; - }; - cpuinfo { compatible = "rockchip,cpuinfo"; nvmem-cells = <&otp_id>, <&otp_cpu_version>, <&cpu_code>; @@ -423,6 +410,23 @@ status = "disabled"; }; + csu: csu { + compatible = "rockchip,rk3562-csu"; + rockchip,clock = , + , + , + ; + rockchip,bus = <0 0x00a000a8 0x7001>, + <1 0x00a000a8 0x7c39>, + <2 0x00a000a8 0x7c39>, + <3 0x00a000a8 0x7c39>, + <4 0x00a000a4 0xb007>, + <5 0x00a000a8 0x7034>, + <6 0x00a000a8 0x7034>, + <7 0x00a000a8 0x7034>, + <8 0x00a000a8 0x7001>; + }; + display_subsystem: display-subsystem { compatible = "rockchip,display-subsystem"; ports = <&vop_out>; @@ -1896,6 +1900,8 @@ reset-names = "axi", "ahb", "dclk_vp0"; + rockchip,csu = <&csu CSU_VOP_ACLK>; + rockchip,csu-names = "aclk"; iommus = <&vop_mmu>; power-domains = <&power RK3562_PD_VO>; rockchip,grf = <&ioc_grf>; @@ -2837,6 +2843,8 @@ "pclk_mac", "aclk_mac"; resets = <&cru SRST_A_GMAC>; reset-names = "stmmaceth"; + rockchip,csu = <&csu CSU_GMAC_ACLK>, <&csu CSU_GMAC_PCLK>; + rockchip,csu-names = "aclk", "pclk"; snps,mixed-burst; snps,tso; @@ -2955,6 +2963,8 @@ "pclk_mac", "aclk_mac"; resets = <&cru SRST_A_MAC100>; reset-names = "stmmaceth"; + rockchip,csu = <&csu CSU_GMAC_ACLK>, <&csu CSU_GMAC_PCLK>; + rockchip,csu-names = "aclk", "pclk"; status = "disabled"; mdio1: mdio { diff --git a/arch/arm64/boot/dts/rockchip/rk3567-evb2-lp4x-v10-dual-channel-lvds.dts b/arch/arm64/boot/dts/rockchip/rk3567-evb2-lp4x-v10-dual-channel-lvds.dts index 04043c5d582a..e6972db42c85 100644 --- a/arch/arm64/boot/dts/rockchip/rk3567-evb2-lp4x-v10-dual-channel-lvds.dts +++ b/arch/arm64/boot/dts/rockchip/rk3567-evb2-lp4x-v10-dual-channel-lvds.dts @@ -70,68 +70,14 @@ }; }; -&backlight1 { - status = "okay"; -}; - &backlight { status = "okay"; }; -&lvds { - status = "okay"; - dual-channel; - - ports { - port@1 { - reg = <1>; - lvds0_out_panel: endpoint { - remote-endpoint = <&panel_in_lvds0>; - }; - }; - }; -}; - -&lvds1 { - status = "okay"; - - ports { - port@1 { - reg = <1>; - lvds1_out_panel: endpoint { - remote-endpoint = <&panel_in_lvds1>; - }; - }; - }; -}; - -&lvds_in_vp1 { +&backlight1 { status = "okay"; }; -&lvds1_in_vp1 { - status = "disabled"; -}; - -&lvds1_in_vp2 { - status = "okay"; -}; - -/* enable hdmi */ -&hdmi_in_vp1 { - status = "okay"; -}; - -/* enable video phy */ -&video_phy0 { - status = "okay"; -}; - -&video_phy1 { - status = "okay"; -}; - -/* disable other encoder output */ &dsi0 { status = "disabled"; }; @@ -152,10 +98,52 @@ status = "disabled"; }; -&rgb_in_vp2 { +&hdmi_in_vp1 { + status = "okay"; +}; + +&lvds0 { + status = "okay"; + dual-channel; + + ports { + port@1 { + reg = <1>; + lvds0_out_panel: endpoint { + remote-endpoint = <&panel_in_lvds0>; + }; + }; + }; +}; + +&lvds0_in_vp1 { + status = "okay"; +}; + +&lvds1 { + status = "okay"; + + ports { + port@1 { + reg = <1>; + lvds1_out_panel: endpoint { + remote-endpoint = <&panel_in_lvds1>; + }; + }; + }; +}; + +&lvds1_in_vp1 { + status = "okay"; +}; + +&lvds1_in_vp2 { status = "disabled"; }; +&rgb_in_vp2 { + status = "disabled"; +}; &vcc3v3_lcd0_n { gpio = <&gpio0 RK_PC7 GPIO_ACTIVE_HIGH>; @@ -166,3 +154,11 @@ gpio = <&gpio0 RK_PC5 GPIO_ACTIVE_HIGH>; enable-active-high; }; + +&video_phy0 { + status = "okay"; +}; + +&video_phy1 { + status = "okay"; +}; diff --git a/arch/arm64/boot/dts/rockchip/rk3567-evb2-lp4x-v10-dual-lvds.dts b/arch/arm64/boot/dts/rockchip/rk3567-evb2-lp4x-v10-one-vp-two-single-channel-lvds.dts similarity index 90% rename from arch/arm64/boot/dts/rockchip/rk3567-evb2-lp4x-v10-dual-lvds.dts rename to arch/arm64/boot/dts/rockchip/rk3567-evb2-lp4x-v10-one-vp-two-single-channel-lvds.dts index c4516902c9cc..30f9109242a5 100644 --- a/arch/arm64/boot/dts/rockchip/rk3567-evb2-lp4x-v10-dual-lvds.dts +++ b/arch/arm64/boot/dts/rockchip/rk3567-evb2-lp4x-v10-one-vp-two-single-channel-lvds.dts @@ -13,8 +13,8 @@ #include "rk3568-android.dtsi" / { - model = "Rockchip RK3567 EVB2 LP4X V10 Board"; - compatible = "rockchip,rk3567-evb2-lp4x-v10", "rockchip,rk3567"; + model = "Rockchip RK3567 EVB2 LP4X V10 Board with one vp two single channel lvds"; + compatible = "rockchip,rk3567-evb2-lp4x-v10-one-vp-two-single-channel-lvds", "rockchip,rk3567"; /* panel: claa070wp03xg */ panel { @@ -34,7 +34,7 @@ timing0: timing0 { clock-frequency = <134000000>; - hactive = <1600>; + hactive = <1600>; /* each panel show 1600 / 2 = 800 pxiel */ vactive = <1280>; hback-porch = <60>; hfront-porch = <60>; @@ -75,15 +75,39 @@ }; }; -&backlight1 { - status = "okay"; -}; - &backlight { status = "okay"; }; -&lvds { +&backlight1 { + status = "okay"; +}; + +&dsi0 { + status = "disabled"; +}; + +&dsi0_in_vp0 { + status = "disabled"; +}; + +&dsi0_in_vp1 { + status = "disabled"; +}; + +&dsi1_in_vp1 { + status = "disabled"; +}; + +&edp_in_vp1 { + status = "disabled"; +}; + +&hdmi_in_vp1 { + status = "okay"; +}; + +&lvds0 { status = "okay"; dual-channel; @@ -110,50 +134,15 @@ }; }; -&lvds_in_vp1 { +&lvds0_in_vp1 { status = "okay"; }; &lvds1_in_vp1 { - status = "disabled"; + status = "okay"; }; &lvds1_in_vp2 { - status = "okay"; -}; - -/* enable hdmi */ -&hdmi_in_vp1 { - status = "okay"; -}; - -/* enable video phy */ -&video_phy0 { - status = "okay"; -}; - -&video_phy1 { - status = "okay"; -}; - -/* disable other encoder output */ -&dsi0 { - status = "disabled"; -}; - -&dsi0_in_vp0 { - status = "disabled"; -}; - -&dsi0_in_vp1 { - status = "disabled"; -}; - -&dsi1_in_vp1 { - status = "disabled"; -}; - -&edp_in_vp1 { status = "disabled"; }; @@ -161,7 +150,6 @@ status = "disabled"; }; - &vcc3v3_lcd0_n { gpio = <&gpio0 RK_PC7 GPIO_ACTIVE_HIGH>; enable-active-high; @@ -171,3 +159,11 @@ gpio = <&gpio0 RK_PC5 GPIO_ACTIVE_HIGH>; enable-active-high; }; + +&video_phy0 { + status = "okay"; +}; + +&video_phy1 { + status = "okay"; +}; diff --git a/arch/arm64/boot/dts/rockchip/rk3567-evb2-lp4x-v10-single-channel-lvds.dts b/arch/arm64/boot/dts/rockchip/rk3567-evb2-lp4x-v10-single-channel-lvds.dts new file mode 100644 index 000000000000..85621d529671 --- /dev/null +++ b/arch/arm64/boot/dts/rockchip/rk3567-evb2-lp4x-v10-single-channel-lvds.dts @@ -0,0 +1,136 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright (c) 2023 Rockchip Electronics Co., Ltd. + */ + +/dts-v1/; + +#include +#include +#include + +#include "rk3567-evb2-lp4x-v10.dtsi" +#include "rk3568-android.dtsi" + +/ { + model = "Rockchip RK3567 EVB2 LP4X V10 Board with single channel lvds"; + compatible = "rockchip,rk3567-evb2-lp4x-v10-single-channel-lvds", "rockchip,rk3567"; + + /* panel: claa070wp03xg */ + panel { + compatible = "simple-panel"; + backlight = <&backlight>; + power-supply = <&vcc3v3_lcd0_n>; + enable-delay-ms = <20>; + prepare-delay-ms = <20>; + unprepare-delay-ms = <20>; + disable-delay-ms = <20>; + bus-format = ; + width-mm = <217>; + height-mm = <136>; + + display-timings { + native-mode = <&timing0>; + timing0: timing0 { + clock-frequency = <67000000>; + hactive = <800>; + vactive = <1280>; + hback-porch = <60>; + hfront-porch = <60>; + vback-porch = <4>; + vfront-porch = <2>; + hsync-len = <8>; + vsync-len = <8>; + hsync-active = <0>; + vsync-active = <0>; + de-active = <0>; + pixelclk-active = <0>; + }; + }; + + ports { + #address-cells = <1>; + #size-cells = <0>; + port@0 { + reg = <0>; + panel_in_lvds0: endpoint { + remote-endpoint = <&lvds0_out_panel>; + }; + }; + }; + }; +}; + +&backlight { + status = "okay"; +}; + +&backlight1 { + status = "okay"; +}; + +&dsi0 { + status = "disabled"; +}; + +&dsi0_in_vp0 { + status = "disabled"; +}; + +&dsi0_in_vp1 { + status = "disabled"; +}; + +&dsi1_in_vp1 { + status = "disabled"; +}; + +&edp_in_vp1 { + status = "disabled"; +}; + +&hdmi_in_vp1 { + status = "okay"; +}; + +&lvds0 { + status = "okay"; + ports { + port@1 { + reg = <1>; + lvds0_out_panel: endpoint { + remote-endpoint = <&panel_in_lvds0>; + }; + }; + }; +}; + +&lvds0_in_vp1 { + status = "okay"; +}; + +&lvds1 { + status = "disabled"; +}; + +&rgb_in_vp2 { + status = "disabled"; +}; + +&vcc3v3_lcd0_n { + gpio = <&gpio0 RK_PC7 GPIO_ACTIVE_HIGH>; + enable-active-high; +}; + +&vcc3v3_lcd1_n { + gpio = <&gpio0 RK_PC5 GPIO_ACTIVE_HIGH>; + enable-active-high; +}; + +&video_phy0 { + status = "okay"; +}; + +&video_phy1 { + status = "okay"; +}; diff --git a/arch/arm64/boot/dts/rockchip/rk3567-evb2-lp4x-v10-two-vp-two-separate-single-channel-lvds.dts b/arch/arm64/boot/dts/rockchip/rk3567-evb2-lp4x-v10-two-vp-two-separate-single-channel-lvds.dts new file mode 100644 index 000000000000..9f3e37e9ec28 --- /dev/null +++ b/arch/arm64/boot/dts/rockchip/rk3567-evb2-lp4x-v10-two-vp-two-separate-single-channel-lvds.dts @@ -0,0 +1,201 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright (c) 2023 Rockchip Electronics Co., Ltd. + */ + +/dts-v1/; + +#include +#include +#include + +#include "rk3567-evb2-lp4x-v10.dtsi" +#include "rk3568-android.dtsi" + +/ { + model = "Rockchip RK3567 EVB2 LP4X V10 Board with two vp two separate single channel lvds"; + compatible = "rockchip,rk3567-evb2-lp4x-v10-two-vp-two-separate-single-channel-lvds", "rockchip,rk3567"; + + /** + * VP1 -> LVDS0 -> Panel0 + * VP2 -> LVDS1 -> Panel1 + */ + + /* panel: claa070wp03xg */ + panel-lvds0 { + compatible = "simple-panel"; + backlight = <&backlight>; + power-supply = <&vcc3v3_lcd0_n>; + enable-delay-ms = <20>; + prepare-delay-ms = <20>; + unprepare-delay-ms = <20>; + disable-delay-ms = <20>; + bus-format = ; + width-mm = <217>; + height-mm = <136>; + + display-timings { + native-mode = <&timing0>; + timing0: timing0 { + clock-frequency = <67000000>; + hactive = <800>; + vactive = <1280>; + hback-porch = <60>; + hfront-porch = <60>; + vback-porch = <4>; + vfront-porch = <2>; + hsync-len = <8>; + vsync-len = <8>; + hsync-active = <0>; + vsync-active = <0>; + de-active = <0>; + pixelclk-active = <0>; + }; + }; + + ports { + #address-cells = <1>; + #size-cells = <0>; + port@0 { + reg = <0>; + panel_in_lvds0: endpoint { + remote-endpoint = <&lvds0_out_panel>; + }; + }; + }; + }; + + /* panel: claa070wp03xg */ + panel-lvds1 { + compatible = "simple-panel"; + backlight = <&backlight1>; + power-supply = <&vcc3v3_lcd1_n>; + enable-delay-ms = <20>; + prepare-delay-ms = <20>; + unprepare-delay-ms = <20>; + disable-delay-ms = <20>; + bus-format = ; + width-mm = <217>; + height-mm = <136>; + + display-timings { + native-mode = <&timing1>; + timing1: timing1 { + clock-frequency = <67000000>; + hactive = <800>; + vactive = <1280>; + hback-porch = <60>; + hfront-porch = <60>; + vback-porch = <4>; + vfront-porch = <2>; + hsync-len = <8>; + vsync-len = <8>; + hsync-active = <0>; + vsync-active = <0>; + de-active = <0>; + pixelclk-active = <0>; + }; + }; + + ports { + #address-cells = <1>; + #size-cells = <0>; + port@0 { + reg = <0>; + panel_in_lvds1: endpoint { + remote-endpoint = <&lvds1_out_panel>; + }; + }; + }; + }; +}; + +&backlight { + status = "okay"; +}; + +&backlight1 { + status = "okay"; +}; + +&dsi0 { + status = "disabled"; +}; + +&dsi0_in_vp0 { + status = "disabled"; +}; + +&dsi0_in_vp1 { + status = "disabled"; +}; + +&dsi1_in_vp1 { + status = "disabled"; +}; + +&edp_in_vp1 { + status = "disabled"; +}; + +&hdmi_in_vp1 { + status = "okay"; +}; + +&lvds0 { + status = "okay"; + ports { + port@1 { + reg = <1>; + lvds0_out_panel: endpoint { + remote-endpoint = <&panel_in_lvds0>; + }; + }; + }; +}; + +&lvds0_in_vp1 { + status = "okay"; +}; + +&lvds1 { + status = "okay"; + ports { + port@1 { + reg = <1>; + lvds1_out_panel: endpoint { + remote-endpoint = <&panel_in_lvds1>; + }; + }; + }; +}; + +&lvds1_in_vp1 { + status = "disabled"; +}; + +&lvds1_in_vp2 { + status = "okay"; +}; + +&rgb_in_vp2 { + status = "disabled"; +}; + +&vcc3v3_lcd0_n { + gpio = <&gpio0 RK_PC7 GPIO_ACTIVE_HIGH>; + enable-active-high; +}; + +&vcc3v3_lcd1_n { + gpio = <&gpio0 RK_PC5 GPIO_ACTIVE_HIGH>; + enable-active-high; +}; + +&video_phy0 { + status = "okay"; +}; + +&video_phy1 { + status = "okay"; +}; diff --git a/arch/arm64/boot/dts/rockchip/rk3568-evb1-ddr4-v10-dual-lvds.dts b/arch/arm64/boot/dts/rockchip/rk3568-evb1-ddr4-v10-dual-lvds.dts deleted file mode 100644 index 8cff3652b8d1..000000000000 --- a/arch/arm64/boot/dts/rockchip/rk3568-evb1-ddr4-v10-dual-lvds.dts +++ /dev/null @@ -1,14 +0,0 @@ -// SPDX-License-Identifier: (GPL-2.0+ OR MIT) -/* - * Copyright (c) 2023 Rockchip Electronics Co., Ltd. - */ - -/dts-v1/; - -#include "rk3568-evb1-ddr4-v10-dual-lvds.dtsi" -#include "rk3568-android.dtsi" - -/ { - model = "Rockchip RK3568 EVB1 V10 Board with Dual LVDS"; - compatible = "rockchip,rk3568-evb1-ddr4-v10-dual-lvds", "rockchip,rk3568"; -}; diff --git a/arch/arm64/boot/dts/rockchip/rk3568-evb1-ddr4-v10-dual-lvds-linux.dts b/arch/arm64/boot/dts/rockchip/rk3568-evb1-ddr4-v10-one-vp-two-single-channel-lvds-linux.dts similarity index 55% rename from arch/arm64/boot/dts/rockchip/rk3568-evb1-ddr4-v10-dual-lvds-linux.dts rename to arch/arm64/boot/dts/rockchip/rk3568-evb1-ddr4-v10-one-vp-two-single-channel-lvds-linux.dts index 6a15126ee392..fb33ac53f9dc 100644 --- a/arch/arm64/boot/dts/rockchip/rk3568-evb1-ddr4-v10-dual-lvds-linux.dts +++ b/arch/arm64/boot/dts/rockchip/rk3568-evb1-ddr4-v10-one-vp-two-single-channel-lvds-linux.dts @@ -6,12 +6,12 @@ /dts-v1/; #include -#include "rk3568-evb1-ddr4-v10-dual-lvds.dtsi" +#include "rk3568-evb1-ddr4-v10-one-vp-two-single-channel-lvds.dtsi" #include "rk3568-linux.dtsi" / { - model = "Rockchip RK3568 EVB1 V10 Board with Dual LVDS"; - compatible = "rockchip,rk3568-evb1-ddr4-v10-dual-lvds", "rockchip,rk3568"; + model = "Rockchip RK3568 EVB1 V10 Board with one vp two single channel lvds"; + compatible = "rockchip,rk3568-evb1-ddr4-v10-one-vp-two-single-channel-lvds", "rockchip,rk3568"; }; &vp0 { diff --git a/arch/arm64/boot/dts/rockchip/rk3568-evb1-ddr4-v10-one-vp-two-single-channel-lvds.dts b/arch/arm64/boot/dts/rockchip/rk3568-evb1-ddr4-v10-one-vp-two-single-channel-lvds.dts new file mode 100644 index 000000000000..43b0df32cb4b --- /dev/null +++ b/arch/arm64/boot/dts/rockchip/rk3568-evb1-ddr4-v10-one-vp-two-single-channel-lvds.dts @@ -0,0 +1,14 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright (c) 2023 Rockchip Electronics Co., Ltd. + */ + +/dts-v1/; + +#include "rk3568-evb1-ddr4-v10-one-vp-two-single-channel-lvds.dtsi" +#include "rk3568-android.dtsi" + +/ { + model = "Rockchip RK3568 EVB1 V10 Board with one vp two single channel lvds"; + compatible = "rockchip,rk3568-evb1-ddr4-v10-one-vp-two-single-channel-lvds", "rockchip,rk3568"; +}; diff --git a/arch/arm64/boot/dts/rockchip/rk3568-evb1-ddr4-v10-dual-lvds.dtsi b/arch/arm64/boot/dts/rockchip/rk3568-evb1-ddr4-v10-one-vp-two-single-channel-lvds.dtsi similarity index 96% rename from arch/arm64/boot/dts/rockchip/rk3568-evb1-ddr4-v10-dual-lvds.dtsi rename to arch/arm64/boot/dts/rockchip/rk3568-evb1-ddr4-v10-one-vp-two-single-channel-lvds.dtsi index eae796d48b58..51e1d19b99a8 100644 --- a/arch/arm64/boot/dts/rockchip/rk3568-evb1-ddr4-v10-dual-lvds.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3568-evb1-ddr4-v10-one-vp-two-single-channel-lvds.dtsi @@ -27,7 +27,7 @@ timing0: timing0 { clock-frequency = <134000000>; - hactive = <1600>; + hactive = <1600>; /* each panel show 1600 / 2 = 800 pxiel */ vactive = <1280>; hback-porch = <60>; hfront-porch = <60>; @@ -68,11 +68,11 @@ }; }; -&backlight1 { +&backlight { status = "okay"; }; -&backlight { +&backlight1 { status = "okay"; }; @@ -100,7 +100,7 @@ status = "okay"; }; -&lvds { +&lvds0 { status = "okay"; dual-channel; @@ -114,6 +114,10 @@ }; }; +&lvds0_in_vp1 { + status = "okay"; +}; + &lvds1 { status = "okay"; @@ -127,30 +131,18 @@ }; }; -&lvds_in_vp1 { - status = "okay"; -}; - &lvds1_in_vp1 { - status = "disabled"; + status = "okay"; }; &lvds1_in_vp2 { - status = "okay"; + status = "disabled"; }; &rgb_in_vp2 { status = "disabled"; }; -&video_phy0 { - status = "okay"; -}; - -&video_phy1 { - status = "okay"; -}; - &vcc3v3_lcd0_n { gpio = <&gpio0 RK_PC7 GPIO_ACTIVE_HIGH>; enable-active-high; @@ -160,3 +152,11 @@ gpio = <&gpio0 RK_PC5 GPIO_ACTIVE_HIGH>; enable-active-high; }; + +&video_phy0 { + status = "okay"; +}; + +&video_phy1 { + status = "okay"; +}; diff --git a/arch/arm64/boot/dts/rockchip/rk3568-evb1-ddr4-v10-single-channel-lvds.dts b/arch/arm64/boot/dts/rockchip/rk3568-evb1-ddr4-v10-single-channel-lvds.dts new file mode 100644 index 000000000000..e0f543a01c2a --- /dev/null +++ b/arch/arm64/boot/dts/rockchip/rk3568-evb1-ddr4-v10-single-channel-lvds.dts @@ -0,0 +1,133 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright (c) 2023 Rockchip Electronics Co., Ltd. + */ + +#include +#include +#include +#include "rk3568-evb1-ddr4-v10.dtsi" +#include "rk3568-android.dtsi" + +/ { + model = "Rockchip RK3568 EVB1 V10 Board with single channel lvds"; + compatible = "rockchip,rk3568-evb1-ddr4-v10-single-channel-lvds", "rockchip,rk3568"; + + /* panel: claa070wp03xg */ + panel-lvds0 { + compatible = "simple-panel"; + backlight = <&backlight>; + power-supply = <&vcc3v3_lcd0_n>; + enable-delay-ms = <20>; + prepare-delay-ms = <20>; + unprepare-delay-ms = <20>; + disable-delay-ms = <20>; + bus-format = ; + width-mm = <217>; + height-mm = <136>; + + display-timings { + native-mode = <&timing0>; + timing0: timing0 { + clock-frequency = <67000000>; + hactive = <800>; + vactive = <1280>; + hback-porch = <60>; + hfront-porch = <60>; + vback-porch = <4>; + vfront-porch = <2>; + hsync-len = <8>; + vsync-len = <8>; + hsync-active = <0>; + vsync-active = <0>; + de-active = <0>; + pixelclk-active = <0>; + }; + }; + + ports { + #address-cells = <1>; + #size-cells = <0>; + port@0 { + reg = <0>; + panel_in_lvds0: endpoint { + remote-endpoint = <&lvds0_out_panel>; + }; + }; + }; + }; +}; + +&backlight { + status = "okay"; +}; + +&backlight1 { + status = "okay"; +}; + +&dsi0 { + status = "disabled"; +}; + +&dsi0_in_vp0 { + status = "disabled"; +}; + +&dsi0_in_vp1 { + status = "disabled"; +}; + +&dsi1_in_vp1 { + status = "disabled"; +}; + +&edp_in_vp1 { + status = "disabled"; +}; + +&hdmi_in_vp1 { + status = "okay"; +}; + +&lvds0 { + status = "okay"; + ports { + port@1 { + reg = <1>; + lvds0_out_panel: endpoint { + remote-endpoint = <&panel_in_lvds0>; + }; + }; + }; +}; + +&lvds0_in_vp1 { + status = "okay"; +}; + +&lvds1 { + status = "disabled"; +}; + +&rgb_in_vp2 { + status = "disabled"; +}; + +&vcc3v3_lcd0_n { + gpio = <&gpio0 RK_PC7 GPIO_ACTIVE_HIGH>; + enable-active-high; +}; + +&vcc3v3_lcd1_n { + gpio = <&gpio0 RK_PC5 GPIO_ACTIVE_HIGH>; + enable-active-high; +}; + +&video_phy0 { + status = "okay"; +}; + +&video_phy1 { + status = "okay"; +}; diff --git a/arch/arm64/boot/dts/rockchip/rk3568-evb1-ddr4-v10-two-vp-two-separate-single-channel-lvds.dts b/arch/arm64/boot/dts/rockchip/rk3568-evb1-ddr4-v10-two-vp-two-separate-single-channel-lvds.dts new file mode 100644 index 000000000000..13d0f9127995 --- /dev/null +++ b/arch/arm64/boot/dts/rockchip/rk3568-evb1-ddr4-v10-two-vp-two-separate-single-channel-lvds.dts @@ -0,0 +1,198 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright (c) 2023 Rockchip Electronics Co., Ltd. + */ + +#include +#include +#include +#include "rk3568-evb1-ddr4-v10.dtsi" +#include "rk3568-android.dtsi" + +/ { + model = "Rockchip RK3568 EVB1 V10 Board with two vp two separate single channel lvds"; + compatible = "rockchip,rk3568-evb1-ddr4-v10-two-vp-two-separate-single-channel-lvds", "rockchip,rk3568"; + + /** + * VP1 -> LVDS0 -> Panel0 + * VP2 -> LVDS1 -> Panel1 + */ + + /* panel: claa070wp03xg */ + panel-lvds0 { + compatible = "simple-panel"; + backlight = <&backlight>; + power-supply = <&vcc3v3_lcd0_n>; + enable-delay-ms = <20>; + prepare-delay-ms = <20>; + unprepare-delay-ms = <20>; + disable-delay-ms = <20>; + bus-format = ; + width-mm = <217>; + height-mm = <136>; + + display-timings { + native-mode = <&timing0>; + timing0: timing0 { + clock-frequency = <67000000>; + hactive = <800>; + vactive = <1280>; + hback-porch = <60>; + hfront-porch = <60>; + vback-porch = <4>; + vfront-porch = <2>; + hsync-len = <8>; + vsync-len = <8>; + hsync-active = <0>; + vsync-active = <0>; + de-active = <0>; + pixelclk-active = <0>; + }; + }; + + ports { + #address-cells = <1>; + #size-cells = <0>; + port@0 { + reg = <0>; + panel_in_lvds0: endpoint { + remote-endpoint = <&lvds0_out_panel>; + }; + }; + }; + }; + + /* panel: claa070wp03xg */ + panel-lvds1 { + compatible = "simple-panel"; + backlight = <&backlight1>; + power-supply = <&vcc3v3_lcd1_n>; + enable-delay-ms = <20>; + prepare-delay-ms = <20>; + unprepare-delay-ms = <20>; + disable-delay-ms = <20>; + bus-format = ; + width-mm = <217>; + height-mm = <136>; + + display-timings { + native-mode = <&timing1>; + timing1: timing1 { + clock-frequency = <67000000>; + hactive = <800>; + vactive = <1280>; + hback-porch = <60>; + hfront-porch = <60>; + vback-porch = <4>; + vfront-porch = <2>; + hsync-len = <8>; + vsync-len = <8>; + hsync-active = <0>; + vsync-active = <0>; + de-active = <0>; + pixelclk-active = <0>; + }; + }; + + ports { + #address-cells = <1>; + #size-cells = <0>; + port@0 { + reg = <0>; + panel_in_lvds1: endpoint { + remote-endpoint = <&lvds1_out_panel>; + }; + }; + }; + }; +}; + +&backlight { + status = "okay"; +}; + +&backlight1 { + status = "okay"; +}; + +&dsi0 { + status = "disabled"; +}; + +&dsi0_in_vp0 { + status = "disabled"; +}; + +&dsi0_in_vp1 { + status = "disabled"; +}; + +&dsi1_in_vp1 { + status = "disabled"; +}; + +&edp_in_vp1 { + status = "disabled"; +}; + +&hdmi_in_vp1 { + status = "okay"; +}; + +&lvds0 { + status = "okay"; + ports { + port@1 { + reg = <1>; + lvds0_out_panel: endpoint { + remote-endpoint = <&panel_in_lvds0>; + }; + }; + }; +}; + +&lvds0_in_vp1 { + status = "okay"; +}; + +&lvds1 { + status = "okay"; + ports { + port@1 { + reg = <1>; + lvds1_out_panel: endpoint { + remote-endpoint = <&panel_in_lvds1>; + }; + }; + }; +}; + +&lvds1_in_vp1 { + status = "disabled"; +}; + +&lvds1_in_vp2 { + status = "okay"; +}; + +&rgb_in_vp2 { + status = "disabled"; +}; + +&vcc3v3_lcd0_n { + gpio = <&gpio0 RK_PC7 GPIO_ACTIVE_HIGH>; + enable-active-high; +}; + +&vcc3v3_lcd1_n { + gpio = <&gpio0 RK_PC5 GPIO_ACTIVE_HIGH>; + enable-active-high; +}; + +&video_phy0 { + status = "okay"; +}; + +&video_phy1 { + status = "okay"; +}; diff --git a/arch/arm64/configs/rockchip_defconfig b/arch/arm64/configs/rockchip_defconfig index 6175c330cafc..8e96d404a2a6 100644 --- a/arch/arm64/configs/rockchip_defconfig +++ b/arch/arm64/configs/rockchip_defconfig @@ -899,6 +899,7 @@ CONFIG_CPU_RK3562=y CONFIG_CPU_RK3568=y CONFIG_CPU_RK3588=y CONFIG_ROCKCHIP_CPUINFO=y +CONFIG_ROCKCHIP_CSU=y CONFIG_ROCKCHIP_GRF=y CONFIG_ROCKCHIP_IODOMAIN=y CONFIG_ROCKCHIP_IPA=y diff --git a/arch/arm64/configs/rockchip_linux_defconfig b/arch/arm64/configs/rockchip_linux_defconfig index d379d6d72681..a84de18916be 100644 --- a/arch/arm64/configs/rockchip_linux_defconfig +++ b/arch/arm64/configs/rockchip_linux_defconfig @@ -514,6 +514,7 @@ CONFIG_CPU_RK3568=y CONFIG_CPU_RK3588=y CONFIG_ROCKCHIP_AMP=y CONFIG_ROCKCHIP_CPUINFO=y +CONFIG_ROCKCHIP_CSU=y CONFIG_ROCKCHIP_GRF=y CONFIG_ROCKCHIP_IODOMAIN=y CONFIG_ROCKCHIP_IPA=y diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c index 4a8c2966cf99..333a84e681c9 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c @@ -46,6 +46,7 @@ #include #include #include +#include #include #include #include @@ -885,6 +886,7 @@ struct vop2 { struct clk *pclk; struct reset_control *ahb_rst; struct reset_control *axi_rst; + struct csu_clk *csu_aclk; /* list_head of extend clk */ struct list_head extend_clk_list_head; @@ -6111,6 +6113,27 @@ static int vop2_crtc_get_inital_acm_info(struct drm_crtc *crtc) return 0; } +static void vop2_crtc_csu_set_rate(struct drm_crtc *crtc) +{ + struct vop2_video_port *vp = to_vop2_video_port(crtc); + struct vop2 *vop2 = vp->vop2; + unsigned long aclk_rate = 0, dclk_rate = 0; + u32 csu_div = 0; + + if (!vop2->csu_aclk) + return; + + aclk_rate = clk_get_rate(vop2->aclk); + dclk_rate = clk_get_rate(vp->dclk); + if (!dclk_rate) + return; + + /* aclk >= 1/2 * dclk */ + csu_div = aclk_rate * 2 / dclk_rate; + + rockchip_csu_set_div(vop2->csu_aclk, csu_div); +} + static int vop2_crtc_loader_protect(struct drm_crtc *crtc, bool on, void *data) { struct vop2_video_port *vp = to_vop2_video_port(crtc); @@ -6190,6 +6213,8 @@ static int vop2_crtc_loader_protect(struct drm_crtc *crtc, bool on, void *data) cubic_lut_mst = cubic_lut->offset + private->cubic_lut_dma_addr; VOP_MODULE_SET(vop2, vp, cubic_lut_mst, cubic_lut_mst); } + + vop2_crtc_csu_set_rate(crtc); } else { vop2_crtc_atomic_disable(crtc, NULL); } @@ -8123,6 +8148,7 @@ static void vop2_crtc_atomic_enable(struct drm_crtc *crtc, struct drm_atomic_sta if (is_vop3(vop2)) vop3_setup_pipe_dly(vp, NULL); + vop2_crtc_csu_set_rate(crtc); vop2_cfg_done(crtc); /* @@ -11974,6 +12000,10 @@ static int vop2_bind(struct device *dev, struct device *master, void *data) return PTR_ERR(vop2->axi_rst); } + vop2->csu_aclk = rockchip_csu_get(dev, "aclk"); + if (IS_ERR(vop2->csu_aclk)) + vop2->csu_aclk = NULL; + vop2->irq = platform_get_irq(pdev, 0); if (vop2->irq < 0) { DRM_DEV_ERROR(dev, "cannot find irq for vop2\n"); diff --git a/drivers/media/i2c/mis4001.c b/drivers/media/i2c/mis4001.c index d73e92dd768c..a23f73aec373 100644 --- a/drivers/media/i2c/mis4001.c +++ b/drivers/media/i2c/mis4001.c @@ -27,7 +27,7 @@ #include #include -#define DRIVER_VERSION KERNEL_VERSION(0, 0x01, 0x01) +#define DRIVER_VERSION KERNEL_VERSION(0, 0x01, 0x02) #ifndef V4L2_CID_DIGITAL_GAIN #define V4L2_CID_DIGITAL_GAIN V4L2_CID_GAIN @@ -165,177 +165,177 @@ static const struct regval mis4001_global_regs[] = { * mipi_datarate per lane 337.5Mbps, 2lane */ static const struct regval mis4001_linear_10_2560x1440_regs[] = { - {0x300a, 0x01}, - {0x3006, 0x02}, - {0x4220, 0x2b}, - {0x4221, 0x6b}, - {0x4222, 0xab}, - {0x4223, 0xeb}, - {0x3011, 0x2b}, - {0x3302, 0x02}, - {0x3307, 0x64}, - {0x3306, 0x01}, - {0x3309, 0x01}, - {0x3308, 0x03}, - {0x330a, 0x04}, - {0x330b, 0x09}, - {0x310f, 0x68}, - {0x310e, 0x0d}, - {0x310d, 0x25}, - {0x310c, 0x06}, - {0x3115, 0x10}, - {0x3114, 0x00}, - {0x3117, 0x0f}, - {0x3116, 0x0a}, - {0x3111, 0xfc}, - {0x3110, 0x00}, - {0x3113, 0x9d}, - {0x3112, 0x06}, - {0x3128, 0x0f},//FW<4096 FFF - {0x3129, 0xff}, - {0x3012, 0x03}, - {0x3f00, 0x01}, - {0x3f02, 0x07}, - {0x3f01, 0x00}, - {0x3f04, 0x2a}, - {0x3f03, 0x00}, - {0x3f06, 0xa5}, - {0x3f05, 0x04}, - {0x3f08, 0xff}, - {0x3f07, 0x1f}, - {0x3f0a, 0xa4}, - {0x3f09, 0x01}, - {0x3f0c, 0x38}, - {0x3f0b, 0x00}, - {0x3f0e, 0xff}, - {0x3f0d, 0x1f}, - {0x3f10, 0xff}, - {0x3f0f, 0x1f}, - {0x3f13, 0x07}, - {0x3f12, 0x00}, - {0x3f15, 0x9d}, - {0x3f14, 0x01}, - {0x3f17, 0x31}, - {0x3f16, 0x00}, - {0x3f19, 0x73}, - {0x3f18, 0x01}, - {0x3f1b, 0x00}, - {0x3f1a, 0x00}, - {0x3f1d, 0xa9}, - {0x3f1c, 0x04}, - {0x3f1f, 0xff}, - {0x3f1e, 0x1f}, - {0x3f21, 0xff}, - {0x3f20, 0x1f}, - {0x3f23, 0x85}, - {0x3f22, 0x00}, - {0x3f25, 0x27}, - {0x3f24, 0x01}, - {0x3f28, 0x46}, - {0x3f27, 0x00}, - {0x3f2a, 0x07}, - {0x3f29, 0x00}, - {0x3f2c, 0x3f}, - {0x3f2b, 0x00}, - {0x3f2e, 0x70}, - {0x3f2d, 0x01}, - {0x3f30, 0x38}, - {0x3f2f, 0x00}, - {0x3f32, 0x3f}, - {0x3f31, 0x00}, - {0x3f34, 0xd1}, - {0x3f33, 0x00}, - {0x3f36, 0xc0}, - {0x3f35, 0x00}, - {0x3f38, 0x2f}, - {0x3f37, 0x02}, - {0x3f3a, 0x5d}, - {0x3f39, 0x02}, - {0x3f4f, 0x5d}, - {0x3f4e, 0x02}, - {0x3f51, 0x5d}, - {0x3f50, 0x02}, - {0x3f53, 0x5d}, - {0x3f52, 0x02}, - {0x3f55, 0x5d}, - {0x3f54, 0x02}, - {0x3f3c, 0x9a}, - {0x3f3b, 0x00}, - {0x3f3e, 0x09}, - {0x3f3d, 0x04}, - {0x3f40, 0x93}, - {0x3f3f, 0x01}, - {0x3f42, 0x8f}, - {0x3f41, 0x00}, - {0x3f44, 0xb0}, - {0x3f43, 0x04}, - {0x3129, 0x45}, - {0x3128, 0x00}, - {0x312b, 0x4a}, - {0x312a, 0x00}, - {0x312f, 0xb2}, - {0x312e, 0x00}, - {0x3124, 0x09}, - {0x4200, 0x09}, - {0x4201, 0x00}, - {0x4214, 0x60}, - {0x420E, 0x94}, - {0x4240, 0x8d}, - {0x4242, 0x03}, - {0x4224, 0x00}, - {0x4225, 0x0a}, - {0x4226, 0xa0}, - {0x4227, 0x05}, - {0x4228, 0x00}, - {0x4229, 0x0a}, - {0x422a, 0xa0}, - {0x422b, 0x05}, - {0x422c, 0x00}, - {0x422d, 0x0a}, - {0x422e, 0xa0}, - {0x422f, 0x05}, - {0x4230, 0x00}, - {0x4231, 0x0a}, - {0x4232, 0xa0}, - {0x4233, 0x05}, - {0x4509, 0x0f}, - {0x4505, 0x00}, - {0x4501, 0xff}, - {0x4502, 0x33}, - {0x4503, 0x11}, - {0x4501, 0xf0}, - {0x4502, 0x30}, - {0x4503, 0x10}, - {0x3A01, 0xA0}, - {0x401E, 0x3C}, - {0x401d, 0xa0}, - {0x3012, 0x03}, - {0x3E00, 0x00}, - {0x3E01, 0x10}, - {0x400D, 0x30}, - {0x3500, 0x1b}, //1b/13 - {0x3501, 0x03}, - {0x3508, 0x0a}, - {0x3508, 0x04}, - {0x3513, 0x01}, - {0x3514, 0x09}, - {0x3515, 0x0b}, - {0x3702, 0x80}, - {0x3704, 0x80}, - {0x3706, 0x80}, - {0x3708, 0x80}, - {0x400D, 0x30}, //优化奇偶行及行噪 - {0x4004, 0x20}, //RCS CM电流最小优化横带 - {0x4005, 0x0c}, - {0x4009, 0x09}, - {0x400a, 0x48}, - {0x4006, 0x86}, - {0x4019, 0x08}, - {0x4003, 0x0a}, - {0x3f42, 0x58}, - {0x3f49, 0x60}, - {0x3f38, 0x4d}, - {REG_NULL, 0x00}, + {0x300a, 0x01}, + {0x3006, 0x02}, + {0x4220, 0x2b}, + {0x4221, 0x6b}, + {0x4222, 0xab}, + {0x4223, 0xeb}, + {0x3011, 0x2b}, + {0x3302, 0x02}, + {0x3307, 0x64}, + {0x3306, 0x01}, + {0x3309, 0x01}, + {0x3308, 0x03}, + {0x330a, 0x04}, + {0x330b, 0x09}, + {0x310f, 0x68}, + {0x310e, 0x0d}, + {0x310d, 0x25}, + {0x310c, 0x06}, + {0x3115, 0x10}, + {0x3114, 0x00}, + {0x3117, 0x0f}, + {0x3116, 0x0a}, + {0x3111, 0xfc}, + {0x3110, 0x00}, + {0x3113, 0x9d}, + {0x3112, 0x06}, + {0x3128, 0x0f},//FW<4096 FFF + {0x3129, 0xff}, + {0x3012, 0x03}, + {0x3f00, 0x01}, + {0x3f02, 0x07}, + {0x3f01, 0x00}, + {0x3f04, 0x2a}, + {0x3f03, 0x00}, + {0x3f06, 0xa5}, + {0x3f05, 0x04}, + {0x3f08, 0xff}, + {0x3f07, 0x1f}, + {0x3f0a, 0xa4}, + {0x3f09, 0x01}, + {0x3f0c, 0x38}, + {0x3f0b, 0x00}, + {0x3f0e, 0xff}, + {0x3f0d, 0x1f}, + {0x3f10, 0xff}, + {0x3f0f, 0x1f}, + {0x3f13, 0x07}, + {0x3f12, 0x00}, + {0x3f15, 0x9d}, + {0x3f14, 0x01}, + {0x3f17, 0x31}, + {0x3f16, 0x00}, + {0x3f19, 0x73}, + {0x3f18, 0x01}, + {0x3f1b, 0x00}, + {0x3f1a, 0x00}, + {0x3f1d, 0xa9}, + {0x3f1c, 0x04}, + {0x3f1f, 0xff}, + {0x3f1e, 0x1f}, + {0x3f21, 0xff}, + {0x3f20, 0x1f}, + {0x3f23, 0x85}, + {0x3f22, 0x00}, + {0x3f25, 0x27}, + {0x3f24, 0x01}, + {0x3f28, 0x46}, + {0x3f27, 0x00}, + {0x3f2a, 0x07}, + {0x3f29, 0x00}, + {0x3f2c, 0x3f}, + {0x3f2b, 0x00}, + {0x3f2e, 0x70}, + {0x3f2d, 0x01}, + {0x3f30, 0x38}, + {0x3f2f, 0x00}, + {0x3f32, 0x3f}, + {0x3f31, 0x00}, + {0x3f34, 0xd1}, + {0x3f33, 0x00}, + {0x3f36, 0xc0}, + {0x3f35, 0x00}, + {0x3f38, 0x2f}, + {0x3f37, 0x02}, + {0x3f3a, 0x5d}, + {0x3f39, 0x02}, + {0x3f4f, 0x5d}, + {0x3f4e, 0x02}, + {0x3f51, 0x5d}, + {0x3f50, 0x02}, + {0x3f53, 0x5d}, + {0x3f52, 0x02}, + {0x3f55, 0x5d}, + {0x3f54, 0x02}, + {0x3f3c, 0x9a}, + {0x3f3b, 0x00}, + {0x3f3e, 0x09}, + {0x3f3d, 0x04}, + {0x3f40, 0x93}, + {0x3f3f, 0x01}, + {0x3f42, 0x8f}, + {0x3f41, 0x00}, + {0x3f44, 0xb0}, + {0x3f43, 0x04}, + {0x3129, 0x45}, + {0x3128, 0x00}, + {0x312b, 0x4a}, + {0x312a, 0x00}, + {0x312f, 0xb2}, + {0x312e, 0x00}, + {0x3124, 0x09}, + {0x4200, 0x09}, + {0x4201, 0x00}, + {0x4214, 0x60}, + {0x420E, 0x94}, + {0x4240, 0x8d}, + {0x4242, 0x03}, + {0x4224, 0x00}, + {0x4225, 0x0a}, + {0x4226, 0xa0}, + {0x4227, 0x05}, + {0x4228, 0x00}, + {0x4229, 0x0a}, + {0x422a, 0xa0}, + {0x422b, 0x05}, + {0x422c, 0x00}, + {0x422d, 0x0a}, + {0x422e, 0xa0}, + {0x422f, 0x05}, + {0x4230, 0x00}, + {0x4231, 0x0a}, + {0x4232, 0xa0}, + {0x4233, 0x05}, + {0x4509, 0x0f}, + {0x4505, 0x00}, + {0x4501, 0xff}, + {0x4502, 0x33}, + {0x4503, 0x11}, + {0x4501, 0xf0}, + {0x4502, 0x30}, + {0x4503, 0x10}, + {0x3A01, 0xA0}, + {0x401E, 0x3C}, + {0x401d, 0xa0}, + {0x3012, 0x03}, + {0x3E00, 0x00}, + {0x3E01, 0x10}, + {0x400D, 0x30}, + {0x3500, 0x1b}, //1b/13 + {0x3501, 0x03}, + {0x3508, 0x0a}, + {0x3508, 0x04}, + {0x3513, 0x01}, + {0x3514, 0x09}, + {0x3515, 0x0b}, + {0x3702, 0x80}, + {0x3704, 0x80}, + {0x3706, 0x80}, + {0x3708, 0x80}, + {0x400D, 0x30}, //优化奇偶行及行噪 + {0x4004, 0x20}, //RCS CM电流最小优化横带 + {0x4005, 0x0c}, + {0x4009, 0x09}, + {0x400a, 0x48}, + {0x4006, 0x86}, + {0x4019, 0x08}, + {0x4003, 0x0a}, + {0x3f42, 0x58}, + {0x3f49, 0x60}, + {0x3f38, 0x4d}, + {REG_NULL, 0x00}, }; static const struct mis4001_mode supported_modes[] = { @@ -483,6 +483,7 @@ static int mis4001_set_gain_reg(struct mis4001 *mis4001, u32 gain) { u8 gain_h, gain_l, u8Reg0x3102, u8Reg0x3a00, u8Reg0x3a01, u8Reg0x4003; int ret = 0; + u8 u8Reg0x401d = 0; if (gain < 128) gain = 128; @@ -490,89 +491,97 @@ static int mis4001_set_gain_reg(struct mis4001 *mis4001, u32 gain) gain = MIS4001_GAIN_MAX; if (128 <= gain && gain < 256) {//128 * 2 - gain_h = 0; - gain_l = (gain-128)/4 ; - u8Reg0x3a00 = 0; - u8Reg0x3a01 = 160; //128->160, 高亮偏粉 - } else if (gain >= 256 && gain < 512) {//128 * 4 - gain_h = 1; - gain_l = (gain-256)/8; - u8Reg0x3a00 = 0; - u8Reg0x3a01 = 160; - } else if (gain >= 512 && gain < 1024) {//128 * 8 - gain_h = 2; - gain_l = (gain-512)/16; - u8Reg0x3a00 = 0; - u8Reg0x3a01 = 160; - } else if (gain >= 1024 && gain < 2048) {//128 * 16 - gain_h = 3; - gain_l = (gain-1024)/32; - u8Reg0x3a00 = 0; - u8Reg0x3a01 = 160; - } else if (2048 <= gain && gain < 4096) {//128 * 32 Dgain - gain_h = 3; - gain_l = 31; - u8Reg0x3a00 = 0; - u8Reg0x3a01 = ((gain-2048)/16 + 128); - u8Reg0x3a01 = (u8Reg0x3a01<160)?160:u8Reg0x3a01; - } else if (gain >= 4096 && gain < 8192) {//128 * 64 - gain_h = 3; - gain_l = 31; - u8Reg0x3a00 = 1; - u8Reg0x3a01 =((gain-4096)/16); - } else if (gain >= 8192 && gain < 12288) {//128 * 96 - gain_h = 3; - gain_l = 31; - u8Reg0x3a00 = 2; - u8Reg0x3a01 = ((gain-8192)/16); - } else if (gain >= 12288 && gain < 16384) {//128 * 128 - gain_h = 3; - gain_l = 31; - u8Reg0x3a00 = 3; - u8Reg0x3a01 = ((gain-12288)/16); - } else if (gain >= 16384 && gain < 20480) {//128 * 160 - gain_h = 3; - gain_l = 31; - u8Reg0x3a00 = 4; - u8Reg0x3a01 = ((gain-16384)/16); - } else if (gain >= 20480 && gain < 24576) {//128 * 192 - gain_h = 3; - gain_l = 31; - u8Reg0x3a00 = 5; - u8Reg0x3a01 = ((gain-20480)/16); - } else if (gain >= 24576 && gain < 28672) {//128 * 224 - gain_h = 3; - gain_l = 31; - u8Reg0x3a00 = 6; - u8Reg0x3a01 = ((gain-24576)/16); - } else if (gain >= 28672 && gain < 32768) {//128 * 256 - gain_h = 3; - gain_l = 31; - u8Reg0x3a00 = 7; - u8Reg0x3a01 = ((gain-28672)/16); - } else { - gain_h = 3; - gain_l = 31; - u8Reg0x3a00 = 7; - u8Reg0x3a01 = 255; - } + gain_h = 0; + gain_l = (gain - 128) / 4; + u8Reg0x3a00 = 0; + u8Reg0x3a01 = 160; //128->160, 高亮偏粉 + } else if (gain >= 256 && gain < 512) {//128 * 4 + gain_h = 1; + gain_l = (gain - 256) / 8; + u8Reg0x3a00 = 0; + u8Reg0x3a01 = 160; + } else if (gain >= 512 && gain < 1024) {//128 * 8 + gain_h = 2; + gain_l = (gain - 512) / 16; + u8Reg0x3a00 = 0; + u8Reg0x3a01 = 160; + } else if (gain >= 1024 && gain < 2048) {//128 * 16 + gain_h = 3; + gain_l = (gain - 1024) / 32; + u8Reg0x3a00 = 0; + u8Reg0x3a01 = 160; + } else if (gain >= 2048 && gain < 4096) {//128 * 32 Dgain + gain_h = 3; + gain_l = 31; + u8Reg0x3a00 = 0; + u8Reg0x3a01 = ((gain - 2048) / 16 + 128); + u8Reg0x3a01 = (u8Reg0x3a01 < 160) ? 160 : u8Reg0x3a01; + } else if (gain >= 4096 && gain < 8192) {//128 * 64 + gain_h = 3; + gain_l = 31; + u8Reg0x3a00 = 1; + u8Reg0x3a01 = ((gain - 4096) / 16); + } else if (gain >= 8192 && gain < 12288) {//128 * 96 + gain_h = 3; + gain_l = 31; + u8Reg0x3a00 = 2; + u8Reg0x3a01 = ((gain - 8192) / 16); + } else if (gain >= 12288 && gain < 16384) {//128 * 128 + gain_h = 3; + gain_l = 31; + u8Reg0x3a00 = 3; + u8Reg0x3a01 = ((gain - 12288) / 16); + } else if (gain >= 16384 && gain < 20480) {//128 * 160 + gain_h = 3; + gain_l = 31; + u8Reg0x3a00 = 4; + u8Reg0x3a01 = ((gain - 16384) / 16); + } else if (gain >= 20480 && gain < 24576) {//128 * 192 + gain_h = 3; + gain_l = 31; + u8Reg0x3a00 = 5; + u8Reg0x3a01 = ((gain - 20480) / 16); + } else if (gain >= 24576 && gain < 28672) {//128 * 224 + gain_h = 3; + gain_l = 31; + u8Reg0x3a00 = 6; + u8Reg0x3a01 = ((gain - 24576) / 16); + } else if (gain >= 28672 && gain < 32768) {//128 * 256 + gain_h = 3; + gain_l = 31; + u8Reg0x3a00 = 7; + u8Reg0x3a01 = ((gain - 28672) / 16); + } else { + gain_h = 3; + gain_l = 31; + u8Reg0x3a00 = 7; + u8Reg0x3a01 = 255; + } - u8Reg0x3102 = ((gain_h << 5)|gain_l); + u8Reg0x3102 = ((gain_h << 5) | gain_l); // 竖条纹优化,但低增益下需添加防止太阳黑子逻辑 - if (128 <= gain && gain <= 256) + if (gain >= 128 && gain <= 256) { u8Reg0x4003 = 0xb; - else + u8Reg0x401d = 0xa0; + } else { u8Reg0x4003 = 0xa; + u8Reg0x401d = 0xa7; + } ret = mis4001_write_reg(mis4001->client, - 0x4003, + 0x401d, MIS4001_REG_VALUE_08BIT, - u8Reg0x4003); + u8Reg0x401d); + ret |= mis4001_write_reg(mis4001->client, - MIS4001_REG_DIG_GAIN, - MIS4001_REG_VALUE_08BIT, - u8Reg0x3a00); + 0x4003, + MIS4001_REG_VALUE_08BIT, + u8Reg0x4003); + ret |= mis4001_write_reg(mis4001->client, + MIS4001_REG_DIG_GAIN, + MIS4001_REG_VALUE_08BIT, + u8Reg0x3a00); ret |= mis4001_write_reg(mis4001->client, MIS4001_REG_DIG_FINE_GAIN, MIS4001_REG_VALUE_08BIT, @@ -1211,10 +1220,8 @@ static int mis4001_set_ctrl(struct v4l2_ctrl *ctrl) s64 max; int ret = 0; u32 val = 0; - u32 u32Read0x3102 = 0; - u32 exp_h = 0; - u32 exp_l = 0; - u32 u32Reg0x4007, expmin, expmax, exp_value = 0; + u32 u32Reg0x4007, expmin, expmax; + u64 sleep_time = 0; /* Propagate change of current control to all related controls */ switch (ctrl->id) { @@ -1245,6 +1252,25 @@ static int mis4001_set_ctrl(struct v4l2_ctrl *ctrl) MIS4001_REG_EXPOSURE_L, MIS4001_REG_VALUE_08BIT, MIS4001_FETCH_EXP_L(val)); + + /* Special strategy: To solve the problem of exposure layering: + * When the exposure is not fully filled, the gain will be increased, + * resulting in layering phenomenon + */ + + //When the exposure time is 1/200 (0.005) s, the exp register is 196 + expmin = (mis4001->cur_mode->max_fps.denominator / mis4001->cur_mode->max_fps.numerator) + * mis4001->cur_mode->vts_def * 1 / 200; + expmax = mis4001->cur_mode->vts_def - expmin; + if (((expmin <= val) && (expmax >= val))) + u32Reg0x4007 = 0x78; + else + u32Reg0x4007 = 0xc4; + + ret |= mis4001_write_reg(mis4001->client, + 0x4007, + MIS4001_REG_VALUE_08BIT, + u32Reg0x4007); } break; case V4L2_CID_ANALOGUE_GAIN: @@ -1254,17 +1280,29 @@ static int mis4001_set_ctrl(struct v4l2_ctrl *ctrl) break; case V4L2_CID_VBLANK: dev_dbg(&client->dev, "set vblank 0x%x\n", ctrl->val); + mis4001->cur_vts = ctrl->val + mis4001->cur_mode->height; ret = mis4001_write_reg(mis4001->client, - MIS4001_REG_VTS_H, + MIS4001_REG_CTRL_MODE, MIS4001_REG_VALUE_08BIT, - (ctrl->val + mis4001->cur_mode->height) - >> 8); + 0x02); + sleep_time = mis4001->cur_mode->max_fps.denominator / mis4001->cur_mode->max_fps.numerator * + mis4001->cur_mode->vts_def / mis4001->cur_vts; + sleep_time = div_u64(1000000, sleep_time); + usleep_range(sleep_time, sleep_time + 1000); + ret |= mis4001_write_reg(mis4001->client, + MIS4001_REG_VTS_H, + MIS4001_REG_VALUE_08BIT, + (ctrl->val + mis4001->cur_mode->height) + >> 8); ret |= mis4001_write_reg(mis4001->client, MIS4001_REG_VTS_L, MIS4001_REG_VALUE_08BIT, (ctrl->val + mis4001->cur_mode->height) & 0xff); - mis4001->cur_vts = ctrl->val + mis4001->cur_mode->height; + ret |= mis4001_write_reg(mis4001->client, + MIS4001_REG_CTRL_MODE, + MIS4001_REG_VALUE_08BIT, + 0x00); if (mis4001->cur_vts != mis4001->cur_mode->vts_def) mis4001_modify_fps_info(mis4001); break; @@ -1294,38 +1332,6 @@ static int mis4001_set_ctrl(struct v4l2_ctrl *ctrl) __func__, ctrl->id, ctrl->val); break; } - ret = mis4001_read_reg(mis4001->client, - MIS4001_REG_ANA_GAIN, - MIS4001_REG_VALUE_08BIT, - &u32Read0x3102); - ret |= mis4001_read_reg(mis4001->client, - MIS4001_REG_EXPOSURE_H, - MIS4001_REG_VALUE_08BIT, - &exp_h); - ret |= mis4001_read_reg(mis4001->client, - MIS4001_REG_EXPOSURE_L, - MIS4001_REG_VALUE_08BIT, - &exp_l); - exp_value = ((exp_h << 8) | exp_l); - - /* Special strategy: To solve the problem of exposure layering: - * When the exposure is not fully filled, the gain will be increased, - * resulting in layering phenomenon */ - - //When the exposure time is 1/200 (0.005) s, the exp register is 196 - expmin = (mis4001->cur_mode->max_fps.denominator / mis4001->cur_mode->max_fps.numerator) - * mis4001->cur_mode->vts_def * 1/200; - expmax = mis4001->cur_mode->vts_def - expmin; - if((127 == u32Read0x3102) && - ((expmin <= exp_value) && (expmax >= exp_value))) - u32Reg0x4007 = 0x78; - else - u32Reg0x4007 = 0xc4; - - ret = mis4001_write_reg(mis4001->client, - 0x4007, - MIS4001_REG_VALUE_08BIT, - u32Reg0x4007); pm_runtime_put(&client->dev); diff --git a/drivers/media/platform/rockchip/isp/isp_params_v21.c b/drivers/media/platform/rockchip/isp/isp_params_v21.c index 6fac6ab466d1..e13e97ca53d0 100644 --- a/drivers/media/platform/rockchip/isp/isp_params_v21.c +++ b/drivers/media/platform/rockchip/isp/isp_params_v21.c @@ -1178,6 +1178,12 @@ isp_rawaebig_config(struct rkisp_isp_params_vdev *params_vdev, ISP2X_REG_WR_MASK); wnd_num_idx = arg->wnd_num; + if (wnd_num_idx >= ARRAY_SIZE(ae_wnd_num)) { + wnd_num_idx = ARRAY_SIZE(ae_wnd_num) - 1; + dev_err(params_vdev->dev->dev, + "%s invalid wnd_num:%d, set to %d\n", + __func__, arg->wnd_num, wnd_num_idx); + } value |= ISP2X_RAWAEBIG_WNDNUM_SET(wnd_num_idx); if (arg->subwin_en[0]) @@ -2291,6 +2297,12 @@ isp_rawhstbig_cfg_sram(struct rkisp_isp_params_vdev *params_vdev, return; wnd_num_idx = arg->wnd_num; + if (wnd_num_idx >= ARRAY_SIZE(hist_wnd_num)) { + wnd_num_idx = ARRAY_SIZE(hist_wnd_num) - 1; + dev_err(params_vdev->dev->dev, + "%s invalid wnd_num:%d, set to %d\n", + __func__, arg->wnd_num, wnd_num_idx); + } memset(weight15x15, 0, sizeof(weight15x15)); for (i = 0; i < hist_wnd_num[wnd_num_idx]; i++) { for (j = 0; j < hist_wnd_num[wnd_num_idx]; j++) { @@ -2338,6 +2350,12 @@ isp_rawhstbig_config(struct rkisp_isp_params_vdev *params_vdev, } wnd_num_idx = arg->wnd_num; + if (wnd_num_idx >= ARRAY_SIZE(hist_wnd_num)) { + wnd_num_idx = ARRAY_SIZE(hist_wnd_num) - 1; + dev_err(params_vdev->dev->dev, + "%s invalid wnd_num:%d, set to %d\n", + __func__, arg->wnd_num, wnd_num_idx); + } /* avoid to override the old enable value */ hist_ctrl = rkisp_ioread32(params_vdev, addr + ISP_RAWHIST_BIG_CTRL); hist_ctrl &= ISP2X_RAWHSTBIG_CTRL_EN_MASK; diff --git a/drivers/media/platform/rockchip/isp/isp_params_v2x.c b/drivers/media/platform/rockchip/isp/isp_params_v2x.c index 2877ab1d2fd8..c1497a92ffd1 100644 --- a/drivers/media/platform/rockchip/isp/isp_params_v2x.c +++ b/drivers/media/platform/rockchip/isp/isp_params_v2x.c @@ -461,6 +461,12 @@ isp_sihst_config(struct rkisp_isp_params_vdev *params_vdev, }; wnd_num_idx = arg->wnd_num; + if (wnd_num_idx >= ARRAY_SIZE(hist_wnd_num)) { + wnd_num_idx = ARRAY_SIZE(hist_wnd_num) - 1; + dev_err(params_vdev->dev->dev, + "%s invalid wnd_num:%d, set to %d\n", + __func__, arg->wnd_num, wnd_num_idx); + } for (i = 0; i < ISP2X_SIHIST_WIN_NUM; i++) { /* avoid to override the old enable value */ hist_ctrl = rkisp_ioread32(params_vdev, ISP_HIST_HIST_CTRL + i * 0x10); @@ -1758,6 +1764,12 @@ isp_rawaebig_config(struct rkisp_isp_params_vdev *params_vdev, ISP2X_REG_WR_MASK); wnd_num_idx = arg->wnd_num; + if (wnd_num_idx >= ARRAY_SIZE(ae_wnd_num)) { + wnd_num_idx = ARRAY_SIZE(ae_wnd_num) - 1; + dev_err(params_vdev->dev->dev, + "%s invalid wnd_num:%d, set to %d\n", + __func__, arg->wnd_num, wnd_num_idx); + } value |= ISP2X_RAWAEBIG_WNDNUM_SET(wnd_num_idx); if (arg->subwin_en[0]) @@ -2831,6 +2843,12 @@ isp_rawhstbig_cfg_sram(struct rkisp_isp_params_vdev *params_vdev, return; wnd_num_idx = arg->wnd_num; + if (wnd_num_idx >= ARRAY_SIZE(hist_wnd_num)) { + wnd_num_idx = ARRAY_SIZE(hist_wnd_num) - 1; + dev_err(params_vdev->dev->dev, + "%s invalid wnd_num:%d, set to %d\n", + __func__, arg->wnd_num, wnd_num_idx); + } memset(weight15x15, 0, sizeof(weight15x15)); for (i = 0; i < hist_wnd_num[wnd_num_idx]; i++) { for (j = 0; j < hist_wnd_num[wnd_num_idx]; j++) { @@ -2879,6 +2897,12 @@ isp_rawhstbig_config(struct rkisp_isp_params_vdev *params_vdev, } wnd_num_idx = arg->wnd_num; + if (wnd_num_idx >= ARRAY_SIZE(hist_wnd_num)) { + wnd_num_idx = ARRAY_SIZE(hist_wnd_num) - 1; + dev_err(params_vdev->dev->dev, + "%s invalid wnd_num:%d, set to %d\n", + __func__, arg->wnd_num, wnd_num_idx); + } /* avoid to override the old enable value */ hist_ctrl = rkisp_ioread32(params_vdev, addr + ISP_RAWHIST_BIG_CTRL); hist_ctrl &= ISP2X_RAWHSTBIG_CTRL_EN_MASK; diff --git a/drivers/media/platform/rockchip/isp/isp_params_v32.c b/drivers/media/platform/rockchip/isp/isp_params_v32.c index 255451cf7fee..ebc0b707b916 100644 --- a/drivers/media/platform/rockchip/isp/isp_params_v32.c +++ b/drivers/media/platform/rockchip/isp/isp_params_v32.c @@ -1436,6 +1436,12 @@ isp_rawaebig_config(struct rkisp_isp_params_vdev *params_vdev, value &= ISP3X_RAWAE_BIG_EN; wnd_num_idx = arg->wnd_num; + if (wnd_num_idx >= ARRAY_SIZE(ae_wnd_num)) { + wnd_num_idx = ARRAY_SIZE(ae_wnd_num) - 1; + dev_err(params_vdev->dev->dev, + "%s invalid wnd_num:%d, set to %d\n", + __func__, arg->wnd_num, wnd_num_idx); + } value |= ISP3X_RAWAE_BIG_WND0_NUM(wnd_num_idx); if (arg->subwin_en[0]) @@ -2413,6 +2419,12 @@ isp_rawhstbig_cfg_sram(struct rkisp_isp_params_vdev *params_vdev, return; wnd_num_idx = arg->wnd_num; + if (wnd_num_idx >= ARRAY_SIZE(hist_wnd_num)) { + wnd_num_idx = ARRAY_SIZE(hist_wnd_num) - 1; + dev_err(params_vdev->dev->dev, + "%s invalid wnd_num:%d, set to %d\n", + __func__, arg->wnd_num, wnd_num_idx); + } memset(weight15x15, 0, sizeof(weight15x15)); for (i = 0; i < hist_wnd_num[wnd_num_idx]; i++) { for (j = 0; j < hist_wnd_num[wnd_num_idx]; j++) { @@ -2463,6 +2475,12 @@ isp_rawhstbig_config(struct rkisp_isp_params_vdev *params_vdev, } wnd_num_idx = arg->wnd_num; + if (wnd_num_idx >= ARRAY_SIZE(hist_wnd_num)) { + wnd_num_idx = ARRAY_SIZE(hist_wnd_num) - 1; + dev_err(params_vdev->dev->dev, + "%s invalid wnd_num:%d, set to %d\n", + __func__, arg->wnd_num, wnd_num_idx); + } /* avoid to override the old enable value */ hist_ctrl = isp3_param_read(params_vdev, addr + ISP3X_RAWHIST_BIG_CTRL, id); hist_ctrl &= ISP3X_RAWHIST_EN; diff --git a/drivers/media/platform/rockchip/isp/isp_params_v3x.c b/drivers/media/platform/rockchip/isp/isp_params_v3x.c index 2478c09d7062..0491cc9bd8ba 100644 --- a/drivers/media/platform/rockchip/isp/isp_params_v3x.c +++ b/drivers/media/platform/rockchip/isp/isp_params_v3x.c @@ -1291,6 +1291,12 @@ isp_rawaebig_config(struct rkisp_isp_params_vdev *params_vdev, value &= ISP3X_RAWAE_BIG_EN; wnd_num_idx = arg->wnd_num; + if (wnd_num_idx >= ARRAY_SIZE(ae_wnd_num)) { + wnd_num_idx = ARRAY_SIZE(ae_wnd_num) - 1; + dev_err(params_vdev->dev->dev, + "%s invalid wnd_num:%d, set to %d\n", + __func__, arg->wnd_num, wnd_num_idx); + } value |= ISP3X_RAWAE_BIG_WND0_NUM(wnd_num_idx); if (arg->subwin_en[0]) @@ -2424,6 +2430,12 @@ isp_rawhstbig_cfg_sram(struct rkisp_isp_params_vdev *params_vdev, return; wnd_num_idx = arg->wnd_num; + if (wnd_num_idx >= ARRAY_SIZE(hist_wnd_num)) { + wnd_num_idx = ARRAY_SIZE(hist_wnd_num) - 1; + dev_err(params_vdev->dev->dev, + "%s invalid wnd_num:%d, set to %d\n", + __func__, arg->wnd_num, wnd_num_idx); + } memset(weight15x15, 0, sizeof(weight15x15)); for (i = 0; i < hist_wnd_num[wnd_num_idx]; i++) { for (j = 0; j < hist_wnd_num[wnd_num_idx]; j++) { @@ -2471,6 +2483,12 @@ isp_rawhstbig_config(struct rkisp_isp_params_vdev *params_vdev, } wnd_num_idx = arg->wnd_num; + if (wnd_num_idx >= ARRAY_SIZE(hist_wnd_num)) { + wnd_num_idx = ARRAY_SIZE(hist_wnd_num) - 1; + dev_err(params_vdev->dev->dev, + "%s invalid wnd_num:%d, set to %d\n", + __func__, arg->wnd_num, wnd_num_idx); + } /* avoid to override the old enable value */ hist_ctrl = isp3_param_read(params_vdev, addr + ISP3X_RAWHIST_BIG_CTRL, id); hist_ctrl &= ISP3X_RAWHIST_EN; diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index 02b1a828ad93..a8d994135524 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig @@ -1274,6 +1274,14 @@ config MFD_RK806 through SPI interface. The device supports multiple sub-devices including interrupts, LDO & DCDC regulators, and onkey. +config MFD_RK806_I2C + tristate "RK806 Power Management chip with I2C" + select MFD_RK806 + select REGMAP_I2C + select REGMAP_IRQ + help + If you say yes here you get support for the RK806 PM chips with I2c interface. + config MFD_RK806_SPI tristate "RK806 Power Management chip with SPI" select MFD_RK806 diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile index 7e348d555e54..b482699a05b6 100644 --- a/drivers/mfd/Makefile +++ b/drivers/mfd/Makefile @@ -231,6 +231,7 @@ obj-$(CONFIG_MFD_RK630) += rk630.o obj-$(CONFIG_MFD_RK630_I2C) += rk630-i2c.o obj-$(CONFIG_MFD_RK630_SPI) += rk630-spi.o obj-$(CONFIG_MFD_RK806) += rk806-core.o +obj-$(CONFIG_MFD_RK806_I2C) += rk806-i2c.o obj-$(CONFIG_MFD_RK806_SPI) += rk806-spi.o obj-$(CONFIG_MFD_RK808) += rk808.o obj-$(CONFIG_MFD_RK1000) += rk1000-core.o diff --git a/drivers/mfd/rk806-core.c b/drivers/mfd/rk806-core.c index 5421ac95578f..1ab83fbf397c 100644 --- a/drivers/mfd/rk806-core.c +++ b/drivers/mfd/rk806-core.c @@ -352,13 +352,13 @@ static const struct regmap_access_table rk806_volatile_table = { .n_yes_ranges = ARRAY_SIZE(rk806_yes_ranges), }; -const struct regmap_config rk806_regmap_config_spi = { +const struct regmap_config rk806_regmap_config = { .reg_bits = 8, .val_bits = 8, .cache_type = REGCACHE_RBTREE, .volatile_table = &rk806_volatile_table, }; -EXPORT_SYMBOL_GPL(rk806_regmap_config_spi); +EXPORT_SYMBOL_GPL(rk806_regmap_config); static struct kobject *rk806_kobj[2]; static struct rk806 *rk806_master; @@ -825,6 +825,12 @@ int rk806_device_exit(struct rk806 *rk806) } EXPORT_SYMBOL_GPL(rk806_device_exit); +const struct of_device_id rk806_of_match[] = { + { .compatible = "rockchip,rk806", }, + { } +}; +EXPORT_SYMBOL_GPL(rk806_of_match); + MODULE_AUTHOR("Xu Shengfei "); MODULE_DESCRIPTION("rk806 MFD Driver"); MODULE_LICENSE("GPL v2"); diff --git a/drivers/mfd/rk806-i2c.c b/drivers/mfd/rk806-i2c.c new file mode 100644 index 000000000000..26558e90d1fe --- /dev/null +++ b/drivers/mfd/rk806-i2c.c @@ -0,0 +1,62 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * rk806-i2c.c -- I2C access for Rockchip RK806 + * + * Copyright (c) 2023 Rockchip Electronics Co., Ltd. + * + * Author: Xu Shengfei + */ + +#include +#include +#include + +static int rk806_i2c_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct rk806 *rk806; + + rk806 = devm_kzalloc(&client->dev, sizeof(*rk806), GFP_KERNEL); + if (!rk806) + return -ENOMEM; + + i2c_set_clientdata(client, rk806); + rk806->dev = &client->dev; + rk806->irq = client->irq; + + if (!client->irq) { + dev_err(&client->dev, "No interrupt support, no core IRQ\n"); + return -EINVAL; + } + + rk806->regmap = devm_regmap_init_i2c(client, &rk806_regmap_config); + if (IS_ERR(rk806->regmap)) { + dev_err(&client->dev, "regmap initialization failed\n"); + return PTR_ERR(rk806->regmap); + } + + return rk806_device_init(rk806); +} + +static int rk806_remove(struct i2c_client *client) +{ + struct rk806 *rk806 = i2c_get_clientdata(client); + + rk806_device_exit(rk806); + + return 0; +} + +static struct i2c_driver rk806_i2c_driver = { + .driver = { + .name = "rk806", + .of_match_table = of_match_ptr(rk806_of_match), + }, + .probe = rk806_i2c_probe, + .remove = rk806_remove, +}; +module_i2c_driver(rk806_i2c_driver); + +MODULE_AUTHOR("Xu Shengfei "); +MODULE_DESCRIPTION("RK806 I2C Interface Driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/mfd/rk806-spi.c b/drivers/mfd/rk806-spi.c index ed4b7511bd88..c1053078558a 100644 --- a/drivers/mfd/rk806-spi.c +++ b/drivers/mfd/rk806-spi.c @@ -12,12 +12,6 @@ #include #include -static const struct of_device_id rk806_spi_of_match_table[] = { - { .compatible = "rockchip,rk806", }, - { } -}; -MODULE_DEVICE_TABLE(of, rk806_spi_of_match_table); - static int rk806_spi_write(struct spi_device *spi, char addr, const char *data, @@ -101,7 +95,7 @@ static int rk806_spi_probe(struct spi_device *spi) rk806->regmap = devm_regmap_init(&spi->dev, &rk806_regmap_bus_spi, &spi->dev, - &rk806_regmap_config_spi); + &rk806_regmap_config); if (IS_ERR(rk806->regmap)) { dev_err(rk806->dev, "Failed to initialize register map\n"); return PTR_ERR(rk806->regmap); @@ -127,7 +121,7 @@ static struct spi_driver rk806_spi_driver = { .driver = { .name = "rk806", .owner = THIS_MODULE, - .of_match_table = rk806_spi_of_match_table, + .of_match_table = of_match_ptr(rk806_of_match), }, .probe = rk806_spi_probe, .remove = rk806_spi_remove, diff --git a/drivers/misc/rockchip/pcie-rkep.c b/drivers/misc/rockchip/pcie-rkep.c index 70b0e9eb50c3..cc45f5bf3c32 100644 --- a/drivers/misc/rockchip/pcie-rkep.c +++ b/drivers/misc/rockchip/pcie-rkep.c @@ -91,6 +91,10 @@ static DEFINE_MUTEX(rkep_mutex); #define RKEP_EP_VIRTUAL_ID_MAX (8 * 4096) #define RKEP_EP_ELBI_TIEMOUT_US 100000 +#define PCIE_RK3568_RC_DBI_BASE 0xf6000000 +#define PCIE_RK3588_RC_DBI_BASE 0xf5000000 +#define PCIE_DBI_SIZE 0x400000 + struct pcie_rkep_msix_context { struct pci_dev *dev; u16 msg_id; @@ -102,12 +106,14 @@ struct pcie_rkep { void __iomem *bar0; void __iomem *bar2; void __iomem *bar4; - struct miscdevice dev; + int cur_mmap_res; struct msix_entry msix_entries[RKEP_NUM_MSIX_VECTORS]; struct pcie_rkep_msix_context msix_ctx[RKEP_NUM_MSIX_VECTORS]; struct pcie_rkep_msix_context msi_ctx[RKEP_NUM_MSI_VECTORS]; bool msi_enable; bool msix_enable; + + struct miscdevice dev; struct dma_trx_obj *dma_obj; struct pcie_ep_obj_info *obj_info; struct page *user_pages; /* Allocated physical memory for user space */ @@ -275,33 +281,73 @@ static ssize_t pcie_rkep_write(struct file *file, const char __user *buf, { struct pcie_file *pcie_file = file->private_data; struct pcie_rkep *pcie_rkep = pcie_file->pcie_rkep; - u32 *bar0_buf; - int loop, i = 0; - size_t raw_count = count; + struct pci_dev *dev = pcie_rkep->pdev; + unsigned int size = count; + loff_t init_off = *ppos, off = *ppos; + u8 *data; - count = (count % 4) ? (count - count % 4) : count; - - if (count > BAR_0_SZ) - return -EINVAL; - - bar0_buf = kzalloc(count, GFP_KERNEL); - if (!bar0_buf) + data = kzalloc(PCI_CFG_SPACE_EXP_SIZE, GFP_KERNEL); + if (!data) return -ENOMEM; - if (copy_from_user(bar0_buf, buf, count)) { - raw_count = -EFAULT; - goto exit; + if (off > dev->cfg_size) { + kfree(data); + return 0; + } + if (off + count > dev->cfg_size) { + size = dev->cfg_size - off; + count = size; } - for (loop = 0; loop < count / 4; loop++) { - iowrite32(bar0_buf[i], pcie_rkep->bar0 + loop * 4); - i++; + if (copy_from_user(data, buf, count)) { + kfree(data); + return -EFAULT; } -exit: - kfree(bar0_buf); + if ((off & 1) && size) { + pci_write_config_byte(dev, off, data[off - init_off]); + off++; + size--; + } - return raw_count; + if ((off & 3) && size > 2) { + u16 val = data[off - init_off]; + + val |= (u16) data[off - init_off + 1] << 8; + pci_write_config_word(dev, off, val); + off += 2; + size -= 2; + } + + while (size > 3) { + u32 val = data[off - init_off]; + + val |= (u32) data[off - init_off + 1] << 8; + val |= (u32) data[off - init_off + 2] << 16; + val |= (u32) data[off - init_off + 3] << 24; + pci_write_config_dword(dev, off, val); + off += 4; + size -= 4; + } + + if (size >= 2) { + u16 val = data[off - init_off]; + + val |= (u16) data[off - init_off + 1] << 8; + pci_write_config_word(dev, off, val); + off += 2; + size -= 2; + } + + if (size) { + pci_write_config_byte(dev, off, data[off - init_off]); + off++; + --size; + } + + kfree(data); + + return count; } static ssize_t pcie_rkep_read(struct file *file, char __user *buf, @@ -309,33 +355,82 @@ static ssize_t pcie_rkep_read(struct file *file, char __user *buf, { struct pcie_file *pcie_file = file->private_data; struct pcie_rkep *pcie_rkep = pcie_file->pcie_rkep; - u32 *bar0_buf; - int loop, i = 0; - size_t raw_count = count; + struct pci_dev *dev = pcie_rkep->pdev; + unsigned int size = count; + loff_t init_off = *ppos, off = *ppos; + u8 *data; - count = (count % 4) ? (count - count % 4) : count; - - if (count > BAR_0_SZ) - return -EINVAL; - - bar0_buf = kzalloc(count, GFP_ATOMIC); - if (!bar0_buf) + data = kzalloc(PCI_CFG_SPACE_EXP_SIZE, GFP_KERNEL); + if (!data) return -ENOMEM; - for (loop = 0; loop < count / 4; loop++) { - bar0_buf[i] = ioread32(pcie_rkep->bar0 + loop * 4); - i++; + if (off > dev->cfg_size) { + kfree(data); + return 0; + } + if (off + count > dev->cfg_size) { + size = dev->cfg_size - off; + count = size; } - if (copy_to_user(buf, bar0_buf, count)) { - raw_count = -EFAULT; - goto exit; + if ((off & 1) && size) { + u8 val; + + pci_read_config_byte(dev, off, &val); + data[off - init_off] = val; + off++; + size--; } -exit: - kfree(bar0_buf); + if ((off & 3) && size > 2) { + u16 val; - return raw_count; + pci_read_config_word(dev, off, &val); + data[off - init_off] = val & 0xff; + data[off - init_off + 1] = (val >> 8) & 0xff; + off += 2; + size -= 2; + } + + while (size > 3) { + u32 val; + + pci_read_config_dword(dev, off, &val); + data[off - init_off] = val & 0xff; + data[off - init_off + 1] = (val >> 8) & 0xff; + data[off - init_off + 2] = (val >> 16) & 0xff; + data[off - init_off + 3] = (val >> 24) & 0xff; + off += 4; + size -= 4; + } + + if (size >= 2) { + u16 val; + + pci_read_config_word(dev, off, &val); + data[off - init_off] = val & 0xff; + data[off - init_off + 1] = (val >> 8) & 0xff; + off += 2; + size -= 2; + } + + if (size > 0) { + u8 val; + + pci_read_config_byte(dev, off, &val); + data[off - init_off] = val; + off++; + --size; + } + + if (copy_to_user(buf, data, count)) { + kfree(data); + return -EFAULT; + } + + kfree(data); + + return count; } static int pcie_rkep_mmap(struct file *file, struct vm_area_struct *vma) @@ -343,26 +438,81 @@ static int pcie_rkep_mmap(struct file *file, struct vm_area_struct *vma) u64 addr; struct pcie_file *pcie_file = file->private_data; struct pcie_rkep *pcie_rkep = pcie_file->pcie_rkep; + struct pci_dev *dev = pcie_rkep->pdev; size_t size = vma->vm_end - vma->vm_start; + resource_size_t bar_size; + int err; - if (size > RKEP_USER_MEM_SIZE) { - dev_warn(&pcie_rkep->pdev->dev, "mmap size is out of limitation\n"); + switch (pcie_rkep->cur_mmap_res) { + case PCIE_EP_MMAP_RESOURCE_RK3568_RC_DBI: + if (size > PCIE_DBI_SIZE) { + dev_warn(&pcie_rkep->pdev->dev, "dbi mmap size is out of limitation\n"); + return -EINVAL; + } + addr = PCIE_RK3568_RC_DBI_BASE; + break; + case PCIE_EP_MMAP_RESOURCE_RK3588_RC_DBI: + if (size > PCIE_DBI_SIZE) { + dev_warn(&pcie_rkep->pdev->dev, "dbi mmap size is out of limitation\n"); + return -EINVAL; + } + addr = PCIE_RK3588_RC_DBI_BASE; + break; + case PCIE_EP_MMAP_RESOURCE_BAR0: + bar_size = pci_resource_len(dev, 0); + if (size > bar_size) { + dev_warn(&pcie_rkep->pdev->dev, "bar0 mmap size is out of limitation\n"); + return -EINVAL; + } + addr = pci_resource_start(dev, 0); + break; + case PCIE_EP_MMAP_RESOURCE_BAR2: + bar_size = pci_resource_len(dev, 2); + if (size > bar_size) { + dev_warn(&pcie_rkep->pdev->dev, "bar2 mmap size is out of limitation\n"); + return -EINVAL; + } + addr = pci_resource_start(dev, 2); + break; + case PCIE_EP_MMAP_RESOURCE_BAR4: + bar_size = pci_resource_len(dev, 4); + if (size > bar_size) { + dev_warn(&pcie_rkep->pdev->dev, "bar4 mmap size is out of limitation\n"); + return -EINVAL; + } + addr = pci_resource_start(dev, 4); + break; + case PCIE_EP_MMAP_RESOURCE_USER_MEM: + if (size > RKEP_USER_MEM_SIZE) { + dev_warn(&pcie_rkep->pdev->dev, "mmap size is out of limitation\n"); + return -EINVAL; + } + + if (!pcie_rkep->user_pages) { + dev_warn(&pcie_rkep->pdev->dev, "user_pages has not been allocated yet\n"); + return -EINVAL; + } + addr = page_to_phys(pcie_rkep->user_pages); + break; + default: + dev_err(&pcie_rkep->pdev->dev, "cur mmap_res %d is unsurreport\n", pcie_rkep->cur_mmap_res); return -EINVAL; } - if (!pcie_rkep->user_pages) { - dev_warn(&pcie_rkep->pdev->dev, "user_pages has not been allocated yet\n"); - return -EINVAL; - } - - addr = page_to_phys(pcie_rkep->user_pages); vma->vm_flags |= VM_IO; - vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot); + vma->vm_flags |= (VM_DONTEXPAND | VM_DONTDUMP); - if (io_remap_pfn_range(vma, vma->vm_start, addr >> PAGE_SHIFT, size, vma->vm_page_prot)) { - dev_err(&pcie_rkep->pdev->dev, "io_remap_pfn_range failed\n"); + if (pcie_rkep->cur_mmap_res == PCIE_EP_MMAP_RESOURCE_BAR2 || + pcie_rkep->cur_mmap_res == PCIE_EP_MMAP_RESOURCE_USER_MEM) + vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot); + else + vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); + + err = remap_pfn_range(vma, vma->vm_start, + __phys_to_pfn(addr), + size, vma->vm_page_prot); + if (err) return -EAGAIN; - } return 0; } @@ -375,6 +525,7 @@ static long pcie_rkep_ioctl(struct file *file, unsigned int cmd, unsigned long a struct pcie_ep_dma_cache_cfg cfg; struct pcie_ep_dma_block_req dma; void __user *uarg = (void __user *)args; + int mmap_res; int ret; int index; u64 addr; @@ -462,6 +613,20 @@ static long pcie_rkep_ioctl(struct file *file, unsigned int cmd, unsigned long a return -EFAULT; } break; + case PCIE_EP_SET_MMAP_RESOURCE: + ret = copy_from_user(&mmap_res, uarg, sizeof(mmap_res)); + if (ret) { + dev_err(&pcie_rkep->pdev->dev, "failed to get copy from\n"); + return -EFAULT; + } + + if (mmap_res >= PCIE_EP_MMAP_RESOURCE_MAX || mmap_res < 0) { + dev_err(&pcie_rkep->pdev->dev, "mmap index %d is out of number\n", mmap_res); + return -EINVAL; + } + + pcie_rkep->cur_mmap_res = mmap_res; + break; default: break; } @@ -478,7 +643,7 @@ static const struct file_operations pcie_rkep_fops = { .mmap = pcie_rkep_mmap, .fasync = pcie_rkep_fasync, .release = pcie_rkep_release, - .llseek = no_llseek, + .llseek = default_llseek, }; static inline void pcie_rkep_writel_dbi(struct pcie_rkep *pcie_rkep, u32 reg, u32 val) @@ -985,6 +1150,7 @@ static int pcie_rkep_probe(struct pci_dev *pdev, const struct pci_device_id *id) pcie_dw_dmatest_unregister(pcie_rkep->dma_obj); goto err_register_obj; } + pcie_rkep->cur_mmap_res = PCIE_EP_MMAP_RESOURCE_USER_MEM; dev_err(&pdev->dev, "successfully allocate continuouse buffer for userspace\n"); #endif diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c index 12ebda64592f..28bdf6f2b54b 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c @@ -25,6 +25,7 @@ #include #include #include +#include #include "stmmac_platform.h" #include "dwmac-rk-tool.h" @@ -82,6 +83,9 @@ struct rk_priv_data { unsigned char otp_data; unsigned int bgs_increment; + + struct csu_clk *csu_aclk; + struct csu_clk *csu_pclk; }; /* XPCS */ @@ -2354,6 +2358,21 @@ static int rk_gmac_clk_init(struct plat_stmmacenet_data *plat) return 0; } +static int rk_gmac_csu_init(struct plat_stmmacenet_data *plat) +{ + struct rk_priv_data *bsp_priv = plat->bsp_priv; + struct device *dev = &bsp_priv->pdev->dev; + + bsp_priv->csu_aclk = rockchip_csu_get(dev, "aclk"); + if (IS_ERR(bsp_priv->csu_aclk)) + bsp_priv->csu_aclk = NULL; + bsp_priv->csu_pclk = rockchip_csu_get(dev, "pclk"); + if (IS_ERR(bsp_priv->csu_pclk)) + bsp_priv->csu_pclk = NULL; + + return 0; +} + static int gmac_clk_enable(struct rk_priv_data *bsp_priv, bool enable) { int phy_iface = bsp_priv->phy_iface; @@ -2399,6 +2418,9 @@ static int gmac_clk_enable(struct rk_priv_data *bsp_priv, bool enable) bsp_priv->ops->set_clock_selection(bsp_priv, bsp_priv->clock_input, true); + rockchip_csu_disable(bsp_priv->csu_aclk); + rockchip_csu_disable(bsp_priv->csu_pclk); + /** * if (!IS_ERR(bsp_priv->clk_mac)) * clk_prepare_enable(bsp_priv->clk_mac); @@ -2434,6 +2456,9 @@ static int gmac_clk_enable(struct rk_priv_data *bsp_priv, bool enable) clk_disable_unprepare(bsp_priv->clk_xpcs_eee); + rockchip_csu_enable(bsp_priv->csu_aclk); + rockchip_csu_enable(bsp_priv->csu_pclk); + /** * if (!IS_ERR(bsp_priv->clk_mac)) * clk_disable_unprepare(bsp_priv->clk_mac); @@ -2866,6 +2891,8 @@ static int rk_gmac_probe(struct platform_device *pdev) goto err_remove_config_dt; } + rk_gmac_csu_init(plat_dat); + ret = rk_gmac_clk_init(plat_dat); if (ret) goto err_remove_config_dt; diff --git a/drivers/pci/controller/dwc/pcie-dw-rockchip.c b/drivers/pci/controller/dwc/pcie-dw-rockchip.c index 839b2e9b6a05..797935ee99cd 100644 --- a/drivers/pci/controller/dwc/pcie-dw-rockchip.c +++ b/drivers/pci/controller/dwc/pcie-dw-rockchip.c @@ -8,6 +8,7 @@ * Author: Simon Xue */ +#include #include #include #include @@ -2175,6 +2176,12 @@ static int __maybe_unused rockchip_dw_pcie_suspend(struct device *dev) no_l2: rk_pcie_disable_ltssm(rk_pcie); + ret = phy_validate(rk_pcie->phy, PHY_TYPE_PCIE, 0, NULL); + if (ret && ret != -EOPNOTSUPP) { + dev_err(dev, "PHY is reused by other controller, check the dts!\n"); + return ret; + } + /* make sure assert phy success */ usleep_range(200, 300); diff --git a/drivers/phy/rockchip/phy-rockchip-naneng-combphy.c b/drivers/phy/rockchip/phy-rockchip-naneng-combphy.c index 5a41b9c04568..e9fcc9eb0961 100644 --- a/drivers/phy/rockchip/phy-rockchip-naneng-combphy.c +++ b/drivers/phy/rockchip/phy-rockchip-naneng-combphy.c @@ -275,9 +275,42 @@ static int rockchip_combphy_exit(struct phy *phy) return 0; } +static const char *rockchip_combphy_mode2str(enum phy_mode mode) +{ + switch (mode) { + case PHY_TYPE_SATA: + return "SATA"; + case PHY_TYPE_PCIE: + return "PCIe"; + case PHY_TYPE_USB3: + return "USB3"; + case PHY_TYPE_SGMII: + case PHY_TYPE_QSGMII: + return "GMII"; + default: + return "Unknown"; + } +} + +static int rockchip_combphy_validate(struct phy *phy, enum phy_mode mode, int submode, + union phy_configure_opts *opts) +{ + struct rockchip_combphy_priv *priv = phy_get_drvdata(phy); + + if (mode != priv->mode) { + dev_err(priv->dev, "expected mode is %s, but current mode is %s\n", + rockchip_combphy_mode2str(mode), + rockchip_combphy_mode2str(priv->mode)); + return -EINVAL; + } + + return 0; +} + static const struct phy_ops rochchip_combphy_ops = { .init = rockchip_combphy_init, .exit = rockchip_combphy_exit, + .validate = rockchip_combphy_validate, .owner = THIS_MODULE, }; diff --git a/drivers/soc/rockchip/Kconfig b/drivers/soc/rockchip/Kconfig index 732894afa71f..a3a87aa7ccf1 100644 --- a/drivers/soc/rockchip/Kconfig +++ b/drivers/soc/rockchip/Kconfig @@ -44,6 +44,12 @@ config ROCKCHIP_CPUINFO If unsure, say N. +config ROCKCHIP_CSU + tristate "Rockchip Clock Subunit Driver" + depends on ARCH_ROCKCHIP + help + This adds the clock subunit driver for Rockchip SoCs. + config ROCKCHIP_GRF tristate "Rockchip General Register Files support" help diff --git a/drivers/soc/rockchip/Makefile b/drivers/soc/rockchip/Makefile index d447a620c48d..af49767415c5 100644 --- a/drivers/soc/rockchip/Makefile +++ b/drivers/soc/rockchip/Makefile @@ -4,6 +4,7 @@ # obj-$(CONFIG_ROCKCHIP_AMP) += rockchip_amp.o obj-$(CONFIG_ROCKCHIP_CPUINFO) += rockchip-cpuinfo.o +obj-$(CONFIG_ROCKCHIP_CSU) += rockchip_csu.o obj-$(CONFIG_ROCKCHIP_GRF) += grf.o obj-$(CONFIG_ROCKCHIP_HW_DECOMPRESS) += rockchip_decompress.o obj-$(CONFIG_ROCKCHIP_HW_DECOMPRESS_USER) += rockchip_decompress_user.o diff --git a/drivers/soc/rockchip/rockchip_csu.c b/drivers/soc/rockchip/rockchip_csu.c new file mode 100644 index 000000000000..04a6a5b39715 --- /dev/null +++ b/drivers/soc/rockchip/rockchip_csu.c @@ -0,0 +1,377 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2023, Rockchip Electronics Co., Ltd. + * Author: Finley Xiao + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +struct csu_bus { + unsigned int id; + unsigned int cfg_val; + unsigned int en_mask; + unsigned int disable_count; +}; + +struct csu_clk { + unsigned int clk_id; + unsigned int bus_id; +}; + +struct rockchip_csu { + struct device *dev; + struct csu_bus *bus; + struct csu_clk *clk; + unsigned int bus_cnt; + unsigned int clk_cnt; +}; + +static struct rockchip_csu *rk_csu; +static DEFINE_MUTEX(csu_lock); + +static int rockchip_csu_sip_config(struct device *dev, u32 bus_id, u32 cfg, + u32 enable_msk) +{ + struct arm_smccc_res res; + + dev_dbg(dev, "id=%u, cfg=0x%x, en_mask=0x%x\n", bus_id, cfg, enable_msk); + res = sip_smc_bus_config(bus_id, cfg, enable_msk); + + return res.a0; +} + +struct csu_clk *rockchip_csu_get(struct device *dev, const char *name) +{ + struct of_phandle_args args; + struct csu_clk *clk = ERR_PTR(-ENOENT); + unsigned int clk_id = 0; + int index = 0, i = 0; + + if (!dev || !dev->of_node) + return ERR_PTR(-ENODEV); + if (!rk_csu || !rk_csu->bus || !rk_csu->clk) + return ERR_PTR(-ENODEV); + + if (name) + index = of_property_match_string(dev->of_node, + "rockchip,csu-names", + name); + if (of_parse_phandle_with_fixed_args(dev->of_node, "rockchip,csu", 1, + index, &args)) { + dev_err(dev, "Missing the phandle args name %s\n", name); + return ERR_PTR(-ENODEV); + } + clk_id = args.args[0]; + + for (i = 0; i < rk_csu->clk_cnt; i++) { + if (clk_id == rk_csu->clk[i].clk_id) { + clk = &rk_csu->clk[i]; + break; + } + } + + return clk; +} +EXPORT_SYMBOL(rockchip_csu_get); + +static int csu_disable(struct csu_clk *clk, bool disable) +{ + struct csu_bus *bus = NULL; + unsigned int en_mask = 0; + int ret = 0; + + if (IS_ERR_OR_NULL(clk)) + return 0; + if (clk->bus_id >= rk_csu->bus_cnt) + return 0; + bus = &rk_csu->bus[clk->bus_id]; + if (!bus) + return 0; + + mutex_lock(&csu_lock); + + if (disable) + bus->disable_count++; + else if (bus->disable_count > 0) + bus->disable_count--; + + if (bus->disable_count) + en_mask = bus->en_mask & CSU_EN_MASK; + else + en_mask = bus->en_mask; + + ret = rockchip_csu_sip_config(rk_csu->dev, bus->id, bus->cfg_val, en_mask); + if (ret) + dev_err(rk_csu->dev, "csu sip config disable error\n"); + + mutex_unlock(&csu_lock); + + return ret; +} + +int rockchip_csu_enable(struct csu_clk *clk) +{ + return csu_disable(clk, false); +} +EXPORT_SYMBOL(rockchip_csu_enable); + +int rockchip_csu_disable(struct csu_clk *clk) +{ + return csu_disable(clk, true); +} +EXPORT_SYMBOL(rockchip_csu_disable); + +int rockchip_csu_set_div(struct csu_clk *clk, unsigned int div) +{ + struct csu_bus *bus = NULL; + unsigned int cfg_val = 0; + int ret = 0; + + if (IS_ERR_OR_NULL(clk)) + return 0; + if (clk->bus_id >= rk_csu->bus_cnt) + return 0; + bus = &rk_csu->bus[clk->bus_id]; + if (!bus) + return 0; + + mutex_lock(&csu_lock); + + if (div > CSU_MAX_DIV) + div = CSU_MAX_DIV; + cfg_val = (bus->cfg_val & ~CSU_DIV_MASK) | ((div - 1) & CSU_DIV_MASK); + + ret = rockchip_csu_sip_config(rk_csu->dev, bus->id, cfg_val, bus->en_mask); + if (ret) + dev_err(rk_csu->dev, "csu sip config freq error\n"); + + mutex_unlock(&csu_lock); + + return ret; +} +EXPORT_SYMBOL(rockchip_csu_set_div); + +static int rockchip_csu_parse_clk(struct rockchip_csu *csu) +{ + struct device *dev = csu->dev; + struct device_node *np = dev->of_node; + char *prop_name = "rockchip,clock"; + struct csu_clk *tmp; + const struct property *prop; + int count, i; + + prop = of_find_property(np, prop_name, NULL); + if (!prop) + return -EINVAL; + + if (!prop->value) + return -ENODATA; + + count = of_property_count_u32_elems(np, prop_name); + if (count < 0) + return -EINVAL; + + if (count % 2) + return -EINVAL; + + tmp = devm_kcalloc(dev, count / 2, sizeof(*tmp), GFP_KERNEL); + if (!tmp) + return -ENOMEM; + + for (i = 0; i < count / 2; i++) { + of_property_read_u32_index(np, prop_name, 2 * i, + &tmp[i].clk_id); + of_property_read_u32_index(np, prop_name, 2 * i + 1, + &tmp[i].bus_id); + } + + csu->clk = tmp; + csu->clk_cnt = count / 2; + + return 0; +} + +static int rockchip_csu_parse_bus_table(struct rockchip_csu *csu) +{ + struct device *dev = csu->dev; + struct device_node *np = dev->of_node; + char *prop_name = "rockchip,bus"; + struct csu_bus *tmp; + const struct property *prop; + int count, i; + + prop = of_find_property(np, prop_name, NULL); + if (!prop) + return -EINVAL; + + if (!prop->value) + return -ENODATA; + + count = of_property_count_u32_elems(np, prop_name); + if (count < 0) + return -EINVAL; + + if (count % 3) + return -EINVAL; + + tmp = devm_kcalloc(dev, count / 3, sizeof(*tmp), GFP_KERNEL); + if (!tmp) + return -ENOMEM; + + for (i = 0; i < count / 3; i++) { + of_property_read_u32_index(np, prop_name, 3 * i, + &tmp[i].id); + of_property_read_u32_index(np, prop_name, 3 * i + 1, + &tmp[i].cfg_val); + of_property_read_u32_index(np, prop_name, 3 * i + 2, + &tmp[i].en_mask); + } + + csu->bus = tmp; + csu->bus_cnt = count / 3; + + return 0; +} + +static int rockchip_csu_bus_table(struct rockchip_csu *csu) +{ + struct device *dev = csu->dev; + struct csu_bus *bus; + int i; + + if (rockchip_csu_parse_bus_table(csu)) + return -EINVAL; + + for (i = 0; i < csu->bus_cnt; i++) { + bus = &csu->bus[i]; + if (!bus || !bus->cfg_val) { + dev_info(dev, "bus %d cfg-val invalid\n", i); + continue; + } + if (rockchip_csu_sip_config(dev, bus->id, bus->cfg_val, bus->en_mask)) + dev_err(dev, "csu sip config error\n"); + } + + return 0; +} + +static int rockchip_csu_bus_node(struct rockchip_csu *csu) +{ + struct device *dev = csu->dev; + struct device_node *np = dev->of_node; + struct device_node *child; + struct csu_bus *bus; + int bus_cnt = 0, i = 0; + + for_each_available_child_of_node(np, child) + bus_cnt++; + if (bus_cnt <= 0) + return 0; + + csu->bus = devm_kcalloc(dev, bus_cnt, sizeof(*csu->bus), GFP_KERNEL); + if (!csu->bus) + return -ENOMEM; + csu->bus_cnt = bus_cnt; + + for_each_available_child_of_node(np, child) { + bus = &csu->bus[i++]; + if (of_property_read_u32_index(child, "bus-id", 0, &bus->id)) { + dev_info(dev, "get bus-id error\n"); + continue; + } + + if (of_property_read_u32_index(child, "cfg-val", 0, + &bus->cfg_val)) { + dev_info(dev, "get cfg-val error\n"); + continue; + } + if (!bus->cfg_val) { + dev_info(dev, "cfg-val invalid\n"); + continue; + } + + if (of_property_read_u32_index(child, "enable-msk", 0, + &bus->en_mask)) { + dev_info(dev, "get enable_msk error\n"); + continue; + } + + if (rockchip_csu_sip_config(dev, bus->id, bus->cfg_val, bus->en_mask)) + dev_info(dev, "csu smc config error\n"); + } + + return 0; +} + +static const struct of_device_id rockchip_csu_of_match[] = { + { .compatible = "rockchip,rk3562-csu", }, + { }, +}; + +MODULE_DEVICE_TABLE(of, rockchip_csu_of_match); + +static int rockchip_csu_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct device_node *np = dev->of_node; + struct rockchip_csu *csu; + int ret = 0; + + csu = devm_kzalloc(dev, sizeof(*csu), GFP_KERNEL); + if (!csu) + return -ENOMEM; + + csu->dev = dev; + platform_set_drvdata(pdev, csu); + + rockchip_csu_parse_clk(csu); + + if (of_find_property(np, "rockchip,bus", NULL)) + ret = rockchip_csu_bus_table(csu); + else + ret = rockchip_csu_bus_node(csu); + if (!ret) + rk_csu = csu; + + return ret; +} + +static struct platform_driver rockchip_csu_driver = { + .probe = rockchip_csu_probe, + .driver = { + .name = "rockchip,csu", + .of_match_table = rockchip_csu_of_match, + }, +}; + +static int __init rockchip_csu_init(void) +{ + int ret; + + ret = platform_driver_register(&rockchip_csu_driver); + if (ret) { + pr_err("failed to register csu driver\n"); + return ret; + } + + return 0; +} + +static void __exit rockchip_csu_exit(void) +{ + return platform_driver_unregister(&rockchip_csu_driver); +} + +subsys_initcall(rockchip_csu_init); +module_exit(rockchip_csu_exit); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Finley Xiao "); +MODULE_DESCRIPTION("Rockchip clock subunit driver"); diff --git a/include/dt-bindings/soc/rockchip-csu.h b/include/dt-bindings/soc/rockchip-csu.h new file mode 100644 index 000000000000..8b0442533c3f --- /dev/null +++ b/include/dt-bindings/soc/rockchip-csu.h @@ -0,0 +1,15 @@ +/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */ +/* + * Copyright (c) 2023 Rockchip Electronics Co. Ltd. + * Author: Finley Xiao + */ + +#ifndef _DT_BINDINGS_ROCKCHIP_CSU_H +#define _DT_BINDINGS_ROCKCHIP_CSU_H + +#define CSU_GMAC_ACLK 0 +#define CSU_GMAC_PCLK 1 +#define CSU_VOP_ACLK 2 +#define CSU_MCU_CLK 3 + +#endif diff --git a/include/linux/mfd/rk806.h b/include/linux/mfd/rk806.h index 71e833c51444..7735121592c8 100644 --- a/include/linux/mfd/rk806.h +++ b/include/linux/mfd/rk806.h @@ -6,6 +6,7 @@ #ifndef __LINUX_REGULATOR_RK806_H #define __LINUX_REGULATOR_RK806_H +#include #include #include #include @@ -518,7 +519,8 @@ struct rk806 { int vb_lo_irq; }; -extern const struct regmap_config rk806_regmap_config_spi; +extern const struct regmap_config rk806_regmap_config; +extern const struct of_device_id rk806_of_match[]; int rk806_device_init(struct rk806 *rk806); int rk806_device_exit(struct rk806 *rk806); int rk806_field_write(struct rk806 *rk806, diff --git a/include/soc/rockchip/rockchip_csu.h b/include/soc/rockchip/rockchip_csu.h new file mode 100644 index 000000000000..4338d68359f7 --- /dev/null +++ b/include/soc/rockchip/rockchip_csu.h @@ -0,0 +1,46 @@ +/* SPDX-License-Identifier: (GPL-2.0+ OR MIT) */ +/* + * Copyright (c) 2023, Rockchip Electronics Co., Ltd + */ + +#ifndef __SOC_ROCKCHIP_CSU_H +#define __SOC_ROCKCHIP_CSU_H + +#include + +#define CSU_MAX_DIV 8 +#define CSU_DIV_MASK 0x7 +#define CSU_EN_MASK 0xefff + +struct csu_clk; + +#if IS_REACHABLE(CONFIG_ROCKCHIP_CSU) +struct csu_clk *rockchip_csu_get(struct device *dev, const char *name); +int rockchip_csu_enable(struct csu_clk *clk); +int rockchip_csu_disable(struct csu_clk *clk); +int rockchip_csu_set_div(struct csu_clk *clk, unsigned int div); +#else +static inline struct csu_clk * +rockchip_csu_get(struct device *dev, const char *name) +{ + return ERR_PTR(-EOPNOTSUPP); +} + +static inline int rockchip_csu_enable(struct csu_clk *clk) +{ + return -EOPNOTSUPP; +} + +static inline int rockchip_csu_disable(struct csu_clk *clk) +{ + return -EOPNOTSUPP; +} + +static inline int +rockchip_csu_set_div(struct csu_clk *clk, unsigned int div) +{ + return -EOPNOTSUPP; +} +#endif + +#endif diff --git a/include/uapi/linux/rk-pcie-ep.h b/include/uapi/linux/rk-pcie-ep.h index 89b6c4fa558b..345c6c2e9e86 100644 --- a/include/uapi/linux/rk-pcie-ep.h +++ b/include/uapi/linux/rk-pcie-ep.h @@ -74,6 +74,9 @@ enum pcie_ep_mmap_resource { PCIE_EP_MMAP_RESOURCE_BAR0, PCIE_EP_MMAP_RESOURCE_BAR2, PCIE_EP_MMAP_RESOURCE_BAR4, + PCIE_EP_MMAP_RESOURCE_USER_MEM, + PCIE_EP_MMAP_RESOURCE_RK3568_RC_DBI, + PCIE_EP_MMAP_RESOURCE_RK3588_RC_DBI, PCIE_EP_MMAP_RESOURCE_MAX, }; @@ -87,7 +90,8 @@ struct pcie_ep_obj_info { __u16 mode; __u16 submode; } devmode; - __u8 reserved[0x1F4]; + __u32 msi_data[0x8]; + __u8 reserved[0x1D4]; __u32 irq_type_rc; /* Generate in ep isr, valid only for rc, clear in rc */ struct pcie_ep_obj_irq_dma_status dma_status_rc; /* Generate in ep isr, valid only for rc, clear in rc */ @@ -103,7 +107,7 @@ struct pcie_ep_obj_info { #define PCIE_DMA_IRQ_MASK_ALL _IOW(PCIE_BASE, 3, int) #define PCIE_DMA_RAISE_MSI_OBJ_IRQ_USER _IOW(PCIE_BASE, 4, int) #define PCIE_EP_GET_USER_INFO _IOR(PCIE_BASE, 5, struct pcie_ep_user_data) -#define PCIE_EP_SET_MMAP_RESOURCE _IOW(PCIE_BASE, 6, enum pcie_ep_mmap_resource) +#define PCIE_EP_SET_MMAP_RESOURCE _IOW(PCIE_BASE, 6, int) #define PCIE_EP_RAISE_ELBI _IOW(PCIE_BASE, 7, int) #define PCIE_EP_REQUEST_VIRTUAL_ID _IOR(PCIE_BASE, 16, int) #define PCIE_EP_RELEASE_VIRTUAL_ID _IOW(PCIE_BASE, 17, int)