diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile index ee686acdecda..2399b3e96c88 100644 --- a/arch/arm/boot/dts/Makefile +++ b/arch/arm/boot/dts/Makefile @@ -1177,6 +1177,8 @@ dtb-$(CONFIG_ARCH_ROCKCHIP) += \ rv1126-evb-ddr3-v13.dtb \ rv1126b-evb1-v10.dtb \ rv1126b-evb1-v10-bt-sco.dtb \ + rv1126b-evb1-v10-dual-4k.dtb \ + rv1126b-evb1-v10-spi-nor.dtb \ rv1126b-evb2-v10.dtb \ rv1126b-evb2-v10-mcu-k350c4516t.dtb \ rv1126b-evb2-v10-rgb-Q7050ITH2641AA1T.dtb \ diff --git a/arch/arm/boot/dts/rv1126b-evb1-v10-dual-4k.dts b/arch/arm/boot/dts/rv1126b-evb1-v10-dual-4k.dts new file mode 100644 index 000000000000..92f5229f3cb6 --- /dev/null +++ b/arch/arm/boot/dts/rv1126b-evb1-v10-dual-4k.dts @@ -0,0 +1,6 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright (c) 2025 Rockchip Electronics Co., Ltd. + */ + +#include "arm64/rockchip/rv1126b-evb1-v10-dual-4k.dts" diff --git a/arch/arm/boot/dts/rv1126b-evb1-v10-spi-nor.dts b/arch/arm/boot/dts/rv1126b-evb1-v10-spi-nor.dts new file mode 100644 index 000000000000..e9f6a400b3a0 --- /dev/null +++ b/arch/arm/boot/dts/rv1126b-evb1-v10-spi-nor.dts @@ -0,0 +1,6 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright (c) 2025 Rockchip Electronics Co., Ltd. + */ + +#include "arm64/rockchip/rv1126b-evb1-v10-spi-nor.dts" diff --git a/arch/arm/configs/rv1126b-evb.config b/arch/arm/configs/rv1126b-evb.config index b47e29dc2647..8f438225560c 100644 --- a/arch/arm/configs/rv1126b-evb.config +++ b/arch/arm/configs/rv1126b-evb.config @@ -29,6 +29,7 @@ CONFIG_PHY_ROCKCHIP_NANENG_COMBO_PHY=y CONFIG_RK_CMA_PROCFS=y CONFIG_RK_DMABUF_PROCFS=y CONFIG_RK_MEMBLOCK_PROCFS=y +CONFIG_ROCKCHIP_DEBUG=y CONFIG_ROCKCHIP_OPP=y CONFIG_ROCKCHIP_RGA_PROC_FS=y CONFIG_ROCKCHIP_VENDOR_STORAGE=y diff --git a/arch/arm/configs/rv1126b-pm.config b/arch/arm/configs/rv1126b-pm.config new file mode 100644 index 000000000000..ae75f6d56bed --- /dev/null +++ b/arch/arm/configs/rv1126b-pm.config @@ -0,0 +1,6 @@ +CONFIG_PM_DEBUG=y +CONFIG_PM_SLEEP=y +CONFIG_PM_SLEEP_DEBUG=y +CONFIG_PM_WAKELOCKS=y +CONFIG_SUSPEND=y +CONFIG_ROCKCHIP_SUSPEND_MODE=y diff --git a/arch/arm/configs/rv1126b-wakeup.config b/arch/arm/configs/rv1126b-wakeup.config new file mode 100644 index 000000000000..bcb2874830e8 --- /dev/null +++ b/arch/arm/configs/rv1126b-wakeup.config @@ -0,0 +1,5 @@ +CONFIG_INPUT=y +CONFIG_INPUT_EVDEV=y +CONFIG_INPUT_KEYBOARD=y +CONFIG_KEYBOARD_GPIO=y +CONFIG_SND_JACK_INPUT_DEV=y diff --git a/arch/arm/configs/rv1126b_defconfig b/arch/arm/configs/rv1126b_defconfig index 18e7a3d5b3c8..396d926f83ed 100644 --- a/arch/arm/configs/rv1126b_defconfig +++ b/arch/arm/configs/rv1126b_defconfig @@ -125,6 +125,7 @@ CONFIG_MEDIA_CAMERA_SUPPORT=y CONFIG_MEDIA_PLATFORM_SUPPORT=y CONFIG_V4L_PLATFORM_DRIVERS=y CONFIG_VIDEO_ROCKCHIP_AIISP=m +CONFIG_VIDEO_ROCKCHIP_AVSP=m CONFIG_VIDEO_ROCKCHIP_CIF=m CONFIG_VIDEO_ROCKCHIP_ISP=m CONFIG_VIDEO_ROCKCHIP_VPSS=m diff --git a/arch/arm64/boot/dts/rockchip/Makefile b/arch/arm64/boot/dts/rockchip/Makefile index dd9a3600f1fd..cf4892da4769 100644 --- a/arch/arm64/boot/dts/rockchip/Makefile +++ b/arch/arm64/boot/dts/rockchip/Makefile @@ -56,6 +56,7 @@ dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3328-roc-cc.dtb dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3328-roc-pc.dtb dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3358-evb-ddr3-v10-linux.dtb dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3358m-automotive-ddr3-v11-linux.dtb +dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3358m-automotive-ddr3-v11-linux-tb.dtb dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3358m-vehicle-v10.dtb dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3368-evb-act8846.dtb dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3368-geekbox.dtb @@ -365,6 +366,8 @@ dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3588s-tablet-v10.dtb dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3588s-tablet-v11.dtb dtb-$(CONFIG_ARCH_ROCKCHIP) += rv1126b-evb1-v10.dtb dtb-$(CONFIG_ARCH_ROCKCHIP) += rv1126b-evb1-v10-bt-sco.dtb +dtb-$(CONFIG_ARCH_ROCKCHIP) += rv1126b-evb1-v10-dual-4k.dtb +dtb-$(CONFIG_ARCH_ROCKCHIP) += rv1126b-evb1-v10-spi-nor.dtb dtb-$(CONFIG_ARCH_ROCKCHIP) += rv1126b-evb2-v10.dtb dtb-$(CONFIG_ARCH_ROCKCHIP) += rv1126b-evb2-v10-mcu-k350c4516t.dtb dtb-$(CONFIG_ARCH_ROCKCHIP) += rv1126b-evb2-v10-rgb-Q7050ITH2641AA1T.dtb diff --git a/arch/arm64/boot/dts/rockchip/rk3358m-automotive-ddr3-v11-linux-tb.dts b/arch/arm64/boot/dts/rockchip/rk3358m-automotive-ddr3-v11-linux-tb.dts new file mode 100644 index 000000000000..a63903fe2822 --- /dev/null +++ b/arch/arm64/boot/dts/rockchip/rk3358m-automotive-ddr3-v11-linux-tb.dts @@ -0,0 +1,59 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright (c) 2024 Rockchip Electronics Co., Ltd. + * + */ + +/dts-v1/; + +#include "rk3358m-automotive-ddr3-v11-linux.dts" + +/ { + model = "Rockchip RK3358M AUTOMOTIVE DDR3 V11 Linux TB board"; + compatible = "rockchip,rk3358m-automotive-ddr3-v11-linux", "rockchip,px30", "rockchip,rk3358"; + + chosen { + bootargs = "earlycon=uart8250,mmio32,0xff160000 console=ttyFIQ0 skip_initramfs root=/dev/rd0 rootfstype=squashfs init=/sbin/init"; + }; + + /* + * This memory mapping range represents a 512MB memory space + * starting from the physical address 0x00000000 + * where: + * 0x00000000 - base address + * 0x0 - address cells + * 0x0 - size cells + * 0x20000000 - memory size (512MB) + * Note: The actual available memory size depends on the hardware design + * and may differ from the 512MB defined here. + * Adjustment is needed based on the specific hardware memory configuration. + */ + memory: memory { + device_type = "memory"; + reg = <0x00000000 0x0 0x0 0x20000000>; + }; + + ramdisk: ramdisk { + compatible = "rockchip,ramdisk"; + memory-region = <&ramdisk_r>; + }; + + reserved-memory { + #address-cells = <2>; + #size-cells = <2>; + ranges; + atf: atf@0 { + reg = <0x0 0x00000 0x0 0x200000>; + no-map; + }; + + mmc_dma_buf@200000 { + reg = <0x0 0x200000 0x0 0x200000>; + }; + + ramdisk_r: ramdisk_r@4000000 { + /* Do not exceed 132MB which used by TEE */ + reg = <0x0 0x4000000 0x0 0x2000000>; + }; + }; +}; diff --git a/arch/arm64/boot/dts/rockchip/rk3358m-automotive-ddr3-v11-linux.dts b/arch/arm64/boot/dts/rockchip/rk3358m-automotive-ddr3-v11-linux.dts index 8252455991e3..b9f2110a61df 100644 --- a/arch/arm64/boot/dts/rockchip/rk3358m-automotive-ddr3-v11-linux.dts +++ b/arch/arm64/boot/dts/rockchip/rk3358m-automotive-ddr3-v11-linux.dts @@ -10,51 +10,6 @@ #include "rk3358-linux.dtsi" / { - model = "Rockchip RK3358M AUTOMOTIVE DDR3 V11 board"; + model = "Rockchip RK3358M AUTOMOTIVE DDR3 V11 Linux board"; compatible = "rockchip,rk3358m-automotive-ddr3-v11-linux", "rockchip,px30", "rockchip,rk3358"; - - chosen { - bootargs = "earlycon=uart8250,mmio32,0xff160000 console=ttyFIQ0 skip_initramfs root=/dev/rd0 rootfstype=squashfs init=/sbin/init"; - }; - - /* - * This memory mapping range represents a 512MB memory space - * starting from the physical address 0x00000000 - * where: - * 0x00000000 - base address - * 0x0 - address cells - * 0x0 - size cells - * 0x20000000 - memory size (512MB) - * Note: The actual available memory size depends on the hardware design - * and may differ from the 512MB defined here. - * Adjustment is needed based on the specific hardware memory configuration. - */ - memory: memory { - device_type = "memory"; - reg = <0x00000000 0x0 0x0 0x20000000>; - }; - - ramdisk: ramdisk { - compatible = "rockchip,ramdisk"; - memory-region = <&ramdisk_r>; - }; - - reserved-memory { - #address-cells = <2>; - #size-cells = <2>; - ranges; - atf: atf@0 { - reg = <0x0 0x00000 0x0 0x200000>; - no-map; - }; - - mmc_dma_buf@200000 { - reg = <0x0 0x200000 0x0 0x200000>; - }; - - ramdisk_r: ramdisk_r@4000000 { - /* Do not exceed 132MB which used by TEE */ - reg = <0x0 0x4000000 0x0 0x2000000>; - }; - }; }; diff --git a/arch/arm64/boot/dts/rockchip/rk3358m-automotive-ddr3-v11.dtsi b/arch/arm64/boot/dts/rockchip/rk3358m-automotive-ddr3-v11.dtsi index fba82b6ffe53..770b29bcdce3 100644 --- a/arch/arm64/boot/dts/rockchip/rk3358m-automotive-ddr3-v11.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3358m-automotive-ddr3-v11.dtsi @@ -201,6 +201,8 @@ snps,reset-gpio = <&gpio2 12 GPIO_ACTIVE_LOW>; snps,reset-active-low; snps,reset-delays-us = <0 50000 50000>; + pinctrl-names = "default"; + pinctrl-0 = <&rmii_pins_fixed &mac_refclk_12ma>; status = "okay"; }; @@ -422,6 +424,7 @@ }; vcc1v8_ser: LDO_REG8 { + regulator-always-on; regulator-boot-on; regulator-min-microvolt = <1800000>; regulator-max-microvolt = <1800000>; @@ -434,6 +437,7 @@ }; vdd1v2_ser: LDO_REG9 { + regulator-always-on; regulator-boot-on; regulator-min-microvolt = <1200000>; regulator-max-microvolt = <1200000>; @@ -553,6 +557,21 @@ }; &pinctrl { + gmac { + rmii_pins_fixed: rmii-pins-fixed { + rockchip,pins = + <2 RK_PA0 2 &pcfg_pull_none_12ma>, /* mac_txen */ + <2 RK_PA1 2 &pcfg_pull_none_12ma>, /* mac_txd1 */ + <2 RK_PA2 2 &pcfg_pull_none_12ma>, /* mac_txd0 */ + <2 RK_PA3 2 &pcfg_pull_none>, /* mac_rxd0 */ + <2 RK_PA4 2 &pcfg_pull_none>, /* mac_rxd1 */ + //<2 RK_PA5 2 &pcfg_pull_none>, /* mac_rxer */ + <2 RK_PA6 2 &pcfg_pull_none>, /* mac_rxdv */ + <2 RK_PA7 2 &pcfg_pull_none>, /* mac_mdio */ + <2 RK_PB1 2 &pcfg_pull_none>; /* mac_mdc */ + }; + }; + lcd { lcd0_pwren: lcd0-pwren { rockchip,pins = <1 RK_PD6 RK_FUNC_GPIO &pcfg_output_high>; diff --git a/arch/arm64/boot/dts/rockchip/rk3576-evb1-v10-edp-NV140QUM-N61.dts b/arch/arm64/boot/dts/rockchip/rk3576-evb1-v10-edp-NV140QUM-N61.dts index 013459c64ec3..120b55ba2ba7 100644 --- a/arch/arm64/boot/dts/rockchip/rk3576-evb1-v10-edp-NV140QUM-N61.dts +++ b/arch/arm64/boot/dts/rockchip/rk3576-evb1-v10-edp-NV140QUM-N61.dts @@ -90,7 +90,7 @@ }; &route_edp { - status = "disabled"; + status = "okay"; connect = <&vp0_out_edp>; }; diff --git a/arch/arm64/boot/dts/rockchip/rv1126b-evb-cam-csi0.dtsi b/arch/arm64/boot/dts/rockchip/rv1126b-evb-cam-csi0.dtsi index 2e4cd0299fdd..d706786b18f6 100644 --- a/arch/arm64/boot/dts/rockchip/rv1126b-evb-cam-csi0.dtsi +++ b/arch/arm64/boot/dts/rockchip/rv1126b-evb-cam-csi0.dtsi @@ -46,7 +46,7 @@ }; csi_dphy_input5: endpoint@6 { - reg = <5>; + reg = <6>; remote-endpoint = <&gc8613_out>; data-lanes = <1 2 3 4>; }; diff --git a/arch/arm64/boot/dts/rockchip/rv1126b-evb1-v10-dual-4k.dts b/arch/arm64/boot/dts/rockchip/rv1126b-evb1-v10-dual-4k.dts new file mode 100644 index 000000000000..b6f3660a033d --- /dev/null +++ b/arch/arm64/boot/dts/rockchip/rv1126b-evb1-v10-dual-4k.dts @@ -0,0 +1,15 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright (c) 2025 Rockchip Electronics Co., Ltd. + */ + +/dts-v1/; +#include "rv1126b.dtsi" +#include "rv1126b-evb.dtsi" +#include "rv1126b-evb-dual-cam-4k.dtsi" +#include "rv1126b-evb1-v10.dtsi" + +/ { + model = "Rockchip RV1126B EVB1 V10 DUAL 4K Board"; + compatible = "rockchip,rv1126b-evb1-v10-dual-4k", "rockchip,rv1126b"; +}; diff --git a/arch/arm64/boot/dts/rockchip/rv1126b-evb1-v10-spi-nor.dts b/arch/arm64/boot/dts/rockchip/rv1126b-evb1-v10-spi-nor.dts new file mode 100644 index 000000000000..dcbcf18e5ec8 --- /dev/null +++ b/arch/arm64/boot/dts/rockchip/rv1126b-evb1-v10-spi-nor.dts @@ -0,0 +1,25 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright (c) 2025 Rockchip Electronics Co., Ltd. + */ + +/dts-v1/; +#include "rv1126b-evb1-v10.dts" + +/ { + model = "Rockchip RV1126B EVB1 V10 Board"; + compatible = "rockchip,rv1126b-evb1-v10-spi-nor", "rockchip,rv1126b"; + +}; + +&fspi0 { + status = "okay"; + + flash@0 { + compatible = "jedec,spi-nor"; + reg = <0>; + spi-max-frequency = <75000000>; + spi-rx-bus-width = <4>; + spi-tx-bus-width = <1>; + }; +}; diff --git a/arch/arm64/boot/dts/rockchip/rv1126b-evb1-v10.dts b/arch/arm64/boot/dts/rockchip/rv1126b-evb1-v10.dts index 9eadbf6f6877..0108270ecbd1 100644 --- a/arch/arm64/boot/dts/rockchip/rv1126b-evb1-v10.dts +++ b/arch/arm64/boot/dts/rockchip/rv1126b-evb1-v10.dts @@ -7,484 +7,9 @@ #include "rv1126b.dtsi" #include "rv1126b-evb.dtsi" #include "rv1126b-evb-cam-csi0.dtsi" +#include "rv1126b-evb1-v10.dtsi" / { model = "Rockchip RV1126B EVB1 V10 Board"; compatible = "rockchip,rv1126b-evb1-v10", "rockchip,rv1126b"; - - sdio_pwrseq: sdio-pwrseq { - compatible = "mmc-pwrseq-simple"; - pinctrl-names = "default"; - pinctrl-0 = <&wifi_enable_h>; - - /* - * On the module itself this is one of these (depending - * on the actual card populated): - * - SDIO_RESET_L_WL_REG_ON - * - PDN (power down when low) - */ - reset-gpios = <&gpio0 RK_PB2 GPIO_ACTIVE_LOW>; - }; - - vcc5v0_sys: vcc5v0-sys { - compatible = "regulator-fixed"; - regulator-name = "vcc5v0_sys"; - regulator-always-on; - regulator-boot-on; - regulator-min-microvolt = <5000000>; - regulator-max-microvolt = <5000000>; - vin-supply = <&vcc12v_dcin>; - status = "okay"; - }; - - vbus5v0_typec: vbus5v0-typec { - compatible = "regulator-fixed"; - regulator-name = "vbus5v0_typec"; - regulator-min-microvolt = <5000000>; - regulator-max-microvolt = <5000000>; - enable-active-high; - gpio = <&gpio5 RK_PD6 GPIO_ACTIVE_HIGH>; - vin-supply = <&vcc5v0_sys>; - pinctrl-names = "default"; - pinctrl-0 = <&typec5v_pwren>; - }; - - vcc5v0_host: vcc5v0-host { - compatible = "regulator-fixed"; - regulator-name = "vcc5v0_host"; - regulator-boot-on; - regulator-always-on; - regulator-min-microvolt = <5000000>; - regulator-max-microvolt = <5000000>; - enable-active-high; - gpio = <&gpio5 RK_PA7 GPIO_ACTIVE_HIGH>; - vin-supply = <&vcc5v0_sys>; - pinctrl-names = "default"; - pinctrl-0 = <&vcc5v0_host_en>; - }; - - vcc_mipi: vcc-mipi { - compatible = "regulator-fixed"; - regulator-name = "vcc_mipi"; - gpio = <&gpio7 RK_PA2 GPIO_ACTIVE_HIGH>; - enable-active-high; - regulator-boot-on; - }; - - vcc_sd: vcc-sd { - compatible = "regulator-fixed"; - gpio = <&gpio0 RK_PB0 GPIO_ACTIVE_LOW>; - regulator-name = "vcc_sd"; - regulator-min-microvolt = <3300000>; - regulator-max-microvolt = <3300000>; - enable-active-low; - regulator-boot-on; // The legacy U-Boot GPIO driver needs this to set correct SDMMC0_PWREN value - vin-supply = <&vcc12v_dcin>; - }; - - vccio_sd: vccio-sd { - compatible = "regulator-gpio"; - regulator-boot-on; - regulator-name = "vccio_sd"; - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <3300000>; - pinctrl-names = "default"; - pinctrl-0 = <&sdmmc_volt>; - gpios = <&gpio0 RK_PA6 GPIO_ACTIVE_HIGH>; - vin-supply = <&vcc5v0_sys>; - states = <1800000 0x0 - 3300000 0x1>; - }; - - vdd_npu: vdd-npu { - compatible = "pwm-regulator"; - pwms = <&pwm0_8ch_0 0 25000 1>; - regulator-name = "vdd_npu"; - regulator-init-microvolt = <950000>; - regulator-min-microvolt = <750000>; - regulator-max-microvolt = <1100000>; - regulator-always-on; - regulator-boot-on; - enable-gpios = <&gpio0 RK_PA3 GPIO_ACTIVE_HIGH>; - pwm-supply = <&vcc5v0_sys>; - }; - - wireless-bluetooth { - compatible = "bluetooth-platdata"; - uart_rts_gpios = <&gpio3 RK_PA6 GPIO_ACTIVE_LOW>; - pinctrl-names = "default", "rts_gpio"; - pinctrl-0 = <&uart2m0_rtsn_pins>; - pinctrl-1 = <&uart2_gpios>; - BT,power_gpio = <&gpio0 RK_PA0 GPIO_ACTIVE_HIGH>; - status = "okay"; - }; - - wireless-wlan { - compatible = "wlan-platdata"; - rockchip,grf = <&grf>; - pinctrl-names = "default"; - pinctrl-0 = <&wifi_wake_host>; - wifi_chip_type = "rk96x"; - WIFI,host_wake_irq = <&gpio0 RK_PB1 GPIO_ACTIVE_HIGH>; - status = "okay"; - }; -}; - -&acdcdig_dsm { - status = "okay"; - pa-ctl-gpios = <&gpio0 RK_PA4 GPIO_ACTIVE_HIGH>; -}; - -&acodec_sound { - status = "okay"; -}; - -&audio_codec { - status = "okay"; -}; - -&backlight { - pwms = <&pwm2_8ch_4 0 25000 0>; -}; - -&cpu0 { - cpu-supply = <&vdd_cpu>; -}; - -&display_subsystem { - status = "okay"; -}; - -&dsi { - status = "okay"; -}; - -&dsi_in_vop { - status = "okay"; -}; - -&dsi_panel { - power-supply = <&vcc_mipi>; -}; - -&emmc { - bus-width = <8>; - cap-mmc-highspeed; - non-removable; - mmc-hs200-1_8v; - rockchip,default-sample-phase = <90>; - no-sdio; - no-sd; - status = "okay"; -}; - -&fspi0 { - status = "okay"; - - flash@0 { - compatible = "spi-nand"; - reg = <0>; - spi-max-frequency = <75000000>; - spi-rx-bus-width = <4>; - spi-tx-bus-width = <1>; - }; -}; - -&gmac { - phy-mode = "rmii"; - clock_in_out = "input"; - phy-handle = <&rmii_phy>; - status = "okay"; -}; - -&i2c0 { - status = "okay"; - - rk801: rk801@27 { - compatible = "rockchip,rk801"; - status = "okay"; - reg = <0x27>; - interrupt-parent = <&gpio0>; - interrupts = ; - pwrctrl-gpios = <&gpio0 RK_PC1 GPIO_ACTIVE_HIGH>; - - pinctrl-names = "default"; - pinctrl-0 = <&pmic_int>; - rockchip,system-power-controller; - wakeup-source; - - vcc1-supply = <&vcc12v_dcin>; - vcc2-supply = <&vcc12v_dcin>; - vcc3-supply = <&vcc5v0_sys>; - vcc4-supply = <&vcc5v0_sys>; - vcc5-supply = <&vcc3v3_sys>; - vcc6-supply = <&vcc3v3_sys>; - vcc7-supply = <&vcc3v3_sys>; - - regulators { - vdd_cpu: DCDC_REG1 { - regulator-name = "vdd_cpu"; - regulator-min-microvolt = <500000>; - regulator-max-microvolt = <1500000>; - regulator-initial-mode = <0x1>; - regulator-boot-on; - regulator-always-on; - regulator-state-mem { - regulator-mode = <0x2>; - regulator-on-in-suspend; - regulator-suspend-microvolt = <950000>; - }; - }; - - vcc3v3_sys: DCDC_REG2 { - regulator-name = "vcc3v3_sys"; - regulator-min-microvolt = <3300000>; - regulator-max-microvolt = <3300000>; - regulator-initial-mode = <0x1>; - regulator-boot-on; - regulator-always-on; - regulator-state-mem { - regulator-mode = <0x2>; - regulator-on-in-suspend; - regulator-suspend-microvolt = <3300000>; - }; - }; - - vcc_ddr: DCDC_REG3 { - regulator-name = "vcc_ddr"; - regulator-boot-on; - regulator-always-on; - regulator-state-mem { - regulator-mode = <0x2>; - regulator-on-in-suspend; - }; - }; - - vdd_logic: DCDC_REG4 { - regulator-name = "vdd_logic"; - regulator-min-microvolt = <500000>; - regulator-max-microvolt = <1500000>; - regulator-initial-mode = <0x1>; - regulator-boot-on; - regulator-always-on; - regulator-state-mem { - regulator-mode = <0x2>; - regulator-on-in-suspend; - regulator-suspend-microvolt = <5000000>; - }; - }; - - vdd0v9_sys: LDO_REG1 { - regulator-name = "vdd0v9_sys"; - regulator-min-microvolt = <900000>; - regulator-max-microvolt = <900000>; - regulator-boot-on; - regulator-always-on; - regulator-state-mem { - regulator-on-in-suspend; - regulator-suspend-microvolt = <900000>; - }; - }; - - vcc_1v8: LDO_REG2 { - regulator-name = "vcc_1v8"; - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <1800000>; - regulator-boot-on; - regulator-always-on; - regulator-state-mem { - regulator-on-in-suspend; - regulator-suspend-microvolt = <1800000>; - }; - }; - - vcc_3v3: SWITCH_REG1 { - regulator-name = "vcc_3v3"; - regulator-boot-on; - regulator-always-on; - regulator-state-mem { - regulator-on-in-suspend; - }; - }; - }; - }; -}; - -&i2c4 { - status = "okay"; - pinctrl-names = "default"; - pinctrl-0 = <&i2c4m3_pins>; - - gt1x: gt1x@14 { - compatible = "goodix,gt1x"; - reg = <0x14>; - pinctrl-names = "default"; - pinctrl-0 = <&touch_gpio>; - power-supply = <&vcc_mipi>; - goodix,rst-gpio = <&gpio7 RK_PA7 GPIO_ACTIVE_HIGH>; - goodix,irq-gpio = <&gpio7 RK_PA6 IRQ_TYPE_LEVEL_LOW>; - }; -}; - -&mdio { - rmii_phy: ethernet-phy@2 { - compatible = "ethernet-phy-id0680.8101", "ethernet-phy-ieee802.3-c22"; - reg = <2>; - clocks = <&cru CLK_MACPHY>; - clock-frequency = <50000000>; - resets = <&cru SRST_RESETN_MACPHY>; - pinctrl-names = "default"; - pinctrl-0 = <&fephym1_pins>; - phy-is-integrated; - }; -}; - -&mipi_dphy { - status = "okay"; -}; - -&pinctrl { - pmic { - pmic_int: pmic-int { - rockchip,pins = <0 RK_PC0 RK_FUNC_GPIO &pcfg_pull_up>; - }; - }; - - sdio-pwrseq { - wifi_enable_h: wifi-enable-h { - rockchip,pins = <0 RK_PB2 RK_FUNC_GPIO &pcfg_pull_none>; - }; - }; - - sdmmc { - /omit-if-no-ref/ - sdmmc_volt: sdmmc-volt { - rockchip,pins = <0 RK_PA6 RK_FUNC_GPIO &pcfg_pull_none>; - }; - }; - - touch { - touch_gpio: touch-gpio { - rockchip,pins = - <7 RK_PA6 RK_FUNC_GPIO &pcfg_pull_up>, - <7 RK_PA7 RK_FUNC_GPIO &pcfg_pull_up>; - }; - }; - - usb { - typec5v_pwren: typec5v-pwren { - rockchip,pins = <5 RK_PD6 RK_FUNC_GPIO &pcfg_pull_none>; - }; - - vcc5v0_host_en: vcc5v0-host-en { - rockchip,pins = <5 RK_PA7 RK_FUNC_GPIO &pcfg_pull_none>; - }; - }; - - wireless-bluetooth { - uart2_gpios: uart2-gpios { - rockchip,pins = <3 RK_PA6 RK_FUNC_GPIO &pcfg_pull_none>; - }; - }; - - wireless-wlan { - wifi_wake_host: wifi-wake-host { - rockchip,pins = <0 RK_PB1 RK_FUNC_GPIO &pcfg_pull_up>; - }; - }; -}; - -&pwm0_8ch_0 { - status = "okay"; -}; - -&pwm2_8ch_4 { - pinctrl-0 = <&pwm2m1_ch4_pins>; - status = "okay"; -}; - -&rkaiisp { - status = "okay"; -}; - -&rkaiisp_mmu { - status = "okay"; -}; - -&rkaiisp_vir0 { - status = "okay"; -}; - -&rkfec { - status = "okay"; -}; - -&rkfec_mmu { - status = "okay"; -}; - -&rknpu { - rknpu-supply = <&vdd_npu>; -}; - -&route_dsi { - status = "okay"; -}; - -&sai2 { - status = "okay"; - /delete-property/ pinctrl-names; - /delete-property/ pinctrl-0; -}; - -&saradc0 { - vref-supply = <&vcc_1v8>; -}; - -&sdmmc0 { - max-frequency = <200000000>; - no-sdio; - no-mmc; - bus-width = <4>; - cap-mmc-highspeed; - cap-sd-highspeed; - disable-wp; - sd-uhs-sdr104; - vmmc-supply = <&vcc_sd>; - vqmmc-supply = <&vccio_sd>; - status = "okay"; -}; - -&sdmmc1 { - bus-width = <4>; - cap-sd-highspeed; - no-sd; - no-mmc; - max-frequency = <200000000>; - pinctrl-names = "default"; - pinctrl-0 = <&sdmmc1_clk_pins &sdmmc1_cmd_pins &sdmmc1_bus4_pins>; - keep-power-in-suspend; - non-removable; - mmc-pwrseq = <&sdio_pwrseq>; - //sd-uhs-sdr104; - status = "okay"; -}; - -&uart2 { - status = "okay"; - pinctrl-names = "default"; - pinctrl-0 = <&uart2m0_xfer_pins &uart2m0_ctsn_pins>; -}; - -&usb2phy_host { - phy-supply = <&vcc5v0_host>; -}; - -&usb2phy_otg { - vbus-supply = <&vbus5v0_typec>; -}; - -&usb_drd_dwc3 { - dr_mode = "otg"; - extcon = <&usb2phy>; }; diff --git a/arch/arm64/boot/dts/rockchip/rv1126b-evb1-v10.dtsi b/arch/arm64/boot/dts/rockchip/rv1126b-evb1-v10.dtsi new file mode 100644 index 000000000000..c57ab9efd776 --- /dev/null +++ b/arch/arm64/boot/dts/rockchip/rv1126b-evb1-v10.dtsi @@ -0,0 +1,491 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright (c) 2025 Rockchip Electronics Co., Ltd. + * + */ + +/ { + sdio_pwrseq: sdio-pwrseq { + compatible = "mmc-pwrseq-simple"; + pinctrl-names = "default"; + pinctrl-0 = <&wifi_enable_h>; + + /* + * On the module itself this is one of these (depending + * on the actual card populated): + * - SDIO_RESET_L_WL_REG_ON + * - PDN (power down when low) + */ + reset-gpios = <&gpio0 RK_PB2 GPIO_ACTIVE_LOW>; + }; + + vcc5v0_sys: vcc5v0-sys { + compatible = "regulator-fixed"; + regulator-name = "vcc5v0_sys"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + vin-supply = <&vcc12v_dcin>; + status = "okay"; + }; + + vbus5v0_typec: vbus5v0-typec { + compatible = "regulator-fixed"; + regulator-name = "vbus5v0_typec"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + enable-active-high; + gpio = <&gpio5 RK_PD6 GPIO_ACTIVE_HIGH>; + vin-supply = <&vcc5v0_sys>; + pinctrl-names = "default"; + pinctrl-0 = <&typec5v_pwren>; + }; + + vcc5v0_host: vcc5v0-host { + compatible = "regulator-fixed"; + regulator-name = "vcc5v0_host"; + regulator-boot-on; + regulator-always-on; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + enable-active-high; + gpio = <&gpio5 RK_PA7 GPIO_ACTIVE_HIGH>; + vin-supply = <&vcc5v0_sys>; + pinctrl-names = "default"; + pinctrl-0 = <&vcc5v0_host_en>; + }; + + vcc_mipi: vcc-mipi { + compatible = "regulator-fixed"; + regulator-name = "vcc_mipi"; + gpio = <&gpio7 RK_PA2 GPIO_ACTIVE_HIGH>; + enable-active-high; + regulator-boot-on; + }; + + vcc_sd: vcc-sd { + compatible = "regulator-fixed"; + gpio = <&gpio0 RK_PB0 GPIO_ACTIVE_LOW>; + regulator-name = "vcc_sd"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + enable-active-low; + regulator-boot-on; // The legacy U-Boot GPIO driver needs this to set correct SDMMC0_PWREN value + vin-supply = <&vcc12v_dcin>; + }; + + vccio_sd: vccio-sd { + compatible = "regulator-gpio"; + regulator-boot-on; + regulator-name = "vccio_sd"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <3300000>; + pinctrl-names = "default"; + pinctrl-0 = <&sdmmc_volt>; + gpios = <&gpio0 RK_PA6 GPIO_ACTIVE_HIGH>; + vin-supply = <&vcc5v0_sys>; + states = <1800000 0x0 + 3300000 0x1>; + }; + + vdd_npu: vdd-npu { + compatible = "pwm-regulator"; + pwms = <&pwm0_8ch_0 0 25000 1>; + regulator-name = "vdd_npu"; + regulator-init-microvolt = <950000>; + regulator-min-microvolt = <750000>; + regulator-max-microvolt = <1100000>; + regulator-always-on; + regulator-boot-on; + enable-gpios = <&gpio0 RK_PA3 GPIO_ACTIVE_HIGH>; + pwm-supply = <&vcc5v0_sys>; + }; + + wireless-bluetooth { + compatible = "bluetooth-platdata"; + uart_rts_gpios = <&gpio3 RK_PA6 GPIO_ACTIVE_LOW>; + pinctrl-names = "default", "rts_gpio"; + pinctrl-0 = <&uart2m0_rtsn_pins>; + pinctrl-1 = <&uart2_gpios>; + BT,power_gpio = <&gpio0 RK_PA0 GPIO_ACTIVE_HIGH>; + status = "okay"; + }; + + wireless-wlan { + compatible = "wlan-platdata"; + rockchip,grf = <&grf>; + pinctrl-names = "default"; + pinctrl-0 = <&wifi_wake_host>; + wifi_chip_type = "rk96x"; + WIFI,host_wake_irq = <&gpio0 RK_PB1 GPIO_ACTIVE_HIGH>; + status = "okay"; + }; +}; + +&acdcdig_dsm { + status = "okay"; + pa-ctl-gpios = <&gpio0 RK_PA4 GPIO_ACTIVE_HIGH>; +}; + +&acodec_sound { + status = "okay"; +}; + +&audio_codec { + status = "okay"; +}; + +&backlight { + pwms = <&pwm2_8ch_4 0 25000 0>; +}; + +&cpu0 { + cpu-supply = <&vdd_cpu>; +}; + +&display_subsystem { + status = "okay"; +}; + +&dsi { + status = "okay"; +}; + +&dsi_in_vop { + status = "okay"; +}; + +&dsi_panel { + power-supply = <&vcc_mipi>; +}; + +&emmc { + bus-width = <8>; + cap-mmc-highspeed; + non-removable; + mmc-hs200-1_8v; + rockchip,default-sample-phase = <90>; + no-sdio; + no-sd; + status = "okay"; +}; + +&fspi0 { + status = "okay"; + + flash@0 { + compatible = "spi-nand"; + reg = <0>; + spi-max-frequency = <75000000>; + spi-rx-bus-width = <4>; + spi-tx-bus-width = <1>; + }; +}; + +&gmac { + phy-mode = "rmii"; + clock_in_out = "input"; + phy-handle = <&rmii_phy>; + status = "okay"; +}; + +&i2c0 { + status = "okay"; + + rk801: rk801@27 { + compatible = "rockchip,rk801"; + status = "okay"; + reg = <0x27>; + interrupt-parent = <&gpio0>; + interrupts = ; + pwrctrl-gpios = <&gpio0 RK_PC1 GPIO_ACTIVE_HIGH>; + + pinctrl-names = "default"; + pinctrl-0 = <&pmic_int>; + rockchip,system-power-controller; + wakeup-source; + + vcc1-supply = <&vcc12v_dcin>; + vcc2-supply = <&vcc12v_dcin>; + vcc3-supply = <&vcc5v0_sys>; + vcc4-supply = <&vcc5v0_sys>; + vcc5-supply = <&vcc3v3_sys>; + vcc6-supply = <&vcc3v3_sys>; + vcc7-supply = <&vcc3v3_sys>; + + regulators { + vdd_cpu: DCDC_REG1 { + regulator-name = "vdd_cpu"; + regulator-min-microvolt = <500000>; + regulator-max-microvolt = <1500000>; + regulator-initial-mode = <0x1>; + regulator-boot-on; + regulator-always-on; + regulator-state-mem { + regulator-mode = <0x2>; + regulator-on-in-suspend; + regulator-suspend-microvolt = <950000>; + }; + }; + + vcc3v3_sys: DCDC_REG2 { + regulator-name = "vcc3v3_sys"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-initial-mode = <0x1>; + regulator-boot-on; + regulator-always-on; + regulator-state-mem { + regulator-mode = <0x2>; + regulator-on-in-suspend; + regulator-suspend-microvolt = <3300000>; + }; + }; + + vcc_ddr: DCDC_REG3 { + regulator-name = "vcc_ddr"; + regulator-boot-on; + regulator-always-on; + regulator-state-mem { + regulator-mode = <0x2>; + regulator-on-in-suspend; + }; + }; + + vdd_logic: DCDC_REG4 { + regulator-name = "vdd_logic"; + regulator-min-microvolt = <500000>; + regulator-max-microvolt = <1500000>; + regulator-initial-mode = <0x1>; + regulator-boot-on; + regulator-always-on; + regulator-state-mem { + regulator-mode = <0x2>; + regulator-on-in-suspend; + regulator-suspend-microvolt = <5000000>; + }; + }; + + vdd0v9_sys: LDO_REG1 { + regulator-name = "vdd0v9_sys"; + regulator-min-microvolt = <900000>; + regulator-max-microvolt = <900000>; + regulator-boot-on; + regulator-always-on; + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <900000>; + }; + }; + + vcc_1v8: LDO_REG2 { + regulator-name = "vcc_1v8"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-boot-on; + regulator-always-on; + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <1800000>; + }; + }; + + vcc_3v3: SWITCH_REG1 { + regulator-name = "vcc_3v3"; + regulator-boot-on; + regulator-always-on; + regulator-state-mem { + regulator-on-in-suspend; + }; + }; + }; + }; +}; + +&i2c4 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&i2c4m3_pins>; + + gt1x: gt1x@14 { + compatible = "goodix,gt1x"; + reg = <0x14>; + pinctrl-names = "default"; + pinctrl-0 = <&touch_gpio>; + power-supply = <&vcc_mipi>; + goodix,rst-gpio = <&gpio7 RK_PA7 GPIO_ACTIVE_HIGH>; + goodix,irq-gpio = <&gpio7 RK_PA6 IRQ_TYPE_LEVEL_LOW>; + }; +}; + +&mdio { + rmii_phy: ethernet-phy@2 { + compatible = "ethernet-phy-id0680.8101", "ethernet-phy-ieee802.3-c22"; + reg = <2>; + clocks = <&cru CLK_MACPHY>; + clock-frequency = <50000000>; + resets = <&cru SRST_RESETN_MACPHY>; + pinctrl-names = "default"; + pinctrl-0 = <&fephym1_pins>; + phy-is-integrated; + }; +}; + +&mipi_dphy { + status = "okay"; +}; + +&pinctrl { + pmic { + pmic_int: pmic-int { + rockchip,pins = <0 RK_PC0 RK_FUNC_GPIO &pcfg_pull_up>; + }; + }; + + sdio-pwrseq { + wifi_enable_h: wifi-enable-h { + rockchip,pins = <0 RK_PB2 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; + + sdmmc { + /omit-if-no-ref/ + sdmmc_volt: sdmmc-volt { + rockchip,pins = <0 RK_PA6 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; + + touch { + touch_gpio: touch-gpio { + rockchip,pins = + <7 RK_PA6 RK_FUNC_GPIO &pcfg_pull_up>, + <7 RK_PA7 RK_FUNC_GPIO &pcfg_pull_up>; + }; + }; + + usb { + typec5v_pwren: typec5v-pwren { + rockchip,pins = <5 RK_PD6 RK_FUNC_GPIO &pcfg_pull_none>; + }; + + vcc5v0_host_en: vcc5v0-host-en { + rockchip,pins = <5 RK_PA7 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; + + wireless-bluetooth { + uart2_gpios: uart2-gpios { + rockchip,pins = <3 RK_PA6 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; + + wireless-wlan { + wifi_wake_host: wifi-wake-host { + rockchip,pins = <0 RK_PB1 RK_FUNC_GPIO &pcfg_pull_up>; + }; + }; +}; + +&pwm0_8ch_0 { + status = "okay"; +}; + +&pwm2_8ch_4 { + pinctrl-0 = <&pwm2m1_ch4_pins>; + status = "okay"; +}; + +&rkaiisp { + status = "okay"; +}; + +&rkaiisp_mmu { + status = "okay"; +}; + +&rkaiisp_vir0 { + status = "okay"; +}; + +&rkavsp { + status = "okay"; +}; + +&rkavsp_mmu { + status = "okay"; +}; + +&rkfec { + status = "okay"; +}; + +&rkfec_mmu { + status = "okay"; +}; + +&rknpu { + rknpu-supply = <&vdd_npu>; +}; + +&route_dsi { + status = "okay"; +}; + +&sai2 { + status = "okay"; + /delete-property/ pinctrl-names; + /delete-property/ pinctrl-0; +}; + +&saradc0 { + vref-supply = <&vcc_1v8>; +}; + +&sdmmc0 { + max-frequency = <200000000>; + no-sdio; + no-mmc; + bus-width = <4>; + cap-mmc-highspeed; + cap-sd-highspeed; + disable-wp; + sd-uhs-sdr104; + vmmc-supply = <&vcc_sd>; + vqmmc-supply = <&vccio_sd>; + status = "okay"; +}; + +&sdmmc1 { + bus-width = <4>; + cap-sd-highspeed; + no-sd; + no-mmc; + max-frequency = <200000000>; + pinctrl-names = "default"; + pinctrl-0 = <&sdmmc1_clk_pins &sdmmc1_cmd_pins &sdmmc1_bus4_pins>; + keep-power-in-suspend; + non-removable; + mmc-pwrseq = <&sdio_pwrseq>; + //sd-uhs-sdr104; + status = "okay"; +}; + +&uart2 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&uart2m0_xfer_pins &uart2m0_ctsn_pins>; +}; + +&usb2phy_host { + phy-supply = <&vcc5v0_host>; +}; + +&usb2phy_otg { + vbus-supply = <&vbus5v0_typec>; +}; + +&usb_drd_dwc3 { + dr_mode = "otg"; + extcon = <&usb2phy>; +}; diff --git a/arch/arm64/boot/dts/rockchip/rv1126b-evb2-v10.dts b/arch/arm64/boot/dts/rockchip/rv1126b-evb2-v10.dts index 773e1a0e945e..bf2b2289d1af 100644 --- a/arch/arm64/boot/dts/rockchip/rv1126b-evb2-v10.dts +++ b/arch/arm64/boot/dts/rockchip/rv1126b-evb2-v10.dts @@ -12,6 +12,21 @@ model = "Rockchip RV1126B EVB2 V10 Board"; compatible = "rockchip,rv1126b-evb2-v10", "rockchip,rv1126b"; + gpio-keys { + compatible = "gpio-keys"; + autorepeat; + pinctrl-names = "default"; + pinctrl-0 = <&pwr_key>; + power-key { + gpios = <&gpio0 RK_PA4 GPIO_ACTIVE_LOW>; + linux,code = ; + label ="GPIO Key Power"; + debounce-interval = <100>; + wakeup-source; + /* gpio-key,wakeup; */ + }; + }; + vcc5v0_dcin: vcc5v0-dcin { compatible = "regulator-fixed"; regulator-name = "vcc5v0_dcin"; @@ -203,6 +218,26 @@ pwm-supply = <&vccsys_stb>; status = "okay"; }; + + wireless-bluetooth { + compatible = "bluetooth-platdata"; + uart_rts_gpios = <&gpio3 RK_PA6 GPIO_ACTIVE_LOW>; + pinctrl-names = "default", "rts_gpio"; + pinctrl-0 = <&uart2m0_rtsn_pins>; + pinctrl-1 = <&uart2_gpios>; + BT,power_gpio = <&gpio0 RK_PA0 GPIO_ACTIVE_HIGH>; + status = "okay"; + }; + + wireless-wlan { + compatible = "wlan-platdata"; + rockchip,grf = <&grf>; + pinctrl-names = "default"; + pinctrl-0 = <&wifi_wake_host>; + wifi_chip_type = "rk96x"; + WIFI,host_wake_irq = <&gpio0 RK_PC0 GPIO_ACTIVE_HIGH>; + status = "okay"; + }; }; &acdcdig_dsm { @@ -296,6 +331,12 @@ }; &pinctrl { + buttons { + pwr_key: pwr-key { + rockchip,pins = <0 RK_PA4 RK_FUNC_GPIO &pcfg_pull_up>; + }; + }; + sdmmc { /omit-if-no-ref/ sdmmc_volt: sdmmc-volt { @@ -316,6 +357,18 @@ rockchip,pins = <0 RK_PD1 RK_FUNC_GPIO &pcfg_pull_none>; }; }; + + wireless-bluetooth { + uart2_gpios: uart2-gpios { + rockchip,pins = <3 RK_PA6 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; + + wireless-wlan { + wifi_wake_host: wifi-wake-host { + rockchip,pins = <0 RK_PB1 RK_FUNC_GPIO &pcfg_pull_up>; + }; + }; }; &pwm0_8ch_0 { @@ -350,10 +403,28 @@ rknpu-supply = <&vdd_npu>; }; +&rockchip_suspend { + status = "okay"; + + rockchip,sleep-pin-config = < + (0 + | RKPM_SLEEP_PIN0_EN + ) + (0 + | RKPM_SLEEP_PIN0_ACT_LOW + ) + >; +}; + &route_dsi { status = "okay"; }; +&rtc { + rockchip,rtc-suspend-bypass; + status = "okay"; +}; + &sai2 { rockchip,sai-rx-route = <1 0 2 3>; status = "okay"; @@ -387,6 +458,27 @@ status = "okay"; }; +&sdmmc1 { + bus-width = <1>; + cap-sd-highspeed; + no-sd; + no-mmc; + max-frequency = <200000000>; + pinctrl-names = "default"; + pinctrl-0 = <&sdmmc1_clk_pins &sdmmc1_cmd_pins &sdmmc1_bus4_pins>; + keep-power-in-suspend; + non-removable; + //mmc-pwrseq = <&sdio_pwrseq>; + //sd-uhs-sdr104; + status = "okay"; +}; + +&uart2 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&uart2m0_xfer_pins &uart2m0_ctsn_pins>; +}; + &usb2phy_host { phy-supply = <&vcc5v0_host>; }; diff --git a/arch/arm64/boot/dts/rockchip/rv1126b-evb3-v10.dts b/arch/arm64/boot/dts/rockchip/rv1126b-evb3-v10.dts index 6da087f73bc4..727e7341355f 100644 --- a/arch/arm64/boot/dts/rockchip/rv1126b-evb3-v10.dts +++ b/arch/arm64/boot/dts/rockchip/rv1126b-evb3-v10.dts @@ -11,6 +11,20 @@ model = "Rockchip RV1126B EVB3 V10 Board"; compatible = "rockchip,rv1126b-evb3-v10", "rockchip,rv1126b"; + sdio_pwrseq: sdio-pwrseq { + compatible = "mmc-pwrseq-simple"; + pinctrl-names = "default"; + pinctrl-0 = <&wifi_enable_h>; + + /* + * On the module itself this is one of these (depending + * on the actual card populated): + * - SDIO_RESET_L_WL_REG_ON + * - PDN (power down when low) + */ + reset-gpios = <&gpio0 RK_PB2 GPIO_ACTIVE_LOW>; + }; + vcc5v0_dcin: vcc5v0-dcin { compatible = "regulator-fixed"; regulator-name = "vcc5v0_dcin"; @@ -95,6 +109,14 @@ vin-supply = <&vcc1v8_pmu>; }; + vcc_mipi: vcc-mipi { + compatible = "regulator-fixed"; + regulator-name = "vcc_mipi"; + gpio = <&gpio7 RK_PA7 GPIO_ACTIVE_HIGH>; + enable-active-high; + regulator-boot-on; + }; + vcc_1v8: vcc-1v8 { compatible = "regulator-fixed"; regulator-name = "vcc_1v8"; @@ -115,6 +137,28 @@ vin-supply = <&vccsys_stb>; }; + vcc_sd: vcc-sd { + compatible = "regulator-fixed"; + gpio = <&gpio7 RK_PA2 GPIO_ACTIVE_LOW>; + regulator-name = "vcc_sd"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + enable-active-low; + vin-supply = <&vcc_3v3>; + }; + + vccio_sd: vccio-sd { + compatible = "regulator-gpio"; + regulator-boot-on; + regulator-name = "vccio_sd"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <3300000>; + gpios = <&gpio7 RK_PA3 GPIO_ACTIVE_LOW>; + vin-supply = <&vccsys_stb>; + states = <1800000 0x0 + 3300000 0x1>; + }; + vdd_log: vdd-log { compatible = "pwm-regulator"; pwms = <&pwm1_4ch_2 0 25000 1>; @@ -144,7 +188,7 @@ vdd_npu: vdd-npu { compatible = "pwm-regulator"; pwms = <&pwm1_4ch_1 0 25000 1>; - regulator-name = "vdd_cpu"; + regulator-name = "vdd_npu"; regulator-init-microvolt = <950000>; regulator-min-microvolt = <750000>; regulator-max-microvolt = <1100000>; @@ -153,12 +197,52 @@ pwm-supply = <&vccsys_stb>; status = "okay"; }; + + wireless-bluetooth { + compatible = "bluetooth-platdata"; + uart_rts_gpios = <&gpio3 RK_PA6 GPIO_ACTIVE_LOW>; + pinctrl-names = "default", "rts_gpio"; + pinctrl-0 = <&uart2m0_rtsn_pins>; + pinctrl-1 = <&uart2_gpios>; + BT,power_gpio = <&gpio0 RK_PA0 GPIO_ACTIVE_HIGH>; + status = "okay"; + }; + + wireless-wlan { + compatible = "wlan-platdata"; + rockchip,grf = <&grf>; + pinctrl-names = "default"; + pinctrl-0 = <&wifi_wake_host>; + wifi_chip_type = "rk96x"; + WIFI,host_wake_irq = <&gpio0 RK_PB1 GPIO_ACTIVE_HIGH>; + status = "okay"; + }; +}; + +&backlight { + pwms = <&pwm2_8ch_7 0 25000 0>; }; &cpu0 { cpu-supply = <&vdd_cpu>; }; +&display_subsystem { + status = "okay"; +}; + +&dsi { + status = "okay"; +}; + +&dsi_in_vop { + status = "okay"; +}; + +&dsi_panel { + power-supply = <&vcc_mipi>; +}; + &fspi0 { status = "okay"; @@ -171,6 +255,26 @@ }; }; +&i2c4 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&i2c4m3_pins>; + + gt1x: gt1x@14 { + compatible = "goodix,gt1x"; + reg = <0x14>; + pinctrl-names = "default"; + pinctrl-0 = <&touch_gpio>; + power-supply = <&vcc_mipi>; + goodix,rst-gpio = <&gpio5 RK_PD6 GPIO_ACTIVE_HIGH>; + goodix,irq-gpio = <&gpio3 RK_PB7 IRQ_TYPE_LEVEL_LOW>; + }; +}; + +&mipi_dphy { + status = "okay"; +}; + &rkaiisp { status = "okay"; }; @@ -187,12 +291,42 @@ rknpu-supply = <&vdd_npu>; }; +&route_dsi { + status = "okay"; +}; + &pinctrl { + sdio-pwrseq { + wifi_enable_h: wifi-enable-h { + rockchip,pins = <0 RK_PB2 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; + + touch { + touch_gpio: touch-gpio { + rockchip,pins = + <3 RK_PB7 RK_FUNC_GPIO &pcfg_pull_up>, + <5 RK_PD6 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; + usb { vcc5v0_host_en: vcc5v0-host-en { rockchip,pins = <7 RK_PA6 RK_FUNC_GPIO &pcfg_pull_none>; }; }; + + wireless-bluetooth { + uart2_gpios: uart2-gpios { + rockchip,pins = <3 RK_PA6 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; + + wireless-wlan { + wifi_wake_host: wifi-wake-host { + rockchip,pins = <0 RK_PB1 RK_FUNC_GPIO &pcfg_pull_up>; + }; + }; }; &pwm1_4ch_0 { @@ -210,6 +344,34 @@ status = "okay"; }; +&pwm2_8ch_7 { + status = "okay"; +}; + +&saradc0 { + vref-supply = <&vcc_1v8>; +}; + +&sdmmc0 { + max-frequency = <200000000>; + no-sdio; + no-mmc; + bus-width = <4>; + cap-mmc-highspeed; + cap-sd-highspeed; + disable-wp; + sd-uhs-sdr104; + vmmc-supply = <&vcc_sd>; + vqmmc-supply = <&vccio_sd>; + status = "okay"; +}; + +&uart2 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&uart2m0_xfer_pins &uart2m0_ctsn_pins>; +}; + &usb2phy_host { phy-supply = <&vcc5v0_host>; }; diff --git a/arch/arm64/boot/dts/rockchip/rv1126b-evb4-v10.dts b/arch/arm64/boot/dts/rockchip/rv1126b-evb4-v10.dts index 29ed7fe299ec..e9aae040fb69 100644 --- a/arch/arm64/boot/dts/rockchip/rv1126b-evb4-v10.dts +++ b/arch/arm64/boot/dts/rockchip/rv1126b-evb4-v10.dts @@ -12,6 +12,20 @@ model = "Rockchip RV1126B EVB4 V10 Board"; compatible = "rockchip,rv1126b-evb4-v10", "rockchip,rv1126b"; + sdio_pwrseq: sdio-pwrseq { + compatible = "mmc-pwrseq-simple"; + pinctrl-names = "default"; + pinctrl-0 = <&wifi_enable_h>; + + /* + * On the module itself this is one of these (depending + * on the actual card populated): + * - SDIO_RESET_L_WL_REG_ON + * - PDN (power down when low) + */ + reset-gpios = <&gpio0 RK_PB2 GPIO_ACTIVE_LOW>; + }; + vcc_mipi: vcc-mipi { compatible = "regulator-fixed"; regulator-name = "vcc_mipi"; @@ -69,6 +83,26 @@ enable-gpios = <&gpio0 RK_PA3 GPIO_ACTIVE_HIGH>; pwm-supply = <&vcc5v0_sys>; }; + + wireless-bluetooth { + compatible = "bluetooth-platdata"; + uart_rts_gpios = <&gpio3 RK_PA6 GPIO_ACTIVE_LOW>; + pinctrl-names = "default", "rts_gpio"; + pinctrl-0 = <&uart2m0_rtsn_pins>; + pinctrl-1 = <&uart2_gpios>; + BT,power_gpio = <&gpio0 RK_PA0 GPIO_ACTIVE_HIGH>; + status = "okay"; + }; + + wireless-wlan { + compatible = "wlan-platdata"; + rockchip,grf = <&grf>; + pinctrl-names = "default"; + pinctrl-0 = <&wifi_wake_host>; + wifi_chip_type = "rk96x"; + WIFI,host_wake_irq = <&gpio0 RK_PB1 GPIO_ACTIVE_HIGH>; + status = "okay"; + }; }; &backlight { @@ -243,6 +277,12 @@ }; }; + sdio-pwrseq { + wifi_enable_h: wifi-enable-h { + rockchip,pins = <0 RK_PB2 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; + usb { typec5v_pwren: typec5v-pwren { rockchip,pins = <5 RK_PD6 RK_FUNC_GPIO &pcfg_pull_none>; @@ -252,6 +292,18 @@ rockchip,pins = <6 RK_PA3 RK_FUNC_GPIO &pcfg_pull_none>; }; }; + + wireless-bluetooth { + uart2_gpios: uart2-gpios { + rockchip,pins = <3 RK_PA6 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; + + wireless-wlan { + wifi_wake_host: wifi-wake-host { + rockchip,pins = <0 RK_PB1 RK_FUNC_GPIO &pcfg_pull_up>; + }; + }; }; &pwm0_8ch_0 { @@ -270,6 +322,27 @@ status = "okay"; }; +&sdmmc1 { + bus-width = <4>; + cap-sd-highspeed; + no-sd; + no-mmc; + max-frequency = <200000000>; + pinctrl-names = "default"; + pinctrl-0 = <&sdmmc1_clk_pins &sdmmc1_cmd_pins &sdmmc1_bus4_pins>; + keep-power-in-suspend; + non-removable; + mmc-pwrseq = <&sdio_pwrseq>; + //sd-uhs-sdr104; + status = "okay"; +}; + +&uart2 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&uart2m0_xfer_pins &uart2m0_ctsn_pins>; +}; + &usb2phy_host { phy-supply = <&vcc5v0_host>; }; diff --git a/arch/arm64/boot/dts/rockchip/rv1126b.dtsi b/arch/arm64/boot/dts/rockchip/rv1126b.dtsi index 4b189c269450..72a4a1c395a4 100644 --- a/arch/arm64/boot/dts/rockchip/rv1126b.dtsi +++ b/arch/arm64/boot/dts/rockchip/rv1126b.dtsi @@ -12,6 +12,7 @@ #include #include #include +#include / { compatible = "rockchip,rv1126b"; @@ -214,6 +215,15 @@ assigned-clock-rates = <550000000>; }; + pvtpll_aisp: pvtpll-aisp@21fc0000 { + compatible = "rockchip,rv1126b-aisp-pvtpll"; + reg = <0x21fc0000 0x100>; + #clock-cells = <0>; + clock-output-names = "clk_vcp_pvtpll"; + assigned-clocks = <&pvtpll_aisp>; + assigned-clock-rates = <775000000>; + }; + pvtpll_npu: pvtpll-npu@22080000 { compatible = "rockchip,rv1126b-npu-pvtpll", "syscon"; reg = <0x22080000 0x100>; @@ -393,7 +403,7 @@ compatible = "rockchip,fiq-debugger"; rockchip,serial-id = <0>; rockchip,wake-irq = <0>; - rockchip,irq-mode-enable = <0>; + rockchip,irq-mode-enable = <1>; rockchip,baudrate = <1500000>; /* Only 115200 and 1500000 */ interrupts = ; status = "disabled"; @@ -749,6 +759,25 @@ }; }; + rockchip_suspend: rockchip-suspend { + compatible = "rockchip,pm-config"; + status = "disabled"; + + rockchip,sleep-mode-config = < + (0 + | RKPM_SLP_ARMOFF_PMUOFF + | RKPM_SLP_PMU_PMUALIVE_32K + | RKPM_SLP_PMU_DIS_OSC + | RKPM_SLP_32K_EXT + ) + >; + rockchip,wakeup-config = < + (0 + | RKPM_GPIO0_WKUP_EN + ) + >; + }; + rockchip_system_monitor: rockchip-system-monitor { compatible = "rockchip,system-monitor"; }; diff --git a/arch/arm64/configs/rk3588_vehicle.config b/arch/arm64/configs/rk3588_vehicle.config index 42026d98f983..329f4bbe6299 100644 --- a/arch/arm64/configs/rk3588_vehicle.config +++ b/arch/arm64/configs/rk3588_vehicle.config @@ -22,7 +22,6 @@ CONFIG_CPU_IDLE_GOV_TEO=y # CONFIG_CPU_RK3528 is not set # CONFIG_CPU_RK3562 is not set # CONFIG_CPU_RK3568 is not set -# CONFIG_CRYPTO_DEV_ROCKCHIP_V1 is not set # CONFIG_CRYPTO_DEV_ROCKCHIP_V3 is not set # CONFIG_DRM_MAXIM_MAX96745 is not set # CONFIG_DRM_MAXIM_MAX96755F is not set @@ -34,13 +33,15 @@ CONFIG_GPIO_NCA9539=y # CONFIG_HALL_DEVICE is not set CONFIG_HZ=1000 CONFIG_HZ_1000=y -# CONFIG_HZ_300 is not set +# CONFIG_HZ_250 is not set # CONFIG_IIO_ST_LSM6DSR is not set # CONFIG_INPUT_TABLET is not set # CONFIG_LIGHT_DEVICE is not set CONFIG_LOG_BUF_SHIFT=20 # CONFIG_MALI400 is not set # CONFIG_MALI_MIDGARD is not set +# CONFIG_MFD_MAX96745 is not set +# CONFIG_MFD_MAX96755F is not set # CONFIG_MFD_RK618 is not set # CONFIG_MFD_RK630_I2C is not set # CONFIG_MFD_RKX110_X120 is not set @@ -56,15 +57,9 @@ CONFIG_REALTEK_PHY=y # CONFIG_REGULATOR_WL2868C is not set # CONFIG_REGULATOR_XZ3216 is not set # CONFIG_ROCKCHIP_CHARGER_MANAGER is not set -# CONFIG_ROCKCHIP_CLK_BOOST is not set # CONFIG_ROCKCHIP_CLK_INV is not set # CONFIG_ROCKCHIP_CLK_PVTM is not set -# CONFIG_ROCKCHIP_DDRCLK_SIP is not set -# CONFIG_ROCKCHIP_DDRCLK_SIP_V2 is not set CONFIG_ROCKCHIP_DRM_DIRECT_SHOW=y -# CONFIG_ROCKCHIP_PLL_RK3066 is not set -# CONFIG_ROCKCHIP_PLL_RK3399 is not set -# CONFIG_ROCKCHIP_SERDES_DRM_PANEL is not set CONFIG_RTC_DRV_S35390A=y # CONFIG_SLUB_SYSFS is not set # CONFIG_SND_SOC_AW883XX is not set @@ -118,9 +113,6 @@ CONFIG_VIDEO_MAXIM_SERDES=y # CONFIG_VIDEO_RK628_BT1120 is not set # CONFIG_VIDEO_RK628_CSI is not set # CONFIG_VIDEO_RK_IRCUT is not set -# CONFIG_VIDEO_ROCKCHIP_ISP_VERSION_V1X is not set -# CONFIG_VIDEO_ROCKCHIP_ISP_VERSION_V21 is not set -# CONFIG_VIDEO_ROCKCHIP_ISP_VERSION_V32 is not set # CONFIG_VIDEO_S5K3L6XX is not set # CONFIG_VIDEO_S5KJN1 is not set # CONFIG_VIDEO_SGM3784 is not set @@ -141,10 +133,10 @@ CONFIG_SERDES_DISPLAY_CHIP_ROHM=y CONFIG_SERDES_DISPLAY_CHIP_ROHM_BU18RL82=y CONFIG_SERDES_DISPLAY_CHIP_ROHM_BU18TL82=y CONFIG_VIDEO_MAXIM_CAM_DUMMY=y +CONFIG_VIDEO_MAXIM_CAM_OS04A10=y CONFIG_VIDEO_MAXIM_CAM_OV231X=y CONFIG_VIDEO_MAXIM_CAM_OX01F10=y CONFIG_VIDEO_MAXIM_CAM_OX03J10=y -CONFIG_VIDEO_MAXIM_CAM_OS04A10=y CONFIG_VIDEO_MAXIM_CAM_SC320AT=y # CONFIG_VIDEO_MAXIM_DES_MAXIM2C is not set CONFIG_VIDEO_MAXIM_DES_MAXIM4C=y diff --git a/arch/arm64/configs/rockchip_linux_defconfig b/arch/arm64/configs/rockchip_linux_defconfig index 895097420356..d3bd3c30fe0e 100644 --- a/arch/arm64/configs/rockchip_linux_defconfig +++ b/arch/arm64/configs/rockchip_linux_defconfig @@ -117,7 +117,9 @@ CONFIG_IP_NF_MANGLE=y CONFIG_CAN=y CONFIG_BT=y CONFIG_BT_RFCOMM=y +CONFIG_BT_RFCOMM_TTY=y CONFIG_BT_HIDP=y +CONFIG_BT_HS=y CONFIG_BT_HCIBTUSB=y CONFIG_BT_HCIUART=y CONFIG_BT_HCIUART_ATH3K=y @@ -205,6 +207,7 @@ CONFIG_R8168=y # CONFIG_NET_VENDOR_SIS is not set # CONFIG_NET_VENDOR_SMSC is not set CONFIG_STMMAC_ETH=y +# CONFIG_DWMAC_GENERIC is not set # CONFIG_NET_VENDOR_SUN is not set # CONFIG_NET_VENDOR_SYNOPSYS is not set # CONFIG_NET_VENDOR_TEHUTI is not set @@ -212,6 +215,7 @@ CONFIG_STMMAC_ETH=y # CONFIG_NET_VENDOR_VIA is not set # CONFIG_NET_VENDOR_WIZNET is not set CONFIG_MOTORCOMM_PHY=y +CONFIG_ROCKCHIP_FEPHY=y CONFIG_ROCKCHIP_PHY=y CONFIG_RK630_PHY=y CONFIG_CANFD_RK3576=y @@ -305,6 +309,7 @@ CONFIG_REGULATOR_GPIO=y CONFIG_REGULATOR_LP8752=y CONFIG_REGULATOR_MP8865=y CONFIG_REGULATOR_PWM=y +CONFIG_REGULATOR_RK801=y CONFIG_REGULATOR_RK806=y CONFIG_REGULATOR_RK808=y CONFIG_REGULATOR_RK860X=y @@ -317,6 +322,7 @@ CONFIG_USB_VIDEO_CLASS=y # CONFIG_USB_VIDEO_CLASS_INPUT_EVDEV is not set CONFIG_V4L_PLATFORM_DRIVERS=y CONFIG_V4L_MEM2MEM_DRIVERS=y +CONFIG_VIDEO_ROCKCHIP_AIISP=y CONFIG_VIDEO_ROCKCHIP_CIF=y CONFIG_VIDEO_ROCKCHIP_RKISP1=y CONFIG_VIDEO_ROCKCHIP_ISP=y @@ -334,7 +340,10 @@ CONFIG_VIDEO_OV4689=y CONFIG_VIDEO_OV50C40=y CONFIG_VIDEO_OV5695=y CONFIG_VIDEO_OV7251=y +CONFIG_VIDEO_SC200AI=y CONFIG_VIDEO_SC4336=y +CONFIG_VIDEO_SC450AI=y +CONFIG_VIDEO_SC850SL=y CONFIG_VIDEO_LT6911UXC=y CONFIG_VIDEO_LT6911UXE=y CONFIG_VIDEO_LT7911D=y @@ -396,6 +405,7 @@ CONFIG_ROCKCHIP_MPP_IEP2=y CONFIG_ROCKCHIP_MPP_JPGDEC=y CONFIG_ROCKCHIP_MPP_JPGENC=y CONFIG_ROCKCHIP_MPP_AV1DEC=y +CONFIG_ROCKCHIP_MPP_OSAL=y CONFIG_SOUND=y CONFIG_SND=y CONFIG_SND_HRTIMER=y @@ -430,6 +440,7 @@ CONFIG_SND_SOC_ES8323=y CONFIG_SND_SOC_ES8326=y CONFIG_SND_SOC_RK3308=y CONFIG_SND_SOC_RK3328=y +CONFIG_SND_SOC_RK3506=y CONFIG_SND_SOC_RK3528=y CONFIG_SND_SOC_RK817=y CONFIG_SND_SOC_RK_CODEC_DIGITAL=y @@ -511,22 +522,28 @@ CONFIG_RTC_DRV_HYM8563=y CONFIG_RTC_DRV_RK808=y CONFIG_DMADEVICES=y CONFIG_PL330_DMA=y +CONFIG_ROCKCHIP_DMA=y CONFIG_RK_DMABUF_DEBUG=y CONFIG_SW_SYNC=y CONFIG_DMABUF_HEAPS=y CONFIG_DMABUF_SYSFS_STATS=y CONFIG_DMABUF_HEAPS_SYSTEM=y CONFIG_DMABUF_HEAPS_CMA=y +CONFIG_DMABUF_HEAPS_ROCKCHIP=y +CONFIG_DMABUF_HEAPS_ROCKCHIP_CMA_HEAP=y +CONFIG_DMABUF_RK_HEAPS_DEBUG=y CONFIG_STAGING=y CONFIG_COMMON_CLK_RK808=y CONFIG_COMMON_CLK_SCMI=y CONFIG_COMMON_CLK_PWM=y +CONFIG_ROCKCHIP_CLK_PVTPLL=y CONFIG_MAILBOX=y CONFIG_ROCKCHIP_MBOX=y CONFIG_ROCKCHIP_IOMMU=y CONFIG_ARM_SMMU_V3=y CONFIG_RPMSG_ROCKCHIP_MBOX=y CONFIG_RPMSG_VIRTIO=y +CONFIG_CPU_RV1126B=y CONFIG_CPU_PX30=y CONFIG_CPU_RK1808=y CONFIG_CPU_RK3328=y @@ -558,7 +575,6 @@ 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 CONFIG_DEVFREQ_GOV_USERSPACE=y diff --git a/arch/arm64/configs/rv1126b_defconfig b/arch/arm64/configs/rv1126b_defconfig index a8993723222e..980b2f94984f 100644 --- a/arch/arm64/configs/rv1126b_defconfig +++ b/arch/arm64/configs/rv1126b_defconfig @@ -225,19 +225,6 @@ CONFIG_BACKLIGHT_PWM=y CONFIG_ROCKCHIP_MULTI_RGA=y CONFIG_ROCKCHIP_RGA_PROC_FS=y # CONFIG_ROCKCHIP_RGA_DEBUG_FS is not set -CONFIG_ROCKCHIP_MPP_SERVICE=y -CONFIG_ROCKCHIP_MPP_RKVDEC=y -CONFIG_ROCKCHIP_MPP_RKVDEC2=y -CONFIG_ROCKCHIP_MPP_RKVENC=y -CONFIG_ROCKCHIP_MPP_RKVENC2=y -CONFIG_ROCKCHIP_MPP_VDPU1=y -CONFIG_ROCKCHIP_MPP_VEPU1=y -CONFIG_ROCKCHIP_MPP_VDPU2=y -CONFIG_ROCKCHIP_MPP_VEPU2=y -CONFIG_ROCKCHIP_MPP_IEP2=y -CONFIG_ROCKCHIP_MPP_JPGDEC=y -CONFIG_ROCKCHIP_MPP_JPGENC=y -CONFIG_ROCKCHIP_MPP_AV1DEC=y CONFIG_ROCKCHIP_MPP_OSAL=y CONFIG_SOUND=y CONFIG_SND=y @@ -292,6 +279,7 @@ CONFIG_RTC_DRV_RK808=y CONFIG_DMADEVICES=y CONFIG_ROCKCHIP_DMA=y CONFIG_DMABUF_HEAPS=y +CONFIG_DMABUF_HEAPS_SYSTEM=y CONFIG_DMABUF_HEAPS_ROCKCHIP=y CONFIG_DMABUF_HEAPS_ROCKCHIP_CMA_HEAP=y CONFIG_DMABUF_RK_HEAPS_DEBUG=y diff --git a/drivers/clk/rockchip/clk-pvtpll.c b/drivers/clk/rockchip/clk-pvtpll.c index fae8d76d2491..978f690af748 100644 --- a/drivers/clk/rockchip/clk-pvtpll.c +++ b/drivers/clk/rockchip/clk-pvtpll.c @@ -139,6 +139,11 @@ static struct pvtpll_table rv1103b_npu_pvtpll_table[] = { ROCKCHIP_PVTPLL_VOLT_SEL(700000000, 1, 32, 4), }; +static struct pvtpll_table rv1126b_aisp_pvtpll_table[] = { + /* rate_hz, ring_se, length */ + ROCKCHIP_PVTPLL(775000000, 0, 28), +}; + static struct pvtpll_table rv1126b_core_pvtpll_table[] = { /* rate_hz, ring_sel, length */ ROCKCHIP_PVTPLL_VOLT_SEL(1608000000, 0, 30, 0), @@ -590,6 +595,12 @@ static const struct rockchip_clock_pvtpll_info rv1103b_npu_pvtpll_data = { .pvtpll_calibrate = rv1103b_pvtpll_calibrate, }; +static const struct rockchip_clock_pvtpll_info rv1126b_aisp_pvtpll_data = { + .config = rv1103b_pvtpll_configs, + .table_size = ARRAY_SIZE(rv1126b_aisp_pvtpll_table), + .table = rv1126b_aisp_pvtpll_table, +}; + static const struct rockchip_clock_pvtpll_info rv1126b_core_pvtpll_data = { .config = rv1103b_pvtpll_configs, .table_size = ARRAY_SIZE(rv1126b_core_pvtpll_table), @@ -635,6 +646,10 @@ static const struct of_device_id rockchip_clock_pvtpll_match[] = { .compatible = "rockchip,rv1103b-npu-pvtpll", .data = (void *)&rv1103b_npu_pvtpll_data, }, + { + .compatible = "rockchip,rv1126b-aisp-pvtpll", + .data = (void *)&rv1126b_aisp_pvtpll_data, + }, { .compatible = "rockchip,rv1126b-core-pvtpll", .data = (void *)&rv1126b_core_pvtpll_data, @@ -719,9 +734,27 @@ static int rockchip_clock_pvtpll_remove(struct platform_device *pdev) return 0; } +static int rockchip_clock_pvtpll_resume(struct device *dev) +{ + struct rockchip_clock_pvtpll *pvtpll = dev_get_drvdata(dev); + struct pvtpll_table *table; + + table = rockchip_get_pvtpll_settings(pvtpll, pvtpll->cur_rate); + if (!table) + return 0; + + pvtpll->info->config(pvtpll, table); + + return 0; +} + +static DEFINE_SIMPLE_DEV_PM_OPS(rockchip_clock_pvtpll_pm_ops, NULL, + rockchip_clock_pvtpll_resume); + static struct platform_driver rockchip_clock_pvtpll_driver = { .driver = { .name = "rockchip-clcok-pvtpll", + .pm = pm_sleep_ptr(&rockchip_clock_pvtpll_pm_ops), .of_match_table = rockchip_clock_pvtpll_match, }, .probe = rockchip_clock_pvtpll_probe, diff --git a/drivers/clk/rockchip/clk-rk3576.c b/drivers/clk/rockchip/clk-rk3576.c index 095157d5a34b..4f493784d090 100644 --- a/drivers/clk/rockchip/clk-rk3576.c +++ b/drivers/clk/rockchip/clk-rk3576.c @@ -91,6 +91,7 @@ static struct rockchip_pll_rate_table rk3576_pll_rates[] = { RK3588_PLL_RATE(773000000, 2, 258, 2, 43690), RK3588_PLL_RATE(722534400, 8, 963, 2, 24850), RK3588_PLL_RATE(697000000, 2, 232, 2, 21845), + RK3588_PLL_RATE(610400000, 3, 305, 2, 13107), RK3588_PLL_RATE(604800000, 1, 101, 2, 52428), RK3588_PLL_RATE(600000000, 2, 200, 2, 0), RK3588_PLL_RATE(594000000, 2, 198, 2, 0), diff --git a/drivers/clk/rockchip/clk-rv1126b.c b/drivers/clk/rockchip/clk-rv1126b.c index 03c42a11db5e..ea567a8d856f 100644 --- a/drivers/clk/rockchip/clk-rv1126b.c +++ b/drivers/clk/rockchip/clk-rv1126b.c @@ -421,7 +421,7 @@ static struct rockchip_clk_branch rv1126b_clk_branches[] __initdata = { COMPOSITE_NODIV(TCLK_WDT_NS_SRC, "tclk_wdt_ns_src", mux_100m_24m_p, 0, RV1126B_CLKSEL_CON(46), 12, 1, MFLAGS, RV1126B_CLKGATE_CON(8), 0, GFLAGS), - COMPOSITE_NODIV(TCLK_WDT_S, "tclk_wdt_s", mux_100m_24m_p, 0, + COMPOSITE_NODIV(TCLK_WDT_S_SRC, "tclk_wdt_s_src", mux_100m_24m_p, 0, RV1126B_CLKSEL_CON(46), 13, 1, MFLAGS, RV1126B_CLKGATE_CON(8), 1, GFLAGS), COMPOSITE_NODIV(TCLK_WDT_HPMCU, "tclk_wdt_hpmcu", mux_100m_24m_p, 0, @@ -459,10 +459,10 @@ static struct rockchip_clk_branch rv1126b_clk_branches[] __initdata = { COMPOSITE_NODIV(CLK_PWM3, "clk_pwm3", mux_100m_24m_p, 0, RV1126B_CLKSEL_CON(50), 11, 1, MFLAGS, RV1126B_CLKGATE_CON(9), 3, GFLAGS), - COMPOSITE_NODIV(CLK_PKA_RKCE_SRC, "clk_pka_rkce_src", mux_300m_200m_p, 0, + COMPOSITE_NODIV(CLK_PKA_RKCE_SRC, "clk_pka_rkce_src", mux_300m_200m_p, CLK_IS_CRITICAL, RV1126B_CLKSEL_CON(50), 12, 1, MFLAGS, RV1126B_CLKGATE_CON(9), 4, GFLAGS), - COMPOSITE_NODIV(ACLK_RKCE_SRC, "aclk_rkce_src", mux_200m_24m_p, 0, + COMPOSITE_NODIV(ACLK_RKCE_SRC, "aclk_rkce_src", mux_200m_24m_p, CLK_IS_CRITICAL, RV1126B_CLKSEL_CON(50), 13, 1, MFLAGS, RV1126B_CLKGATE_CON(9), 5, GFLAGS), COMPOSITE_NODIV(ACLK_VCP_ROOT, "aclk_vcp_root", mux_500m_400m_200m_p, CLK_IS_CRITICAL, @@ -865,6 +865,10 @@ static struct rockchip_clk_branch rv1126b_clk_branches[] __initdata = { COMPOSITE_NODIV(CLK_TIMER4, "clk_timer4", clk_timer4_parents_p, 0, RV1126B_BUSCLKSEL_CON(2), 8, 2, MFLAGS, RV1126B_BUSCLKGATE_CON(2), 10, GFLAGS), + GATE(HCLK_RKRNG_NS, "hclk_rkrng_ns", "hclk_bus_root", 0, + RV1126B_BUSCLKGATE_CON(2), 15, GFLAGS), + GATE(HCLK_RKRNG_S_NS, "hclk_rkrng_s_ns", "hclk_bus_root", 0, + RV1126B_BUSCLKGATE_CON(2), 14, GFLAGS), GATE(CLK_TIMER5, "clk_timer5", "clk_timer_root", 0, RV1126B_BUSCLKGATE_CON(2), 11, GFLAGS), GATE(PCLK_I2C0, "pclk_i2c0", "pclk_bus_root", 0, @@ -948,7 +952,7 @@ static struct rockchip_clk_branch rv1126b_clk_branches[] __initdata = { GATE(MCLK_AUDIO_ADC_BUS, "mclk_audio_adc_bus", "mclk_sai2", 0, RV1126B_BUSCLKGATE_CON(5), 14, GFLAGS), FACTOR(MCLK_AUDIO_ADC_DIV4_BUS, "mclk_audio_adc_div4_bus", "mclk_audio_adc_bus", 0, 1, 4), - GATE(PCLK_RKCE, "pclk_rkce", "pclk_bus_root", 0, + GATE(PCLK_RKCE, "pclk_rkce", "pclk_bus_root", CLK_IS_CRITICAL, RV1126B_BUSCLKGATE_CON(6), 0, GFLAGS), GATE(HCLK_NS_RKCE, "hclk_ns_rkce", "hclk_bus_root", 0, RV1126B_BUSCLKGATE_CON(6), 1, GFLAGS), diff --git a/drivers/gpu/drm/bridge/sii902x.c b/drivers/gpu/drm/bridge/sii902x.c index 9c5c235090b2..689bb351a943 100644 --- a/drivers/gpu/drm/bridge/sii902x.c +++ b/drivers/gpu/drm/bridge/sii902x.c @@ -620,7 +620,7 @@ static void sii902x_bridge_mode_set(struct drm_bridge *bridge, if (ret) goto out; - if (sii902x->mode.flags & DRM_MODE_FLAG_INTERLACE) + if (sii902x->mode.flags & DRM_MODE_FLAG_DBLCLK) ratio = SII902X_TPI_CLK_RATIO_2X; else ratio = SII902X_TPI_CLK_RATIO_1X; diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c index 81c22c3b89be..88e612945a3b 100644 --- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c +++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c @@ -2646,10 +2646,13 @@ dw_hdmi_connector_detect(struct drm_connector *connector, bool force) } out: - if (result == connector_status_connected) + if (result == connector_status_connected) { extcon_set_state_sync(hdmi->extcon, EXTCON_DISP_HDMI, true); - else + handle_plugged_change(hdmi, true); + } else { extcon_set_state_sync(hdmi->extcon, EXTCON_DISP_HDMI, false); + handle_plugged_change(hdmi, false); + } return result; } @@ -3577,7 +3580,6 @@ static void dw_hdmi_qp_bridge_atomic_disable(struct drm_bridge *bridge, dw_hdmi_qp_hdcp_disable(hdmi, conn_state); - handle_plugged_change(hdmi, false); if (hdmi->plat_data->crtc_pre_disable) hdmi->plat_data->crtc_pre_disable(data, bridge->encoder->crtc); mutex_lock(&hdmi->mutex); @@ -3661,8 +3663,6 @@ static void dw_hdmi_qp_bridge_atomic_enable(struct drm_bridge *bridge, dw_hdmi_qp_audio_enable(hdmi); hdmi_clk_regenerator_update_pixel_clock(hdmi); - handle_plugged_change(hdmi, true); - if (hdmi->panel) drm_panel_enable(hdmi->panel); diff --git a/drivers/gpu/drm/rockchip/ebc-dev/tcon/Makefile b/drivers/gpu/drm/rockchip/ebc-dev/tcon/Makefile index 913d4813773b..c068e38bfff6 100644 --- a/drivers/gpu/drm/rockchip/ebc-dev/tcon/Makefile +++ b/drivers/gpu/drm/rockchip/ebc-dev/tcon/Makefile @@ -1,3 +1,3 @@ # SPDX-License-Identifier: GPL-2.0 -obj-$(CONFIG_ROCKCHIP_EBC_DEV) += ebc_tcon.o eink_tcon.o +obj-$(CONFIG_ROCKCHIP_EBC_DEV) += ebc_tcon.o diff --git a/drivers/gpu/drm/rockchip/ebc-dev/tcon/eink_tcon.c b/drivers/gpu/drm/rockchip/ebc-dev/tcon/eink_tcon.c deleted file mode 100644 index 8c6f96cb991b..000000000000 --- a/drivers/gpu/drm/rockchip/ebc-dev/tcon/eink_tcon.c +++ /dev/null @@ -1,301 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Copyright (c) 2020 Rockchip Electronics Co., Ltd. - * - * Author: Zorro Liu - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "ebc_tcon.h" - -#define HIWORD_UPDATE(x, l, h) (((x) << (l)) | (GENMASK(h, l) << 16)) -#define UPDATE(x, h, l) (((x) << (l)) & GENMASK((h), (l))) - -/* eink register define */ -#define EINK_IP_ENABLE 0x00 -#define EINK_SFT_UPDATE 0x04 -#define EINK_SIT_UPDATE 0x08 -#define EINK_PRE_IMAGE_BUF_ADDR 0x0c -#define EINK_CUR_IMAGE_BUF_ADDR 0x10 -#define EINK_IMAGE_PROCESS_BUF_ADDR 0x14 -#define EINK_LINE_DATA_ADDR_OFFSET 0x18 -#define EINK_IMAGE_WIDTH 0x1c -#define EINK_IMAGE_HEIGHT 0x20 -#define EINK_DATA_FORMAT 0x24 -#define EINK_IP_STATUS 0x28 -#define EINK_IP_VERSION 0x2c -#define EINK_IP_CLR_INT 0x30 -#define EINK_INT_SETTING0 0x34 -#define EINK_INT_SETTING1 0x38 -#define EINK_INT_SETTING2 0x3c -#define EINK_INT_SETTING3 0x40 -#define EINK_INT_SETTING4 0x44 -#define EINK_INT_SETTING5 0x48 -#define EINK_INT_SETTING6 0x4c -#define EINK_INT_SETTING7 0x50 -#define EINK_WF_SETTING0 0x54 -#define EINK_WF_SETTING1 0x58 -#define EINK_WF_SETTING2 0x5c -#define EINK_WF_SETTING3 0x60 -#define EINK_WF_SETTING4 0x64 -#define EINK_WF_SETTING5 0x68 -#define EINK_WF_SETTING6 0x6c -#define EINK_WF_SETTING7 0x70 - -struct eink_reg_data { - int addr; - int value; -}; - -static const struct eink_reg_data PANEL_1200x825_INIT[] = { - { EINK_SFT_UPDATE, 0x00030001 }, - { EINK_SIT_UPDATE, 0x00050000 }, - { EINK_LINE_DATA_ADDR_OFFSET, 0x000004b0 }, //width - { EINK_IMAGE_WIDTH, 0x000004af }, //width - 1 - { EINK_IMAGE_HEIGHT, 0x00000338 }, //height - 1 - - { EINK_INT_SETTING0, 0x0e56676f }, - { EINK_INT_SETTING1, 0x40674408 }, - { EINK_INT_SETTING2, 0xd7eb7743 }, - { EINK_INT_SETTING3, 0x19414d35 }, - { EINK_INT_SETTING4, 0x12561c00 }, - { EINK_INT_SETTING5, 0x05552e0a }, - { EINK_INT_SETTING6, 0x4a400e10 }, - { EINK_INT_SETTING7, 0x15496e2b }, - - { EINK_WF_SETTING0, 0xb3f33a52 }, - { EINK_WF_SETTING1, 0x2042b122 }, - { EINK_WF_SETTING2, 0xbdb0f3be }, - { EINK_WF_SETTING3, 0xe289a0ca }, - { EINK_WF_SETTING4, 0xb0d3b2c8 }, - { EINK_WF_SETTING5, 0x3a32ab20 }, - { EINK_WF_SETTING6, 0xa69a634c }, - { EINK_WF_SETTING7, 0xd87af2c0 }, -}; - -static const struct eink_reg_data PANEL_1872x1404_INIT[] = { - { EINK_SFT_UPDATE, 0x00030001 }, - { EINK_SIT_UPDATE, 0x00050000 }, - { EINK_LINE_DATA_ADDR_OFFSET, 0x00000750 }, //width - { EINK_IMAGE_WIDTH, 0x0000074f }, //width - 1 - { EINK_IMAGE_HEIGHT, 0x0000057c }, //height -1 - - { EINK_INT_SETTING0, 0x0e56676f }, - { EINK_INT_SETTING1, 0x40674408 }, - { EINK_INT_SETTING2, 0xb14a4643 }, - { EINK_INT_SETTING3, 0x19414d35 }, - { EINK_INT_SETTING4, 0x12561c00 }, - { EINK_INT_SETTING5, 0x05552e0a }, - { EINK_INT_SETTING6, 0x4a400e10 }, - { EINK_INT_SETTING7, 0x15496e2b }, - - { EINK_WF_SETTING0, 0xb3f33a52 }, - { EINK_WF_SETTING1, 0x2042b122 }, - { EINK_WF_SETTING2, 0x34b0708b }, - { EINK_WF_SETTING3, 0xe289a0ca }, - { EINK_WF_SETTING4, 0xb0d3b2c8 }, - { EINK_WF_SETTING5, 0x3a32ab20 }, - { EINK_WF_SETTING6, 0x2f9ae079 }, - { EINK_WF_SETTING7, 0xd87af2c0 }, -}; - -static inline void tcon_write(struct eink_tcon *tcon, unsigned int reg, - unsigned int value) -{ - regmap_write(tcon->regmap_base, reg, value); -} - -static inline unsigned int tcon_read(struct eink_tcon *tcon, unsigned int reg) -{ - unsigned int value; - - regmap_read(tcon->regmap_base, reg, &value); - - return value; -} - -static inline void tcon_update_bits(struct eink_tcon *tcon, unsigned int reg, - unsigned int mask, unsigned int val) -{ - regmap_update_bits(tcon->regmap_base, reg, mask, val); -} - -static int tcon_enable(struct eink_tcon *tcon, struct ebc_panel *panel) -{ - int reg_num = 0; - int i; - const struct eink_reg_data *pre_init_reg; - - clk_prepare_enable(tcon->pclk); - clk_prepare_enable(tcon->hclk); - pm_runtime_get_sync(tcon->dev); - - if ((panel->width == 1872) && (panel->height == 1404)) { - pre_init_reg = PANEL_1872x1404_INIT; - reg_num = ARRAY_SIZE(PANEL_1872x1404_INIT); - } else if ((panel->width == 1200) && (panel->height == 825)) { - pre_init_reg = PANEL_1200x825_INIT; - reg_num = ARRAY_SIZE(PANEL_1200x825_INIT); - } else { - pre_init_reg = PANEL_1872x1404_INIT; - reg_num = ARRAY_SIZE(PANEL_1872x1404_INIT); - } - for (i = 0; i < reg_num; i++) { - tcon_write(tcon, pre_init_reg[i].addr, pre_init_reg[i].value); - } - - enable_irq(tcon->irq); - - return 0; -} - -static void tcon_disable(struct eink_tcon *tcon) -{ - disable_irq(tcon->irq); - - pm_runtime_put_sync(tcon->dev); - clk_disable_unprepare(tcon->hclk); - clk_disable_unprepare(tcon->pclk); -} - -static void tcon_image_addr_set(struct eink_tcon *tcon, u32 pre_image_buf_addr, - u32 cur_image_buf_addr, u32 image_process_buf_addr) -{ - tcon_write(tcon, EINK_PRE_IMAGE_BUF_ADDR, pre_image_buf_addr); - tcon_write(tcon, EINK_CUR_IMAGE_BUF_ADDR, cur_image_buf_addr); - tcon_write(tcon, EINK_IMAGE_PROCESS_BUF_ADDR, image_process_buf_addr); -} - -static void tcon_frame_start(struct eink_tcon *tcon) -{ - tcon_write(tcon, EINK_IP_ENABLE, 1); -} - -static irqreturn_t tcon_irq_hanlder(int irq, void *dev_id) -{ - struct eink_tcon *tcon = (struct eink_tcon *)dev_id; - u32 intr_status; - - intr_status = tcon_read(tcon, EINK_IP_STATUS); - - if (intr_status & 0x1) { - tcon_update_bits(tcon, EINK_IP_CLR_INT, 0x1, 0x1); - - if (tcon->dsp_end_callback) - tcon->dsp_end_callback(); - } - - return IRQ_HANDLED; -} - -static struct regmap_config eink_regmap_config = { - .reg_bits = 32, - .val_bits = 32, - .reg_stride = 4, -}; - -static int eink_tcon_probe(struct platform_device *pdev) -{ - struct device *dev = &pdev->dev; - struct eink_tcon *tcon; - struct resource *res; - int ret; - - tcon = devm_kzalloc(dev, sizeof(*tcon), GFP_KERNEL); - if (!tcon) - return -ENOMEM; - - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - tcon->regs = devm_ioremap_resource(dev, res); - if (IS_ERR(tcon->regs)) - return PTR_ERR(tcon->regs); - - tcon->len = resource_size(res); - eink_regmap_config.max_register = resource_size(res) - 4; - eink_regmap_config.name = "rockchip,eink_tcon"; - tcon->regmap_base = devm_regmap_init_mmio(dev, tcon->regs, &eink_regmap_config); - if (IS_ERR(tcon->regmap_base)) - return PTR_ERR(tcon->regmap_base); - - tcon->hclk = devm_clk_get(dev, "hclk"); - if (IS_ERR(tcon->hclk)) { - ret = PTR_ERR(tcon->hclk); - dev_err(dev, "failed to get hclk clock: %d\n", ret); - return ret; - } - - tcon->pclk = devm_clk_get(dev, "pclk"); - if (IS_ERR(tcon->pclk)) { - ret = PTR_ERR(tcon->pclk); - dev_err(dev, "failed to get dclk clock: %d\n", ret); - return ret; - } - - tcon->irq = platform_get_irq(pdev, 0); - if (tcon->irq < 0) { - dev_err(dev, "No IRQ resource!\n"); - return tcon->irq; - } - - irq_set_status_flags(tcon->irq, IRQ_NOAUTOEN); - ret = devm_request_irq(dev, tcon->irq, tcon_irq_hanlder, - 0, dev_name(dev), tcon); - if (ret < 0) { - dev_err(dev, "failed to requeset irq: %d\n", ret); - return ret; - } - - tcon->dev = dev; - tcon->enable = tcon_enable; - tcon->disable = tcon_disable; - tcon->image_addr_set = tcon_image_addr_set; - tcon->frame_start = tcon_frame_start; - platform_set_drvdata(pdev, tcon); - - pm_runtime_enable(dev); - - return 0; -} - -static int eink_tcon_remove(struct platform_device *pdev) -{ - pm_runtime_disable(&pdev->dev); - - return 0; -} - -static const struct of_device_id eink_tcon_of_match[] = { - { .compatible = "rockchip,rk3568-eink-tcon" }, - {} -}; -MODULE_DEVICE_TABLE(of, eink_tcon_of_match); - -static struct platform_driver eink_tcon_driver = { - .driver = { - .name = "rk-eink-tcon", - .of_match_table = eink_tcon_of_match, - }, - .probe = eink_tcon_probe, - .remove = eink_tcon_remove, -}; -module_platform_driver(eink_tcon_driver); - -MODULE_AUTHOR("Zorro Liu "); -MODULE_DESCRIPTION("ROCKCHIP EINK tcon driver"); -MODULE_LICENSE("GPL v2"); diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c index fb783942b5b7..0ac44924a50e 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c @@ -1906,6 +1906,7 @@ static int rockchip_drm_bind(struct device *dev) goto err_drm_fbdev_fini; rockchip_drm_error_event_init(drm_dev); + rockchip_clocks_loader_unprotect(); return 0; err_drm_fbdev_fini: diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_logo.c b/drivers/gpu/drm/rockchip/rockchip_drm_logo.c index e1277c8cae1f..0491503b9ee9 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_logo.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_logo.c @@ -1311,7 +1311,7 @@ static const char *const loader_protect_clocks[] __initconst = { "dclk_vp3", }; -static struct clk **loader_clocks __initdata; +static struct clk **loader_clocks; static int __init rockchip_clocks_loader_protect(void) { int nclocks = ARRAY_SIZE(loader_protect_clocks); @@ -1335,7 +1335,7 @@ static int __init rockchip_clocks_loader_protect(void) } arch_initcall_sync(rockchip_clocks_loader_protect); -static int __init rockchip_clocks_loader_unprotect(void) +int rockchip_clocks_loader_unprotect(void) { int i; @@ -1349,8 +1349,8 @@ static int __init rockchip_clocks_loader_unprotect(void) clk_disable_unprepare(clk); } kfree(loader_clocks); + loader_clocks = NULL; return 0; } -late_initcall_sync(rockchip_clocks_loader_unprotect); #endif diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_logo.h b/drivers/gpu/drm/rockchip/rockchip_drm_logo.h index 7e1b1d2dfdf4..ab3fe550713c 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_logo.h +++ b/drivers/gpu/drm/rockchip/rockchip_drm_logo.h @@ -42,5 +42,13 @@ struct rockchip_drm_mode_set { void rockchip_drm_show_logo(struct drm_device *drm_dev); void rockchip_free_loader_memory(struct drm_device *drm); +#ifndef MODULE +int rockchip_clocks_loader_unprotect(void); +#else +static inline int rockchip_clocks_loader_unprotect(void) +{ + return 0; +} +#endif #endif diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c index 10e31fb0b468..0b8ea45eba6f 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c @@ -2626,7 +2626,8 @@ static void vop_plane_atomic_update(struct drm_plane *plane, } if ((vop->version == VOP_VERSION_RK3036 || vop->version == VOP_VERSION_RK3506 || - vop->version == VOP_VERSION_RK3576_LITE) && + vop->version == VOP_VERSION_RK3576_LITE || + vop->version == VOP_VERSION_RV1126B) && (adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE)) dsp_h = dsp_h / 2; @@ -2643,7 +2644,8 @@ static void vop_plane_atomic_update(struct drm_plane *plane, dsp_sty = dest->y1 + mode->crtc_vtotal - mode->crtc_vsync_start; if ((vop->version == VOP_VERSION_RK3036 || vop->version == VOP_VERSION_RK3506 || - vop->version == VOP_VERSION_RK3576_LITE) && + vop->version == VOP_VERSION_RK3576_LITE || + vop->version == VOP_VERSION_RV1126B) && (adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE)) dsp_sty = dest->y1 / 2 + mode->crtc_vtotal - mode->crtc_vsync_start; dsp_st = dsp_sty << 16 | (dsp_stx & 0xffff); @@ -3444,10 +3446,10 @@ vop_crtc_mode_valid(struct drm_crtc *crtc, const struct drm_display_mode *mode) /* * Dclk need to be double if BT656 interface and vop version >= 2.12. - * That is RV1126/RV1106/RK3576_LITE/RK3506 + * That is RV1126/RV1106/RK3576_LITE/RK3506/RV1126B */ if (mode->flags & DRM_MODE_FLAG_DBLCLK || - (VOP_MAJOR(vop->version) == 2 && VOP_MINOR(vop->version) >= 12 && + (vop->version >= VOP_VERSION_RV1106 && vop->version <= VOP_VERSION_RK3288 && s->output_if & VOP_OUTPUT_IF_BT656)) request_clock *= 2; clock = clk_round_rate(vop->dclk, request_clock * 1000) / 1000; @@ -3719,21 +3721,26 @@ static void vop_crtc_send_mcu_cmd(struct drm_crtc *crtc, u32 type, u32 value) if (vop && vop->is_enabled) { switch (type) { case MCU_WRCMD: + VOP_CTRL_SET(vop, mcu_force_rdn, 1); VOP_CTRL_SET(vop, mcu_rs, 0); VOP_CTRL_SET(vop, mcu_rw_bypass_port, value); VOP_CTRL_SET(vop, mcu_rs, 1); break; case MCU_WRDATA: + VOP_CTRL_SET(vop, mcu_force_rdn, 1); VOP_CTRL_SET(vop, mcu_rs, 1); VOP_CTRL_SET(vop, mcu_rw_bypass_port, value); break; case MCU_RDDATA: + VOP_CTRL_SET(vop, mcu_force_rdn, 0); VOP_CTRL_SET(vop, mcu_rs, 1); val = VOP_CTRL_GET(vop, mcu_rw_bypass_port); DRM_DEBUG_DRIVER("mcu read reg[0x%02x] = 0x%02x", value, val); break; case MCU_SETBYPASS: VOP_CTRL_SET(vop, mcu_bypass, value ? 1 : 0); + if (!value) + VOP_CTRL_SET(vop, mcu_force_rdn, 1); break; default: break; @@ -3898,10 +3905,10 @@ static bool vop_crtc_mode_fixup(struct drm_crtc *crtc, /* * Dclk need to be double if BT656 interface and vop version >= 2.12. - * That is RV1126/RV1106/RK3576_LITE/RK3506 + * That is RV1126/RV1106/RK3576_LITE/RK3506/RV1126B */ if (mode->flags & DRM_MODE_FLAG_DBLCLK || - (VOP_MAJOR(vop->version) == 2 && VOP_MINOR(vop->version) >= 12 && + (vop->version >= VOP_VERSION_RV1106 && vop->version <= VOP_VERSION_RK3288 && s->output_if & VOP_OUTPUT_IF_BT656)) adj_mode->crtc_clock *= 2; @@ -4005,11 +4012,11 @@ static void vop_update_csc(struct drm_crtc *crtc) u32 val; /* - * When using BT656, set RV1126/RV1106/RK3576_LITE/RK3506 to P8888 mode. + * When using BT656, set RV1126/RV1106/RK3576_LITE/RK3506/RV1126B to P8888 mode. */ if ((s->output_mode == ROCKCHIP_OUT_MODE_AAAA && !(vop->data->feature & VOP_FEATURE_OUTPUT_10BIT)) || - (VOP_MAJOR(vop->version) == 2 && VOP_MINOR(vop->version) >= 12 && + (vop->version >= VOP_VERSION_RV1106 && vop->version <= VOP_VERSION_RK3288 && s->output_if & VOP_OUTPUT_IF_BT656)) s->output_mode = ROCKCHIP_OUT_MODE_P888; diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.h b/drivers/gpu/drm/rockchip/rockchip_drm_vop.h index 8a701fb77903..449c75963fc0 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.h +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.h @@ -457,6 +457,7 @@ struct vop_ctrl { struct vop_reg mcu_bypass; struct vop_reg mcu_type; struct vop_reg mcu_rw_bypass_port; + struct vop_reg mcu_force_rdn; /* bt1120 */ struct vop_reg bt1120_uv_swap; diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c index f74775464357..3fd603febdf3 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c @@ -1549,20 +1549,27 @@ static void vop2_load_sdr2hdr_table(struct vop2_video_port *vp, int sdr2hdr_tf) const struct vop2_video_port_regs *regs = vp->regs; uint32_t sdr2hdr_eotf_oetf_yn[65]; uint32_t sdr2hdr_oetf_dx_dxpow[64]; - int i; + int i, bt1886_eotf_coe = 1; for (i = 0; i < 65; i++) { + /* + * rk3568/rk3588 sdr2hdr bt1886 eotf dx << 1 by mistake, so add + * bt1886_eotf_coe to adapt it. + */ + if (i == 64) + bt1886_eotf_coe = 0; + if (sdr2hdr_tf == SDR2HDR_FOR_BT2020) sdr2hdr_eotf_oetf_yn[i] = - table->sdr2hdr_bt1886eotf_yn_for_bt2020[i] + + (table->sdr2hdr_bt1886eotf_yn_for_bt2020[i] << bt1886_eotf_coe) + (table->sdr2hdr_st2084oetf_yn_for_bt2020[i] << 18); else if (sdr2hdr_tf == SDR2HDR_FOR_HDR) sdr2hdr_eotf_oetf_yn[i] = - table->sdr2hdr_bt1886eotf_yn_for_hdr[i] + + (table->sdr2hdr_bt1886eotf_yn_for_hdr[i] << bt1886_eotf_coe) + (table->sdr2hdr_st2084oetf_yn_for_hdr[i] << 18); else if (sdr2hdr_tf == SDR2HDR_FOR_HLG_HDR) sdr2hdr_eotf_oetf_yn[i] = - table->sdr2hdr_bt1886eotf_yn_for_hlg_hdr[i] + + (table->sdr2hdr_bt1886eotf_yn_for_hlg_hdr[i] << bt1886_eotf_coe) + (table->sdr2hdr_st2084oetf_yn_for_hlg_hdr[i] << 18); } @@ -11070,7 +11077,7 @@ static void vop2_setup_hdr10(struct vop2_video_port *vp, uint8_t win_phys_id) bool sdr2hdr_en = 0; bool sdr2hdr_tf = 0; bool hdr2sdr_tf_update = 1; - bool sdr2hdr_tf_update = 0; /* default sdr2hdr curve is 1000 nit */ + bool sdr2hdr_tf_update = 1; unsigned long win_mask = vp->win_mask; int phys_id; bool have_sdr_layer = false; diff --git a/drivers/gpu/drm/rockchip/rockchip_vop2_reg.c b/drivers/gpu/drm/rockchip/rockchip_vop2_reg.c index 1651d719852c..2c4957ad8100 100644 --- a/drivers/gpu/drm/rockchip/rockchip_vop2_reg.c +++ b/drivers/gpu/drm/rockchip/rockchip_vop2_reg.c @@ -415,24 +415,24 @@ static const u32 sdr2hdr_bt1886eotf_yn_for_bt2020[65] = { }; static u32 sdr2hdr_bt1886eotf_yn_for_hdr[65] = { - /* dst_range 425int */ + /* dst_range 500 nit */ 0, - 5, 21, 49, 91, - 150, 225, 320, 434, - 569, 726, 905, 1108, - 1336, 1588, 1866, 2171, - 2502, 2862, 3250, 3667, - 3887, 4114, 4349, 4591, - 4841, 5099, 5364, 5638, - 5920, 6209, 6507, 6812, - 6968, 7126, 7287, 7449, - 7613, 7779, 7948, 8118, - 8291, 8466, 8643, 8822, - 9003, 9187, 9372, 9560, - 9655, 9750, 9846, 9942, - 10039, 10136, 10234, 10333, - 10432, 10531, 10631, 10732, - 10833, 10935, 11038, 11141, + 6, 29, 72, 135, + 221, 330, 463, 621, + 804, 1014, 1251, 1515, + 1807, 2126, 2475, 2853, + 3260, 3696, 4163, 4661, + 4921, 5189, 5464, 5748, + 6039, 6338, 6646, 6961, + 7284, 7615, 7954, 8301, + 8477, 8656, 8837, 9019, + 9204, 9391, 9580, 9771, + 9964, 10159, 10356, 10555, + 10756, 10959, 11165, 11372, + 11477, 11582, 11687, 11793, + 11900, 12007, 12115, 12223, + 12332, 12441, 12551, 12661, + 12772, 12883, 12995, 13107, }; static const u32 sdr2hdr_st2084oetf_yn_for_hlg_hdr[65] = { diff --git a/drivers/gpu/drm/rockchip/rockchip_vop_reg.c b/drivers/gpu/drm/rockchip/rockchip_vop_reg.c index e4df700d012d..2272f3994117 100644 --- a/drivers/gpu/drm/rockchip/rockchip_vop_reg.c +++ b/drivers/gpu/drm/rockchip/rockchip_vop_reg.c @@ -1639,6 +1639,7 @@ static const struct vop_win_phy px30_win23_data = { .csc_mode = VOP_REG(RK3368_WIN2_CTRL0, 0x3, 2), .format = VOP_REG(RK3368_WIN2_CTRL0, 0x3, 5), .rb_swap = VOP_REG(RK3368_WIN2_CTRL0, 0x1, 20), + .interlace_read = VOP_REG_VER(RK3368_WIN2_CTRL0, 0x1, 1, 2, 0xf, -1), .dsp_info = VOP_REG(RK3368_WIN2_DSP_INFO0, 0x0fff0fff, 0), .dsp_st = VOP_REG(RK3368_WIN2_DSP_ST0, 0x1fff1fff, 0), .yrgb_mst = VOP_REG(RK3368_WIN2_MST0, 0xffffffff, 0), @@ -1942,6 +1943,9 @@ static const struct vop_ctrl rv1126b_ctrl_data = { .mipi_pin_pol = VOP_REG(RK3366_LIT_DSP_CTRL0, 0x7, 26), .bt1120_yc_swap = VOP_REG(RK3366_LIT_DSP_CTRL0, 0x1, 30), .bt1120_en = VOP_REG(RK3366_LIT_DSP_CTRL0, 0x1, 31), + .bt656_en = VOP_REG(RK3366_LIT_DSP_CTRL0, 0x1, 6), + + .mcu_force_rdn = VOP_REG(RV1126B_DSP_CTRL1, 0x1, 21), .dsp_interlace = VOP_REG(RK3366_LIT_DSP_CTRL2, 0x1, 0), .dither_up_en = VOP_REG(RK3366_LIT_DSP_CTRL2, 0x1, 2), diff --git a/drivers/gpu/drm/rockchip/rockchip_vop_reg.h b/drivers/gpu/drm/rockchip/rockchip_vop_reg.h index c1086ab10700..d175c742c613 100644 --- a/drivers/gpu/drm/rockchip/rockchip_vop_reg.h +++ b/drivers/gpu/drm/rockchip/rockchip_vop_reg.h @@ -1039,6 +1039,7 @@ #define RV1126_GRF_IOFUNC_CON3 0x1026c +#define RV1126B_DSP_CTRL1 0x0024 #define RV1126B_CLK_CNT 0x0040 #define RV1126B_GRF_VOP_LCDC_CON 0x30b9c #define RV1126B_WB_CTRL 0x0280 diff --git a/drivers/media/i2c/Kconfig b/drivers/media/i2c/Kconfig index 5f521b111836..a42301db7fca 100644 --- a/drivers/media/i2c/Kconfig +++ b/drivers/media/i2c/Kconfig @@ -837,6 +837,19 @@ config VIDEO_IMX586 To compile this driver as a module, choose M here: the module will be called imx586. +config VIDEO_IMX766 + tristate "Sony IMX766 sensor support" + depends on I2C && VIDEO_DEV + depends on MEDIA_CAMERA_SUPPORT + select MEDIA_CONTROLLER + select VIDEO_V4L2_SUBDEV_API + help + This is a Video4Linux2 sensor driver for the Sony + IMX766 camera. + + To compile this driver as a module, choose M here: the + module will be called imx766. + config VIDEO_JX_F37 tristate "Soi JX_F37 sensor support" depends on I2C && VIDEO_DEV diff --git a/drivers/media/i2c/Makefile b/drivers/media/i2c/Makefile index d2353fbc6f42..9c89270f1ce5 100644 --- a/drivers/media/i2c/Makefile +++ b/drivers/media/i2c/Makefile @@ -105,6 +105,7 @@ obj-$(CONFIG_VIDEO_IMX492) += imx492.o obj-$(CONFIG_VIDEO_IMX498) += imx498.o obj-$(CONFIG_VIDEO_IMX577) += imx577.o obj-$(CONFIG_VIDEO_IMX586) += imx586.o +obj-$(CONFIG_VIDEO_IMX766) += imx766.o obj-$(CONFIG_VIDEO_IR_I2C) += ir-kbd-i2c.o obj-$(CONFIG_VIDEO_ISL7998X) += isl7998x.o obj-$(CONFIG_VIDEO_IT6616) += it6616.o diff --git a/drivers/media/i2c/dw9800v.c b/drivers/media/i2c/dw9800v.c index f6468f45075a..1a29f4c981be 100644 --- a/drivers/media/i2c/dw9800v.c +++ b/drivers/media/i2c/dw9800v.c @@ -713,6 +713,7 @@ static int __dw9800v_set_power(struct dw9800v_device *dw9800v, bool on) goto unlock_and_return; } dw9800v->power_on = true; + usleep_range(5000, 6000); } else { ret = regulator_disable(dw9800v->supply); if (ret < 0) { diff --git a/drivers/media/i2c/dw9800w.c b/drivers/media/i2c/dw9800w.c index 21fe6a40775b..ce534c9631f4 100644 --- a/drivers/media/i2c/dw9800w.c +++ b/drivers/media/i2c/dw9800w.c @@ -32,6 +32,12 @@ #define DW9800W_CHIP_ID 0xF2 #define DW9800W_REG_CHIP_ID 0x00 +static const char * const dw9800w_supply_names[] = { + "avdd", /* Analog power */ +}; + +#define DW9800W_NUM_SUPPLIES ARRAY_SIZE(dw9800w_supply_names) + enum mode_e { SAC2_MODE, SAC3_MODE, @@ -43,6 +49,7 @@ enum mode_e { /* dw9800w device structure */ struct dw9800w_device { + struct regulator_bulk_data supplies[DW9800W_NUM_SUPPLIES]; struct v4l2_ctrl_handler ctrls_vcm; struct v4l2_ctrl *focus; struct i2c_client *client; @@ -564,9 +571,19 @@ static int dw9800w_init_controls(struct dw9800w_device *dev_vcm) static int __dw9800w_set_power(struct dw9800w_device *dw9800w_dev, bool on) { + int ret = 0; + if (dw9800w_dev->power_gpio) gpiod_direction_output(dw9800w_dev->power_gpio, on); + if (on) { + ret = regulator_bulk_enable(DW9800W_NUM_SUPPLIES, dw9800w_dev->supplies); + if (ret < 0) + dev_err(&dw9800w_dev->client->dev, "Failed to enable regulators\n"); + usleep_range(5000, 6000); + } else { + regulator_bulk_disable(DW9800W_NUM_SUPPLIES, dw9800w_dev->supplies); + } return 0; } @@ -604,6 +621,18 @@ err: return -1; } +static int dw9800w_configure_regulators(struct dw9800w_device *dw9800w_dev) +{ + unsigned int i; + + for (i = 0; i < DW9800W_NUM_SUPPLIES; i++) + dw9800w_dev->supplies[i].supply = dw9800w_supply_names[i]; + + return devm_regulator_bulk_get(&dw9800w_dev->client->dev, + DW9800W_NUM_SUPPLIES, + dw9800w_dev->supplies); +} + static int dw9800w_probe(struct i2c_client *client, const struct i2c_device_id *id) { @@ -693,6 +722,12 @@ static int dw9800w_probe(struct i2c_client *client, "Failed to get power-gpios, maybe no use\n"); } + ret = dw9800w_configure_regulators(dw9800w_dev); + if (ret) { + dev_err(&client->dev, "Failed to get power regulators\n"); + return ret; + } + ret = dw9800w_check_id(dw9800w_dev); if (ret) goto err_power_off; diff --git a/drivers/media/i2c/gc8613.c b/drivers/media/i2c/gc8613.c index c18cf06c2c9f..fa4c7962ca12 100644 --- a/drivers/media/i2c/gc8613.c +++ b/drivers/media/i2c/gc8613.c @@ -443,12 +443,12 @@ static const struct regval gc8613ya_dag_12bit_3840x2160_30fps_regs[] = { {0x025a, 0x98}, //30fps 0x08f8 - //{0x0340, 0x08}, - //{0x0341, 0xf8}, + {0x0340, 0x08}, + {0x0341, 0xf8}, //15fps:0x11f0 - {0x0340, 0x11}, - {0x0341, 0xf0}, + //{0x0340, 0x11}, + //{0x0341, 0xf0}, {0x0345, 0x02}, {0x0347, 0x02}, @@ -864,12 +864,12 @@ static const struct regval gc8613yn_dag_12bit_3840x2160_30fps_regs[] = { {0x025a, 0x98}, //30fps 0x08f8 - //{0x0340, 0x08}, - //{0x0341, 0xf8}, + {0x0340, 0x08}, + {0x0341, 0xf8}, //15fps:0x11f0 - {0x0340, 0x11}, - {0x0341, 0xf0}, + //{0x0340, 0x11}, + //{0x0341, 0xf0}, {0x0345, 0x02}, {0x0347, 0x02}, @@ -1253,11 +1253,11 @@ static const struct gc8613_mode supported_modes[] = { .height = 2160, .max_fps = { .numerator = 10000, - .denominator = 150000, + .denominator = 300000, }, .exp_def = 0x0327, .hts_def = 0x0310 * 8, - .vts_def = 0x08f8 * 2, + .vts_def = 0x08f8, .bus_fmt = MEDIA_BUS_FMT_SRGGB12_1X12, .reg_list[0] = gc8613yn_dag_12bit_3840x2160_30fps_regs, .reg_list[1] = gc8613ya_dag_12bit_3840x2160_30fps_regs, diff --git a/drivers/media/i2c/imx766.c b/drivers/media/i2c/imx766.c new file mode 100644 index 000000000000..a1ad9cc879df --- /dev/null +++ b/drivers/media/i2c/imx766.c @@ -0,0 +1,2359 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * imx766 driver + * + * Copyright (C) 2025 Rockchip Electronics Co., Ltd. + * + * V0.0X01.0X01 add poweron function. + * V0.0X01.0X02 fix mclk issue when probe multiple camera. + * V0.0X01.0X03 add enum_frame_interval function. + * V0.0X01.0X04 add quick stream on/off + * V0.0X01.0X05 add function g_mbus_config + * V0.0X01.0X06 support capture spd data and embedded data + */ + +#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, 0x06) + +#ifndef V4L2_CID_DIGITAL_GAIN +#define V4L2_CID_DIGITAL_GAIN V4L2_CID_GAIN +#endif + +#define IMX766_LANES 4 +#define IMX766_BITS_PER_SAMPLE 10 +#define IMX766_LINK_FREQ_436MHZ 436000000 // 872/2 +/* pixel rate = link frequency * 2 * lanes / BITS_PER_SAMPLE */ +#define IMX766_PIXEL_RATE_FULL_SIZE 799200000 +#define IMX766_PIXEL_RATE_BINNING 348800000 +#define IMX766_XVCLK_FREQ 24000000 + +#define CHIP_ID 0x0766 +#define IMX766_REG_CHIP_ID 0x0016 + +#define IMX766_REG_CTRL_MODE 0x0100 +#define IMX766_MODE_SW_STANDBY 0x0 +#define IMX766_MODE_STREAMING BIT(0) + +#define IMX766_REG_EXPOSURE 0x0202 +#define IMX766_EXPOSURE_MIN 10 +#define IMX766_EXPOSURE_STEP 4 +#define IMX766_VTS_MAX (0xffff-0x48) + +#define IMX766_REG_GAIN_H 0x0204 +#define IMX766_REG_GAIN_L 0x0205 +#define IMX766_GAIN_MIN 0 +#define IMX766_GAIN_MAX 0x3F00 +#define IMX766_GAIN_STEP 1 +#define IMX766_GAIN_DEFAULT 0x0 + +#define IMX766_REG_TEST_PATTERN 0x0600 +#define IMX766_TEST_PATTERN_ENABLE 0x80 +#define IMX766_TEST_PATTERN_DISABLE 0x0 + +#define IMX766_REG_VTS 0x0340 + +#define REG_NULL 0xFFFF + +#define IMX766_REG_VALUE_08BIT 1 +#define IMX766_REG_VALUE_16BIT 2 +#define IMX766_REG_VALUE_24BIT 3 + +#define OF_CAMERA_PINCTRL_STATE_DEFAULT "rockchip,camera_default" +#define OF_CAMERA_PINCTRL_STATE_SLEEP "rockchip,camera_sleep" + +#define IMX766_NAME "imx766" + +static const char * const imx766_supply_names[] = { + "avdd", /* Analog power */ + "dovdd", /* Digital I/O power */ + "dvdd", /* Digital core power */ +}; + +#define IMX766_NUM_SUPPLIES ARRAY_SIZE(imx766_supply_names) + +struct regval { + u16 addr; + u8 val; +}; + +struct other_data { + u32 width; + u32 height; + u32 bus_fmt; + u32 data_type; + u32 data_bit; +}; + +struct imx766_mode { + u32 bus_fmt; + u32 width; + u32 height; + struct v4l2_fract max_fps; + u32 hts_def; + u32 vts_def; + u32 exp_def; + const struct regval *reg_list; + /* Shield Pix Data */ + const struct other_data *spd; + /* embedded Data */ + const struct other_data *ebd; + u32 hdr_mode; + u32 vc[PAD_MAX]; +}; + +struct imx766 { + struct i2c_client *client; + struct clk *xvclk; + struct gpio_desc *reset_gpio; + struct gpio_desc *pwdn_gpio; + struct gpio_desc *power_gpio; + struct regulator_bulk_data supplies[IMX766_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 *test_pattern; + struct mutex mutex; + bool streaming; + bool power_on; + const struct imx766_mode *cur_mode; + u32 cfg_num; + u32 module_index; + const char *module_facing; + const char *module_name; + const char *len_name; + struct v4l2_ctrl *link_freq; + struct v4l2_ctrl *pixel_rate; + struct otp_info *otp; + u32 spd_id; + u32 ebd_id; +}; + +#define to_imx766(sd) container_of(sd, struct imx766, subdev) + +/* + * Xclk 24Mhz + */ +static const struct regval imx766_global_regs[] = { + {0x0100, 0x00}, + {0x0136, 0x18}, + {0x0137, 0x00}, + {0x33F0, 0x09}, + {0x33F1, 0x05}, + {0x0111, 0x02}, + {0x33D3, 0x01}, + {0x3892, 0x01}, + {0x4C14, 0x00}, + {0x4C15, 0x07}, + {0x4C16, 0x00}, + {0x4C17, 0x1B}, + {0x4C1A, 0x00}, + {0x4C1B, 0x03}, + {0x4C1C, 0x00}, + {0x4C1D, 0x00}, + {0x4C1E, 0x00}, + {0x4C1F, 0x02}, + {0x4C20, 0x00}, + {0x4C21, 0x5F}, + {0x4C26, 0x00}, + {0x4C27, 0x43}, + {0x4C28, 0x00}, + {0x4C29, 0x09}, + {0x4C2A, 0x00}, + {0x4C2B, 0x4A}, + {0x4C2C, 0x00}, + {0x4C2D, 0x00}, + {0x4C2E, 0x00}, + {0x4C2F, 0x02}, + {0x4C30, 0x00}, + {0x4C31, 0xC6}, + {0x4C3E, 0x00}, + {0x4C3F, 0x55}, + {0x4C52, 0x00}, + {0x4C53, 0x97}, + {0x4CB4, 0x00}, + {0x4CB5, 0x55}, + {0x4CC8, 0x00}, + {0x4CC9, 0x97}, + {0x4D04, 0x00}, + {0x4D05, 0x4F}, + {0x4D74, 0x00}, + {0x4D75, 0x55}, + {0x4F06, 0x00}, + {0x4F07, 0x5F}, + {0x4F48, 0x00}, + {0x4F49, 0xC6}, + {0x544A, 0xFF}, + {0x544B, 0xFF}, + {0x544E, 0x01}, + {0x544F, 0xBD}, + {0x5452, 0xFF}, + {0x5453, 0xFF}, + {0x5456, 0x00}, + {0x5457, 0xA5}, + {0x545A, 0xFF}, + {0x545B, 0xFF}, + {0x545E, 0x00}, + {0x545F, 0xA5}, + {0x5496, 0x00}, + {0x5497, 0xA2}, + {0x54F6, 0x01}, + {0x54F7, 0x55}, + {0x54F8, 0x01}, + {0x54F9, 0x61}, + {0x5670, 0x00}, + {0x5671, 0x85}, + {0x5672, 0x01}, + {0x5673, 0x77}, + {0x5674, 0x01}, + {0x5675, 0x2F}, + {0x5676, 0x02}, + {0x5677, 0x55}, + {0x5678, 0x00}, + {0x5679, 0x85}, + {0x567A, 0x01}, + {0x567B, 0x77}, + {0x567C, 0x01}, + {0x567D, 0x2F}, + {0x567E, 0x02}, + {0x567F, 0x55}, + {0x5680, 0x00}, + {0x5681, 0x85}, + {0x5682, 0x01}, + {0x5683, 0x77}, + {0x5684, 0x01}, + {0x5685, 0x2F}, + {0x5686, 0x02}, + {0x5687, 0x55}, + {0x5688, 0x00}, + {0x5689, 0x85}, + {0x568A, 0x01}, + {0x568B, 0x77}, + {0x568C, 0x01}, + {0x568D, 0x2F}, + {0x568E, 0x02}, + {0x568F, 0x55}, + {0x5690, 0x01}, + {0x5691, 0x7A}, + {0x5692, 0x02}, + {0x5693, 0x6C}, + {0x5694, 0x01}, + {0x5695, 0x35}, + {0x5696, 0x02}, + {0x5697, 0x5B}, + {0x5698, 0x01}, + {0x5699, 0x7A}, + {0x569A, 0x02}, + {0x569B, 0x6C}, + {0x569C, 0x01}, + {0x569D, 0x35}, + {0x569E, 0x02}, + {0x569F, 0x5B}, + {0x56A0, 0x01}, + {0x56A1, 0x7A}, + {0x56A2, 0x02}, + {0x56A3, 0x6C}, + {0x56A4, 0x01}, + {0x56A5, 0x35}, + {0x56A6, 0x02}, + {0x56A7, 0x5B}, + {0x56A8, 0x01}, + {0x56A9, 0x80}, + {0x56AA, 0x02}, + {0x56AB, 0x72}, + {0x56AC, 0x01}, + {0x56AD, 0x2F}, + {0x56AE, 0x02}, + {0x56AF, 0x55}, + {0x5902, 0x0E}, + {0x5A50, 0x04}, + {0x5A51, 0x04}, + {0x5A69, 0x01}, + {0x5C49, 0x0D}, + {0x5D60, 0x08}, + {0x5D61, 0x08}, + {0x5D62, 0x08}, + {0x5D63, 0x08}, + {0x5D64, 0x08}, + {0x5D67, 0x08}, + {0x5D6C, 0x08}, + {0x5D6E, 0x08}, + {0x5D71, 0x08}, + {0x5D8E, 0x14}, + {0x5D90, 0x03}, + {0x5D91, 0x0A}, + {0x5D92, 0x1F}, + {0x5D93, 0x05}, + {0x5D97, 0x1F}, + {0x5D9A, 0x06}, + {0x5D9C, 0x1F}, + {0x5DA1, 0x1F}, + {0x5DA6, 0x1F}, + {0x5DA8, 0x1F}, + {0x5DAB, 0x1F}, + {0x5DC0, 0x06}, + {0x5DC1, 0x06}, + {0x5DC2, 0x07}, + {0x5DC3, 0x06}, + {0x5DC4, 0x07}, + {0x5DC7, 0x07}, + {0x5DCC, 0x07}, + {0x5DCE, 0x07}, + {0x5DD1, 0x07}, + {0x5E3E, 0x00}, + {0x5E3F, 0x00}, + {0x5E41, 0x00}, + {0x5E48, 0x00}, + {0x5E49, 0x00}, + {0x5E4A, 0x00}, + {0x5E4C, 0x00}, + {0x5E4D, 0x00}, + {0x5E4E, 0x00}, + {0x6026, 0x03}, + {0x6028, 0x03}, + {0x602A, 0x03}, + {0x602C, 0x03}, + {0x602F, 0x03}, + {0x6036, 0x03}, + {0x6038, 0x03}, + {0x603A, 0x03}, + {0x603C, 0x03}, + {0x603F, 0x03}, + {0x6074, 0x19}, + {0x6076, 0x19}, + {0x6078, 0x19}, + {0x607A, 0x19}, + {0x607D, 0x19}, + {0x6084, 0x32}, + {0x6086, 0x32}, + {0x6088, 0x32}, + {0x608A, 0x32}, + {0x608D, 0x32}, + {0x60C2, 0x4A}, + {0x60C4, 0x4A}, + {0x60CB, 0x4A}, + {0x60D2, 0x4A}, + {0x60D4, 0x4A}, + {0x60DB, 0x4A}, + {0x62F9, 0x14}, + {0x6305, 0x13}, + {0x6307, 0x13}, + {0x630A, 0x13}, + {0x630D, 0x0D}, + {0x6317, 0x0D}, + {0x632F, 0x2E}, + {0x6333, 0x2E}, + {0x6339, 0x2E}, + {0x6343, 0x2E}, + {0x6347, 0x2E}, + {0x634D, 0x2E}, + {0x6352, 0x00}, + {0x6353, 0x5F}, + {0x6366, 0x00}, + {0x6367, 0x5F}, + {0x638F, 0x95}, + {0x6393, 0x95}, + {0x6399, 0x95}, + {0x63A3, 0x95}, + {0x63A7, 0x95}, + {0x63AD, 0x95}, + {0x63B2, 0x00}, + {0x63B3, 0xC6}, + {0x63C6, 0x00}, + {0x63C7, 0xC6}, + {0x8BDB, 0x02}, + {0x8BDE, 0x02}, + {0x8BE1, 0x2D}, + {0x8BE4, 0x00}, + {0x8BE5, 0x00}, + {0x8BE6, 0x01}, + {0x9002, 0x14}, + {0x9200, 0xB5}, + {0x9201, 0x9E}, + {0x9202, 0xB5}, + {0x9203, 0x42}, + {0x9204, 0xB5}, + {0x9205, 0x43}, + {0x9206, 0xBD}, + {0x9207, 0x20}, + {0x9208, 0xBD}, + {0x9209, 0x22}, + {0x920A, 0xBD}, + {0x920B, 0x23}, + {0xB5D7, 0x10}, + {0xBD24, 0x00}, + {0xBD25, 0x00}, + {0xBD26, 0x00}, + {0xBD27, 0x00}, + {0xBD28, 0x00}, + {0xBD29, 0x00}, + {0xBD2A, 0x00}, + {0xBD2B, 0x00}, + {0xBD2C, 0x32}, + {0xBD2D, 0x70}, + {0xBD2E, 0x25}, + {0xBD2F, 0x30}, + {0xBD30, 0x3B}, + {0xBD31, 0xE0}, + {0xBD32, 0x69}, + {0xBD33, 0x40}, + {0xBD34, 0x25}, + {0xBD35, 0x90}, + {0xBD36, 0x58}, + {0xBD37, 0x00}, + {0xBD38, 0x00}, + {0xBD39, 0x00}, + {0xBD3A, 0x00}, + {0xBD3B, 0x00}, + {0xBD3C, 0x32}, + {0xBD3D, 0x70}, + {0xBD3E, 0x25}, + {0xBD3F, 0x90}, + {0xBD40, 0x58}, + {0xBD41, 0x00}, + {0x793B, 0x01}, + {0xACC6, 0x00}, + {0xACF5, 0x00}, + {0x793B, 0x00}, + {0x1F04, 0xB3}, + {0x1F05, 0x01}, + {0x1F06, 0x07}, + {0x1F07, 0x66}, + {0x1F08, 0x01}, + {0x4D18, 0x00}, + {0x4D19, 0x9D}, + {0x4D88, 0x00}, + {0x4D89, 0x97}, + {0x5C57, 0x0A}, + {0x5D94, 0x1F}, + {0x5D9E, 0x1F}, + {0x5E50, 0x23}, + {0x5E51, 0x20}, + {0x5E52, 0x07}, + {0x5E53, 0x20}, + {0x5E54, 0x07}, + {0x5E55, 0x27}, + {0x5E56, 0x0B}, + {0x5E57, 0x24}, + {0x5E58, 0x0B}, + {0x5E60, 0x24}, + {0x5E61, 0x24}, + {0x5E62, 0x1B}, + {0x5E63, 0x23}, + {0x5E64, 0x1B}, + {0x5E65, 0x28}, + {0x5E66, 0x22}, + {0x5E67, 0x28}, + {0x5E68, 0x23}, + {0x5E70, 0x25}, + {0x5E71, 0x24}, + {0x5E72, 0x20}, + {0x5E73, 0x24}, + {0x5E74, 0x20}, + {0x5E75, 0x28}, + {0x5E76, 0x27}, + {0x5E77, 0x29}, + {0x5E78, 0x24}, + {0x5E80, 0x25}, + {0x5E81, 0x25}, + {0x5E82, 0x24}, + {0x5E83, 0x25}, + {0x5E84, 0x23}, + {0x5E85, 0x2A}, + {0x5E86, 0x28}, + {0x5E87, 0x2A}, + {0x5E88, 0x28}, + {0x5E90, 0x24}, + {0x5E91, 0x24}, + {0x5E92, 0x28}, + {0x5E93, 0x29}, + {0x5E97, 0x25}, + {0x5E98, 0x25}, + {0x5E99, 0x2A}, + {0x5E9A, 0x2A}, + {0x5E9E, 0x3A}, + {0x5E9F, 0x3F}, + {0x5EA0, 0x17}, + {0x5EA1, 0x3F}, + {0x5EA2, 0x17}, + {0x5EA3, 0x32}, + {0x5EA4, 0x10}, + {0x5EA5, 0x33}, + {0x5EA6, 0x10}, + {0x5EAE, 0x3D}, + {0x5EAF, 0x48}, + {0x5EB0, 0x3B}, + {0x5EB1, 0x45}, + {0x5EB2, 0x37}, + {0x5EB3, 0x3A}, + {0x5EB4, 0x31}, + {0x5EB5, 0x3A}, + {0x5EB6, 0x31}, + {0x5EBE, 0x40}, + {0x5EBF, 0x48}, + {0x5EC0, 0x3F}, + {0x5EC1, 0x45}, + {0x5EC2, 0x3F}, + {0x5EC3, 0x3A}, + {0x5EC4, 0x32}, + {0x5EC5, 0x3A}, + {0x5EC6, 0x33}, + {0x5ECE, 0x4B}, + {0x5ECF, 0x4A}, + {0x5ED0, 0x48}, + {0x5ED1, 0x4C}, + {0x5ED2, 0x45}, + {0x5ED3, 0x3F}, + {0x5ED4, 0x3A}, + {0x5ED5, 0x3F}, + {0x5ED6, 0x3A}, + {0x5EDE, 0x48}, + {0x5EDF, 0x45}, + {0x5EE0, 0x3A}, + {0x5EE1, 0x3A}, + {0x5EE5, 0x4A}, + {0x5EE6, 0x4C}, + {0x5EE7, 0x3F}, + {0x5EE8, 0x3F}, + {0x5EEC, 0x06}, + {0x5EED, 0x06}, + {0x5EEE, 0x02}, + {0x5EEF, 0x06}, + {0x5EF0, 0x01}, + {0x5EF1, 0x09}, + {0x5EF2, 0x05}, + {0x5EF3, 0x06}, + {0x5EF4, 0x04}, + {0x5EFC, 0x07}, + {0x5EFD, 0x09}, + {0x5EFE, 0x05}, + {0x5EFF, 0x08}, + {0x5F00, 0x04}, + {0x5F01, 0x09}, + {0x5F02, 0x05}, + {0x5F03, 0x09}, + {0x5F04, 0x04}, + {0x5F0C, 0x08}, + {0x5F0D, 0x09}, + {0x5F0E, 0x06}, + {0x5F0F, 0x09}, + {0x5F10, 0x06}, + {0x5F11, 0x09}, + {0x5F12, 0x09}, + {0x5F13, 0x09}, + {0x5F14, 0x06}, + {0x5F1C, 0x09}, + {0x5F1D, 0x09}, + {0x5F1E, 0x09}, + {0x5F1F, 0x09}, + {0x5F20, 0x08}, + {0x5F21, 0x09}, + {0x5F22, 0x09}, + {0x5F23, 0x09}, + {0x5F24, 0x09}, + {0x5F2C, 0x09}, + {0x5F2D, 0x09}, + {0x5F2E, 0x09}, + {0x5F2F, 0x09}, + {0x5F33, 0x09}, + {0x5F34, 0x09}, + {0x5F35, 0x09}, + {0x5F36, 0x09}, + {0x5F3A, 0x01}, + {0x5F3D, 0x07}, + {0x5F3F, 0x01}, + {0x5F4B, 0x01}, + {0x5F4D, 0x04}, + {0x5F4F, 0x02}, + {0x5F51, 0x02}, + {0x5F5A, 0x02}, + {0x5F5B, 0x01}, + {0x5F5D, 0x03}, + {0x5F5E, 0x07}, + {0x5F5F, 0x01}, + {0x5F60, 0x01}, + {0x5F61, 0x01}, + {0x5F6A, 0x01}, + {0x5F6C, 0x01}, + {0x5F6D, 0x01}, + {0x5F6E, 0x04}, + {0x5F70, 0x02}, + {0x5F72, 0x02}, + {0x5F7A, 0x01}, + {0x5F7B, 0x03}, + {0x5F7C, 0x01}, + {0x5F7D, 0x01}, + {0x5F82, 0x01}, + {0x60C6, 0x4A}, + {0x60C8, 0x4A}, + {0x60D6, 0x4A}, + {0x60D8, 0x4A}, + {0x62E4, 0x33}, + {0x62E9, 0x33}, + {0x62EE, 0x1C}, + {0x62EF, 0x33}, + {0x62F3, 0x33}, + {0x62F6, 0x1C}, + {0x33F2, 0x01}, + {0x1F04, 0xA3}, + {0x1F05, 0x01}, + {0x406E, 0x00}, + {0x406F, 0x08}, + {0x4D08, 0x00}, + {0x4D09, 0x2C}, + {0x4D0E, 0x00}, + {0x4D0F, 0x64}, + {0x4D18, 0x00}, + {0x4D19, 0xB1}, + {0x4D1E, 0x00}, + {0x4D1F, 0xCB}, + {0x4D3A, 0x00}, + {0x4D3B, 0x91}, + {0x4D40, 0x00}, + {0x4D41, 0x64}, + {0x4D4C, 0x00}, + {0x4D4D, 0xE8}, + {0x4D52, 0x00}, + {0x4D53, 0xCB}, + {0x4D78, 0x00}, + {0x4D79, 0x2C}, + {0x4D7E, 0x00}, + {0x4D7F, 0x64}, + {0x4D88, 0x00}, + {0x4D89, 0xAB}, + {0x4D8E, 0x00}, + {0x4D8F, 0xCB}, + {0x4DA6, 0x00}, + {0x4DA7, 0xE7}, + {0x4DAC, 0x00}, + {0x4DAD, 0xCB}, + {0x5B98, 0x00}, + {0x5C52, 0x05}, + {0x5C57, 0x09}, + {0x5D94, 0x0A}, + {0x5D9E, 0x0A}, + {0x5E50, 0x22}, + {0x5E51, 0x22}, + {0x5E52, 0x07}, + {0x5E53, 0x20}, + {0x5E54, 0x06}, + {0x5E55, 0x23}, + {0x5E56, 0x0A}, + {0x5E57, 0x23}, + {0x5E58, 0x0A}, + {0x5E60, 0x25}, + {0x5E61, 0x29}, + {0x5E62, 0x1C}, + {0x5E63, 0x26}, + {0x5E64, 0x1C}, + {0x5E65, 0x2D}, + {0x5E66, 0x1E}, + {0x5E67, 0x2A}, + {0x5E68, 0x1E}, + {0x5E70, 0x26}, + {0x5E71, 0x26}, + {0x5E72, 0x22}, + {0x5E73, 0x23}, + {0x5E74, 0x20}, + {0x5E75, 0x28}, + {0x5E76, 0x23}, + {0x5E77, 0x28}, + {0x5E78, 0x23}, + {0x5E80, 0x28}, + {0x5E81, 0x28}, + {0x5E82, 0x29}, + {0x5E83, 0x27}, + {0x5E84, 0x26}, + {0x5E85, 0x2A}, + {0x5E86, 0x2D}, + {0x5E87, 0x2A}, + {0x5E88, 0x2A}, + {0x5E90, 0x26}, + {0x5E91, 0x23}, + {0x5E92, 0x28}, + {0x5E93, 0x28}, + {0x5E97, 0x2F}, + {0x5E98, 0x2E}, + {0x5E99, 0x32}, + {0x5E9A, 0x32}, + {0x5E9E, 0x50}, + {0x5E9F, 0x50}, + {0x5EA0, 0x1E}, + {0x5EA1, 0x50}, + {0x5EA2, 0x1D}, + {0x5EA3, 0x3E}, + {0x5EA4, 0x14}, + {0x5EA5, 0x3E}, + {0x5EA6, 0x14}, + {0x5EAE, 0x58}, + {0x5EAF, 0x5E}, + {0x5EB0, 0x4B}, + {0x5EB1, 0x5A}, + {0x5EB2, 0x4B}, + {0x5EB3, 0x4C}, + {0x5EB4, 0x3A}, + {0x5EB5, 0x4C}, + {0x5EB6, 0x38}, + {0x5EBE, 0x56}, + {0x5EBF, 0x57}, + {0x5EC0, 0x50}, + {0x5EC1, 0x55}, + {0x5EC2, 0x50}, + {0x5EC3, 0x46}, + {0x5EC4, 0x3E}, + {0x5EC5, 0x46}, + {0x5EC6, 0x3E}, + {0x5ECE, 0x5A}, + {0x5ECF, 0x5F}, + {0x5ED0, 0x5E}, + {0x5ED1, 0x5A}, + {0x5ED2, 0x5A}, + {0x5ED3, 0x50}, + {0x5ED4, 0x4C}, + {0x5ED5, 0x50}, + {0x5ED6, 0x4C}, + {0x5EDE, 0x57}, + {0x5EDF, 0x55}, + {0x5EE0, 0x46}, + {0x5EE1, 0x46}, + {0x5EE5, 0x73}, + {0x5EE6, 0x6E}, + {0x5EE7, 0x5F}, + {0x5EE8, 0x5A}, + {0x5EEC, 0x0A}, + {0x5EED, 0x0A}, + {0x5EEE, 0x0F}, + {0x5EEF, 0x0A}, + {0x5EF0, 0x0E}, + {0x5EF1, 0x08}, + {0x5EF2, 0x0C}, + {0x5EF3, 0x0C}, + {0x5EF4, 0x0F}, + {0x5EFC, 0x0A}, + {0x5EFD, 0x0A}, + {0x5EFE, 0x14}, + {0x5EFF, 0x0A}, + {0x5F00, 0x14}, + {0x5F01, 0x0A}, + {0x5F02, 0x14}, + {0x5F03, 0x0A}, + {0x5F04, 0x19}, + {0x5F0C, 0x0A}, + {0x5F0D, 0x0A}, + {0x5F0E, 0x0A}, + {0x5F0F, 0x05}, + {0x5F10, 0x0A}, + {0x5F11, 0x06}, + {0x5F12, 0x08}, + {0x5F13, 0x0A}, + {0x5F14, 0x0C}, + {0x5F1C, 0x0A}, + {0x5F1D, 0x0A}, + {0x5F1E, 0x0A}, + {0x5F1F, 0x0A}, + {0x5F20, 0x0A}, + {0x5F21, 0x0A}, + {0x5F22, 0x0A}, + {0x5F23, 0x0A}, + {0x5F24, 0x0A}, + {0x5F2C, 0x0A}, + {0x5F2D, 0x05}, + {0x5F2E, 0x06}, + {0x5F2F, 0x0A}, + {0x5F33, 0x0A}, + {0x5F34, 0x0A}, + {0x5F35, 0x0A}, + {0x5F36, 0x0A}, + {0x5F3A, 0x00}, + {0x5F3D, 0x02}, + {0x5F3F, 0x0A}, + {0x5F4A, 0x0A}, + {0x5F4B, 0x0A}, + {0x5F4D, 0x0F}, + {0x5F4F, 0x00}, + {0x5F51, 0x00}, + {0x5F5A, 0x00}, + {0x5F5B, 0x00}, + {0x5F5D, 0x0A}, + {0x5F5E, 0x02}, + {0x5F5F, 0x0A}, + {0x5F60, 0x0A}, + {0x5F61, 0x00}, + {0x5F6A, 0x00}, + {0x5F6C, 0x0A}, + {0x5F6D, 0x06}, + {0x5F6E, 0x0F}, + {0x5F70, 0x00}, + {0x5F72, 0x00}, + {0x5F7A, 0x00}, + {0x5F7B, 0x0A}, + {0x5F7C, 0x0A}, + {0x5F7D, 0x00}, + {0x5F82, 0x06}, + {0x60C6, 0x36}, + {0x60C8, 0x36}, + {0x60D6, 0x36}, + {0x60D8, 0x36}, + {0x62DF, 0x56}, + {0x62E0, 0x52}, + {0x62E4, 0x38}, + {0x62E5, 0x51}, + {0x62E9, 0x35}, + {0x62EA, 0x54}, + {0x62EE, 0x1D}, + {0x62EF, 0x38}, + {0x62F3, 0x33}, + {0x62F6, 0x26}, + {0x6412, 0x1E}, + {0x6413, 0x1E}, + {0x6414, 0x1E}, + {0x6415, 0x1E}, + {0x6416, 0x1E}, + {0x6417, 0x1E}, + {0x6418, 0x1E}, + {0x641A, 0x1E}, + {0x641B, 0x1E}, + {0x641C, 0x1E}, + {0x641D, 0x1E}, + {0x641E, 0x1E}, + {0x641F, 0x1E}, + {0x6420, 0x1E}, + {0x6421, 0x1E}, + {0x6422, 0x1E}, + {0x6424, 0x1E}, + {0x6425, 0x1E}, + {0x6426, 0x1E}, + {0x6427, 0x1E}, + {0x6428, 0x1E}, + {0x6429, 0x1E}, + {0x642A, 0x1E}, + {0x642B, 0x1E}, + {0x642C, 0x1E}, + {0x642E, 0x1E}, + {0x642F, 0x1E}, + {0x6430, 0x1E}, + {0x6431, 0x1E}, + {0x6432, 0x1E}, + {0x6433, 0x1E}, + {0x6434, 0x1E}, + {0x6435, 0x1E}, + {0x6436, 0x1E}, + {0x6438, 0x1E}, + {0x6439, 0x1E}, + {0x643A, 0x1E}, + {0x643B, 0x1E}, + {0x643D, 0x1E}, + {0x643E, 0x1E}, + {0x643F, 0x1E}, + {0x6441, 0x1E}, + {0x33F2, 0x02}, + {0x1F08, 0x00}, + {0xA307, 0x30}, + {0xA309, 0x30}, + {0xA30B, 0x30}, + {0xA406, 0x03}, + {0xA407, 0x48}, + {0xA408, 0x03}, + {0xA409, 0x48}, + {0xA40A, 0x03}, + {0xA40B, 0x48}, + {REG_NULL, 0x00}, +}; + +/* + * Xclk 24Mhz + * max_framerate 7fps + * mipi_datarate per lane 600Mbps + */ +static const struct regval imx766_4096x3072_regs[] = { + {0x0112, 0x0A}, + {0x0113, 0x0A}, + {0x0114, 0x03}, + {0x0342, 0xB7}, + {0x0343, 0x00}, + {0x0340, 0x0C}, + {0x0341, 0x5C}, + {0x0344, 0x00}, + {0x0345, 0x00}, + {0x0346, 0x00}, + {0x0347, 0x00}, + {0x0348, 0x1F}, + {0x0349, 0xFF}, + {0x034A, 0x17}, + {0x034B, 0xFF}, + {0x0900, 0x01}, + {0x0901, 0x22}, + {0x0902, 0x08}, + {0x3005, 0x02}, + {0x3120, 0x04}, + {0x3121, 0x01}, + {0x3200, 0x41}, + {0x3201, 0x41}, + {0x32D6, 0x00}, + {0x0408, 0x00}, + {0x0409, 0x00}, + {0x040A, 0x00}, + {0x040B, 0x00}, + {0x040C, 0x10}, + {0x040D, 0x00}, + {0x040E, 0x0C}, + {0x040F, 0x00}, + {0x034C, 0x10}, + {0x034D, 0x00}, + {0x034E, 0x0C}, + {0x034F, 0x00}, + {0x0301, 0x05}, + {0x0303, 0x02}, + {0x0305, 0x04}, + {0x0306, 0x01}, + {0x0307, 0x35}, + {0x030B, 0x04}, + {0x030D, 0x03}, + {0x030E, 0x01}, + {0x030F, 0xB4}, + {0x30CB, 0x00}, + {0x30CC, 0x10}, + {0x30CD, 0x00}, + {0x30CE, 0x03}, + {0x30CF, 0x00}, + {0x319C, 0x01}, + {0x3800, 0x01}, + {0x3801, 0x01}, + {0x3802, 0x02}, + {0x3847, 0x03}, + {0x38B0, 0x00}, + {0x38B1, 0x64}, + {0x38B2, 0x00}, + {0x38B3, 0x64}, + {0x38C4, 0x00}, + {0x38C5, 0x64}, + {0x4C3A, 0x02}, + {0x4C3B, 0xD2}, + {0x4C68, 0x04}, + {0x4C69, 0x7E}, + {0x4CF8, 0x16}, + {0x4CF9, 0xE0}, + {0x4DB8, 0x08}, + {0x4DB9, 0x98}, + {0x0202, 0x0C}, + {0x0203, 0x2C}, + {0x0224, 0x01}, + {0x0225, 0xF4}, + {0x313A, 0x01}, + {0x313B, 0xF4}, + {0x3803, 0x00}, + {0x3804, 0x17}, + {0x3805, 0xC0}, + {0x0204, 0x00}, + {0x0205, 0x00}, + {0x020E, 0x01}, + {0x020F, 0x00}, + {0x0216, 0x00}, + {0x0217, 0x00}, + {0x0218, 0x01}, + {0x0219, 0x00}, + {0x313C, 0x00}, + {0x313D, 0x00}, + {0x313E, 0x01}, + {0x313F, 0x00}, + {0x30B4, 0x01}, + {0x3066, 0x01}, + {0x3067, 0x30}, + {0x3068, 0x01}, + {0x3069, 0x30}, + {0x33D0, 0x00}, + {0x33D1, 0x00}, + {0x33D4, 0x01}, + {0x33DC, 0x0A}, + {0x33DD, 0x0A}, + {0x33DE, 0x0A}, + {0x33DF, 0x0A}, + {0x3070, 0x01}, + {0x3077, 0x01}, + {0x3078, 0x30}, + {0x3079, 0x01}, + {0x307A, 0x30}, + {0x307B, 0x01}, + {0x3080, 0x02}, + {0x3087, 0x02}, + {0x3088, 0x30}, + {0x3089, 0x02}, + {0x308A, 0x30}, + {0x308B, 0x02}, + {0x3901, 0x2B}, + {0x3902, 0x00}, + {0x3903, 0x12}, + {0x3905, 0x2B}, + {0x3906, 0x01}, + {0x3907, 0x12}, + {0x3909, 0x2B}, + {0x390A, 0x02}, + {0x390B, 0x12}, + {0x3911, 0x00}, + {REG_NULL, 0x00}, +}; + +static const struct other_data imx766_full_spd = { + .width = 4096, + .height = 768, + .bus_fmt = MEDIA_BUS_FMT_SPD_2X8, + .data_type = 0x30, + .data_bit = 10, +}; + +static const struct other_data imx766_full_ebd = { + .width = 320, + .height = 2, + .bus_fmt = MEDIA_BUS_FMT_EBD_1X8, +}; + +static const struct imx766_mode supported_modes[] = { + { + .bus_fmt = MEDIA_BUS_FMT_SBGGR10_1X10, + .width = 4096, + .height = 3072, + .max_fps = { + .numerator = 10000, + .denominator = 200000, + }, + .exp_def = 0x0C2C, + .hts_def = 0xB700, + .vts_def = 0x0C5C, + .reg_list = imx766_4096x3072_regs, + .spd = &imx766_full_spd, + .ebd = &imx766_full_ebd, + .hdr_mode = NO_HDR, + .vc[PAD0] = 0, + }, +}; + +static const s64 link_freq_menu_items[] = { + IMX766_LINK_FREQ_436MHZ +}; + +static const char * const imx766_test_pattern_menu[] = { + "Disabled", + "Vertical Color Bar Type 1", + "Vertical Color Bar Type 2", + "Vertical Color Bar Type 3", + "Vertical Color Bar Type 4" +}; + +#define WRITE_COUNT 5 +/* Write registers up to 4 at a time */ +static int imx766_write_reg(struct i2c_client *client, u16 reg, + int len, u32 val) +{ + u32 buf_i, val_i, i; + u8 buf[6]; + u8 *val_p; + __be32 val_be; + + if (len > 4) + return -EINVAL; + + buf[0] = reg >> 8; + buf[1] = reg & 0xff; + + val_be = cpu_to_be32(val); + val_p = (u8 *)&val_be; + buf_i = 2; + val_i = 4 - len; + + while (val_i < 4) + buf[buf_i++] = val_p[val_i++]; + i = 0; + while (i < WRITE_COUNT) { + if (i2c_master_send(client, buf, len + 2) == len + 2) + break; + i++; + } + if (i >= WRITE_COUNT) + return -EIO; + + return 0; +} + +static int imx766_write_array(struct i2c_client *client, + const struct regval *regs) +{ + u32 i; + int ret = 0; + + for (i = 0; ret == 0 && regs[i].addr != REG_NULL; i++) + ret = imx766_write_reg(client, regs[i].addr, + IMX766_REG_VALUE_08BIT, + regs[i].val); + return ret; +} + +/* Read registers up to 4 at a time */ +static int imx766_read_reg(struct i2c_client *client, u16 reg, + unsigned int len, u32 *val) +{ + struct i2c_msg msgs[2]; + u8 *data_be_p; + __be32 data_be = 0; + __be16 reg_addr_be = cpu_to_be16(reg); + int ret; + + if (len > 4 || !len) + return -EINVAL; + + data_be_p = (u8 *)&data_be; + /* Write register address */ + msgs[0].addr = client->addr; + msgs[0].flags = 0; + msgs[0].len = 2; + msgs[0].buf = (u8 *)®_addr_be; + + /* Read data from register */ + msgs[1].addr = client->addr; + msgs[1].flags = I2C_M_RD; + msgs[1].len = len; + msgs[1].buf = &data_be_p[4 - len]; + + ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs)); + if (ret != ARRAY_SIZE(msgs)) + return -EIO; + + *val = be32_to_cpu(data_be); + + return 0; +} + +static int imx766_get_reso_dist(const struct imx766_mode *mode, + struct v4l2_mbus_framefmt *framefmt) +{ + return abs(mode->width - framefmt->width) + + abs(mode->height - framefmt->height); +} + +static const struct imx766_mode * + imx766_find_best_fit(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 < ARRAY_SIZE(supported_modes); i++) { + dist = imx766_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 imx766_set_fmt(struct v4l2_subdev *sd, + struct v4l2_subdev_state *sd_state, + struct v4l2_subdev_format *fmt) +{ + struct imx766 *imx766 = to_imx766(sd); + const struct imx766_mode *mode; + s64 h_blank, vblank_def; + + mutex_lock(&imx766->mutex); + + mode = imx766_find_best_fit(fmt); + fmt->format.code = MEDIA_BUS_FMT_SRGGB10_1X10; + 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(&imx766->mutex); + return -ENOTTY; +#endif + } else { + imx766->cur_mode = mode; + h_blank = mode->hts_def - mode->width; + __v4l2_ctrl_modify_range(imx766->hblank, h_blank, + h_blank, 1, h_blank); + vblank_def = mode->vts_def - mode->height; + __v4l2_ctrl_modify_range(imx766->vblank, vblank_def, + IMX766_VTS_MAX - mode->height, + 1, vblank_def); + if (mode->width == 4096 && mode->height == 3072) { + __v4l2_ctrl_s_ctrl(imx766->link_freq, + link_freq_menu_items[0]); + __v4l2_ctrl_s_ctrl_int64(imx766->pixel_rate, + IMX766_PIXEL_RATE_BINNING); + } else { + __v4l2_ctrl_s_ctrl(imx766->link_freq, + link_freq_menu_items[0]); + __v4l2_ctrl_s_ctrl_int64(imx766->pixel_rate, + IMX766_PIXEL_RATE_FULL_SIZE); + } + } + mutex_unlock(&imx766->mutex); + + return 0; +} + +static int imx766_get_fmt(struct v4l2_subdev *sd, + struct v4l2_subdev_state *sd_state, + struct v4l2_subdev_format *fmt) +{ + struct imx766 *imx766 = to_imx766(sd); + const struct imx766_mode *mode = imx766->cur_mode; + + mutex_lock(&imx766->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(&imx766->mutex); + return -ENOTTY; +#endif + } else { + fmt->format.width = mode->width; + fmt->format.height = mode->height; + fmt->format.code = MEDIA_BUS_FMT_SRGGB10_1X10; + fmt->format.field = V4L2_FIELD_NONE; + /* to csi rawwr3, other rawwr also can use */ + if (fmt->pad == imx766->spd_id && mode->spd) { + fmt->format.width = mode->spd->width; + fmt->format.height = mode->spd->height; + fmt->format.code = mode->spd->bus_fmt; + //Set the vc channel to be consistent with the valid data + fmt->reserved[0] = 0; + } else if (fmt->pad == imx766->ebd_id && mode->ebd) { + fmt->format.width = mode->ebd->width; + fmt->format.height = mode->ebd->height; + fmt->format.code = mode->ebd->bus_fmt; + //Set the vc channel to be consistent with the valid data + fmt->reserved[0] = 0; + } + } + mutex_unlock(&imx766->mutex); + + return 0; +} + +static int imx766_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 = MEDIA_BUS_FMT_SRGGB10_1X10; + + return 0; +} + +static int imx766_enum_frame_sizes(struct v4l2_subdev *sd, + struct v4l2_subdev_state *sd_state, + struct v4l2_subdev_frame_size_enum *fse) +{ + if (fse->index >= ARRAY_SIZE(supported_modes)) + return -EINVAL; + + if (fse->code != MEDIA_BUS_FMT_SRGGB10_1X10) + 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 imx766_enable_test_pattern(struct imx766 *imx766, u32 pattern) +{ + u32 val; + + if (pattern) + val = (pattern - 1) | IMX766_TEST_PATTERN_ENABLE; + else + val = IMX766_TEST_PATTERN_DISABLE; + + return imx766_write_reg(imx766->client, + IMX766_REG_TEST_PATTERN, + IMX766_REG_VALUE_08BIT, + val); +} + +static int imx766_g_frame_interval(struct v4l2_subdev *sd, + struct v4l2_subdev_frame_interval *fi) +{ + struct imx766 *imx766 = to_imx766(sd); + const struct imx766_mode *mode = imx766->cur_mode; + + mutex_lock(&imx766->mutex); + fi->interval = mode->max_fps; + mutex_unlock(&imx766->mutex); + + return 0; +} + +static void imx766_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.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 imx766_get_module_inf(struct imx766 *imx766, + struct rkmodule_inf *inf) +{ + struct otp_info *otp = imx766->otp; + + memset(inf, 0, sizeof(*inf)); + strscpy(inf->base.sensor, IMX766_NAME, sizeof(inf->base.sensor)); + strscpy(inf->base.module, imx766->module_name, + sizeof(inf->base.module)); + strscpy(inf->base.lens, imx766->len_name, sizeof(inf->base.lens)); + if (otp) + imx766_get_otp(otp, inf); +} + +static int imx766_get_channel_info(struct imx766 *imx766, struct rkmodule_channel_info *ch_info) +{ + const struct imx766_mode *mode = imx766->cur_mode; + + if (ch_info->index < PAD0 || ch_info->index >= PAD_MAX) + return -EINVAL; + + if (ch_info->index == imx766->spd_id && mode->spd) { + ch_info->vc = 1; + ch_info->width = mode->spd->width; + ch_info->height = mode->spd->height; + ch_info->bus_fmt = mode->spd->bus_fmt; + ch_info->data_type = mode->spd->data_type; + ch_info->data_bit = mode->spd->data_bit; + } else { + ch_info->vc = imx766->cur_mode->vc[ch_info->index]; + ch_info->width = imx766->cur_mode->width; + ch_info->height = imx766->cur_mode->height; + ch_info->bus_fmt = imx766->cur_mode->bus_fmt; + } + return 0; +} + +static long imx766_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg) +{ + struct imx766 *imx766 = to_imx766(sd); + struct rkmodule_hdr_cfg *hdr_cfg; + struct rkmodule_channel_info *ch_info; + long ret = 0; + u32 stream = 0; + u32 i, h, w; + + switch (cmd) { + case RKMODULE_SET_QUICK_STREAM: + + stream = *((u32 *)arg); + + if (stream) + ret = imx766_write_reg(imx766->client, + IMX766_REG_CTRL_MODE, + IMX766_REG_VALUE_08BIT, + IMX766_MODE_STREAMING); + else + ret = imx766_write_reg(imx766->client, + IMX766_REG_CTRL_MODE, + IMX766_REG_VALUE_08BIT, + IMX766_MODE_SW_STANDBY); + break; + case RKMODULE_SET_HDR_CFG: + hdr_cfg = (struct rkmodule_hdr_cfg *)arg; + w = imx766->cur_mode->width; + h = imx766->cur_mode->height; + for (i = 0; i < imx766->cfg_num; i++) { + if (w == supported_modes[i].width && + h == supported_modes[i].height && + supported_modes[i].hdr_mode == hdr_cfg->hdr_mode) { + imx766->cur_mode = &supported_modes[i]; + break; + } + } + if (i == imx766->cfg_num) { + dev_err(&imx766->client->dev, + "not find hdr mode:%d %dx%d config\n", + hdr_cfg->hdr_mode, w, h); + ret = -EINVAL; + } else { + w = imx766->cur_mode->hts_def - imx766->cur_mode->width; + h = imx766->cur_mode->vts_def - imx766->cur_mode->height; + __v4l2_ctrl_modify_range(imx766->hblank, w, w, 1, w); + __v4l2_ctrl_modify_range(imx766->vblank, h, + IMX766_VTS_MAX - imx766->cur_mode->height, + 1, h); + dev_info(&imx766->client->dev, + "sensor mode: %d\n", + imx766->cur_mode->hdr_mode); + } + break; + case RKMODULE_GET_HDR_CFG: + hdr_cfg = (struct rkmodule_hdr_cfg *)arg; + hdr_cfg->esp.mode = HDR_NORMAL_VC; + hdr_cfg->hdr_mode = imx766->cur_mode->hdr_mode; + break; + case RKMODULE_GET_MODULE_INFO: + imx766_get_module_inf(imx766, (struct rkmodule_inf *)arg); + break; + case RKMODULE_GET_CHANNEL_INFO: + ch_info = (struct rkmodule_channel_info *)arg; + ret = imx766_get_channel_info(imx766, ch_info); + break; + default: + ret = -ENOTTY; + break; + } + + return ret; +} + +#ifdef CONFIG_COMPAT +static long imx766_compat_ioctl32(struct v4l2_subdev *sd, + unsigned int cmd, unsigned long arg) +{ + void __user *up = compat_ptr(arg); + struct rkmodule_hdr_cfg *hdr; + struct rkmodule_inf *inf; + struct rkmodule_channel_info *ch_info; + long ret = 0; + u32 stream = 0; + + switch (cmd) { + case RKMODULE_GET_HDR_CFG: + hdr = kzalloc(sizeof(*hdr), GFP_KERNEL); + if (!hdr) { + ret = -ENOMEM; + return ret; + } + + ret = imx766_ioctl(sd, cmd, hdr); + if (!ret) { + ret = copy_to_user(up, hdr, sizeof(*hdr)); + if (ret) { + kfree(hdr); + return -EFAULT; + } + } + kfree(hdr); + break; + case RKMODULE_SET_HDR_CFG: + hdr = kzalloc(sizeof(*hdr), GFP_KERNEL); + if (!hdr) { + ret = -ENOMEM; + return ret; + } + + ret = copy_from_user(hdr, up, sizeof(*hdr)); + if (ret) { + kfree(hdr); + return -EFAULT; + } + ret = imx766_ioctl(sd, cmd, hdr); + kfree(hdr); + break; + case RKMODULE_SET_QUICK_STREAM: + ret = copy_from_user(&stream, up, sizeof(u32)); + if (ret) + return -EFAULT; + ret = imx766_ioctl(sd, cmd, &stream); + break; + case RKMODULE_GET_MODULE_INFO: + inf = kzalloc(sizeof(*inf), GFP_KERNEL); + if (!inf) { + ret = -ENOMEM; + return ret; + } + + ret = imx766_ioctl(sd, cmd, inf); + if (!ret) { + ret = copy_to_user(up, inf, sizeof(*inf)); + if (ret) + ret = -EFAULT; + } + kfree(inf); + break; + case RKMODULE_GET_CHANNEL_INFO: + ch_info = kzalloc(sizeof(*ch_info), GFP_KERNEL); + if (!ch_info) { + ret = -ENOMEM; + return ret; + } + ret = copy_from_user(ch_info, up, sizeof(*ch_info)); + if (!ret) { + ret = imx766_ioctl(sd, cmd, ch_info); + if (!ret) { + ret = copy_to_user(up, ch_info, sizeof(*ch_info)); + if (ret) + ret = -EFAULT; + } + } else { + ret = -EFAULT; + } + kfree(ch_info); + break; + default: + ret = -ENOTTY; + break; + } + return ret; +} +#endif + +/*--------------------------------------------------------------------------*/ + +#define IMX766_QSC_CONFIG_ADDR 0xC800 +#define IMX766_RD_QSC_KNOT_VALUE_OFFSET 0x86A9 +#define IMX766_QSC_EN 0x32D2 +static void imx766_config_qsc(struct imx766 *imx766) +{ + struct otp_info *otp = imx766->otp; + u8 *qsc_calib; + u32 i; + + if (otp && otp->qsc_data.flag) { + qsc_calib = &otp->qsc_data.qsc_calib[0]; + for (i = 0; i < 3072; i++) { + imx766_write_reg(imx766->client, IMX766_QSC_CONFIG_ADDR + i, + IMX766_REG_VALUE_08BIT, + qsc_calib[i]); + dev_dbg(&imx766->client->dev, + "set qscdata: qsc_calib[%d]: 0x%x\n", + i, qsc_calib[i]); + } + imx766_write_reg(imx766->client, IMX766_RD_QSC_KNOT_VALUE_OFFSET, + IMX766_REG_VALUE_08BIT, + 0x4E); + imx766_write_reg(imx766->client, IMX766_QSC_EN, + IMX766_REG_VALUE_08BIT, + 0x01); + } +} + +static int __imx766_start_stream(struct imx766 *imx766) +{ + int ret; + + ret = imx766_write_array(imx766->client, imx766->cur_mode->reg_list); + if (ret) + return ret; + + imx766_config_qsc(imx766); + + /* In case these controls are set before streaming */ + mutex_unlock(&imx766->mutex); + ret = v4l2_ctrl_handler_setup(&imx766->ctrl_handler); + mutex_lock(&imx766->mutex); + if (ret) + return ret; + + return imx766_write_reg(imx766->client, + IMX766_REG_CTRL_MODE, + IMX766_REG_VALUE_08BIT, + IMX766_MODE_STREAMING); +} + +static int __imx766_stop_stream(struct imx766 *imx766) +{ + return imx766_write_reg(imx766->client, + IMX766_REG_CTRL_MODE, + IMX766_REG_VALUE_08BIT, + IMX766_MODE_SW_STANDBY); +} + +static int imx766_s_stream(struct v4l2_subdev *sd, int on) +{ + struct imx766 *imx766 = to_imx766(sd); + struct i2c_client *client = imx766->client; + int ret = 0; + + mutex_lock(&imx766->mutex); + on = !!on; + if (on == imx766->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 = __imx766_start_stream(imx766); + if (ret) { + v4l2_err(sd, "start stream failed while write regs\n"); + pm_runtime_put(&client->dev); + goto unlock_and_return; + } + } else { + __imx766_stop_stream(imx766); + pm_runtime_put(&client->dev); + } + + imx766->streaming = on; + +unlock_and_return: + mutex_unlock(&imx766->mutex); + + return ret; +} + +static int imx766_s_power(struct v4l2_subdev *sd, int on) +{ + struct imx766 *imx766 = to_imx766(sd); + struct i2c_client *client = imx766->client; + int ret = 0; + + mutex_lock(&imx766->mutex); + + /* If the power state is not modified - no work to do. */ + if (imx766->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 = imx766_write_array(imx766->client, imx766_global_regs); + if (ret) { + v4l2_err(sd, "could not set init registers\n"); + pm_runtime_put_noidle(&client->dev); + goto unlock_and_return; + } + + imx766->power_on = true; + } else { + pm_runtime_put(&client->dev); + imx766->power_on = false; + } + +unlock_and_return: + mutex_unlock(&imx766->mutex); + + return ret; +} + +/* Calculate the delay in us by clock rate and clock cycles */ +static inline u32 imx766_cal_delay(u32 cycles) +{ + return DIV_ROUND_UP(cycles, IMX766_XVCLK_FREQ / 1000 / 1000); +} + +static int __imx766_power_on(struct imx766 *imx766) +{ + int ret; + u32 delay_us; + struct device *dev = &imx766->client->dev; + + if (!IS_ERR(imx766->power_gpio)) + gpiod_set_value_cansleep(imx766->power_gpio, 1); + usleep_range(10000, 12000); + + if (!IS_ERR_OR_NULL(imx766->pins_default)) { + ret = pinctrl_select_state(imx766->pinctrl, + imx766->pins_default); + if (ret < 0) + dev_err(dev, "could not set pins\n"); + } + ret = clk_set_rate(imx766->xvclk, IMX766_XVCLK_FREQ); + if (ret < 0) + dev_warn(dev, "Failed to set xvclk rate (24MHz)\n"); + if (clk_get_rate(imx766->xvclk) != IMX766_XVCLK_FREQ) + dev_warn(dev, "xvclk mismatched, modes are based on 24MHz\n"); + ret = clk_prepare_enable(imx766->xvclk); + if (ret < 0) { + dev_err(dev, "Failed to enable xvclk\n"); + return ret; + } + + if (!IS_ERR(imx766->reset_gpio)) + gpiod_set_value_cansleep(imx766->reset_gpio, 0); + usleep_range(10000, 12000); + + ret = regulator_bulk_enable(IMX766_NUM_SUPPLIES, imx766->supplies); + if (ret < 0) { + dev_err(dev, "Failed to enable regulators\n"); + goto disable_clk; + } + + if (!IS_ERR(imx766->reset_gpio)) + gpiod_set_value_cansleep(imx766->reset_gpio, 1); + + usleep_range(10000, 12000); + if (!IS_ERR(imx766->pwdn_gpio)) + gpiod_set_value_cansleep(imx766->pwdn_gpio, 1); + + /* 8192 cycles prior to first SCCB transaction */ + delay_us = imx766_cal_delay(8192); + usleep_range(delay_us, delay_us * 2); + + return 0; + +disable_clk: + clk_disable_unprepare(imx766->xvclk); + + return ret; +} + +static void __imx766_power_off(struct imx766 *imx766) +{ + int ret; + + if (!IS_ERR(imx766->power_gpio)) + gpiod_set_value_cansleep(imx766->power_gpio, 0); + + + if (!IS_ERR(imx766->pwdn_gpio)) + gpiod_set_value_cansleep(imx766->pwdn_gpio, 0); + clk_disable_unprepare(imx766->xvclk); + if (!IS_ERR(imx766->reset_gpio)) + gpiod_set_value_cansleep(imx766->reset_gpio, 0); + if (!IS_ERR_OR_NULL(imx766->pins_sleep)) { + ret = pinctrl_select_state(imx766->pinctrl, + imx766->pins_sleep); + if (ret < 0) + dev_dbg(&imx766->client->dev, "could not set pins\n"); + } + regulator_bulk_disable(IMX766_NUM_SUPPLIES, imx766->supplies); +} + +static int imx766_runtime_resume(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct v4l2_subdev *sd = i2c_get_clientdata(client); + struct imx766 *imx766 = to_imx766(sd); + + return __imx766_power_on(imx766); +} + +static int imx766_runtime_suspend(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct v4l2_subdev *sd = i2c_get_clientdata(client); + struct imx766 *imx766 = to_imx766(sd); + + __imx766_power_off(imx766); + + return 0; +} + +#ifdef CONFIG_VIDEO_V4L2_SUBDEV_API +static int imx766_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) +{ + struct imx766 *imx766 = to_imx766(sd); + struct v4l2_mbus_framefmt *try_fmt = + v4l2_subdev_get_try_format(sd, fh->state, 0); + const struct imx766_mode *def_mode = &supported_modes[0]; + + mutex_lock(&imx766->mutex); + /* Initialize try_fmt */ + try_fmt->width = def_mode->width; + try_fmt->height = def_mode->height; + try_fmt->code = MEDIA_BUS_FMT_SRGGB10_1X10; + try_fmt->field = V4L2_FIELD_NONE; + + mutex_unlock(&imx766->mutex); + /* No crop or compose */ + + return 0; +} +#endif + +static int imx766_enum_frame_interval(struct v4l2_subdev *sd, + struct v4l2_subdev_state *sd_state, + struct v4l2_subdev_frame_interval_enum *fie) +{ + if (fie->index >= ARRAY_SIZE(supported_modes)) + return -EINVAL; + + fie->code = supported_modes[fie->index].bus_fmt; + fie->width = supported_modes[fie->index].width; + fie->height = supported_modes[fie->index].height; + fie->interval = supported_modes[fie->index].max_fps; + fie->reserved[0] = supported_modes[fie->index].hdr_mode; + return 0; +} + +static int imx766_g_mbus_config(struct v4l2_subdev *sd, unsigned int pad_id, + struct v4l2_mbus_config *config) +{ + config->type = V4L2_MBUS_CSI2_DPHY; + config->bus.mipi_csi2.num_data_lanes = IMX766_LANES; + + return 0; +} + +static const struct dev_pm_ops imx766_pm_ops = { + SET_RUNTIME_PM_OPS(imx766_runtime_suspend, + imx766_runtime_resume, NULL) +}; + +#ifdef CONFIG_VIDEO_V4L2_SUBDEV_API +static const struct v4l2_subdev_internal_ops imx766_internal_ops = { + .open = imx766_open, +}; +#endif + +static const struct v4l2_subdev_core_ops imx766_core_ops = { + .s_power = imx766_s_power, + .ioctl = imx766_ioctl, +#ifdef CONFIG_COMPAT + .compat_ioctl32 = imx766_compat_ioctl32, +#endif +}; + +static const struct v4l2_subdev_video_ops imx766_video_ops = { + .s_stream = imx766_s_stream, + .g_frame_interval = imx766_g_frame_interval, +}; + +static const struct v4l2_subdev_pad_ops imx766_pad_ops = { + .enum_mbus_code = imx766_enum_mbus_code, + .enum_frame_size = imx766_enum_frame_sizes, + .enum_frame_interval = imx766_enum_frame_interval, + .get_fmt = imx766_get_fmt, + .set_fmt = imx766_set_fmt, + .get_mbus_config = imx766_g_mbus_config, +}; + +static const struct v4l2_subdev_ops imx766_subdev_ops = { + .core = &imx766_core_ops, + .video = &imx766_video_ops, + .pad = &imx766_pad_ops, +}; + +static int imx766_set_gain_reg(struct imx766 *imx766, u32 a_gain) +{ + int ret = 0; + u32 gain_reg = 0; + + gain_reg = (16384 - (16384*1024 / a_gain)); + + if (gain_reg > 16128) //960 + gain_reg = 16128; + + ret = imx766_write_reg(imx766->client, + IMX766_REG_GAIN_H, + IMX766_REG_VALUE_08BIT, + ((gain_reg & 0x3f00) >> 8)); + ret |= imx766_write_reg(imx766->client, + IMX766_REG_GAIN_L, + IMX766_REG_VALUE_08BIT, + (gain_reg & 0xff)); + return ret; +} + +static int imx766_set_ctrl(struct v4l2_ctrl *ctrl) +{ + struct imx766 *imx766 = container_of(ctrl->handler, + struct imx766, ctrl_handler); + struct i2c_client *client = imx766->client; + s64 max; + int ret = 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 = imx766->cur_mode->height + ctrl->val - 4; + __v4l2_ctrl_modify_range(imx766->exposure, + imx766->exposure->minimum, max, + imx766->exposure->step, + imx766->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 */ + ret = imx766_write_reg(imx766->client, + IMX766_REG_EXPOSURE, + IMX766_REG_VALUE_16BIT, + ctrl->val); + + break; + case V4L2_CID_ANALOGUE_GAIN: + ret = imx766_set_gain_reg(imx766, ctrl->val); + break; + case V4L2_CID_VBLANK: + ret = imx766_write_reg(imx766->client, + IMX766_REG_VTS, + IMX766_REG_VALUE_16BIT, + ctrl->val + imx766->cur_mode->height); + break; + case V4L2_CID_TEST_PATTERN: + ret = imx766_enable_test_pattern(imx766, ctrl->val); + 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 imx766_ctrl_ops = { + .s_ctrl = imx766_set_ctrl, +}; + +static int imx766_initialize_controls(struct imx766 *imx766) +{ + const struct imx766_mode *mode; + struct v4l2_ctrl_handler *handler; + s64 exposure_max, vblank_def; + u32 h_blank; + int ret; + + handler = &imx766->ctrl_handler; + mode = imx766->cur_mode; + ret = v4l2_ctrl_handler_init(handler, 8); + if (ret) + return ret; + handler->lock = &imx766->mutex; + + imx766->link_freq = v4l2_ctrl_new_int_menu(handler, NULL, + V4L2_CID_LINK_FREQ, 1, 0, + link_freq_menu_items); + + imx766->pixel_rate = v4l2_ctrl_new_std(handler, NULL, + V4L2_CID_PIXEL_RATE, 0, IMX766_PIXEL_RATE_BINNING, + 1, IMX766_PIXEL_RATE_BINNING); + + h_blank = mode->hts_def - mode->width; + imx766->hblank = v4l2_ctrl_new_std(handler, NULL, + V4L2_CID_HBLANK, h_blank, h_blank, 1, h_blank); + if (imx766->hblank) + imx766->hblank->flags |= V4L2_CTRL_FLAG_READ_ONLY; + + vblank_def = mode->vts_def - mode->height; + imx766->vblank = v4l2_ctrl_new_std(handler, &imx766_ctrl_ops, + V4L2_CID_VBLANK, vblank_def, + IMX766_VTS_MAX - mode->height, + 1, vblank_def); + + exposure_max = mode->vts_def - 4; + imx766->exposure = v4l2_ctrl_new_std(handler, &imx766_ctrl_ops, + V4L2_CID_EXPOSURE, IMX766_EXPOSURE_MIN, + exposure_max, IMX766_EXPOSURE_STEP, + mode->exp_def); + + imx766->anal_gain = v4l2_ctrl_new_std(handler, &imx766_ctrl_ops, + V4L2_CID_ANALOGUE_GAIN, IMX766_GAIN_MIN, + IMX766_GAIN_MAX, IMX766_GAIN_STEP, + IMX766_GAIN_DEFAULT); + + imx766->test_pattern = v4l2_ctrl_new_std_menu_items(handler, + &imx766_ctrl_ops, V4L2_CID_TEST_PATTERN, + ARRAY_SIZE(imx766_test_pattern_menu) - 1, + 0, 0, imx766_test_pattern_menu); + + if (handler->error) { + ret = handler->error; + dev_err(&imx766->client->dev, + "Failed to init controls(%d)\n", ret); + goto err_free_handler; + } + + imx766->subdev.ctrl_handler = handler; + + return 0; + +err_free_handler: + v4l2_ctrl_handler_free(handler); + + return ret; +} + +static int imx766_check_sensor_id(struct imx766 *imx766, + struct i2c_client *client) +{ + struct device *dev = &imx766->client->dev; + int ret = 0; + u32 id = 0; + int i; + + for (i = 0; i < 5; i++) { + ret = imx766_read_reg(client, IMX766_REG_CHIP_ID, + IMX766_REG_VALUE_16BIT, &id); + if (id == CHIP_ID) + break; + usleep_range(300, 1500); + } + if (id != CHIP_ID) { + dev_err(dev, "Unexpected sensor id(%06x), ret(%d)\n", id, ret); + return -ENODEV; + } + + return 0; +} + +static int imx766_configure_regulators(struct imx766 *imx766) +{ + unsigned int i; + + for (i = 0; i < IMX766_NUM_SUPPLIES; i++) + imx766->supplies[i].supply = imx766_supply_names[i]; + + return devm_regulator_bulk_get(&imx766->client->dev, + IMX766_NUM_SUPPLIES, + imx766->supplies); +} + +static int imx766_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct device *dev = &client->dev; + struct device_node *node = dev->of_node; + struct imx766 *imx766; + struct v4l2_subdev *sd; + char facing[2]; + struct device_node *eeprom_ctrl_node; + struct i2c_client *eeprom_ctrl_client; + struct v4l2_subdev *eeprom_ctrl; + struct otp_info *otp_ptr; + int ret; + + dev_info(dev, "driver version: %02x.%02x.%02x", + DRIVER_VERSION >> 16, + (DRIVER_VERSION & 0xff00) >> 8, + DRIVER_VERSION & 0x00ff); + + imx766 = devm_kzalloc(dev, sizeof(*imx766), GFP_KERNEL); + if (!imx766) + return -ENOMEM; + + ret = of_property_read_u32(node, RKMODULE_CAMERA_MODULE_INDEX, + &imx766->module_index); + ret |= of_property_read_string(node, RKMODULE_CAMERA_MODULE_FACING, + &imx766->module_facing); + ret |= of_property_read_string(node, RKMODULE_CAMERA_MODULE_NAME, + &imx766->module_name); + ret |= of_property_read_string(node, RKMODULE_CAMERA_LENS_NAME, + &imx766->len_name); + if (ret) { + dev_err(dev, "could not get module information!\n"); + return -EINVAL; + } + + imx766->client = client; + imx766->cfg_num = ARRAY_SIZE(supported_modes); + imx766->cur_mode = &supported_modes[0]; + + imx766->xvclk = devm_clk_get(dev, "xvclk"); + if (IS_ERR(imx766->xvclk)) { + dev_err(dev, "Failed to get xvclk\n"); + return -EINVAL; + } + + imx766->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_LOW); + if (IS_ERR(imx766->reset_gpio)) + dev_warn(dev, "Failed to get reset-gpios\n"); + + imx766->pwdn_gpio = devm_gpiod_get(dev, "pwdn", GPIOD_OUT_LOW); + if (IS_ERR(imx766->pwdn_gpio)) + dev_warn(dev, "Failed to get pwdn-gpios\n"); + + imx766->power_gpio = devm_gpiod_get(dev, "power", GPIOD_OUT_LOW); + if (IS_ERR(imx766->power_gpio)) + dev_warn(dev, "Failed to get power-gpios\n"); + + + ret = of_property_read_u32(node, + "rockchip,spd-id", + &imx766->spd_id); + if (ret != 0) { + imx766->spd_id = PAD_MAX; + dev_err(dev, + "failed get spd_id, will not to use spd\n"); + } + ret = of_property_read_u32(node, + "rockchip,ebd-id", + &imx766->ebd_id); + if (ret != 0) { + imx766->ebd_id = PAD_MAX; + dev_err(dev, + "failed get ebd_id, will not to use ebd\n"); + } + + ret = imx766_configure_regulators(imx766); + if (ret) { + dev_err(dev, "Failed to get power regulators\n"); + return ret; + } + + imx766->pinctrl = devm_pinctrl_get(dev); + if (!IS_ERR(imx766->pinctrl)) { + imx766->pins_default = + pinctrl_lookup_state(imx766->pinctrl, + OF_CAMERA_PINCTRL_STATE_DEFAULT); + if (IS_ERR(imx766->pins_default)) + dev_err(dev, "could not get default pinstate\n"); + + imx766->pins_sleep = + pinctrl_lookup_state(imx766->pinctrl, + OF_CAMERA_PINCTRL_STATE_SLEEP); + if (IS_ERR(imx766->pins_sleep)) + dev_err(dev, "could not get sleep pinstate\n"); + } + + mutex_init(&imx766->mutex); + + sd = &imx766->subdev; + v4l2_i2c_subdev_init(sd, client, &imx766_subdev_ops); + ret = imx766_initialize_controls(imx766); + if (ret) + goto err_destroy_mutex; + + ret = __imx766_power_on(imx766); + if (ret) + goto err_free_handler; + + ret = imx766_check_sensor_id(imx766, 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) { + imx766->otp = otp_ptr; + } else { + imx766->otp = NULL; + devm_kfree(dev, otp_ptr); + } + } + } + +continue_probe: + +#ifdef CONFIG_VIDEO_V4L2_SUBDEV_API + sd->internal_ops = &imx766_internal_ops; + sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE | + V4L2_SUBDEV_FL_HAS_EVENTS; +#endif +#if defined(CONFIG_MEDIA_CONTROLLER) + imx766->pad.flags = MEDIA_PAD_FL_SOURCE; + sd->entity.function = MEDIA_ENT_F_CAM_SENSOR; + ret = media_entity_pads_init(&sd->entity, 1, &imx766->pad); + if (ret < 0) + goto err_power_off; +#endif + + memset(facing, 0, sizeof(facing)); + if (strcmp(imx766->module_facing, "back") == 0) + facing[0] = 'b'; + else + facing[0] = 'f'; + + snprintf(sd->name, sizeof(sd->name), "m%02d_%s_%s %s", + imx766->module_index, facing, + IMX766_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: + __imx766_power_off(imx766); +err_free_handler: + v4l2_ctrl_handler_free(&imx766->ctrl_handler); +err_destroy_mutex: + mutex_destroy(&imx766->mutex); + + return ret; +} + +static void imx766_remove(struct i2c_client *client) +{ + struct v4l2_subdev *sd = i2c_get_clientdata(client); + struct imx766 *imx766 = to_imx766(sd); + + v4l2_async_unregister_subdev(sd); +#if defined(CONFIG_MEDIA_CONTROLLER) + media_entity_cleanup(&sd->entity); +#endif + v4l2_ctrl_handler_free(&imx766->ctrl_handler); + mutex_destroy(&imx766->mutex); + + pm_runtime_disable(&client->dev); + if (!pm_runtime_status_suspended(&client->dev)) + __imx766_power_off(imx766); + pm_runtime_set_suspended(&client->dev); +} + +#if IS_ENABLED(CONFIG_OF) +static const struct of_device_id imx766_of_match[] = { + { .compatible = "sony,imx766" }, + {}, +}; +MODULE_DEVICE_TABLE(of, imx766_of_match); +#endif + +static const struct i2c_device_id imx766_match_id[] = { + { "sony,imx766", 0 }, + { }, +}; + +static struct i2c_driver imx766_i2c_driver = { + .driver = { + .name = IMX766_NAME, + .pm = &imx766_pm_ops, + .of_match_table = of_match_ptr(imx766_of_match), + }, + .probe = &imx766_probe, + .remove = &imx766_remove, + .id_table = imx766_match_id, +}; + +static int __init sensor_mod_init(void) +{ + return i2c_add_driver(&imx766_i2c_driver); +} + +static void __exit sensor_mod_exit(void) +{ + i2c_del_driver(&imx766_i2c_driver); +} + +device_initcall_sync(sensor_mod_init); +module_exit(sensor_mod_exit); + +MODULE_DESCRIPTION("Sony imx766 sensor driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/media/i2c/otp_eeprom.c b/drivers/media/i2c/otp_eeprom.c index 50c96e35f3fe..540e3f57fcd2 100644 --- a/drivers/media/i2c/otp_eeprom.c +++ b/drivers/media/i2c/otp_eeprom.c @@ -731,6 +731,58 @@ static void rkotp_read_af(struct eeprom_device *eeprom_dev, } +static void rkotp_read_qsc(struct eeprom_device *eeprom_dev, + struct otp_info *otp_ptr, + u32 base_addr) +{ + struct i2c_client *client = eeprom_dev->client; + struct device *dev = &eeprom_dev->client->dev; + u8 *qsc_calib = &otp_ptr->qsc_data.qsc_calib[0]; + u32 checksum = 0; + u32 temp = 0; + int i = 0; + int ret = 0; + + ret = read_reg_otp(client, base_addr, + 4, &otp_ptr->qsc_data.size); + checksum += otp_ptr->qsc_data.size; + base_addr += 4; + ret |= read_reg_otp(client, base_addr, + 2, &otp_ptr->qsc_data.version); + checksum += otp_ptr->qsc_data.version; + base_addr += 2; + ret |= read_reg_otp(client, base_addr, + 2, &otp_ptr->qsc_data.qsc_size); + checksum += otp_ptr->qsc_data.qsc_size; + base_addr += 2; + + ret |= read_reg_otp_buf(client, base_addr, RK_QSC_SIZE, qsc_calib); + base_addr += RK_QSC_SIZE; + + for (i = 0; i < RK_QSC_SIZE; i++) + checksum += qsc_calib[i]; + + for (i = 0; i < RK_QSC_RESERVED_SIZE; i++) { + ret |= read_reg_otp(client, base_addr, 1, &temp); + checksum += temp; + base_addr += 1; + } + + ret |= read_reg_otp(client, base_addr, + 1, &otp_ptr->qsc_data.checksum); + if ((checksum % 255 + 1) == otp_ptr->qsc_data.checksum && (!ret)) { + otp_ptr->qsc_data.flag = 0x01; + dev_info(dev, "qsc info:(data[0] 0x%x, checksum 0x%x)\n", + otp_ptr->qsc_data.qsc_calib[0], + (int)otp_ptr->qsc_data.checksum); + } else { + otp_ptr->qsc_data.flag = 0x00; + dev_info(dev, "qsc info: checksum err, checksum %d, reg_checksum %d\n", + (int)(checksum % 255 + 1), + (int)otp_ptr->qsc_data.checksum); + } +} + static int rkotp_read_data(struct eeprom_device *eeprom_dev) { struct i2c_client *client = eeprom_dev->client; @@ -780,6 +832,12 @@ static int rkotp_read_data(struct eeprom_device *eeprom_dev) base_addr + 1); base_addr += 0x20; break; + case RKOTP_QSC_ID: + rkotp_read_qsc(eeprom_dev, + otp_ptr, + base_addr + 1); + base_addr += 0x1010; + break; default: id = -1; break; diff --git a/drivers/media/i2c/otp_eeprom.h b/drivers/media/i2c/otp_eeprom.h index f284e6d59bb5..9ba9e76b64a5 100644 --- a/drivers/media/i2c/otp_eeprom.h +++ b/drivers/media/i2c/otp_eeprom.h @@ -58,6 +58,8 @@ #define RK_DCCMAP_SIZE 0x0200 #define RK_PDAF_RESERVED_SIZE 0x001e #define RK_AF_RESERVED_SIZE 0x0014 +#define RK_QSC_SIZE 0x1000 +#define RK_QSC_RESERVED_SIZE 0x0006 #define RKOTP_MAX_MODULE 0x0008 #define RKOTP_REG_START 0x0008//v1 0, v2 0x0008 @@ -66,6 +68,7 @@ #define RKOTP_LSC_ID 2 #define RKOTP_PDAF_ID 3 #define RKOTP_AF_ID 4 +#define RKOTP_QSC_ID 5 struct id_defination { u32 supplier_id; @@ -165,6 +168,15 @@ struct af_otp_info { u32 size; }; +struct qsc_otp_info { + u32 flag; + u32 version; + u32 qsc_size; + u8 qsc_calib[RK_QSC_SIZE]; + u32 checksum; + u32 size; +}; + struct otp_info { u32 flag; u32 total_checksum; @@ -174,6 +186,7 @@ struct otp_info { struct sfr_otp_info sfr_otp_data; struct pdaf_otp_info pdaf_data; struct af_otp_info af_data; + struct qsc_otp_info qsc_data; }; /* eeprom device structure */ diff --git a/drivers/media/platform/rockchip/cif/capture.c b/drivers/media/platform/rockchip/cif/capture.c index 6fda40cdc31e..be3d39a21926 100644 --- a/drivers/media/platform/rockchip/cif/capture.c +++ b/drivers/media/platform/rockchip/cif/capture.c @@ -8561,7 +8561,7 @@ int rkcif_do_start_stream(struct rkcif_stream *stream, enum rkcif_stream_mode mo } } if (dev->chip_id >= CHIP_RK1808_CIF) { - if (dev->active_sensor && + if (dev->active_sensor && (dev->active_sensor->mbus.type == V4L2_MBUS_CSI2_DPHY || dev->active_sensor->mbus.type == V4L2_MBUS_CSI2_CPHY || dev->active_sensor->mbus.type == V4L2_MBUS_CCP2)) { @@ -8997,12 +8997,18 @@ void rkcif_stream_init(struct rkcif_device *dev, u32 id) stream->frame_loss = 0; } -static int rkcif_sensor_set_power(struct rkcif_stream *stream, int on) +int rkcif_sensor_set_power(struct rkcif_stream *stream, int on) { struct rkcif_device *cif_dev = stream->cifdev; struct sditf_priv *priv = cif_dev->sditf[0]; int i = 0; + if (!on && atomic_dec_if_positive(&cif_dev->sd_power_cnt)) + return 0; + + if (on && atomic_inc_return(&cif_dev->sd_power_cnt) > 1) + return 0; + if (cif_dev->terminal_sensor.sd) v4l2_subdev_call(cif_dev->terminal_sensor.sd, core, s_power, on); @@ -9068,11 +9074,11 @@ static int rkcif_fh_open(struct file *filp) ret = v4l2_pipeline_pm_get(&vnode->vdev.entity); v4l2_dbg(1, rkcif_debug, vdev, "open video, entity use_count %d\n", vnode->vdev.entity.use_count); + ret = rkcif_sensor_set_power(stream, on); mutex_unlock(&cifdev->stream_lock); if (ret < 0) vb2_fop_release(filp); } - ret = rkcif_sensor_set_power(stream, on); return ret; } @@ -9088,6 +9094,7 @@ static int rkcif_fh_release(struct file *filp) ret = vb2_fop_release(filp); if (!ret) { mutex_lock(&cifdev->stream_lock); + ret = rkcif_sensor_set_power(stream, on); v4l2_pipeline_pm_put(&vnode->vdev.entity); v4l2_dbg(1, rkcif_debug, vdev, "close video, entity use_count %d\n", vnode->vdev.entity.use_count); @@ -9095,7 +9102,6 @@ static int rkcif_fh_release(struct file *filp) } pm_runtime_put_sync(cifdev->dev); - ret = rkcif_sensor_set_power(stream, on); return ret; } @@ -10819,7 +10825,7 @@ void rkcif_irq_oneframe(struct rkcif_device *cif_dev) /* There are two irqs enabled: * - PST_INF_FRAME_END: cif FIFO is ready, this is prior to FRAME_END - * - FRAME_END: cif has saved frame to memory, a frame ready + * - FRAME_END: cif has saved frame to memory, a frame ready */ stream = &cif_dev->stream[RKCIF_STREAM_CIF]; @@ -11970,6 +11976,7 @@ static void rkcif_update_stream(struct rkcif_device *cif_dev, mipi_id); if (ret && cif_dev->chip_id < CHIP_RK3588_CIF) return; + stream->last_frame_idx = stream->frame_idx; } else { ret = rkcif_update_new_buffer_wake_up_mode(stream); if (ret && cif_dev->chip_id < CHIP_RK3588_CIF) @@ -13602,6 +13609,12 @@ static void rkcif_toisp_check_stop_status(struct sditf_priv *priv, stream->stopping = false; wake_up(&stream->wq_stopped); } + if (!(stream->cur_stream_mode & RKCIF_STREAM_MODE_CAPTURE)) { + cur_time = rkcif_time_get_ns(stream->cifdev); + stream->readout.total_time = cur_time - stream->readout.fe_timestamp; + stream->readout.readout_time = cur_time - stream->readout.fs_timestamp; + stream->readout.fe_timestamp = cur_time; + } spin_lock_irqsave(&stream->cifdev->stream_spinlock, flags); if (stream->is_wait_stop_complete) { @@ -13747,9 +13760,6 @@ static void rkcif_toisp_check_stop_status(struct sditf_priv *priv, (priv->hdr_cfg.hdr_mode == HDR_X2 && stream->id == 1) || (priv->hdr_cfg.hdr_mode == HDR_X3 && stream->id == 2))) sditf_disable_immediately(priv); - cur_time = rkcif_time_get_ns(stream->cifdev); - stream->readout.total_time = cur_time - stream->readout.fs_timestamp; - stream->readout.fs_timestamp = cur_time; stream->buf_wake_up_cnt++; if (stream->frame_idx % 2) stream->fps_stats.frm0_timestamp = rkcif_time_get_ns(stream->cifdev); diff --git a/drivers/media/platform/rockchip/cif/dev.c b/drivers/media/platform/rockchip/cif/dev.c index 24b33d0ec9ee..27d7a3da08ca 100644 --- a/drivers/media/platform/rockchip/cif/dev.c +++ b/drivers/media/platform/rockchip/cif/dev.c @@ -2876,6 +2876,7 @@ int rkcif_plat_init(struct rkcif_device *cif_dev, struct device_node *node, int atomic_set(&cif_dev->power_cnt, 0); atomic_set(&cif_dev->streamoff_cnt, 0); atomic_set(&cif_dev->sensor_off, 1); + atomic_set(&cif_dev->sd_power_cnt, 0); cif_dev->is_start_hdr = false; cif_dev->pipe.open = rkcif_pipeline_open; cif_dev->pipe.close = rkcif_pipeline_close; diff --git a/drivers/media/platform/rockchip/cif/dev.h b/drivers/media/platform/rockchip/cif/dev.h index 67bebcee90c9..89522611533e 100644 --- a/drivers/media/platform/rockchip/cif/dev.h +++ b/drivers/media/platform/rockchip/cif/dev.h @@ -967,6 +967,7 @@ struct rkcif_device { atomic_t power_cnt; atomic_t streamoff_cnt; atomic_t sensor_off; + atomic_t sd_power_cnt; struct mutex stream_lock; /* lock between streams */ struct mutex scale_lock; /* lock between scale dev */ struct mutex tools_lock; /* lock between tools dev */ @@ -1179,4 +1180,6 @@ void rkcif_modify_line_int(struct rkcif_stream *stream, bool en); void rkcif_set_sof(struct rkcif_device *cif_dev, u32 seq); void rkcif_set_sensor_streamon_in_sync_mode(struct rkcif_device *cif_dev); +int rkcif_sensor_set_power(struct rkcif_stream *stream, int on); + #endif diff --git a/drivers/media/platform/rockchip/cif/procfs.c b/drivers/media/platform/rockchip/cif/procfs.c index 83fbb65c9de3..1956020b1f75 100644 --- a/drivers/media/platform/rockchip/cif/procfs.c +++ b/drivers/media/platform/rockchip/cif/procfs.c @@ -538,6 +538,7 @@ static void rkcif_show_format(struct rkcif_device *dev, struct seq_file *f) u64 fps, timestamp0, timestamp1; unsigned long flags; u32 time_val = 0; + u32 remainder = 0; if (atomic_read(&pipe->stream_cnt) < 1) return; @@ -586,7 +587,7 @@ static void rkcif_show_format(struct rkcif_device *dev, struct seq_file *f) else fps = timestamp0 > timestamp1 ? timestamp0 - timestamp1 : timestamp1 - timestamp0; - fps = div_u64(fps, 1000000); + fps = div_u64(fps, 1000); seq_puts(f, "Output Info:\n"); seq_printf(f, "\tformat:%s/%ux%u(%u,%u)\n", @@ -596,28 +597,27 @@ static void rkcif_show_format(struct rkcif_device *dev, struct seq_file *f) seq_printf(f, "\tcompact:%s\n", stream->is_compact ? "enable" : "disabled"); seq_printf(f, "\tframe amount:%d\n", stream->frame_idx - 1); if (dev->inf_id == RKCIF_MIPI_LVDS) { - time_val = div_u64(stream->readout.early_time, 1000000); - seq_printf(f, "\tearly:%u ms\n", time_val); + time_val = div_u64(stream->readout.early_time, 1000); + time_val = div_u64_rem(time_val, 1000, &remainder); + seq_printf(f, "\tearly:%u.%u ms\n", time_val, remainder); if (dev->hdr.hdr_mode == NO_HDR || dev->hdr.hdr_mode == HDR_COMPR) { - time_val = div_u64(stream->readout.readout_time, 1000000); - if (dev->sditf[0] && dev->sditf[0]->mode.rdbk_mode < RKISP_VICAP_RDBK_AIQ) - seq_puts(f, "\tsingle readout:N/A\n"); - else - seq_printf(f, "\tsingle readout:%u ms\n", time_val); + time_val = div_u64(stream->readout.readout_time, 1000); + time_val = div_u64_rem(time_val, 1000, &remainder); + seq_printf(f, "\tsingle readout:%u.%u ms\n", time_val, remainder); } else { - time_val = div_u64(stream->readout.readout_time, 1000000); - if (dev->sditf[0] && dev->sditf[0]->mode.rdbk_mode < RKISP_VICAP_RDBK_AIQ) - seq_puts(f, "\tsingle readout:N/A\n"); - else - seq_printf(f, "\tsingle readout:%u ms\n", time_val); - time_val = div_u64(stream->readout.total_time, 1000000); - seq_printf(f, "\ttotal readout:%u ms\n", time_val); + time_val = div_u64(stream->readout.readout_time, 1000); + time_val = div_u64_rem(time_val, 1000, &remainder); + seq_printf(f, "\tsingle readout:%u.%u ms\n", time_val, remainder); + time_val = div_u64(stream->readout.total_time, 1000); + time_val = div_u64_rem(time_val, 1000, &remainder); + seq_printf(f, "\ttotal readout:%u.%u ms\n", time_val, remainder); } } - seq_printf(f, "\trate:%llu ms\n", fps); - fps = div_u64(1000, fps); + time_val = div_u64_rem(fps, 1000, &remainder); + seq_printf(f, "\trate:%u.%u ms\n", time_val, remainder); + fps = div_u64(1000000, fps); seq_printf(f, "\tfps:%llu\n", fps); seq_puts(f, "\tirq statistics:\n"); seq_printf(f, "\t\t\ttotal:%llu\n", diff --git a/drivers/media/platform/rockchip/cif/subdev-itf.c b/drivers/media/platform/rockchip/cif/subdev-itf.c index ec01bfd83c0e..d88c1f1ddeca 100644 --- a/drivers/media/platform/rockchip/cif/subdev-itf.c +++ b/drivers/media/platform/rockchip/cif/subdev-itf.c @@ -1244,6 +1244,7 @@ static int sditf_s_power(struct v4l2_subdev *sd, int on) pm_runtime_put_sync(cif_dev->dev); priv->mode.rdbk_mode = RKISP_VICAP_RDBK_AIQ; } + ret |= rkcif_sensor_set_power(&cif_dev->stream[0], on); v4l2_dbg(1, rkcif_debug, &node->vdev, "s_power %d, entity use_count %d\n", on, node->vdev.entity.use_count); mutex_unlock(&cif_dev->stream_lock); diff --git a/drivers/media/platform/rockchip/isp/isp_params_v35.c b/drivers/media/platform/rockchip/isp/isp_params_v35.c index 9995a76f3df1..7cb381ded56c 100644 --- a/drivers/media/platform/rockchip/isp/isp_params_v35.c +++ b/drivers/media/platform/rockchip/isp/isp_params_v35.c @@ -4033,12 +4033,13 @@ isp_bay3d_enable(struct rkisp_isp_params_vdev *params_vdev, bool en, u32 id) { struct rkisp_isp_params_val_v35 *priv = params_vdev->priv_val; struct rkisp_device *dev = params_vdev->dev; - u32 value, ctrl; + u32 value, ctrl, b3dldc_ctrl; ctrl = isp3_param_read_cache(params_vdev, ISP33_BAY3D_CTRL0, id); if (en == !!(ctrl & ISP35_MODULE_EN)) return; + b3dldc_ctrl = isp3_param_read_cache(params_vdev, ISP35_B3DLDC_CTRL, id); if (en) { if (!priv->buf_bay3d_iir[0].mem_priv || !priv->buf_bay3d_ds[0].mem_priv || @@ -4055,6 +4056,10 @@ isp_bay3d_enable(struct rkisp_isp_params_vdev *params_vdev, bool en, u32 id) isp3_param_write(params_vdev, value, ISP3X_MI_BAY3D_IIR_RD_BASE, id); if (priv->bay3d_iir_rw_fmt == 3) { isp3_param_write(params_vdev, value, ISP35_B3DLDC_WR_ADDR, id); + if (b3dldc_ctrl & ISP35_B3DLDC_EN) { + b3dldc_ctrl |= ISP35_B3DLDC_FORCE_UPD; + isp3_param_write(params_vdev, b3dldc_ctrl, ISP35_B3DLDC_CTRL, id); + } value += priv->bay3d_iir_offs; } isp3_param_write(params_vdev, value, ISP3X_MI_BAY3D_IIR_WR_BASE, id); @@ -4115,6 +4120,12 @@ isp_bay3d_enable(struct rkisp_isp_params_vdev *params_vdev, bool en, u32 id) } else { ctrl &= ~(ISP35_MODULE_EN | ISP35_SELF_FORCE_UPD); isp3_param_write(params_vdev, ctrl, ISP33_BAY3D_CTRL0, id); + if (b3dldc_ctrl & ISP35_B3DLDC_EN) { + b3dldc_ctrl &= ~(ISP35_B3DLDC_FORCE_UPD | ISP35_B3DLDC_EN); + isp3_param_write(params_vdev, b3dldc_ctrl, ISP35_B3DLDC_CTRL, id); + + isp3_param_clear_bits(params_vdev, ISP35_B3DLDC_ADR_STS, ISP35_B3DLDC_EN, id); + } } } @@ -4914,14 +4925,14 @@ static int rkisp_init_mesh_buf(struct rkisp_isp_params_vdev *params_vdev, priv->buf_b3dldc_idx[id] = 0; buf = priv->buf_b3dldc[id]; /* b3d_ldch */ - mesh_w = ALIGN((ALIGN(mesh_w, 16) / 16 + 1) / 2, 2); + mesh_w = DIV_ROUND_UP(ALIGN(mesh_w, 16) / 16 + 1, 2); mesh_h = ALIGN(mesh_h, 8) / 8 + 1; - mesh_size = ALIGN(mesh_w * mesh_h, 16); + mesh_size = ALIGN(mesh_w * 4 * mesh_h, 16); priv->b3dldc_hsize = mesh_w; priv->b3dldch_vsize = mesh_h; /* b3d_ldcv */ mesh_h = ALIGN(meshsize->meas_height, 16) / 16 + 2; - mesh_size += (mesh_w * mesh_h); + mesh_size += (mesh_w * 4 * mesh_h); priv->b3dldcv_vsize = mesh_h; break; default: @@ -4957,7 +4968,7 @@ static int rkisp_init_mesh_buf(struct rkisp_isp_params_vdev *params_vdev, mesh_head->stat = MESH_BUF_INIT; mesh_head->data_oft = ALIGN(sizeof(struct isp2x_mesh_head), 16); mesh_head->data1_oft = mesh_head->data_oft + - ALIGN(priv->b3dldc_hsize * priv->b3dldch_vsize, 16); + ALIGN(priv->b3dldc_hsize * 4 * priv->b3dldch_vsize, 16); } buf++; } @@ -4992,6 +5003,10 @@ rkisp_params_get_meshbuf_inf_v35(struct rkisp_isp_params_vdev *params_vdev, priv->buf_ldch_idx[id] = 0; buf = priv->buf_ldch[id]; break; + case ISP35_MODULE_BAY3D: + priv->buf_b3dldc_idx[id] = 0; + buf = priv->buf_b3dldc[id]; + break; default: return; } diff --git a/drivers/media/platform/rockchip/vpss/regs_v20.h b/drivers/media/platform/rockchip/vpss/regs_v20.h index b9c1b0b13e30..f6b01e3db9cf 100644 --- a/drivers/media/platform/rockchip/vpss/regs_v20.h +++ b/drivers/media/platform/rockchip/vpss/regs_v20.h @@ -263,7 +263,7 @@ /* VPSS2ENC_DEBUG */ #define RKVPSS2X_RO_VPSS2ENC_LINE_CNT(x) ((x) & 0x3fff) -#define RKVPSS2X_RO_VPSS2ENC_FRM_CNT(x) (((x) & 0xffffff) >> 16) +#define RKVPSS2X_RO_VPSS2ENC_FRM_CNT(x) (((x) >> 16) & 0xff) /* VPSS_CTRL_SHD */ diff --git a/drivers/media/platform/rockchip/vpss/stream_v20.c b/drivers/media/platform/rockchip/vpss/stream_v20.c index 196a7a6fc768..8fc95b210f39 100644 --- a/drivers/media/platform/rockchip/vpss/stream_v20.c +++ b/drivers/media/platform/rockchip/vpss/stream_v20.c @@ -826,7 +826,10 @@ static void stream_frame_start(struct rkvpss_stream *stream, u32 irq) !stream->dev->hw_dev->is_single) stream->ops->update_mi(stream); - if (dev->stream_vdev.wrap_line) { + if (dev->stream_vdev.wrap_line && stream->id == RKVPSS_OUTPUT_CH0) { + /* vpss can be holded by enc if isp input offline */ + if (!irq) + rkvpss_unite_set_bits(dev, RKVPSS_VPSS_CTRL, 0, RKVPSS_VPSS2ENC_PIPE_EN); rkvpss_rockit_frame_start(dev); rkvpss_dvbm_event(dev, ROCKIT_DVBM_START); } @@ -898,8 +901,8 @@ static void scl_update_mi(struct rkvpss_stream *stream) stream->ops->enable_mi(stream); } } else if (!stream->is_pause) { - /* wrap mode don't disable mi */ - if (stream->id != RKVPSS_OUTPUT_CH0 || !dev->stream_vdev.wrap_line) { + /* wrap mode don't disable mi for ch0 */ + if (!dev->stream_vdev.wrap_line || stream->id != RKVPSS_OUTPUT_CH0) { stream->is_pause = true; stream->ops->disable_mi(stream); } @@ -918,15 +921,11 @@ static void scl_config_mi(struct rkvpss_stream *stream) struct rkvpss_device *dev = stream->dev; struct capture_fmt *fmt = &stream->out_cap_fmt; struct v4l2_pix_format_mplane *out_fmt = &stream->out_fmt; - u32 reg, val, mask; - - v4l2_dbg(4, rkvpss_debug, &dev->v4l2_dev, - "%s stream:%d\n", __func__, stream->id); + u32 reg, val, mask, height = out_fmt->height; val = out_fmt->plane_fmt[0].bytesperline; reg = stream->config->mi.stride; rkvpss_unite_write(dev, reg, val); - rkvpss_unite_write(dev, reg, val); switch (fmt->fourcc) { case V4L2_PIX_FMT_RGB565: @@ -942,18 +941,27 @@ static void scl_config_mi(struct rkvpss_stream *stream) break; } - val = val * out_fmt->height; + val = val * height; reg = stream->config->mi.y_pic_size; rkvpss_unite_write(dev, reg, val); - if (dev->stream_vdev.wrap_line && stream->id == RKVPSS_OUTPUT_CH0) - val = out_fmt->plane_fmt[0].bytesperline * dev->stream_vdev.wrap_line; - else - val = out_fmt->plane_fmt[0].bytesperline * out_fmt->height; + if (dev->stream_vdev.wrap_line && stream->id == RKVPSS_OUTPUT_CH0) { + mask = RKVPSS_VPSS2ENC_SEL | RKVPSS2X_SENSOR_ID(7) | + RKVPSS_VPSS2ENC_CNT_SEL; + val = RKVPSS_VPSS2ENC_SEL | RKVPSS2X_VPSS2ENC_PATH_EN | + RKVPSS2X_SENSOR_ID(dev->dev_id); + rkvpss_unite_set_bits(dev, RKVPSS_VPSS_CTRL, mask, val); + + height = dev->stream_vdev.wrap_line; + } + val = out_fmt->plane_fmt[0].bytesperline * height; reg = stream->config->mi.y_size; rkvpss_unite_write(dev, reg, val); - val = out_fmt->plane_fmt[1].sizeimage; + if (dev->stream_vdev.wrap_line && stream->id == RKVPSS_OUTPUT_CH0) + val = out_fmt->plane_fmt[0].bytesperline * height / 2; + else + val = out_fmt->plane_fmt[1].sizeimage; reg = stream->config->mi.uv_size; rkvpss_unite_write(dev, reg, val); @@ -1154,14 +1162,14 @@ static void rkvpss_frame_end(struct rkvpss_stream *stream) struct rkvpss_buffer *buf = NULL; unsigned long lock_flags = 0; - v4l2_dbg(3, rkvpss_debug, &dev->v4l2_dev, - "%s stream:%d\n", __func__, stream->id); spin_lock_irqsave(&stream->vbq_lock, lock_flags); if (stream->curr_buf) { - buf = stream->curr_buf; - /* wrap mode use one buffer */ - if (stream->curr_buf->vb.vb2_buf.memory || !dev->stream_vdev.wrap_line) + /* rockit wrap mode use one buffer for ch0 */ + if (stream->curr_buf->vb.vb2_buf.memory || + !dev->stream_vdev.wrap_line || stream->id != RKVPSS_OUTPUT_CH0) { + buf = stream->curr_buf; stream->curr_buf = NULL; + } } spin_unlock_irqrestore(&stream->vbq_lock, lock_flags); @@ -1270,6 +1278,8 @@ static void rkvpss_buf_queue(struct vb2_buffer *vb) if (cap_fmt->mplanes == 1) { for (i = 0; i < cap_fmt->cplanes - 1; i++) { height = pixm->height; + if (dev->stream_vdev.wrap_line && stream->id == RKVPSS_OUTPUT_CH0) + height = dev->stream_vdev.wrap_line; size = (i == 0) ? pixm->plane_fmt[i].bytesperline * height : pixm->plane_fmt[i].sizeimage; @@ -1910,6 +1920,8 @@ static void rkvpss_stop_streaming(struct vb2_queue *queue) rkvpss_stream_stop(stream); rkvpss_pipeline_stream(dev, false); } + if (dev->stream_vdev.wrap_line && stream->id == RKVPSS_OUTPUT_CH0) + rkvpss_dvbm_deinit(dev); destroy_buf_queue(stream, VB2_BUF_STATE_ERROR); rkvpss_pipeline_close(dev); tasklet_disable(&stream->buf_done_tasklet); @@ -2022,7 +2034,8 @@ static int rkvpss_start_streaming(struct vb2_queue *queue, unsigned int count) v4l2_err(&dev->v4l2_dev, "start %s failed\n", node->vdev.name); goto pipe_close; } - + if (dev->stream_vdev.wrap_line && stream->id == RKVPSS_OUTPUT_CH0) + rkvpss_dvbm_init(stream); ret = rkvpss_pipeline_stream(dev, true); if (ret < 0) goto stop_stream; @@ -2037,6 +2050,8 @@ static int rkvpss_start_streaming(struct vb2_queue *queue, unsigned int count) mutex_unlock(&hw->dev_lock); return 0; stop_stream: + if (dev->stream_vdev.wrap_line && stream->id == RKVPSS_OUTPUT_CH0) + rkvpss_dvbm_deinit(dev); stream->streaming = false; rkvpss_stream_stop(stream); pipe_close: @@ -2758,9 +2773,6 @@ static int rkvpss_set_wrap_line(struct rkvpss_stream *stream, int *wrap_line) return -EINVAL; vpss_dev->stream_vdev.wrap_line = *wrap_line; - - //set_wrap todo - return 0; } diff --git a/drivers/media/platform/rockchip/vpss/vpss_dvbm.c b/drivers/media/platform/rockchip/vpss/vpss_dvbm.c index e87033d02298..8e0dc0f14bc6 100644 --- a/drivers/media/platform/rockchip/vpss/vpss_dvbm.c +++ b/drivers/media/platform/rockchip/vpss/vpss_dvbm.c @@ -20,7 +20,7 @@ static struct dvbm_port *g_dvbm; int rkvpss_dvbm_get(struct rkvpss_device *vpss_dev) { - struct device_node *np = vpss_dev->dev->of_node; + struct device_node *np = vpss_dev->hw_dev->dev->of_node; struct device_node *np_dvbm = of_parse_phandle(np, "dvbm", 0); int ret = 0; @@ -35,7 +35,10 @@ int rkvpss_dvbm_get(struct rkvpss_device *vpss_dev) } of_node_put(np_dvbm); - + if (IS_ERR_OR_NULL(g_dvbm)) { + g_dvbm = NULL; + ret = -EINVAL; + } return ret; } @@ -63,7 +66,7 @@ int rkvpss_dvbm_init(struct rkvpss_stream *stream) dvbm_cfg.cbuf_fstd = dvbm_cfg.ybuf_fstd / 2; rk_dvbm_ctrl(g_dvbm, DVBM_VPSS_SET_CFG, &dvbm_cfg); - rk_dvbm_link(g_dvbm, 0); + rk_dvbm_link(g_dvbm, vpss_dev->dev_id); return 0; } @@ -73,7 +76,7 @@ void rkvpss_dvbm_deinit(struct rkvpss_device *vpss_dev) pr_err("g_dvbm %p or vpss_dev %p is NULL\n", g_dvbm, vpss_dev); return; } - rk_dvbm_unlink(g_dvbm, 0); + rk_dvbm_unlink(g_dvbm, vpss_dev->dev_id); } int rkvpss_dvbm_event(struct rkvpss_device *vpss_dev, u32 event) diff --git a/drivers/media/platform/rockchip/vpss/vpss_rockit.c b/drivers/media/platform/rockchip/vpss/vpss_rockit.c index f419bcfa358b..5d6bf1f3315f 100644 --- a/drivers/media/platform/rockchip/vpss/vpss_rockit.c +++ b/drivers/media/platform/rockchip/vpss/vpss_rockit.c @@ -292,12 +292,17 @@ int rkvpss_rockit_buf_done(struct rkvpss_stream *stream, int cmd, struct rkvpss_ curr_buf->vb.sequence, curr_buf->dma[0]); } else { - //tosee if (!(stream->dev->stream_vdev.wrap_line && stream->id == RKVPSS_OUTPUT_CH0)) return 0; rockit_vpss_cfg->frame.u64PTS = vpss_dev->vpss_sdev.frame_timestamp; rockit_vpss_cfg->frame.u32TimeRef = vpss_dev->vpss_sdev.frame_seq; + rockit_vpss_cfg->frame.ispEncCnt = + RKVPSS2X_RO_VPSS2ENC_FRM_CNT(rkvpss_hw_read(vpss_dev->hw_dev, RKVPSS2X_VPSS2ENC_DEBUG)); + v4l2_dbg(2, rkvpss_debug, &vpss_dev->v4l2_dev, + "stream:%d seq:%d enc_frm_cnt:%d rockit buf done:0x%x\n", + stream->id, curr_buf->vb.sequence, + rockit_vpss_cfg->frame.ispEncCnt, curr_buf->dma[0]); } rockit_vpss_cfg->frame.u32Height = stream->out_fmt.height; @@ -571,7 +576,8 @@ void rkvpss_rockit_frame_start(struct rkvpss_device *dev) stream = &dev->stream_vdev.stream[i]; if (!stream->streaming) continue; - rkvpss_rockit_buf_done(stream, ROCKIT_DVBM_START, stream->curr_buf); + if (stream->curr_buf && !stream->curr_buf->vb.vb2_buf.memory) + rkvpss_rockit_buf_done(stream, ROCKIT_DVBM_START, stream->curr_buf); } } diff --git a/drivers/soc/rockchip/rockchip_debug.c b/drivers/soc/rockchip/rockchip_debug.c index 67d14064d1c5..dbc05b9cad27 100644 --- a/drivers/soc/rockchip/rockchip_debug.c +++ b/drivers/soc/rockchip/rockchip_debug.c @@ -79,6 +79,8 @@ #define PMPCSR_LO 0x200 #define PMPCSR_HI 0x204 +#define EDOSLAR 0x300 + #define NUM_CPU_SAMPLES 100 #define NUM_SAMPLES_TO_PRINT 32 @@ -139,6 +141,9 @@ static int rockchip_debug_dump_edpcsr(struct fiq_debugger_output *output) /* Unlock EDLSR.SLK so that EDPCSRhi gets populated */ writel(EDLAR_UNLOCK, base + EDLAR); + /* Disabled os lock */ + writel(0, base + EDOSLAR); + /* Try to read a bunch of times if CPU is actually running */ for (j = 0; j < NUM_CPU_SAMPLES && printed < NUM_SAMPLES_TO_PRINT; j++) { @@ -299,6 +304,9 @@ static int rockchip_panic_notify_edpcsr(struct notifier_block *nb, /* Unlock EDLSR.SLK so that EDPCSRhi gets populated */ writel(EDLAR_UNLOCK, base + EDLAR); + /* Disabled os lock */ + writel(0, base + EDOSLAR); + pr_err("CPU%d online:%d\n", i, cpu_online(i)); /* Try to read a bunch of times if CPU is actually running */ @@ -533,6 +541,8 @@ static int rockchip_hardlock_notify(struct notifier_block *nb, base = rockchip_cpu_debug[cpu]; /* Unlock EDLSR.SLK so that EDPCSRhi gets populated */ writel(EDLAR_UNLOCK, base + EDLAR); + /* Disabled os lock */ + writel(0, base + EDOSLAR); if (sizeof(edpcsr) == 8) edpcsr = ((u64)readl(base + EDPCSR_LO)) | ((u64)readl(base + EDPCSR_HI) << 32); diff --git a/drivers/spi/spi-rockchip-slave.c b/drivers/spi/spi-rockchip-slave.c index 9ec9657b4fd7..4ce660fc734c 100644 --- a/drivers/spi/spi-rockchip-slave.c +++ b/drivers/spi/spi-rockchip-slave.c @@ -141,7 +141,8 @@ #define ROCKCHIP_SPI_VER2_TYPE1 0x05EC0002 #define ROCKCHIP_SPI_VER2_TYPE2 0x00110002 -#define ROCKCHIP_SPI_VER3 0x03110003 +#define ROCKCHIP_SPI_VER3_TYPE1 0x03110003 +#define ROCKCHIP_SPI_VER3_TYPE2 0x03120003 /* * The callback function may not be timely, and even cs has been released, so @@ -889,7 +890,8 @@ static int rockchip_spi_slave_probe(struct platform_device *pdev) init_completion(&rs->xfer_done); switch (rs->version) { - case ROCKCHIP_SPI_VER3: + case ROCKCHIP_SPI_VER3_TYPE2: + case ROCKCHIP_SPI_VER3_TYPE1: rs->ext_spi_clk = true; rs->dma_timeout = 16; rs->fixed_burst_size = 16; diff --git a/drivers/spi/spidev-rkmst.c b/drivers/spi/spidev-rkmst.c index c52cb194f2cc..5b90ce7b0153 100644 --- a/drivers/spi/spidev-rkmst.c +++ b/drivers/spi/spidev-rkmst.c @@ -143,7 +143,7 @@ static int spidev_mst_read(struct spidev_rkmst_data *spidev, void *rxbuf, size_t spi_message_init(&m); spi_message_add_tail(&t, &m); - ret = spidev_mst_wait_for_slave_ready(spidev, SPI_OBJ_MAX_XFER_SIZE); + ret = spidev_mst_wait_for_slave_ready(spidev, SPI_OBJ_DEFAULT_TIMEOUT_US); if (ret < 0) return ret; @@ -169,7 +169,7 @@ static int spidev_slv_write_and_read(struct spidev_rkmst_data *spidev, spi_message_init(&m); spi_message_add_tail(&t, &m); - ret = spidev_mst_wait_for_slave_ready(spidev, SPI_OBJ_MAX_XFER_SIZE); + ret = spidev_mst_wait_for_slave_ready(spidev, SPI_OBJ_DEFAULT_TIMEOUT_US); if (ret < 0) return ret; diff --git a/include/dt-bindings/clock/rockchip,rv1126b-cru.h b/include/dt-bindings/clock/rockchip,rv1126b-cru.h index 37e405ccb982..d622dc64221a 100644 --- a/include/dt-bindings/clock/rockchip,rv1126b-cru.h +++ b/include/dt-bindings/clock/rockchip,rv1126b-cru.h @@ -94,7 +94,7 @@ #define CLK_GMAC_125M 84 #define CLK_TIMER_ROOT 85 #define TCLK_WDT_NS_SRC 86 -#define TCLK_WDT_S 87 +#define TCLK_WDT_S_SRC 87 #define TCLK_WDT_HPMCU 88 #define CLK_CAN0 89 #define CLK_CAN1 90 @@ -369,8 +369,26 @@ #define ACLK_VPSL 359 #define CLK_CORE_VPSL 360 #define CLK_MACPHY 361 +#define HCLK_RKRNG_NS 362 +#define HCLK_RKRNG_S_NS 362 -#define CLK_NR_CLKS (CLK_MACPHY + 1) +/* secure clks */ +#define CLK_USER_OTPC_S 400 +#define CLK_SBPI_OTPC_S 401 +#define PCLK_OTPC_S 402 +#define PCLK_KEY_READER_S 403 +#define HCLK_KL_RKCE_S 404 +#define HCLK_RKCE_S 405 +#define PCLK_WDT_S 406 +#define TCLK_WDT_S 407 +#define CLK_STIMER0 408 +#define CLK_STIMER1 409 +#define PLK_STIMER 410 +#define HCLK_RKRNG_S 411 +#define CLK_PKA_RKCE_S 412 +#define ACLK_RKCE_S 413 + +#define CLK_NR_CLKS (ACLK_RKCE_S + 1) // ======================= TOPCRU module definition bank=0 ======================== // TOPCRU_SOFTRST_CON15(Offset:0xA3C) diff --git a/include/dt-bindings/suspend/rockchip-rv1126b.h b/include/dt-bindings/suspend/rockchip-rv1126b.h new file mode 100644 index 000000000000..013e1317eda8 --- /dev/null +++ b/include/dt-bindings/suspend/rockchip-rv1126b.h @@ -0,0 +1,114 @@ +/* SPDX-License-Identifier: (GPL-2.0+ OR MIT) */ +/* + * Copyright (c) 2025 Rockchip Electronics Co., Ltd. + */ + +#ifndef __DT_BINDINGS_RV1126B_PM_H__ +#define __DT_BINDINGS_RV1126B_PM_H__ +/******************************bits ops************************************/ + +#ifndef BIT +#define BIT(nr) (1 << (nr)) +#endif + +#define RKPM_SLP_ARMPD BIT(0) +#define RKPM_SLP_ARMOFF BIT(1) +#define RKPM_SLP_ARMOFF_DDRPD BIT(2) +#define RKPM_SLP_ARMOFF_LOGOFF BIT(3) +#define RKPM_SLP_ARMOFF_PMUOFF BIT(4) + +#define RKPM_SLP_PMU_HW_PLLS_PD BIT(8) +#define RKPM_SLP_PMU_PMUALIVE_32K BIT(9) +#define RKPM_SLP_PMU_DIS_OSC BIT(10) + +#define RKPM_SLP_CLK_GT BIT(16) +#define RKPM_SLP_PMIC_LP BIT(17) + +#define RKPM_SLP_32K_EXT BIT(24) +#define RKPM_SLP_TIME_OUT_WKUP BIT(25) +#define RKPM_SLP_PMU_DBG BIT(26) +#define RKPM_SLP_LP_PR BIT(27) +#define RKPM_SLP_ARCH_TIMER_RESET BIT(28) + +/* the wake up source */ +#define RKPM_CPU0_WKUP_EN BIT(0) +#define RKPM_CPU1_WKUP_EN BIT(1) +#define RKPM_CPU2_WKUP_EN BIT(2) +#define RKPM_CPU3_WKUP_EN BIT(3) +#define RKPM_GPIO0_WKUP_EN BIT(4) +#define RKPM_SDMMC0_WKUP_EN BIT(5) +#define RKPM_SDMMC1_WKUP_EN BIT(6) +#define RKPM_SDIO_WKUP_EN BIT(7) +#define RKPM_USB_WKUP_EN BIT(8) +#define RKPM_UART0_WKUP_EN BIT(9) +#define RKPM_I2C2_WKUP_EN BIT(10) +#define RKPM_PWM1_WKUP_EN BIT(11) +#define RKPM_TIMER_WKUP_EN BIT(12) +#define RKPM_HPTIMER_WKUP_EN BIT(13) +#define RKPM_SYSINT_WKUP_EN BIT(14) +#define RKPM_AOV_WKUP_EN BIT(15) +#define RKPM_AAD_WKUP_EN BIT(16) +#define RKPM_TIMEOUT_WKUP_EN BIT(17) + +/* sleep pin */ +#define RKPM_SLEEP_PIN0_EN BIT(0) /* GPIO0_A3 */ +#define RKPM_SLEEP_PIN1_EN BIT(1) /* GPIO0_A4 */ +#define RKPM_SLEEP_PIN2_EN BIT(2) /* GPIO0_C1 */ + +#define RKPM_SLEEP_PIN0_ACT_LOW BIT(0) /* GPIO0_A3 */ +#define RKPM_SLEEP_PIN1_ACT_LOW BIT(1) /* GPIO0_A4 */ +#define RKPM_SLEEP_PIN2_ACT_LOW BIT(2) /* GPIO0_C1 */ + +/* io config */ +#define RKPM_IO_CFG_IOMUX_SFT 0 +#define RKPM_IO_CFG_GPIO_DIR_SFT 8 +#define RKPM_IO_CFG_GPIO_LVL_SFT 9 +#define RKPM_IO_CFG_PULL_SFT 10 +#define RKPM_IO_CFG_ID_SFT 16 + +#define RKPM_IO_CFG_IOMUX_MSK 0x3f +#define RKPM_IO_CFG_GPIO_DIR_MSK 0x1 +#define RKPM_IO_CFG_GPIO_LVL_MSK 0x1 +#define RKPM_IO_CFG_PULL_MSK 0x3 +#define RKPM_IO_CFG_ID_MSK 0xffff + +#define RKPM_IO_CFG_IOMUX_GPIO_VAL 0 +#define RKPM_IO_CFG_GPIO_DIR_INPUT_VAL 0 +#define RKPM_IO_CFG_GPIO_DIR_OUTPUT_VAL 1 +#define RKPM_IO_CFG_GPIO_LVL_LOW_VAL 0 +#define RKPM_IO_CFG_GPIO_LVL_HIGH_VAL 1 +#define RKPM_IO_CFG_PULL_NONE_VAL 0 +#define RKPM_IO_CFG_PULL_UP_VAL 1 +#define RKPM_IO_CFG_PULL_DOWN_VAL 2 + +#define RKPM_IO_CFG_IOMUX(func) ((func) << RKPM_IO_CFG_IOMUX_SFT) +#define RKPM_IO_CFG_GPIO_DIR_INPUT \ + (RKPM_IO_CFG_GPIO_DIR_INPUT_VAL << RKPM_IO_CFG_GPIO_DIR_SFT) +#define RKPM_IO_CFG_GPIO_DIR_OUTPUT \ + (RKPM_IO_CFG_GPIO_DIR_OUTPUT_VAL << RKPM_IO_CFG_GPIO_DIR_SFT) +#define RKPM_IO_CFG_GPIO_LVL_LOW \ + (RKPM_IO_CFG_GPIO_LVL_LOW_VAL << RKPM_IO_CFG_GPIO_LVL_SFT) +#define RKPM_IO_CFG_GPIO_LVL_HIGH \ + (RKPM_IO_CFG_GPIO_LVL_HIGH_VAL << RKPM_IO_CFG_GPIO_LVL_SFT) +#define RKPM_IO_CFG_PULL_NONE \ + (RKPM_IO_CFG_PULL_NONE_VAL << RKPM_IO_CFG_PULL_SFT) +#define RKPM_IO_CFG_PULL_UP \ + (RKPM_IO_CFG_PULL_UP_VAL << RKPM_IO_CFG_PULL_SFT) +#define RKPM_IO_CFG_PULL_DOWN \ + (RKPM_IO_CFG_PULL_DOWN_VAL << RKPM_IO_CFG_PULL_SFT) +#define RKPM_IO_CFG_ID(id) ((id) << RKPM_IO_CFG_ID_SFT) +#define RKPM_IO_CFG_IOMUX_GPIO \ + RKPM_IO_CFG_IOMUX(RKPM_IO_CFG_IOMUX_GPIO_VAL) + +#define RKPM_IO_CFG_GET_IOMUX(cfg) \ + (((cfg) >> RKPM_IO_CFG_IOMUX_SFT) & RKPM_IO_CFG_IOMUX_MSK) +#define RKPM_IO_CFG_GET_GPIO_DIR(cfg) \ + (((cfg) >> RKPM_IO_CFG_GPIO_DIR_SFT) & RKPM_IO_CFG_GPIO_DIR_MSK) +#define RKPM_IO_CFG_GET_GPIO_LVL(cfg) \ + (((cfg) >> RKPM_IO_CFG_GPIO_LVL_SFT) & RKPM_IO_CFG_GPIO_LVL_MSK) +#define RKPM_IO_CFG_GET_PULL(cfg) \ + (((cfg) >> RKPM_IO_CFG_PULL_SFT) & RKPM_IO_CFG_PULL_MSK) +#define RKPM_IO_CFG_GET_ID(cfg) \ + (((cfg) >> RKPM_IO_CFG_ID_SFT) & RKPM_IO_CFG_ID_MSK) + +#endif diff --git a/sound/soc/codecs/rk730.c b/sound/soc/codecs/rk730.c index a3a8f2a29e96..a1423bd196b9 100644 --- a/sound/soc/codecs/rk730.c +++ b/sound/soc/codecs/rk730.c @@ -143,6 +143,14 @@ static const struct snd_kcontrol_new rk730_out2_switch = static SOC_ENUM_SINGLE_DECL(ana_ldo_volt_enum, RK730_LDO, 4, ana_ldo_volt_text); +static const char * const adc_sdo_sel_tx_text[] = { + "ADCL ADCR", "ADCL ADCR DACL DACR", "ADCL DACL", "ADCL DACR", + "ADCR DACL", "ADCR DACR", "DACL DACR", +}; + +static SOC_ENUM_SINGLE_DECL(adc_sdo_sel_tx_enum, RK730_DI2S_TXCR2, + 5, adc_sdo_sel_tx_text); + static int rk730_pll_event(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol, int event) { @@ -477,6 +485,7 @@ static const struct snd_kcontrol_new rk730_snd_controls[] = { SOC_ENUM("Mic Bias Volt", micbias_volt_enum), SOC_ENUM("DAC HPF Center Freq", dac_hfp_center_freq_enum), SOC_ENUM("ADC CAPACITY TRIM", adc_capacity_trim_enum), + SOC_ENUM("ADC SDO SEL TX", adc_sdo_sel_tx_enum), SOC_SINGLE("ADC Volume Bypass Switch", RK730_DTOP_VUCTL, 7, 1, 0), SOC_SINGLE("DAC Volume Bypass Switch", RK730_DTOP_VUCTL, 6, 1, 0), SOC_SINGLE("ADC Fade Switch", RK730_DTOP_VUCTL, 5, 1, 0), @@ -792,26 +801,46 @@ static int rk730_dai_hw_params(struct snd_pcm_substream *substream, dev_info(component->dev, "%s:index %d mclk=%d rate=%d\n", __func__, coeff, coeff_div[coeff].mclk, coeff_div[coeff].rate); - switch (params_format(params)) { - case SNDRV_PCM_FORMAT_S16_LE: - snd_soc_component_update_bits(component, RK730_DI2S_RXCR2, - RK730_DI2S_RXCR2_VDW_MASK, - RK730_DI2S_RXCR2_VDW(16)); - snd_soc_component_update_bits(component, RK730_DI2S_TXCR2, - RK730_DI2S_TXCR2_VDW_MASK, - RK730_DI2S_TXCR2_VDW(16)); - break; - case SNDRV_PCM_FORMAT_S24_LE: - case SNDRV_PCM_FORMAT_S32_LE: - snd_soc_component_update_bits(component, RK730_DI2S_RXCR2, - RK730_DI2S_RXCR2_VDW_MASK, - RK730_DI2S_RXCR2_VDW(24)); - snd_soc_component_update_bits(component, RK730_DI2S_TXCR2, - RK730_DI2S_TXCR2_VDW_MASK, - RK730_DI2S_TXCR2_VDW(24)); - break; - default: - return -EINVAL; + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + switch (params_format(params)) { + case SNDRV_PCM_FORMAT_S16_LE: + snd_soc_component_update_bits(component, RK730_DI2S_RXCR2, + RK730_DI2S_RXCR2_VDW_MASK, + RK730_DI2S_RXCR2_VDW(16)); + break; + case SNDRV_PCM_FORMAT_S24_LE: + snd_soc_component_update_bits(component, RK730_DI2S_RXCR2, + RK730_DI2S_RXCR2_VDW_MASK, + RK730_DI2S_RXCR2_VDW(24)); + break; + case SNDRV_PCM_FORMAT_S32_LE: + snd_soc_component_update_bits(component, RK730_DI2S_RXCR2, + RK730_DI2S_RXCR2_VDW_MASK, + RK730_DI2S_RXCR2_VDW(32)); + break; + default: + return -EINVAL; + } + } else { + switch (params_format(params)) { + case SNDRV_PCM_FORMAT_S16_LE: + snd_soc_component_update_bits(component, RK730_DI2S_TXCR2, + RK730_DI2S_TXCR2_VDW_MASK, + RK730_DI2S_TXCR2_VDW(16)); + break; + case SNDRV_PCM_FORMAT_S24_LE: + snd_soc_component_update_bits(component, RK730_DI2S_TXCR2, + RK730_DI2S_TXCR2_VDW_MASK, + RK730_DI2S_TXCR2_VDW(24)); + break; + case SNDRV_PCM_FORMAT_S32_LE: + snd_soc_component_update_bits(component, RK730_DI2S_TXCR2, + RK730_DI2S_TXCR2_VDW_MASK, + RK730_DI2S_TXCR2_VDW(32)); + break; + default: + return -EINVAL; + } } rate = samplerate_to_bit(params_rate(params)); diff --git a/sound/soc/codecs/rk_dsm.c b/sound/soc/codecs/rk_dsm.c index 9a189b7fcea3..07e3793ae51b 100644 --- a/sound/soc/codecs/rk_dsm.c +++ b/sound/soc/codecs/rk_dsm.c @@ -520,6 +520,19 @@ static int rk_dsm_pcm_trigger(struct snd_pcm_substream *substream, snd_soc_component_get_drvdata(dai->component); switch (cmd) { + case SNDRV_PCM_TRIGGER_START: + case SNDRV_PCM_TRIGGER_RESUME: + case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: + /** + * NOTE: Recover DAC volumes and switch RKDSM_ON_FUNC after hw_param() + * again, avoid to incorrect silence during recover from XRUN. + */ + regmap_write(rd->regmap, DACVOLL0, rd->vols.vol_l); + regmap_write(rd->regmap, DACVOLR0, rd->vols.vol_r); + regmap_write(rd->regmap, DACVOGP, rd->vols.polarity); + if (rd->data && rd->data->iomux_switch) + rd->data->iomux_switch(rd->dev, RKDSM_ON_FUNC); + break; case SNDRV_PCM_TRIGGER_SUSPEND: case SNDRV_PCM_TRIGGER_STOP: case SNDRV_PCM_TRIGGER_PAUSE_PUSH: diff --git a/sound/soc/rockchip/rockchip_asrc.c b/sound/soc/rockchip/rockchip_asrc.c index b7d708f920e7..2dd6ef10be1a 100644 --- a/sound/soc/rockchip/rockchip_asrc.c +++ b/sound/soc/rockchip/rockchip_asrc.c @@ -22,6 +22,8 @@ #include "rockchip_asrc.h" +#define RV1126B_ASRC 0x04000000 + /* * structure: * tx: memory->asrc->sai->codec @@ -42,6 +44,7 @@ #define MAXBURST_PER_FIFO 8 #define DEFAULT_SAMPLE_RATE 48000 #define ASRC_DEFAULT_CLK 200000000 +#define ASRC_LRCK_SOURCE_FREQ_DEFAULT 98304000 /* Platform Definition */ /* rk3576 */ @@ -182,7 +185,6 @@ struct rk_asrc_soc_data { int (*lrck_clk_set)(struct device *dev); int (*lrck_clk_en)(struct device *dev); int (*lrck_clk_dis)(struct device *dev); - int lrck_source_freq; }; struct rockchip_asrc_pair { @@ -223,6 +225,9 @@ struct rockchip_asrc { int resample_rate; int dst_link_dai_id; /* This must be set firstly by amixer/tinymixer */ int src_link_dai_id; /* This must be set firstly by amixer/tinymixer */ + int lrck_src_freq; + int lrck_dst_freq; + int version; }; static int rockchip_asrc_calculate_ratio(struct rockchip_asrc *asrc, @@ -405,9 +410,15 @@ static int rockchip_asrc_hw_params(struct snd_pcm_substream *substream, asrc->sample_bits = 16; break; case SNDRV_PCM_FORMAT_S24_LE: + val = ASRC_IWL_24BIT | ASRC_OWL_24BIT | + ASRC_OFMT_32 | ASRC_IFMT_32 | + ASRC_ISJM(0) | ASRC_OSJM(0); + asrc->sample_bits = 32; + break; case SNDRV_PCM_FORMAT_S32_LE: val = ASRC_IWL_24BIT | ASRC_OWL_24BIT | - ASRC_OFMT_32 | ASRC_IFMT_32; + ASRC_OFMT_32 | ASRC_IFMT_32 | + ASRC_ISJM(8) | ASRC_OSJM(8); asrc->sample_bits = 32; break; default: @@ -528,6 +539,7 @@ static bool rockchip_asrc_readable_reg(struct device *dev, unsigned int reg) case ASRC_LRCK_MARGIN: case ASRC_FETCH_LEN: case ASRC_DMA_THRESH: + case ASRC_LRCK_FILT: case ASRC_INT_CON: case ASRC_INT_ST: case ASRC_ST: @@ -564,6 +576,7 @@ static bool rockchip_asrc_writeable_reg(struct device *dev, unsigned int reg) case ASRC_LRCK_MARGIN: case ASRC_FETCH_LEN: case ASRC_DMA_THRESH: + case ASRC_LRCK_FILT: case ASRC_INT_CON: case ASRC_INT_ST: case ASRC_FIFO_IN_WRCNT: @@ -1141,6 +1154,11 @@ static int rockchip_asrc_init(struct rockchip_asrc *asrc) ASRC_RATIO_TRACK_DIV_MSK | ASRC_RATIO_TRACK_PERIOD_MSK, ASRC_RATIO_TRACK_DIV(3) | ASRC_RATIO_TRACK_PERIOD(1023)); + if (asrc->version == RV1126B_ASRC) { + regmap_update_bits(asrc->regmap, ASRC_LRCK_FILT, + ASRC_LRCK_FILT_MSK, ASRC_LRCK_FILT_DIS); + } + return 0; } @@ -1290,7 +1308,7 @@ static void rockchip_asrc_lrck_div_set(struct rockchip_asrc *asrc) switch (asrc->src_link_dai_id) { case DAI_ID_ASRC0 ... DAI_ID_ASRC15: - src_lrck_div = asrc->soc_data->lrck_source_freq / asrc->sample_rate; + src_lrck_div = asrc->lrck_src_freq / asrc->sample_rate; break; case DAI_ID_SPDIF_TX0 ... DAI_ID_SPDIF_RX7: src_lrck_div = 128; @@ -1301,7 +1319,7 @@ static void rockchip_asrc_lrck_div_set(struct rockchip_asrc *asrc) switch (asrc->dst_link_dai_id) { case DAI_ID_ASRC0 ... DAI_ID_ASRC15: - dst_lrck_div = asrc->soc_data->lrck_source_freq / asrc->resample_rate; + dst_lrck_div = asrc->lrck_dst_freq / asrc->resample_rate; break; case DAI_ID_SPDIF_TX0 ... DAI_ID_SPDIF_RX7: dst_lrck_div = 128; @@ -1381,19 +1399,24 @@ static int rk3506_asrc_lrck_clk_set(struct device *dev) clk_set_parent(asrc->src_lrck, asrc->src_lrck_parent); clk_set_parent(asrc->dst_lrck, asrc->dst_lrck_parent); if (rockchip_asrc_is_link_mem(asrc->src_link_dai_id)) { - if (clk_set_rate(asrc->src_lrck_parent, asrc->soc_data->lrck_source_freq)) { + if (clk_set_rate(asrc->src_lrck_parent, asrc->lrck_src_freq)) { dev_err(asrc->dev, "Failed to set src_lrck_parent, freq is %d\n", - asrc->soc_data->lrck_source_freq); + asrc->lrck_src_freq); return -EINVAL; } + + asrc->lrck_src_freq = clk_get_rate(asrc->src_lrck_parent); } if (rockchip_asrc_is_link_mem(asrc->dst_link_dai_id)) { - if (clk_set_rate(asrc->dst_lrck_parent, asrc->soc_data->lrck_source_freq)) { + if (clk_set_rate(asrc->dst_lrck_parent, asrc->lrck_dst_freq)) { dev_err(asrc->dev, "Failed to set dst_lrck_parent, freq is %d\n", - asrc->soc_data->lrck_source_freq); + asrc->lrck_dst_freq); return -EINVAL; } + + /* get the real freq */ + asrc->lrck_dst_freq = clk_get_rate(asrc->dst_lrck_parent); } rockchip_asrc_lrck_div_set(asrc); @@ -1612,19 +1635,23 @@ static int rk3576_asrc_lrck_clk_set(struct device *dev) } if (rockchip_asrc_is_link_mem(asrc->src_link_dai_id)) { - if (clk_set_rate(asrc->cru_src0, asrc->soc_data->lrck_source_freq)) { + if (clk_set_rate(asrc->cru_src0, asrc->lrck_src_freq)) { dev_err(asrc->dev, "Failed to set cru_src0, freq is %d\n", - asrc->soc_data->lrck_source_freq); + asrc->lrck_src_freq); return -EINVAL; } + + asrc->lrck_src_freq = clk_get_rate(asrc->cru_src0); } if (rockchip_asrc_is_link_mem(asrc->dst_link_dai_id)) { - if (clk_set_rate(asrc->cru_src1, asrc->soc_data->lrck_source_freq)) { + if (clk_set_rate(asrc->cru_src1, asrc->lrck_dst_freq)) { dev_err(asrc->dev, "Failed to set cru_src1, freq is %d\n", - asrc->soc_data->lrck_source_freq); + asrc->lrck_dst_freq); return -EINVAL; } + + asrc->lrck_dst_freq = clk_get_rate(asrc->cru_src1); } rockchip_asrc_lrck_div_set(asrc); @@ -1664,7 +1691,6 @@ static const struct rk_asrc_soc_data rk3506_data = { .lrck_clk_set = rk3506_asrc_lrck_clk_set, .lrck_clk_en = rk3506_asrc_lrck_clk_en, .lrck_clk_dis = rk3506_asrc_lrck_clk_dis, - .lrck_source_freq = 98304000, }; static const struct rk_asrc_soc_data rk3576_data = { @@ -1672,7 +1698,6 @@ static const struct rk_asrc_soc_data rk3576_data = { .lrck_clk_set = rk3576_asrc_lrck_clk_set, .lrck_clk_en = rk3576_asrc_lrck_clk_en, .lrck_clk_dis = rk3576_asrc_lrck_clk_dis, - .lrck_source_freq = 49152000, }; static const struct of_device_id rockchip_asrc_match[] = { @@ -1694,6 +1719,8 @@ static int rockchip_asrc_probe(struct platform_device *pdev) if (!asrc) return -ENOMEM; + asrc->lrck_src_freq = ASRC_LRCK_SOURCE_FREQ_DEFAULT; + asrc->lrck_dst_freq = ASRC_LRCK_SOURCE_FREQ_DEFAULT; asrc->dev = &pdev->dev; asrc->pdev = pdev; dev_set_drvdata(&pdev->dev, asrc); @@ -1770,6 +1797,7 @@ static int rockchip_asrc_probe(struct platform_device *pdev) if (ret < 0) goto err_runtime_suspend; + regmap_read(asrc->regmap, ASRC_VERSION, &asrc->version); ret = rockchip_asrc_init(asrc); if (ret) { dev_err(&pdev->dev, "Asrc init error.\n"); diff --git a/sound/soc/rockchip/rockchip_asrc.h b/sound/soc/rockchip/rockchip_asrc.h index 383adcb16df8..15887e164280 100644 --- a/sound/soc/rockchip/rockchip_asrc.h +++ b/sound/soc/rockchip/rockchip_asrc.h @@ -23,6 +23,7 @@ #define ASRC_LRCK_MARGIN 0x0034 #define ASRC_FETCH_LEN 0x0040 #define ASRC_DMA_THRESH 0x0050 +#define ASRC_LRCK_FILT 0x0058 #define ASRC_INT_CON 0x0060 #define ASRC_INT_ST 0x0064 #define ASRC_ST 0x0070 @@ -124,6 +125,15 @@ #define ASRC_DMA_TX_THRESH_MSK (0xf << 0) #define ASRC_DMA_TX_THRESH(x) (x << 0) +/**********************ASRC_LRCK_FILT************************/ +#define ASRC_LRCK_DRIFT_MARGIN_MSK (0x7ff << 0) +#define ASRC_LRCK_DRIFT_MARGIN(x) (x << 0) +#define ASRC_LRCK_SUPER_MARGIN_MSK (0x7ff << 16) +#define ASRC_LRCK_SUPER_MARGIN(x) (x << 16) +#define ASRC_LRCK_FILT_MSK (0x1 << 31) +#define ASRC_LRCK_FILT_EN (0x1 << 31) +#define ASRC_LRCK_FILT_DIS (0x0 << 31) + /**********************ASRC_INT_CON************************/ #define ASRC_DST_LRCK_UNLOCK_MSK (0x1 << 12) #define ASRC_DST_LRCK_UNLOCK_EN (0x1 << 12)