From 3dc042a43b5ec8f54a28780391a54af732b3f075 Mon Sep 17 00:00:00 2001 From: Jos Wang Date: Sun, 9 Feb 2025 15:19:26 +0800 Subject: [PATCH 01/23] UPSTREAM: usb: typec: displayport: Receive DP Status Update NAK request exit dp altmode MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Although some Type-C DRD devices that do not support the DP Sink function (such as Huawei Mate 40Pro), the Source Port initiates Enter Mode CMD, but the device responds to Enter Mode ACK, the Source port then initiates DP Status Update CMD, and the device responds to DP Status Update NAK. As PD2.0 spec ("6.4.4.3.4 Enter Mode Command"),A DR_Swap Message Shall Not be sent during Modal Operation between the Port Partners. At this time, the source port initiates DR_Swap message through the "echo device > /sys/class/typec/port0/data_role" command to switch the data role from host to device. The device will initiate a Hard Reset for recovery, resulting in the failure of data role swap. Therefore, when DP Status Update NAK is received, Exit Mode CMD is initiated to exit the currently entered DP altmode. Change-Id: I9dd50aa0df8e0d3f6fd59a35b4da91d4820dd2aa Signed-off-by: Jos Wang Reviewed-by: Heikki Krogerus Link: https://lore.kernel.org/r/20250209071926.69625-1-joswang1221@gmail.com Signed-off-by: Greg Kroah-Hartman Signed-off-by: Frank Wang (cherry picked from commit b4b38ffb38c91afd4dc387608db26f6fc34ed40b) --- drivers/usb/typec/altmodes/displayport.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/usb/typec/altmodes/displayport.c b/drivers/usb/typec/altmodes/displayport.c index 99b2d1dcbf24..3f5a16ad18f0 100644 --- a/drivers/usb/typec/altmodes/displayport.c +++ b/drivers/usb/typec/altmodes/displayport.c @@ -327,6 +327,10 @@ static int dp_altmode_vdm(struct typec_altmode *alt, break; case CMDT_RSP_NAK: switch (cmd) { + case DP_CMD_STATUS_UPDATE: + if (typec_altmode_exit(alt)) + dev_err(&dp->alt->dev, "Exit Mode Failed!\n"); + break; case DP_CMD_CONFIGURE: dp->data.conf = 0; ret = dp_altmode_configured(dp); From 26ae45e719c916734a8dcabb7a8f90d145c38af9 Mon Sep 17 00:00:00 2001 From: Andrei Kuchynski Date: Tue, 24 Jun 2025 13:32:46 +0000 Subject: [PATCH 02/23] UPSTREAM: usb: typec: displayport: Fix potential deadlock The deadlock can occur due to a recursive lock acquisition of `cros_typec_altmode_data::mutex`. The call chain is as follows: 1. cros_typec_altmode_work() acquires the mutex 2. typec_altmode_vdm() -> dp_altmode_vdm() -> 3. typec_altmode_exit() -> cros_typec_altmode_exit() 4. cros_typec_altmode_exit() attempts to acquire the mutex again To prevent this, defer the `typec_altmode_exit()` call by scheduling it rather than calling it directly from within the mutex-protected context. Change-Id: I6b97900003c324f5bde6d9ce996871d95f604148 Cc: stable Fixes: b4b38ffb38c9 ("usb: typec: displayport: Receive DP Status Update NAK request exit dp altmode") Signed-off-by: Andrei Kuchynski Reviewed-by: Heikki Krogerus Link: https://lore.kernel.org/r/20250624133246.3936737-1-akuchynski@chromium.org Signed-off-by: Greg Kroah-Hartman Signed-off-by: Frank Wang (cherry picked from commit 099cf1fbb8afc3771f408109f62bdec66f85160e) --- drivers/usb/typec/altmodes/displayport.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/usb/typec/altmodes/displayport.c b/drivers/usb/typec/altmodes/displayport.c index 3f5a16ad18f0..c9cf3a365c7b 100644 --- a/drivers/usb/typec/altmodes/displayport.c +++ b/drivers/usb/typec/altmodes/displayport.c @@ -328,8 +328,7 @@ static int dp_altmode_vdm(struct typec_altmode *alt, case CMDT_RSP_NAK: switch (cmd) { case DP_CMD_STATUS_UPDATE: - if (typec_altmode_exit(alt)) - dev_err(&dp->alt->dev, "Exit Mode Failed!\n"); + dp->state = DP_STATE_EXIT; break; case DP_CMD_CONFIGURE: dp->data.conf = 0; From 103d8c78c6646b3d88564de81560d2ea8e41c47e Mon Sep 17 00:00:00 2001 From: Ziyuan Xu Date: Tue, 8 Jul 2025 20:04:10 +0800 Subject: [PATCH 03/23] arm64: dts: rockchip: remove rv1126b-tb files AKA rv1126b-thunderboot only support ARM32. Signed-off-by: Ziyuan Xu Change-Id: I2775fdbab622b8c90c4b2662ee3f793cd678ddd7 --- arch/arm64/boot/dts/rockchip/Makefile | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/arm64/boot/dts/rockchip/Makefile b/arch/arm64/boot/dts/rockchip/Makefile index 1bccd6fa1c84..589b1b6a4931 100644 --- a/arch/arm64/boot/dts/rockchip/Makefile +++ b/arch/arm64/boot/dts/rockchip/Makefile @@ -391,7 +391,6 @@ dtb-$(CONFIG_ARCH_ROCKCHIP) += rv1126b-evb2-v10-aov-dual-cam.dtb dtb-$(CONFIG_ARCH_ROCKCHIP) += rv1126b-evb2-v10-mcu-k350c4516t.dtb dtb-$(CONFIG_ARCH_ROCKCHIP) += rv1126b-evb2-v10-rgb-Q7050ITH2641AA1T.dtb dtb-$(CONFIG_ARCH_ROCKCHIP) += rv1126b-evb2-v10-sii9022-bt1120-to-hdmi.dtb -dtb-$(CONFIG_ARCH_ROCKCHIP) += rv1126b-evb2-v10-tb-400w.dtb dtb-$(CONFIG_ARCH_ROCKCHIP) += rv1126b-evb3-v10.dtb dtb-$(CONFIG_ARCH_ROCKCHIP) += rv1126b-evb4-v10.dtb dtb-$(CONFIG_ARCH_ROCKCHIP) += rv1126b-iotest-v10.dtb From 327f216065138cabfb1a17c05e9c6d8c879da4cc Mon Sep 17 00:00:00 2001 From: Ziyuan Xu Date: Tue, 8 Jul 2025 20:07:38 +0800 Subject: [PATCH 04/23] ARM: dts: rockchip: Add rv1126b-evb2-v10-tb-400w-spi-nor support Move rv1126b-tb files from arm64 to arm32, and rename rv1126b-evb2-v10-tb-400w.dts to rv1126b-evb2-v10-tb-400w-spi-nor.dts. Signed-off-by: Ziyuan Xu Change-Id: Ifa141adf272864de4641b78134798d9501c38f54 --- arch/arm/boot/dts/Makefile | 2 +- .../dts/rv1126b-evb2-v10-tb-400w-spi-nor.dts} | 15 +++++++-------- .../arm/boot/dts/rv1126b-evb2-v10-tb-400w.dts | 19 ------------------- .../boot/dts}/rv1126b-thunder-boot-cam.dtsi | 0 .../boot/dts}/rv1126b-thunder-boot-emmc.dtsi | 0 .../dts}/rv1126b-thunder-boot-spi-nor.dtsi | 0 .../boot/dts}/rv1126b-thunder-boot.dtsi | 2 +- 7 files changed, 9 insertions(+), 29 deletions(-) rename arch/{arm64/boot/dts/rockchip/rv1126b-evb2-v10-tb-400w.dts => arm/boot/dts/rv1126b-evb2-v10-tb-400w-spi-nor.dts} (79%) delete mode 100644 arch/arm/boot/dts/rv1126b-evb2-v10-tb-400w.dts rename arch/{arm64/boot/dts/rockchip => arm/boot/dts}/rv1126b-thunder-boot-cam.dtsi (100%) rename arch/{arm64/boot/dts/rockchip => arm/boot/dts}/rv1126b-thunder-boot-emmc.dtsi (100%) rename arch/{arm64/boot/dts/rockchip => arm/boot/dts}/rv1126b-thunder-boot-spi-nor.dtsi (100%) rename arch/{arm64/boot/dts/rockchip => arm/boot/dts}/rv1126b-thunder-boot.dtsi (98%) diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile index 0d4ae6d03e16..102fa9e6b3ae 100644 --- a/arch/arm/boot/dts/Makefile +++ b/arch/arm/boot/dts/Makefile @@ -1189,7 +1189,7 @@ dtb-$(CONFIG_ARCH_ROCKCHIP) += \ rv1126b-evb2-v10-mcu-k350c4516t.dtb \ rv1126b-evb2-v10-rgb-Q7050ITH2641AA1T.dtb \ rv1126b-evb2-v10-sii9022-bt1120-to-hdmi.dtb \ - rv1126b-evb2-v10-tb-400w.dtb \ + rv1126b-evb2-v10-tb-400w-spi-nor.dtb \ rv1126b-evb3-v10.dtb \ rv1126b-evb4-v10.dtb \ rv1126b-iotest-v10.dtb \ diff --git a/arch/arm64/boot/dts/rockchip/rv1126b-evb2-v10-tb-400w.dts b/arch/arm/boot/dts/rv1126b-evb2-v10-tb-400w-spi-nor.dts similarity index 79% rename from arch/arm64/boot/dts/rockchip/rv1126b-evb2-v10-tb-400w.dts rename to arch/arm/boot/dts/rv1126b-evb2-v10-tb-400w-spi-nor.dts index c1ba05974b77..ad9c331b2226 100644 --- a/arch/arm64/boot/dts/rockchip/rv1126b-evb2-v10-tb-400w.dts +++ b/arch/arm/boot/dts/rv1126b-evb2-v10-tb-400w-spi-nor.dts @@ -4,15 +4,15 @@ */ /dts-v1/; -#include "rv1126b.dtsi" -#include "rv1126b-evb.dtsi" -#include "rv1126b-evb2-v10.dtsi" +#include "arm64/rockchip/rv1126b.dtsi" +#include "arm64/rockchip/rv1126b-evb.dtsi" +#include "arm64/rockchip/rv1126b-evb2-v10.dtsi" #include "rv1126b-thunder-boot-cam.dtsi" #include "rv1126b-thunder-boot-spi-nor.dtsi" / { - model = "Rockchip RV1126B EVB2 V10 ARM64 TB 400W Board"; - compatible = "rockchip,rv1126b-evb2-v10-tb-400w", "rockchip,rv1126b"; + model = "Rockchip RV1126B EVB2 V10 TB 400W SPI NorFlash Board"; + compatible = "rockchip,rv1126b-evb2-v10-tb-400w-spi-nor", "rockchip,rv1126b"; chosen { bootargs = "loglevel=0 initcall_nr_threads=-1 initcall_debug=0 earlycon=uart8250,mmio32,0x20810000 console=ttyFIQ0 root=/dev/rd0 rootfstype=erofs rootflags=dax snd_soc_core.prealloc_buffer_size_kbytes=16 coherent_pool=32K"; @@ -28,7 +28,6 @@ sc450ai: sc450ai@30 { compatible = "smartsens,sc450ai"; - status = "okay"; reg = <0x30>; clocks = <&cru CLK_MIPI0_OUT2IO>; clock-names = "xvclk"; @@ -50,11 +49,11 @@ }; &ramdisk_r { - reg = <0x48c40000 (40 * 0x00100000)>; + reg = <0x48c40000 (30 * 0x00100000)>; }; &ramdisk_c { - reg = <0x4b440000 (20 * 0x00100000)>; + reg = <0x4aa40000 (20 * 0x00100000)>; }; &rkisp_thunderboot { diff --git a/arch/arm/boot/dts/rv1126b-evb2-v10-tb-400w.dts b/arch/arm/boot/dts/rv1126b-evb2-v10-tb-400w.dts deleted file mode 100644 index 5d1bfda82ece..000000000000 --- a/arch/arm/boot/dts/rv1126b-evb2-v10-tb-400w.dts +++ /dev/null @@ -1,19 +0,0 @@ -// SPDX-License-Identifier: (GPL-2.0+ OR MIT) -/* - * Copyright (c) 2025 Rockchip Electronics Co., Ltd. - */ - -#include "arm64/rockchip/rv1126b-evb2-v10-tb-400w.dts" - -/ { - model = "Rockchip RV1126B EVB2 V10 TB 400W Board"; - compatible = "rockchip,rv1126b-evb2-v10-tb-400w", "rockchip,rv1126b"; -}; - -&ramdisk_r { - reg = <0x48c40000 (30 * 0x00100000)>; -}; - -&ramdisk_c { - reg = <0x4aa40000 (20 * 0x00100000)>; -}; diff --git a/arch/arm64/boot/dts/rockchip/rv1126b-thunder-boot-cam.dtsi b/arch/arm/boot/dts/rv1126b-thunder-boot-cam.dtsi similarity index 100% rename from arch/arm64/boot/dts/rockchip/rv1126b-thunder-boot-cam.dtsi rename to arch/arm/boot/dts/rv1126b-thunder-boot-cam.dtsi diff --git a/arch/arm64/boot/dts/rockchip/rv1126b-thunder-boot-emmc.dtsi b/arch/arm/boot/dts/rv1126b-thunder-boot-emmc.dtsi similarity index 100% rename from arch/arm64/boot/dts/rockchip/rv1126b-thunder-boot-emmc.dtsi rename to arch/arm/boot/dts/rv1126b-thunder-boot-emmc.dtsi diff --git a/arch/arm64/boot/dts/rockchip/rv1126b-thunder-boot-spi-nor.dtsi b/arch/arm/boot/dts/rv1126b-thunder-boot-spi-nor.dtsi similarity index 100% rename from arch/arm64/boot/dts/rockchip/rv1126b-thunder-boot-spi-nor.dtsi rename to arch/arm/boot/dts/rv1126b-thunder-boot-spi-nor.dtsi diff --git a/arch/arm64/boot/dts/rockchip/rv1126b-thunder-boot.dtsi b/arch/arm/boot/dts/rv1126b-thunder-boot.dtsi similarity index 98% rename from arch/arm64/boot/dts/rockchip/rv1126b-thunder-boot.dtsi rename to arch/arm/boot/dts/rv1126b-thunder-boot.dtsi index 3c7d15df6207..b66d0d5f6d18 100644 --- a/arch/arm64/boot/dts/rockchip/rv1126b-thunder-boot.dtsi +++ b/arch/arm/boot/dts/rv1126b-thunder-boot.dtsi @@ -116,7 +116,7 @@ }; rtos: rtos@48c00000 { - reg = <0x48c00000 0x0003a000>; + reg = <0x48c00000 0x0003c000>; }; mcu_log: mcu_log@48c3c000 { From 6eae8a814726753bb6e1444f8f32b4eebe82a35d Mon Sep 17 00:00:00 2001 From: Ziyuan Xu Date: Thu, 10 Jul 2025 10:49:22 +0800 Subject: [PATCH 05/23] ARM: dts: rockchip: Add rv1126b-evb2-v10-tb-400w-emmc support Signed-off-by: Ziyuan Xu Change-Id: I082c03df1339eb92ce76af5da9534221ca3cf9b2 --- arch/arm/boot/dts/Makefile | 1 + .../dts/rv1126b-evb2-v10-tb-400w-emmc.dts | 81 +++++++++++++++++++ 2 files changed, 82 insertions(+) create mode 100644 arch/arm/boot/dts/rv1126b-evb2-v10-tb-400w-emmc.dts diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile index 102fa9e6b3ae..296dd3b9d0ef 100644 --- a/arch/arm/boot/dts/Makefile +++ b/arch/arm/boot/dts/Makefile @@ -1189,6 +1189,7 @@ dtb-$(CONFIG_ARCH_ROCKCHIP) += \ rv1126b-evb2-v10-mcu-k350c4516t.dtb \ rv1126b-evb2-v10-rgb-Q7050ITH2641AA1T.dtb \ rv1126b-evb2-v10-sii9022-bt1120-to-hdmi.dtb \ + rv1126b-evb2-v10-tb-400w-emmc.dtb \ rv1126b-evb2-v10-tb-400w-spi-nor.dtb \ rv1126b-evb3-v10.dtb \ rv1126b-evb4-v10.dtb \ diff --git a/arch/arm/boot/dts/rv1126b-evb2-v10-tb-400w-emmc.dts b/arch/arm/boot/dts/rv1126b-evb2-v10-tb-400w-emmc.dts new file mode 100644 index 000000000000..105bdd87ad4b --- /dev/null +++ b/arch/arm/boot/dts/rv1126b-evb2-v10-tb-400w-emmc.dts @@ -0,0 +1,81 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright (c) 2025 Rockchip Electronics Co., Ltd. + */ + +/dts-v1/; +#include "arm64/rockchip/rv1126b.dtsi" +#include "arm64/rockchip/rv1126b-evb.dtsi" +#include "arm64/rockchip/rv1126b-evb2-v10.dtsi" +#include "rv1126b-thunder-boot-cam.dtsi" +#include "rv1126b-thunder-boot-emmc.dtsi" + +/ { + model = "Rockchip RV1126B EVB2 V10 TB 400W eMMC Board"; + compatible = "rockchip,rv1126b-evb2-v10-tb-400w-emmc", "rockchip,rv1126b"; + + chosen { + bootargs = "loglevel=0 initcall_nr_threads=-1 initcall_debug=0 earlycon=uart8250,mmio32,0x20810000 console=ttyFIQ0 root=/dev/rd0 rootfstype=erofs rootflags=dax snd_soc_core.prealloc_buffer_size_kbytes=16 coherent_pool=32K"; + }; +}; + +&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 = "disabled"; +}; + +&i2c3 { + clock-frequency = <400000>; + pinctrl-names = "default"; + pinctrl-0 = <&i2c3m1_pins>; + rockchip,amp-shared; + status = "okay"; + + sc450ai: sc450ai@30 { + compatible = "smartsens,sc450ai"; + reg = <0x30>; + clocks = <&cru CLK_MIPI0_OUT2IO>; + clock-names = "xvclk"; + reset-gpios = <&gpio4 RK_PA7 GPIO_ACTIVE_LOW>; + pwdn-gpios = <&gpio4 RK_PA2 GPIO_ACTIVE_HIGH>; + pinctrl-names = "default"; + pinctrl-0 = <&cam_clk0_pins>; + rockchip,camera-module-index = <0>; + rockchip,camera-module-facing = "back"; + rockchip,camera-module-name = "default"; + rockchip,camera-module-lens-name = "default"; + port { + cam0_out: endpoint { + remote-endpoint = <&csi_dphy_input0>; + data-lanes = <1 2 3 4>; + }; + }; + }; +}; + +&ramdisk_r { + reg = <0x48c40000 (60 * 0x00100000)>; +}; + +&ramdisk_c { + reg = <0x4c840000 (30 * 0x00100000)>; +}; + +&rkisp_thunderboot { + /* reg's offset MUST match with RTOS */ + /* + * vicap, capture raw10, ceil(w*10/8/256)*256*h *4(buf num) + * e.g. 2688x1520: 0x14c8000 + */ + reg = <0x41320000 0x14c8000>; +}; From 02ac4cc230552fa2191fe153c7af6f2c6415c624 Mon Sep 17 00:00:00 2001 From: Shengfei Xu Date: Fri, 11 Jul 2025 10:22:09 +0800 Subject: [PATCH 06/23] power: supply: rockchip-charger-manager: Resolving charging anomalies For devices without a charge pump inserted into a PPS charger, they must be treated directly as PD chargers. Change-Id: Ib39dcd5e6842f5cefb00c1a76fbef8ccbee06ab1 Signed-off-by: Shengfei Xu --- .../power/supply/rockchip_charger_manager.c | 28 +++++++++++-------- 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/drivers/power/supply/rockchip_charger_manager.c b/drivers/power/supply/rockchip_charger_manager.c index f7b1a4ef8c6c..5fd2e0f5ffd2 100644 --- a/drivers/power/supply/rockchip_charger_manager.c +++ b/drivers/power/supply/rockchip_charger_manager.c @@ -2409,7 +2409,7 @@ static int cm_normal_adapter_det(struct charger_manager *cm) fc_config = cm->fc_config; fc_config->adaper_power_init_flag = 0; - cm->is_normal_charge = false; + cm->is_normal_charge = true; cm->is_fast_charge = false; cm->is_pps_charge = false; @@ -2561,6 +2561,15 @@ static int charger_extcon_notifier(struct notifier_block *self, return ret; } switch (val.intval) { + case POWER_SUPPLY_USB_TYPE_PD_PPS: + if ((!cm->is_pps_charge) && (desc->psy_charger_pump_stat)) { + ret = cm_pps_adapter_det(cm); + if (ret) + return NOTIFY_BAD; + CM_DBG("USB-TYPE: POWER_SUPPLY_USB_TYPE_PD\n"); + break; + } + fallthrough; case POWER_SUPPLY_USB_TYPE_PD: if (!cm->is_pps_charge && !cm->is_pd_charge) { ret = cm_pd_adapter_det(cm); @@ -2569,14 +2578,6 @@ static int charger_extcon_notifier(struct notifier_block *self, return NOTIFY_BAD; } break; - case POWER_SUPPLY_USB_TYPE_PD_PPS: - if (!cm->is_pps_charge) { - ret = cm_pps_adapter_det(cm); - if (ret) - return NOTIFY_BAD; - CM_DBG("USB-TYPE: POWER_SUPPLY_USB_TYPE_PD\n"); - } - break; default: if (!cm->is_pps_charge && !cm->is_pd_charge && !cm->is_normal_charge) { ret = cm_normal_adapter_det(cm); @@ -2586,7 +2587,8 @@ static int charger_extcon_notifier(struct notifier_block *self, break; } - if (val.intval != POWER_SUPPLY_USB_TYPE_PD_PPS) { + if ((val.intval != POWER_SUPPLY_USB_TYPE_PD_PPS) || + (!desc->psy_charger_pump_stat)) { if (cm->fc_config->jeita_charge_support) { cancel_delayed_work(&cm->cm_jeita_work); queue_delayed_work(cm->cm_wq, &cm->cm_jeita_work, 0); @@ -2631,9 +2633,11 @@ static void cm_pd_work(struct work_struct *work) switch (usb_type) { case POWER_SUPPLY_USB_TYPE_PD_PPS: CM_DBG("POWER_SUPPLY_USB_TYPE_PD_PPS\n"); - if (!cm->is_pps_charge) + if ((!cm->is_pps_charge) && (desc->psy_charger_pump_stat)) { cm_pps_adapter_det(cm); - break; + break; + } + fallthrough; case POWER_SUPPLY_USB_TYPE_PD: CM_DBG("POWER_SUPPLY_USB_TYPE_PD\n"); power_supply_get_property(desc->tcpm_psy, From 87a53f1122f6f73c74a73c2ffe8b411936d0b258 Mon Sep 17 00:00:00 2001 From: Zefa Chen Date: Fri, 4 Jul 2025 15:59:06 +0800 Subject: [PATCH 07/23] media: rockchip: vicap fixes error triggrer of fs/fe not match when monitor mode enable Change-Id: I4fa5502064f6a589a87a9e675d00bd0d237a839d Signed-off-by: Zefa Chen --- drivers/media/platform/rockchip/cif/capture.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/media/platform/rockchip/cif/capture.c b/drivers/media/platform/rockchip/cif/capture.c index 4da7b20ffd6d..8732d609079b 100644 --- a/drivers/media/platform/rockchip/cif/capture.c +++ b/drivers/media/platform/rockchip/cif/capture.c @@ -11086,7 +11086,8 @@ static bool rkcif_is_csi2_err_trigger_reset(struct rkcif_timer *timer) * or fs and fe had been not paired. */ if (stream->is_fs_fe_not_paired || - stream->fs_cnt_in_single_frame > RKCIF_FS_DETECTED_NUM) { + (stream->fs_cnt_in_single_frame > RKCIF_FS_DETECTED_NUM && + dev->chip_id < CHIP_RK3588_CIF)) { is_triggered = true; v4l2_info(&dev->v4l2_dev, "reset for fs & fe not paired\n"); } @@ -13968,9 +13969,6 @@ static void rkcif_deal_sof(struct rkcif_device *cif_dev) RKISP_VICAP_CMD_SOF, &sof); } - if (cif_dev->chip_id < CHIP_RK3588_CIF) - detect_stream->fs_cnt_in_single_frame++; - if (cif_dev->sditf[0] && cif_dev->sditf[0]->mode.rdbk_mode >= RKISP_VICAP_RDBK_AIQ && (!detect_stream->dma_en) && cif_dev->chip_id < CHIP_RK3576_CIF) From 383d30e79b5b046a4a44ea3866353d8fdb11c763 Mon Sep 17 00:00:00 2001 From: Zefa Chen Date: Mon, 23 Sep 2024 17:02:08 +0800 Subject: [PATCH 08/23] media: rockchip: vicap support "cat /proc/rkcif*" to show mipi csi2 error info Signed-off-by: Zefa Chen Change-Id: Ida097baabb2ab239289c6910ca59ad88203c4fe0 --- .../media/platform/rockchip/cif/mipi-csi2.c | 25 ++++++++++++++++--- .../media/platform/rockchip/cif/mipi-csi2.h | 4 +++ drivers/media/platform/rockchip/cif/procfs.c | 24 ++++++++++++++++++ 3 files changed, 50 insertions(+), 3 deletions(-) diff --git a/drivers/media/platform/rockchip/cif/mipi-csi2.c b/drivers/media/platform/rockchip/cif/mipi-csi2.c index bc74726c94c1..8258dfd669a2 100644 --- a/drivers/media/platform/rockchip/cif/mipi-csi2.c +++ b/drivers/media/platform/rockchip/cif/mipi-csi2.c @@ -282,6 +282,8 @@ static int csi2_start(struct csi2_dev *csi2) else host_type = RK_CSI_RXHOST; + csi2->irq1_timestamp = 0; + csi2->irq2_timestamp = 0; for (i = 0; i < csi2->csi_info.csi_num; i++) { csi_idx = csi2->csi_info.csi_idx[i]; ret |= csi2_hw_start(csi2->csi2_hw[csi_idx], host_type); @@ -840,6 +842,7 @@ static irqreturn_t rk_csirx_irq1_handler(int irq, void *ctx) char cur_str[CSI_ERRSTR_LEN] = {0}; char vc_info[CSI_VCINFO_LEN] = {0}; bool is_add_cnt = false; + u64 cur_timestamp = ktime_get_ns(); if (!csi2_hw) { disable_irq_nosync(irq); @@ -912,7 +915,7 @@ static irqreturn_t rk_csirx_irq1_handler(int irq, void *ctx) } if (val & CSIHOST_ERR1_ERR_ECC2) { - err_list = &csi2->err_list[RK_CSI2_ERR_CRC]; + err_list = &csi2->err_list[RK_CSI2_ERR_ECC2]; err_list->cnt++; is_add_cnt = true; snprintf(cur_str, CSI_ERRSTR_LEN, "(ecc2) "); @@ -920,12 +923,17 @@ static irqreturn_t rk_csirx_irq1_handler(int irq, void *ctx) } if (val & CSIHOST_ERR1_ERR_CTRL) { + err_list = &csi2->err_list[RK_CSI2_ERR_CTRL]; + err_list->cnt++; csi2_find_err_vc((val >> 16) & 0xf, vc_info); snprintf(cur_str, CSI_ERRSTR_LEN, "(ctrl,vc:%s) ", vc_info); csi2_err_strncat(err_str, cur_str); } - pr_err("(0x%x)MIPI_CSI2 ERR1:0x%x %s\n", (u32)csi2_hw->res->start, val, err_str); + if (csi2->irq1_timestamp == 0 || cur_timestamp - csi2->irq1_timestamp > 1000000000) { + csi2->irq1_timestamp = cur_timestamp; + pr_err("(0x%x)MIPI_CSI2 ERR1:0x%x %s\n", (u32)csi2_hw->res->start, val, err_str); + } if (is_add_cnt) { csi2->err_list[RK_CSI2_ERR_ALL].cnt++; @@ -946,16 +954,24 @@ static irqreturn_t rk_csirx_irq2_handler(int irq, void *ctx) { struct device *dev = ctx; struct csi2_hw *csi2_hw = dev_get_drvdata(dev); + struct csi2_dev *csi2 = NULL; u32 val; char cur_str[CSI_ERRSTR_LEN] = {0}; char err_str[CSI_ERRSTR_LEN] = {0}; char vc_info[CSI_VCINFO_LEN] = {0}; + u64 cur_timestamp = ktime_get_ns(); if (!csi2_hw) { disable_irq_nosync(irq); return IRQ_HANDLED; } + csi2 = csi2_hw->csi2; + if (!csi2) { + disable_irq_nosync(irq); + return IRQ_HANDLED; + } + val = read_csihost_reg(csi2_hw->base, CSIHOST_ERR2); if (val) { if (val & CSIHOST_ERR2_PHYERR_ESC) { @@ -983,7 +999,10 @@ static irqreturn_t rk_csirx_irq2_handler(int irq, void *ctx) csi2_err_strncat(err_str, cur_str); } - pr_err("(0x%x)MIPI_CSI2 ERR2:0x%x %s\n", (u32)csi2_hw->res->start, val, err_str); + if (csi2->irq2_timestamp == 0 || cur_timestamp - csi2->irq2_timestamp > 1000000000) { + csi2->irq2_timestamp = cur_timestamp; + pr_err("(0x%x)MIPI_CSI2 ERR2:0x%x %s\n", (u32)csi2_hw->res->start, val, err_str); + } } return IRQ_HANDLED; diff --git a/drivers/media/platform/rockchip/cif/mipi-csi2.h b/drivers/media/platform/rockchip/cif/mipi-csi2.h index 026b48ff552f..93c4bc3fbc9b 100644 --- a/drivers/media/platform/rockchip/cif/mipi-csi2.h +++ b/drivers/media/platform/rockchip/cif/mipi-csi2.h @@ -113,6 +113,8 @@ enum csi2_err { RK_CSI2_ERR_FRM_SEQ_ERR, RK_CSI2_ERR_CRC_ONCE, RK_CSI2_ERR_CRC, + RK_CSI2_ERR_ECC2, + RK_CSI2_ERR_CTRL, RK_CSI2_ERR_ALL, RK_CSI2_ERR_MAX }; @@ -176,6 +178,8 @@ struct csi2_dev { struct rkcif_csi_info csi_info; const char *dev_name; int sw_dbg; + u64 irq1_timestamp; + u64 irq2_timestamp; }; struct csi2_hw { diff --git a/drivers/media/platform/rockchip/cif/procfs.c b/drivers/media/platform/rockchip/cif/procfs.c index 1956020b1f75..6122ab4ff2c8 100644 --- a/drivers/media/platform/rockchip/cif/procfs.c +++ b/drivers/media/platform/rockchip/cif/procfs.c @@ -526,6 +526,27 @@ static void rkcif_show_reg_dbg(struct rkcif_device *dev, struct seq_file *f) } } +static void rkcif_show_mipi_csi2_error_info(struct rkcif_device *dev, struct seq_file *f) +{ + struct csi2_dev *csi2 = container_of(dev->active_sensor->sd, struct csi2_dev, sd); + + seq_puts(f, "\nMipi error info:\n"); + seq_printf(f, "\terr sot sync:%u\n", + csi2->err_list[RK_CSI2_ERR_SOTSYN].cnt); + seq_printf(f, "\terr fs/fe not match:%u\n", + csi2->err_list[RK_CSI2_ERR_FS_FE_MIS].cnt); + seq_printf(f, "\terr frm seq:%u\n", + csi2->err_list[RK_CSI2_ERR_FRM_SEQ_ERR].cnt); + seq_printf(f, "\terr crc once:%u\n", + csi2->err_list[RK_CSI2_ERR_CRC_ONCE].cnt); + seq_printf(f, "\terr crc:%u\n", + csi2->err_list[RK_CSI2_ERR_CRC].cnt); + seq_printf(f, "\terr ecc2:%u\n", + csi2->err_list[RK_CSI2_ERR_ECC2].cnt); + seq_printf(f, "\terr ctrl:%u\n", + csi2->err_list[RK_CSI2_ERR_CTRL].cnt); +} + static void rkcif_show_format(struct rkcif_device *dev, struct seq_file *f) { struct rkcif_stream *stream = &dev->stream[0]; @@ -676,6 +697,9 @@ static void rkcif_show_format(struct rkcif_device *dev, struct seq_file *f) rkcif_show_toisp_info(dev, f); if (dev->reg_dbg) rkcif_show_reg_dbg(dev, f); + if (sensor->mbus.type == V4L2_MBUS_CSI2_DPHY || + sensor->mbus.type == V4L2_MBUS_CSI2_CPHY) + rkcif_show_mipi_csi2_error_info(dev, f); } } From 39a230accf76f15d93bb9b0f27e4be1413077f25 Mon Sep 17 00:00:00 2001 From: Yu Zheng Date: Fri, 11 Apr 2025 14:46:21 +0800 Subject: [PATCH 09/23] arm64: dts: rockchip: add rv1126b-evb2-v10-dv Signed-off-by: Yu Zheng Change-Id: I8ef95e04879741ccbf44573fe62020638beb8002 --- arch/arm64/boot/dts/rockchip/Makefile | 1 + .../boot/dts/rockchip/rv1126b-evb2-v10-dv.dts | 91 +++++++++++++++++++ 2 files changed, 92 insertions(+) create mode 100644 arch/arm64/boot/dts/rockchip/rv1126b-evb2-v10-dv.dts diff --git a/arch/arm64/boot/dts/rockchip/Makefile b/arch/arm64/boot/dts/rockchip/Makefile index 589b1b6a4931..5f5f1fed4985 100644 --- a/arch/arm64/boot/dts/rockchip/Makefile +++ b/arch/arm64/boot/dts/rockchip/Makefile @@ -388,6 +388,7 @@ dtb-$(CONFIG_ARCH_ROCKCHIP) += rv1126b-evb1-v11.dtb dtb-$(CONFIG_ARCH_ROCKCHIP) += rv1126b-evb1-v11-dual-4k.dtb dtb-$(CONFIG_ARCH_ROCKCHIP) += rv1126b-evb2-v10.dtb dtb-$(CONFIG_ARCH_ROCKCHIP) += rv1126b-evb2-v10-aov-dual-cam.dtb +dtb-$(CONFIG_ARCH_ROCKCHIP) += rv1126b-evb2-v10-dv.dtb dtb-$(CONFIG_ARCH_ROCKCHIP) += rv1126b-evb2-v10-mcu-k350c4516t.dtb dtb-$(CONFIG_ARCH_ROCKCHIP) += rv1126b-evb2-v10-rgb-Q7050ITH2641AA1T.dtb dtb-$(CONFIG_ARCH_ROCKCHIP) += rv1126b-evb2-v10-sii9022-bt1120-to-hdmi.dtb diff --git a/arch/arm64/boot/dts/rockchip/rv1126b-evb2-v10-dv.dts b/arch/arm64/boot/dts/rockchip/rv1126b-evb2-v10-dv.dts new file mode 100644 index 000000000000..ae0f9e4f4f10 --- /dev/null +++ b/arch/arm64/boot/dts/rockchip/rv1126b-evb2-v10-dv.dts @@ -0,0 +1,91 @@ +// 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-evb2-v10.dtsi" +#include "rv1126b-evb-cam-csi0.dtsi" + +/ { + model = "Rockchip RV1126B EVB1 V10 DV Board"; + compatible = "rockchip,rv1126b-evb2-v10-dv", "rockchip,rv1126b"; + chosen { + bootargs = "earlycon=uart8250,mmio32,0x20810000 console=ttyFIQ0 rw root=PARTUUID=614e0000-0000 rootfstype=ext4 rootwait snd_soc_core.prealloc_buffer_size_kbytes=16 coherent_pool=32K isolcpus=3 nohz_full=3"; + }; +}; + +&gc8613 { + reset-gpios = <&gpio4 RK_PA7 GPIO_ACTIVE_LOW>; + /delete-property/ pwdn-gpios; +}; + +&gpio5 { + interrupt-affinity = <&cpu0>, <&cpu0>, <&cpu0>, <&cpu3>; + interrupt-pins = <0>, + <0>, + <0>, + ; +}; + +&imx415 { + reset-gpios = <&gpio4 RK_PA7 GPIO_ACTIVE_HIGH>; +}; + +&imx586 { + reset-gpios = <&gpio4 RK_PA7 GPIO_ACTIVE_LOW>; +}; + +&pinctrl { + inv { + inv_int1: inv-int1 { + rockchip,pins = + <5 RK_PB0 RK_FUNC_GPIO &pcfg_pull_up>; + }; + }; +}; + +&rkfec { + status = "okay"; +}; + +&rkfec_mmu { + status = "okay"; +}; + +&rknpu { + status = "disabled"; +}; + +&sc450ai { + reset-gpios = <&gpio4 RK_PA7 GPIO_ACTIVE_LOW>; +}; + +&sc850sl { + reset-gpios = <&gpio4 RK_PA7 GPIO_ACTIVE_HIGH>; +}; + +&spi0 { + status = "okay"; + max-freq = <24000000>; + pinctrl-names = "default"; + pinctrl-0 = <&spi0m2_clk_pins &spi0m2_csn0_pins &inv_int1>; + icm42670: icm42670@0 { + compatible = "invensense,icm42670"; + reg = <0x0>; + spi-max-frequency = <24000000>; + spi-cpha; + spi-cpol; + //vdd-supply = <&vcc_3v3_s0>; + int1-gpio = <&gpio5 RK_PB0 GPIO_ACTIVE_HIGH>; + interrupt-parent = <&gpio5>; + interrupts = <8 IRQ_TYPE_EDGE_FALLING>; + status = "okay"; + }; +}; + +&uart2 { + status = "disabled"; +}; From dce355282db256c1f7e17b33b8c0befcf640c5fd Mon Sep 17 00:00:00 2001 From: Yu Zheng Date: Fri, 11 Jul 2025 15:42:41 +0800 Subject: [PATCH 10/23] ARM: dts: rockchip: add rv1126b-evb2-v10-dv Signed-off-by: Yu Zheng Change-Id: Ibf7ffb7f1acb6487dfec038d8174211c4f74d7a5 --- arch/arm/boot/dts/Makefile | 1 + arch/arm/boot/dts/rv1126b-evb2-v10-dv.dts | 6 ++++++ 2 files changed, 7 insertions(+) create mode 100644 arch/arm/boot/dts/rv1126b-evb2-v10-dv.dts diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile index 296dd3b9d0ef..8b2ff82971de 100644 --- a/arch/arm/boot/dts/Makefile +++ b/arch/arm/boot/dts/Makefile @@ -1186,6 +1186,7 @@ dtb-$(CONFIG_ARCH_ROCKCHIP) += \ rv1126b-evb1-v11.dtb \ rv1126b-evb1-v11-dual-4k.dtb \ rv1126b-evb2-v10.dtb \ + rv1126b-evb2-v10-dv.dtb \ rv1126b-evb2-v10-mcu-k350c4516t.dtb \ rv1126b-evb2-v10-rgb-Q7050ITH2641AA1T.dtb \ rv1126b-evb2-v10-sii9022-bt1120-to-hdmi.dtb \ diff --git a/arch/arm/boot/dts/rv1126b-evb2-v10-dv.dts b/arch/arm/boot/dts/rv1126b-evb2-v10-dv.dts new file mode 100644 index 000000000000..7d841c2f5a2c --- /dev/null +++ b/arch/arm/boot/dts/rv1126b-evb2-v10-dv.dts @@ -0,0 +1,6 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright (c) 2025 Rockchip Electronics Co., Ltd. + */ + +#include "arm64/rockchip/rv1126b-evb2-v10-dv.dts" From 1d2414b4d1e80764d49db54f3dcef8c858e97afc Mon Sep 17 00:00:00 2001 From: Jianwei Zheng Date: Wed, 9 Jul 2025 09:45:32 +0800 Subject: [PATCH 11/23] usb: dwc2: platform: Fix dwc2 resume failed for RK3506 OTG1 The utmi iddig signal of RK3506 OTG1 is left floating by default. Even when the system is suspended and the logic is powered off, once the system resume and the clock is enabled, the controller's current mode will be set to Host mode by default, causing dwc2 fail to reinitialize. To resolve this issue, we found that the ForceHstMode bit in the GUSBCFG register returns to its default value of 0 after the logic is powered off. Once the logic power is restored, this bit does not automatically return to 1. Therefore, we can use this bit to determine whether the logic has been powered off when dr_mode is set to Host. Change-Id: I76c46c9ca7bb9f51f455a6835d3161a3edbeeebb Signed-off-by: Jianwei Zheng --- drivers/usb/dwc2/core.h | 5 +++++ drivers/usb/dwc2/platform.c | 3 ++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/usb/dwc2/core.h b/drivers/usb/dwc2/core.h index 4a4c28083ba6..660c91ccb6dc 100644 --- a/drivers/usb/dwc2/core.h +++ b/drivers/usb/dwc2/core.h @@ -1387,6 +1387,11 @@ static inline int dwc2_is_device_mode(struct dwc2_hsotg *hsotg) return (dwc2_readl(hsotg, GINTSTS) & GINTSTS_CURMODE_HOST) == 0; } +static inline int dwc2_is_force_host_mode(struct dwc2_hsotg *hsotg) +{ + return (dwc2_readl(hsotg, GUSBCFG) & GUSBCFG_FORCEHOSTMODE) != 0; +} + int dwc2_drd_init(struct dwc2_hsotg *hsotg); void dwc2_drd_suspend(struct dwc2_hsotg *hsotg); void dwc2_drd_resume(struct dwc2_hsotg *hsotg); diff --git a/drivers/usb/dwc2/platform.c b/drivers/usb/dwc2/platform.c index 598a4e64205d..fdb989e1068e 100644 --- a/drivers/usb/dwc2/platform.c +++ b/drivers/usb/dwc2/platform.c @@ -796,7 +796,8 @@ static int __maybe_unused dwc2_resume(struct device *dev) dwc2_drd_resume(dwc2); } - if (dwc2->dr_mode == USB_DR_MODE_HOST && dwc2_is_device_mode(dwc2)) { + if (dwc2->dr_mode == USB_DR_MODE_HOST && (dwc2_is_device_mode(dwc2) || + !dwc2_is_force_host_mode(dwc2))) { /* Reinit for Host mode if lost power */ dwc2_force_mode(dwc2, true); From 9a86c24f4d63a40b0f8b5937308ce47edae4137c Mon Sep 17 00:00:00 2001 From: Zefa Chen Date: Tue, 1 Jul 2025 15:23:04 +0800 Subject: [PATCH 12/23] media: i2c: os12d40 support set wbgain and blc Change-Id: I9068988f9712dcb47db51416c2906d8a0cfce0a2 Signed-off-by: Zefa Chen --- drivers/media/i2c/os12d40.c | 196 ++++++++++++++++++++++++++++++++++++ 1 file changed, 196 insertions(+) diff --git a/drivers/media/i2c/os12d40.c b/drivers/media/i2c/os12d40.c index 7eb784d0ed80..ce6687855461 100644 --- a/drivers/media/i2c/os12d40.c +++ b/drivers/media/i2c/os12d40.c @@ -181,6 +181,10 @@ struct os12d40 { const char *module_name; const char *len_name; struct rkmodule_awb_cfg awb_cfg; + bool has_init_wbgain; + bool has_init_blc; + struct rkmodule_wb_gain_group init_wbgain; + struct rkmodule_blc_group init_blc; }; #define to_os12d40(sd) container_of(sd, struct os12d40, subdev) @@ -2271,6 +2275,87 @@ static void os12d40_set_awb_cfg(struct os12d40 *os12d40, mutex_unlock(&os12d40->mutex); } +static int os12d40_set_wb_gain(struct os12d40 *os12d40, + struct rkmodule_wb_gain_group *wb_gain_group) +{ + struct rkmodule_wb_gain wb_gain; + u16 reg_bgain = 0, reg_gbgain = 0, reg_grgain = 0, reg_rgain = 0; + int ret = 0; +#ifdef DEBUG + u32 bgain = 0, gbgain = 0, grgain = 0, rgain = 0; +#endif + + if (!os12d40->has_init_wbgain && !os12d40->streaming) { + os12d40->init_wbgain = *wb_gain_group; + os12d40->has_init_wbgain = true; + dev_dbg(&os12d40->client->dev, "os12d40 don't stream, record wbgain!\n"); + return ret; + } + reg_bgain = 0x7000; + reg_gbgain = 0x7002; + reg_grgain = 0x7004; + reg_rgain = 0x7006; + wb_gain = wb_gain_group->wb_gain[0]; + ret = os12d40_write_reg(os12d40->client, reg_bgain, + OS12D40_REG_VALUE_16BIT, wb_gain.b_gain & 0xffff); + ret |= os12d40_write_reg(os12d40->client, reg_grgain, + OS12D40_REG_VALUE_16BIT, wb_gain.gr_gain & 0xffff); + ret |= os12d40_write_reg(os12d40->client, reg_gbgain, + OS12D40_REG_VALUE_16BIT, wb_gain.gb_gain & 0xffff); + ret |= os12d40_write_reg(os12d40->client, reg_rgain, + OS12D40_REG_VALUE_16BIT, wb_gain.r_gain & 0xffff); + dev_info(&os12d40->client->dev, + "write wb gain, type:%d, b:0x%x, gb:0x%x, gr:0x%x, r:0x%x\n", + wb_gain_group->wb_gain_type[0], + wb_gain.b_gain, wb_gain.gb_gain, + wb_gain.gr_gain, wb_gain.r_gain); +#ifdef DEBUG + ret |= os12d40_read_reg(os12d40->client, reg_bgain, + OS12D40_REG_VALUE_16BIT, &bgain); + ret |= os12d40_read_reg(os12d40->client, reg_gbgain, + OS12D40_REG_VALUE_16BIT, &gbgain); + ret |= os12d40_read_reg(os12d40->client, reg_grgain, + OS12D40_REG_VALUE_16BIT, &grgain); + ret |= os12d40_read_reg(os12d40->client, reg_rgain, + OS12D40_REG_VALUE_16BIT, &rgain); + dev_info(&os12d40->client->dev, + "read wb gain, type %d, b:0x%x, gb:0x%x, gr:0x%x, r:0x%x\n", + wb_gain_group->wb_gain_type[0], bgain, gbgain, grgain, rgain); +#endif + return ret; +} + +static int os12d40_set_blc(struct os12d40 *os12d40, + struct rkmodule_blc_group *blc_group) +{ + u32 reg_blc = 0; + u32 blc_val = 0; + int ret = 0; + + if (!os12d40->has_init_blc && !os12d40->streaming) { + os12d40->init_blc = *blc_group; + os12d40->has_init_blc = true; + dev_dbg(&os12d40->client->dev, "os12d40 don't stream, record blc!\n"); + return ret; + } + reg_blc = 0x4019; + blc_val = blc_group->blc[0]; + ret = os12d40_write_reg(os12d40->client, reg_blc, + OS12D40_REG_VALUE_16BIT, blc_val & 0x3ff); + dev_info(&os12d40->client->dev, + "write blc, type:%d, blc_val:0x%x\n", + blc_group->blc_type[0], + blc_val); +#ifdef DEBUG + ret |= os12d40_read_reg(os12d40->client, reg_blc, + OS12D40_REG_VALUE_16BIT, &blc_val); + dev_info(&os12d40->client->dev, + "read blc, type %d, blc_val:0x%x\n", + blc_group->blc_type[0], blc_val); +#endif + return ret; +} + static long os12d40_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg) { struct os12d40 *os12d40 = to_os12d40(sd); @@ -2278,6 +2363,10 @@ static long os12d40_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg) long ret = 0; u32 stream = 0; u32 *bayer_mode; + struct rkmodule_wb_gain_info *wb_gain_info; + struct rkmodule_blc_info *blc_info; + struct rkmodule_wb_gain_group *wb_gain_group; + struct rkmodule_blc_group *blc_group; switch (cmd) { case RKMODULE_GET_MODULE_INFO: @@ -2318,6 +2407,23 @@ static long os12d40_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg) *bayer_mode = RKMODULE_NORMAL_BAYER; #endif break; + case RKMODULE_GET_WB_GAIN_INFO: + wb_gain_info = (struct rkmodule_wb_gain_info *)arg; + wb_gain_info->coarse_bit = 5; + wb_gain_info->fine_bit = 10; + break; + case RKMODULE_GET_BLC_INFO: + blc_info = (struct rkmodule_blc_info *)arg; + blc_info->bit_width = 10; + break; + case RKMODULE_SET_WB_GAIN: + wb_gain_group = (struct rkmodule_wb_gain_group *)arg; + ret = os12d40_set_wb_gain(os12d40, wb_gain_group); + break; + case RKMODULE_SET_BLC: + blc_group = (struct rkmodule_blc_group *)arg; + ret = os12d40_set_blc(os12d40, blc_group); + break; default: ret = -ENOIOCTLCMD; break; @@ -2337,6 +2443,10 @@ static long os12d40_compat_ioctl32(struct v4l2_subdev *sd, long ret; u32 stream = 0; u32 bayer_mode = 0; + struct rkmodule_wb_gain_info *wb_gain_info; + struct rkmodule_blc_info *blc_info; + struct rkmodule_wb_gain_group *wb_gain_group; + struct rkmodule_blc_group *blc_group; switch (cmd) { case RKMODULE_GET_MODULE_INFO: @@ -2413,6 +2523,68 @@ static long os12d40_compat_ioctl32(struct v4l2_subdev *sd, return -EFAULT; } break; + case RKMODULE_GET_WB_GAIN_INFO: + wb_gain_info = kzalloc(sizeof(*wb_gain_info), GFP_KERNEL); + if (!wb_gain_info) { + ret = -ENOMEM; + return ret; + } + + ret = os12d40_ioctl(sd, cmd, wb_gain_info); + if (!ret) { + if (copy_to_user(up, wb_gain_info, sizeof(*wb_gain_info))) { + kfree(wb_gain_info); + return -EFAULT; + } + } + kfree(wb_gain_info); + break; + case RKMODULE_GET_BLC_INFO: + blc_info = kzalloc(sizeof(*blc_info), GFP_KERNEL); + if (!blc_info) { + ret = -ENOMEM; + return ret; + } + + ret = os12d40_ioctl(sd, cmd, blc_info); + if (!ret) { + if (copy_to_user(up, blc_info, sizeof(*blc_info))) { + kfree(blc_info); + return -EFAULT; + } + } + kfree(blc_info); + break; + case RKMODULE_SET_WB_GAIN: + wb_gain_group = kzalloc(sizeof(*wb_gain_group), GFP_KERNEL); + if (!wb_gain_group) { + ret = -ENOMEM; + return ret; + } + + ret = os12d40_ioctl(sd, cmd, wb_gain_group); + if (!ret) { + ret = copy_to_user(up, wb_gain_group, sizeof(*wb_gain_group)); + if (ret) + return -EFAULT; + } + kfree(wb_gain_group); + break; + case RKMODULE_SET_BLC: + blc_group = kzalloc(sizeof(*blc_group), GFP_KERNEL); + if (!blc_group) { + ret = -ENOMEM; + return ret; + } + + ret = os12d40_ioctl(sd, cmd, blc_group); + if (!ret) { + ret = copy_to_user(up, blc_group, sizeof(*blc_group)); + if (ret) + return -EFAULT; + } + kfree(blc_group); + break; default: ret = -ENOIOCTLCMD; break; @@ -2452,6 +2624,26 @@ static int __os12d40_start_stream(struct os12d40 *os12d40) if (ret) return ret; + if (os12d40->has_init_wbgain) { + ret = os12d40_ioctl(&os12d40->subdev, + RKMODULE_SET_WB_GAIN, + &os12d40->init_wbgain); + if (ret) { + dev_err(&os12d40->client->dev, + "init wbgain fail\n"); + return ret; + } + } + if (os12d40->has_init_blc) { + ret = os12d40_ioctl(&os12d40->subdev, + RKMODULE_SET_BLC, + &os12d40->init_blc); + if (ret) { + dev_err(&os12d40->client->dev, + "init blc fail\n"); + return ret; + } + } ret = os12d40_write_reg(os12d40->client, OS12D40_REG_CTRL_MODE, OS12D40_REG_VALUE_08BIT, OS12D40_MODE_STREAMING); return ret; @@ -2459,6 +2651,8 @@ static int __os12d40_start_stream(struct os12d40 *os12d40) static int __os12d40_stop_stream(struct os12d40 *os12d40) { + os12d40->has_init_wbgain = false; + os12d40->has_init_blc = false; return os12d40_write_reg(os12d40->client, OS12D40_REG_CTRL_MODE, OS12D40_REG_VALUE_08BIT, OS12D40_MODE_SW_STANDBY); } @@ -3001,6 +3195,8 @@ static int os12d40_initialize_controls(struct os12d40 *os12d40) } os12d40->subdev.ctrl_handler = handler; + os12d40->has_init_wbgain = false; + os12d40->has_init_blc = false; return 0; From e66c0f380bbddf0ac80f4dcb0e8d1705807fda43 Mon Sep 17 00:00:00 2001 From: Zefa Chen Date: Tue, 8 Jul 2025 09:09:42 +0800 Subject: [PATCH 13/23] media: rockchip: vicap support config complete frame of toisp Change-Id: I1bea6eb816acbd382f11650e7e736b6a0a65132c Signed-off-by: Zefa Chen --- drivers/media/platform/rockchip/cif/capture.c | 28 +++++++++++++------ drivers/media/platform/rockchip/cif/dev.c | 4 +++ drivers/media/platform/rockchip/cif/dev.h | 1 + 3 files changed, 24 insertions(+), 9 deletions(-) diff --git a/drivers/media/platform/rockchip/cif/capture.c b/drivers/media/platform/rockchip/cif/capture.c index 8732d609079b..ac6be26586bd 100644 --- a/drivers/media/platform/rockchip/cif/capture.c +++ b/drivers/media/platform/rockchip/cif/capture.c @@ -4763,9 +4763,9 @@ static int rkcif_csi_channel_set_v1(struct rkcif_stream *stream, return 0; } + val = rkcif_read_register(dev, CIF_REG_GLB_CTRL); if (stream->sw_dbg_en) { - rkcif_write_register_and(dev, CIF_REG_GLB_CTRL, - ~(u32)BIT(16)); + val &= ~BIT(16); v4l2_subdev_call(dev->active_sensor->sd, core, ioctl, RKCIF_CMD_SET_PPI_DATA_DEBUG, @@ -4776,18 +4776,23 @@ static int rkcif_csi_channel_set_v1(struct rkcif_stream *stream, RKCIF_CMD_SET_PPI_DATA_DEBUG, &stream->sw_dbg_en); } - if (dev->chip_id == CHIP_RK3588_CIF || dev->chip_id == CHIP_RV1106_CIF || dev->chip_id == CHIP_RK3562_CIF) { - val = GLB_RESET_IDI_EN_RK3588; + val |= GLB_RESET_IDI_EN_RK3588; } else if (dev->chip_id == CHIP_RK3576_CIF) { - val = GLB_RESET_IDI_EN_RK3576; + val |= GLB_RESET_IDI_EN_RK3576; val |= rkcif_get_split_dphy_mask_rk3576(dev); } else if (dev->chip_id == CHIP_RV1103B_CIF) { - val = rkcif_get_split_dphy_mask_rv1103b(dev); + val |= rkcif_get_split_dphy_mask_rv1103b(dev); } - rkcif_write_register_or(dev, CIF_REG_GLB_CTRL, val); + if (dev->chip_id == CHIP_RV1103B_CIF) { + if (rkcif_frm_toisp_protect) + val &= ~BIT(28); + else + val |= BIT(28); + } + rkcif_write_register(dev, CIF_REG_GLB_CTRL, val); if (dev->terminal_sensor.hdmi_input_en) { if (dev->chip_id == CHIP_RK3562_CIF || @@ -5075,8 +5080,13 @@ static int rkcif_csi_channel_set_rv1126b(struct rkcif_stream *stream, CSI_DISABLE_CAPTURE); return 0; } - val = rkcif_get_split_mask_rv1126b(dev); - rkcif_write_register_or(dev, CIF_REG_GLB_CTRL, val); + val = rkcif_read_register(dev, CIF_REG_GLB_CTRL); + val |= rkcif_get_split_mask_rv1126b(dev); + if (rkcif_frm_toisp_protect) + val &= ~BIT(28); + else + val |= BIT(28); + rkcif_write_register(dev, CIF_REG_GLB_CTRL, val); rkcif_write_register_and(dev, CIF_REG_MIPI_LVDS_INTSTAT, ~(CSI_START_INTSTAT(channel->id) | CSI_DMA_END_INTSTAT(channel->id) | diff --git a/drivers/media/platform/rockchip/cif/dev.c b/drivers/media/platform/rockchip/cif/dev.c index 69c3b214460a..9a127897d9e6 100644 --- a/drivers/media/platform/rockchip/cif/dev.c +++ b/drivers/media/platform/rockchip/cif/dev.c @@ -36,6 +36,10 @@ int rkcif_debug; module_param_named(debug, rkcif_debug, int, 0644); MODULE_PARM_DESC(debug, "Debug level (0-1)"); +bool rkcif_frm_toisp_protect = true; +module_param_named(toisp_protect, rkcif_frm_toisp_protect, bool, 0644); +MODULE_PARM_DESC(toisp_protect, "frame protect of toisp"); + static char rkcif_version[RKCIF_VERNO_LEN]; module_param_string(version, rkcif_version, RKCIF_VERNO_LEN, 0444); MODULE_PARM_DESC(version, "version number"); diff --git a/drivers/media/platform/rockchip/cif/dev.h b/drivers/media/platform/rockchip/cif/dev.h index ad4b059e51dd..b8bb669f04ff 100644 --- a/drivers/media/platform/rockchip/cif/dev.h +++ b/drivers/media/platform/rockchip/cif/dev.h @@ -232,6 +232,7 @@ struct rkcif_tools_buffer { }; extern int rkcif_debug; +extern bool rkcif_frm_toisp_protect; /* * struct rkcif_sensor_info - Sensor infomations From 83f73e5ee5aec7fbd021926caeabd4c90fd0b34f Mon Sep 17 00:00:00 2001 From: Zefa Chen Date: Sat, 12 Jul 2025 15:10:43 +0800 Subject: [PATCH 14/23] media: rockchip: vicap fixes error of crop enable state Change-Id: I7d47f5d40e89198aa3369ad2f1c3ecefb183a331 Signed-off-by: Zefa Chen --- drivers/media/platform/rockchip/cif/capture.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/media/platform/rockchip/cif/capture.c b/drivers/media/platform/rockchip/cif/capture.c index ac6be26586bd..23a878ef0aea 100644 --- a/drivers/media/platform/rockchip/cif/capture.c +++ b/drivers/media/platform/rockchip/cif/capture.c @@ -6966,6 +6966,7 @@ void rkcif_do_stop_stream(struct rkcif_stream *stream, kfifo_free(&stream->dcg_kfifo); } + stream->crop_enable = false; stream->crop_mask = 0; stream->frame_loss = 0; stream->is_fb_first_frame = true; From 4ec86e75f7ef4a6817e3edceddeaa965474de531 Mon Sep 17 00:00:00 2001 From: Zefa Chen Date: Wed, 4 Jun 2025 17:50:24 +0800 Subject: [PATCH 15/23] media: rockchip: vicap fixes error of tool node get raw Change-Id: Ib0bb1c3266002344b9862844a5d5756478f0ed80 Signed-off-by: Zefa Chen --- drivers/media/platform/rockchip/cif/capture.c | 5 ++-- .../media/platform/rockchip/cif/cif-tools.c | 27 +++++++++++++++---- drivers/media/platform/rockchip/cif/dev.h | 2 ++ .../media/platform/rockchip/cif/subdev-itf.c | 23 +++++++++++++++- 4 files changed, 49 insertions(+), 8 deletions(-) diff --git a/drivers/media/platform/rockchip/cif/capture.c b/drivers/media/platform/rockchip/cif/capture.c index 23a878ef0aea..5559b234c171 100644 --- a/drivers/media/platform/rockchip/cif/capture.c +++ b/drivers/media/platform/rockchip/cif/capture.c @@ -1968,8 +1968,9 @@ static void rkcif_rdbk_with_tools(struct rkcif_stream *stream, unsigned long flags; spin_lock_irqsave(&stream->tools_vdev->vbq_lock, flags); - if (stream->tools_vdev->state == RKCIF_STATE_STREAMING) { - list_add_tail(&active_buf->list, &stream->tools_vdev->buf_done_head); + if (stream->tools_vdev->state == RKCIF_STATE_STREAMING && active_buf) { + list_add_tail(&active_buf->list_tool, &stream->tools_vdev->buf_done_head); + active_buf->use_cnt = 2; if (!work_busy(&stream->tools_vdev->work)) schedule_work(&stream->tools_vdev->work); } diff --git a/drivers/media/platform/rockchip/cif/cif-tools.c b/drivers/media/platform/rockchip/cif/cif-tools.c index f46c744489d6..78e92678036d 100644 --- a/drivers/media/platform/rockchip/cif/cif-tools.c +++ b/drivers/media/platform/rockchip/cif/cif-tools.c @@ -474,6 +474,7 @@ static void rkcif_tools_vb2_stop_streaming(struct vb2_queue *vq) struct rkcif_device *dev = tools_vdev->cifdev; struct rkcif_buffer *buf = NULL; struct rkcif_tools_buffer *tools_buf; + struct rkcif_rx_buffer *rx_buf = NULL; int ret = 0; mutex_lock(&dev->tools_lock); @@ -485,6 +486,12 @@ static void rkcif_tools_vb2_stop_streaming(struct vb2_queue *vq) if (!ret) { rkcif_tools_stop(tools_vdev); tools_vdev->stopping = false; + while (!list_empty(&tools_vdev->buf_done_head)) { + rx_buf = list_first_entry(&tools_vdev->buf_done_head, + struct rkcif_rx_buffer, list_tool); + list_del(&rx_buf->list_tool); + v4l2_subdev_call(&dev->sditf[0]->sd, video, s_rx_buffer, &rx_buf->dbufs, NULL); + } } /* release buffers */ if (tools_vdev->curr_buf) @@ -710,9 +717,9 @@ retry_done_rdbk_buf: spin_lock_irqsave(&tools_vdev->vbq_lock, flags); if (!list_empty(&tools_vdev->buf_done_head)) { buf = list_first_entry(&tools_vdev->buf_done_head, - struct rkcif_rx_buffer, list); + struct rkcif_rx_buffer, list_tool); if (buf) - list_del(&buf->list); + list_del(&buf->list_tool); } spin_unlock_irqrestore(&tools_vdev->vbq_lock, flags); if (!buf) { @@ -724,12 +731,14 @@ retry_done_rdbk_buf: if (tools_vdev->stopping) { rkcif_tools_stop(tools_vdev); tools_vdev->stopping = false; + if (buf) + v4l2_subdev_call(&dev->sditf[0]->sd, video, s_rx_buffer, &buf->dbufs, NULL); spin_lock_irqsave(&tools_vdev->vbq_lock, flags); while (!list_empty(&tools_vdev->buf_done_head)) { buf = list_first_entry(&tools_vdev->buf_done_head, - struct rkcif_rx_buffer, list); - if (buf) - list_del(&buf->list); + struct rkcif_rx_buffer, list_tool); + list_del(&buf->list_tool); + v4l2_subdev_call(&dev->sditf[0]->sd, video, s_rx_buffer, &buf->dbufs, NULL); } spin_unlock_irqrestore(&tools_vdev->vbq_lock, flags); wake_up(&tools_vdev->wq_stopped); @@ -742,9 +751,13 @@ retry_done_rdbk_buf: if (!tools_vdev->curr_buf || tools_vdev->state != RKCIF_STATE_STREAMING) { spin_lock_irqsave(&tools_vdev->vbq_lock, flags); if (!list_empty(&tools_vdev->buf_done_head)) { + if (buf) + v4l2_subdev_call(&dev->sditf[0]->sd, video, s_rx_buffer, &buf->dbufs, NULL); spin_unlock_irqrestore(&stream->tools_vdev->vbq_lock, flags); goto retry_done_rdbk_buf; } + if (buf) + v4l2_subdev_call(&dev->sditf[0]->sd, video, s_rx_buffer, &buf->dbufs, NULL); spin_unlock_irqrestore(&tools_vdev->vbq_lock, flags); return; } @@ -765,10 +778,14 @@ retry_done_rdbk_buf: payload_size); memcpy(dst, src, payload_size); } + v4l2_subdev_call(&dev->sditf[0]->sd, video, s_rx_buffer, &buf->dbufs, NULL); tools_vdev->curr_buf->vb.sequence = buf->dbufs.sequence; tools_vdev->curr_buf->vb.vb2_buf.timestamp = buf->dbufs.timestamp; vb2_buffer_done(&tools_vdev->curr_buf->vb.vb2_buf, VB2_BUF_STATE_DONE); tools_vdev->curr_buf = NULL; + } else { + if (buf) + v4l2_subdev_call(&dev->sditf[0]->sd, video, s_rx_buffer, &buf->dbufs, NULL); } spin_lock_irqsave(&tools_vdev->vbq_lock, flags); diff --git a/drivers/media/platform/rockchip/cif/dev.h b/drivers/media/platform/rockchip/cif/dev.h index b8bb669f04ff..ca6e0983b186 100644 --- a/drivers/media/platform/rockchip/cif/dev.h +++ b/drivers/media/platform/rockchip/cif/dev.h @@ -479,12 +479,14 @@ enum rkcif_capture_mode { struct rkcif_rx_buffer { int buf_idx; struct list_head list; + struct list_head list_tool; struct list_head list_free; struct rkisp_rx_buf dbufs; struct rkcif_dummy_buffer dummy; struct rkisp_thunderboot_shmem shmem; u64 fe_timestamp; bool is_init[RKCIF_MAX_DEV]; + int use_cnt; }; enum rkcif_dma_en_mode { diff --git a/drivers/media/platform/rockchip/cif/subdev-itf.c b/drivers/media/platform/rockchip/cif/subdev-itf.c index bdd562341540..73f8b4376bc9 100644 --- a/drivers/media/platform/rockchip/cif/subdev-itf.c +++ b/drivers/media/platform/rockchip/cif/subdev-itf.c @@ -1345,6 +1345,26 @@ static int sditf_s_power(struct v4l2_subdev *sd, int on) return ret; } +static int sditf_check_toolbuf_return(struct rkcif_stream *stream, struct rkcif_rx_buffer *rx_buf) +{ + struct rkcif_tools_vdev *tools_vdev = stream->tools_vdev; + unsigned long flags; + + if (tools_vdev) { + spin_lock_irqsave(&stream->tools_vdev->vbq_lock, flags); + + if (rx_buf->use_cnt) + rx_buf->use_cnt--; + if (rx_buf->use_cnt) { + spin_unlock_irqrestore(&stream->tools_vdev->vbq_lock, flags); + return false; + } + spin_unlock_irqrestore(&stream->tools_vdev->vbq_lock, flags); + } + + return true; +} + static int sditf_s_rx_buffer(struct v4l2_subdev *sd, void *buf, unsigned int *size) { @@ -1422,7 +1442,8 @@ static int sditf_s_rx_buffer(struct v4l2_subdev *sd, is_free = true; } - if (!is_free && (!dbufs->is_switch) && stream->state == RKCIF_STATE_STREAMING) { + if (!is_free && (!dbufs->is_switch) && stream->state == RKCIF_STATE_STREAMING && + sditf_check_toolbuf_return(stream, rx_buf)) { list_add_tail(&rx_buf->list, &buf_stream->rx_buf_head); rkcif_assign_check_buffer_update_toisp(stream); if (cif_dev->resume_mode != RKISP_RTT_MODE_ONE_FRAME && From c348e9697f8192a95d286957ec346e504e08151d Mon Sep 17 00:00:00 2001 From: Zefa Chen Date: Fri, 4 Jul 2025 17:59:35 +0800 Subject: [PATCH 16/23] media: rockchip: vicap fixes error of stream off when one_frame mode change to mulit_frame mode Change-Id: I97bc6e891342a78a4079d034876c7ad256abff20 Signed-off-by: Zefa Chen --- drivers/media/platform/rockchip/cif/capture.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/media/platform/rockchip/cif/capture.c b/drivers/media/platform/rockchip/cif/capture.c index 5559b234c171..5659bed0cb48 100644 --- a/drivers/media/platform/rockchip/cif/capture.c +++ b/drivers/media/platform/rockchip/cif/capture.c @@ -9790,6 +9790,7 @@ int rkcif_quick_stream_on(struct rkcif_device *dev, bool is_intr) if (dev->sditf[0]->mode.rdbk_mode < RKISP_VICAP_RDBK_AIQ) { for (i = 0; i < stream_num; i++) { stream = &dev->stream[i]; + stream->is_pause_stream = false; if (stream->cifdev->hdr.hdr_mode == NO_HDR || (stream->cifdev->hdr.hdr_mode == HDR_X2 && stream->id == 1) || (stream->cifdev->hdr.hdr_mode == HDR_X3 && stream->id == 2)) { @@ -9819,6 +9820,7 @@ int rkcif_quick_stream_on(struct rkcif_device *dev, bool is_intr) RKISP_VICAP_CMD_MODE, &dev->sditf[0]->mode); } for (i = 0; i < stream_num; i++) { + dev->stream[i].is_pause_stream = false; if (dev->sditf[0]->mode.rdbk_mode != RKISP_VICAP_RDBK_AIQ) dev->stream[i].to_en_dma = RKCIF_DMAEN_BY_ISP; else From d5a7bbea0d800e73b4e431a3611accb68953c6eb Mon Sep 17 00:00:00 2001 From: Zefa Chen Date: Fri, 21 Jun 2024 10:33:12 +0800 Subject: [PATCH 17/23] phy: rockchip: mipi dcphy move apb_rst to runtime resume to avoid break dcphy rx Change-Id: I097eeb7e3fd7decc4f0d1badd335b2d7176ce223 Signed-off-by: Zefa Chen Signed-off-by: Guochun Huang --- drivers/phy/rockchip/phy-rockchip-csi2-dphy.c | 4 +-- .../phy/rockchip/phy-rockchip-samsung-dcphy.c | 35 ++++++++++--------- 2 files changed, 20 insertions(+), 19 deletions(-) diff --git a/drivers/phy/rockchip/phy-rockchip-csi2-dphy.c b/drivers/phy/rockchip/phy-rockchip-csi2-dphy.c index 895d0d8fe849..9bbf7f5d1a3b 100644 --- a/drivers/phy/rockchip/phy-rockchip-csi2-dphy.c +++ b/drivers/phy/rockchip/phy-rockchip-csi2-dphy.c @@ -590,7 +590,7 @@ static int csi2_dphy_enable_clk(struct csi2_dphy *dphy) if (dphy->csi_info.dphy_vendor[i] == PHY_VENDOR_SAMSUNG) { samsung_phy = (struct samsung_mipi_dcphy *)dphy->phy_hw[i]; if (samsung_phy) - clk_prepare_enable(samsung_phy->pclk); + pm_runtime_get_sync(samsung_phy->dev); } else { hw = (struct csi2_dphy_hw *)dphy->phy_hw[i]; if (hw) { @@ -615,7 +615,7 @@ static void csi2_dphy_disable_clk(struct csi2_dphy *dphy) if (dphy->csi_info.dphy_vendor[i] == PHY_VENDOR_SAMSUNG) { samsung_phy = (struct samsung_mipi_dcphy *)dphy->phy_hw[i]; if (samsung_phy) - clk_disable_unprepare(samsung_phy->pclk); + pm_runtime_put(samsung_phy->dev); } else { hw = (struct csi2_dphy_hw *)dphy->phy_hw[i]; if (hw) diff --git a/drivers/phy/rockchip/phy-rockchip-samsung-dcphy.c b/drivers/phy/rockchip/phy-rockchip-samsung-dcphy.c index cc90acdc0726..ff42a0464342 100644 --- a/drivers/phy/rockchip/phy-rockchip-samsung-dcphy.c +++ b/drivers/phy/rockchip/phy-rockchip-samsung-dcphy.c @@ -1781,25 +1781,8 @@ static int samsung_mipi_dcphy_power_on(struct phy *phy) { struct samsung_mipi_dcphy *samsung = phy_get_drvdata(phy); enum phy_mode mode = phy_get_mode(phy); - int on = 0; - struct v4l2_subdev *sensor_sd = NULL; pm_runtime_get_sync(samsung->dev); - reset_control_assert(samsung->apb_rst); - udelay(1); - reset_control_deassert(samsung->apb_rst); - if (atomic_read(&samsung->stream_cnt) && samsung->dphy_dev[0]) { - sensor_sd = get_remote_sensor(&samsung->dphy_dev[0]->sd); - samsung->stream_off(samsung->dphy_dev[0], &samsung->dphy_dev[0]->sd); - if (sensor_sd) - v4l2_subdev_call(sensor_sd, core, ioctl, - RKMODULE_SET_QUICK_STREAM, &on); - samsung->stream_on(samsung->dphy_dev[0], &samsung->dphy_dev[0]->sd); - on = 1; - if (sensor_sd) - v4l2_subdev_call(sensor_sd, core, ioctl, - RKMODULE_SET_QUICK_STREAM, &on); - } switch (mode) { case PHY_MODE_MIPI_DPHY: @@ -2492,6 +2475,22 @@ static int samsung_mipi_dcphy_remove(struct platform_device *pdev) return 0; } +static __maybe_unused int samsung_mipi_dcphy_suspend(struct device *dev) +{ + return 0; +} + +static __maybe_unused int samsung_mipi_dcphy_resume(struct device *dev) +{ + struct samsung_mipi_dcphy *samsung = dev_get_drvdata(dev); + + reset_control_assert(samsung->apb_rst); + udelay(1); + reset_control_deassert(samsung->apb_rst); + + return 0; +} + static __maybe_unused int samsung_mipi_dcphy_runtime_suspend(struct device *dev) { struct samsung_mipi_dcphy *samsung = dev_get_drvdata(dev); @@ -2513,6 +2512,8 @@ static __maybe_unused int samsung_mipi_dcphy_runtime_resume(struct device *dev) } static const struct dev_pm_ops samsung_mipi_dcphy_pm_ops = { + SET_SYSTEM_SLEEP_PM_OPS(samsung_mipi_dcphy_suspend, + samsung_mipi_dcphy_resume) SET_RUNTIME_PM_OPS(samsung_mipi_dcphy_runtime_suspend, samsung_mipi_dcphy_runtime_resume, NULL) }; From 24690200216c430c5ff1e37b42495055c5a5094b Mon Sep 17 00:00:00 2001 From: Hu Kejun Date: Tue, 10 Jun 2025 09:40:07 +0800 Subject: [PATCH 18/23] media: rockchip: aiisp: update airms algo Change-Id: I6a1d1b9dd9bc120925da57ea817593bf639c4a80 Signed-off-by: Hu Kejun --- drivers/media/platform/rockchip/aiisp/aiisp.c | 48 +++++++++++++------ drivers/media/platform/rockchip/aiisp/aiisp.h | 1 - include/uapi/linux/rk-aiisp-config.h | 3 +- 3 files changed, 36 insertions(+), 16 deletions(-) diff --git a/drivers/media/platform/rockchip/aiisp/aiisp.c b/drivers/media/platform/rockchip/aiisp/aiisp.c index 6c37a3069835..e1c6c3c7f6bf 100644 --- a/drivers/media/platform/rockchip/aiisp/aiisp.c +++ b/drivers/media/platform/rockchip/aiisp/aiisp.c @@ -350,6 +350,24 @@ static void rkaiisp_free_buffer(struct rkaiisp_device *aidev, } } +static void __maybe_unused rkaiisp_prepare_buffer(struct rkaiisp_device *aidev, + struct rkaiisp_dummy_buffer *buf) +{ + const struct vb2_mem_ops *g_ops = aidev->hw_dev->mem_ops; + + if (buf && buf->mem_priv) + g_ops->prepare(buf->mem_priv); +} + +static void __maybe_unused rkaiisp_finish_buffer(struct rkaiisp_device *aidev, + struct rkaiisp_dummy_buffer *buf) +{ + const struct vb2_mem_ops *g_ops = aidev->hw_dev->mem_ops; + + if (buf && buf->mem_priv) + g_ops->finish(buf->mem_priv); +} + static void rkaiisp_detach_dmabuf(struct rkaiisp_device *aidev, struct rkaiisp_dummy_buffer *buffer) { @@ -670,7 +688,6 @@ static int rkaiisp_free_airms_pool(struct rkaiisp_device *aidev) for (i = 0; i < aidev->rmsbuf.outbuf_num; i++) rkaiisp_free_buffer(aidev, &aidev->rms_outbuf[i]); - rkaiisp_free_buffer(aidev, &aidev->sigma_buf); rkaiisp_free_buffer(aidev, &aidev->narmap_buf); aidev->init_buf = false; @@ -682,9 +699,12 @@ static int rkaiisp_free_airms_pool(struct rkaiisp_device *aidev) static int rkaiisp_init_airms_pool(struct rkaiisp_device *aidev, struct rkaiisp_rmsbuf_info *rmsbuf) { int i, ret = 0; + u32 bin_width, bin_height; u32 size; - size = rmsbuf->image_width * rmsbuf->image_height * 2; + bin_width = CEIL_BY(CEIL_DOWN(rmsbuf->image_width, 2), 2); + bin_height = CEIL_BY(CEIL_DOWN(rmsbuf->image_height, 2), 2); + size = rmsbuf->image_width * rmsbuf->image_height * 2 + bin_width * bin_height; rmsbuf->inbuf_num = RKAIISP_MIN(rmsbuf->inbuf_num, RKAIISP_AIRMS_BUF_MAXCNT); for (i = 0; i < rmsbuf->inbuf_num; i++) { aidev->rms_inbuf[i].size = size; @@ -700,6 +720,7 @@ static int rkaiisp_init_airms_pool(struct rkaiisp_device *aidev, struct rkaiisp_ rmsbuf->inbuf_fd[i] = aidev->rms_inbuf[i].dma_fd; } + size = rmsbuf->image_width * rmsbuf->image_height * 2; rmsbuf->outbuf_num = RKAIISP_MIN(rmsbuf->outbuf_num, RKAIISP_AIRMS_BUF_MAXCNT); for (i = 0; i < rmsbuf->outbuf_num; i++) { aidev->rms_outbuf[i].size = size; @@ -715,11 +736,6 @@ static int rkaiisp_init_airms_pool(struct rkaiisp_device *aidev, struct rkaiisp_ rmsbuf->outbuf_fd[i] = aidev->rms_outbuf[i].dma_fd; } - aidev->sigma_buf.size = rmsbuf->sigma_width * rmsbuf->sigma_height; - aidev->sigma_buf.is_need_vaddr = false; - aidev->sigma_buf.is_need_dbuf = false; - aidev->sigma_buf.is_need_dmafd = false; - rkaiisp_allow_buffer(aidev, &aidev->sigma_buf); aidev->narmap_buf.size = rmsbuf->narmap_width * rmsbuf->narmap_height; aidev->narmap_buf.is_need_vaddr = false; aidev->narmap_buf.is_need_dbuf = false; @@ -1244,12 +1260,6 @@ static u32 rkaiisp_config_rdchannel(struct rkaiisp_device *aidev, buffer_index = aidev->curr_idxbuf.airms_st.inbuf_idx; dma_addr = aidev->rms_inbuf[buffer_index].dma_addr; break; - case ALLZERO_SIGMA: - width = rmsbuf->sigma_width; - height = rmsbuf->sigma_height; - dma_addr = aidev->sigma_buf.dma_addr; - sig_width = width; - break; case ALLZERO_NARMAP: width = rmsbuf->narmap_width; height = rmsbuf->narmap_height; @@ -1261,6 +1271,15 @@ static u32 rkaiisp_config_rdchannel(struct rkaiisp_device *aidev, buffer_index = aidev->curr_idxbuf.aibnr_st.y_src_index; dma_addr = aidev->ynrinbuf[buffer_index].dma_addr; break; + case VICAP_BAYER_RAW_DOWN: + width = rmsbuf->image_width; + height = rmsbuf->image_height; + buffer_index = aidev->curr_idxbuf.airms_st.inbuf_idx; + dma_addr = aidev->rms_inbuf[buffer_index].dma_addr + width * height * 2; + width = CEIL_BY(CEIL_DOWN(rmsbuf->image_width, 2), 2); + height = CEIL_BY(CEIL_DOWN(rmsbuf->image_height, 2), 2); + sig_width = width; + break; default: width = 0; height = 0; @@ -1462,7 +1481,8 @@ static void rkaiisp_run_cfg(struct rkaiisp_device *aidev, u32 run_idx) rkaiisp_write(aidev, AIISP_CORE_LEVEL_CTRL0 + i * 4, val, false); } - if ((out_chns == 4 && model_cfg->sw_out_d2s_en == 0)) + if (out_chns == 4 && + model_cfg->sw_out_d2s_en == (model_cfg->sw_out_mode == AIISP_OUT_MODE_BYPASS)) sw_lastlv_bypass = 1; if (model_cfg->sw_aiisp_mode == 0 && model_cfg->sw_out_mode == AIISP_OUT_MODE_DIFF_MERGE) sw_m0_diff_merge = 1; diff --git a/drivers/media/platform/rockchip/aiisp/aiisp.h b/drivers/media/platform/rockchip/aiisp/aiisp.h index b45ea78bf38f..37bd8b44e35b 100644 --- a/drivers/media/platform/rockchip/aiisp/aiisp.h +++ b/drivers/media/platform/rockchip/aiisp/aiisp.h @@ -124,7 +124,6 @@ struct rkaiisp_device { struct rkaiisp_rmsbuf_info rmsbuf; struct rkaiisp_dummy_buffer rms_inbuf[RKAIISP_AIRMS_BUF_MAXCNT]; struct rkaiisp_dummy_buffer rms_outbuf[RKAIISP_AIRMS_BUF_MAXCNT]; - struct rkaiisp_dummy_buffer sigma_buf; struct rkaiisp_dummy_buffer narmap_buf; struct aiisp_aiynr_ybuf_cfg ynr_ybuf_cfg; diff --git a/include/uapi/linux/rk-aiisp-config.h b/include/uapi/linux/rk-aiisp-config.h index 6453e62dcc3a..ebbbb8f0b09f 100644 --- a/include/uapi/linux/rk-aiisp-config.h +++ b/include/uapi/linux/rk-aiisp-config.h @@ -56,7 +56,8 @@ enum rkaiisp_chn_src { VICAP_BAYER_RAW, ALLZERO_SIGMA, ALLZERO_NARMAP, - ISP_FINAL_Y + ISP_FINAL_Y, + VICAP_BAYER_RAW_DOWN }; enum rkaiisp_exealgo { From 2be8f9d5fd85f84a203f9748331778e1023111d2 Mon Sep 17 00:00:00 2001 From: Hu Kejun Date: Fri, 4 Jul 2025 18:02:34 +0800 Subject: [PATCH 19/23] media: rockchip: aiisp: support picture width over 4096 in airms algo Change-Id: I5115494f57fc5a745ba066d32fc9e16b3911eb15 Signed-off-by: Hu Kejun --- drivers/media/platform/rockchip/aiisp/aiisp.c | 131 ++++++++++++++---- drivers/media/platform/rockchip/aiisp/aiisp.h | 9 ++ 2 files changed, 116 insertions(+), 24 deletions(-) diff --git a/drivers/media/platform/rockchip/aiisp/aiisp.c b/drivers/media/platform/rockchip/aiisp/aiisp.c index e1c6c3c7f6bf..85591f813469 100644 --- a/drivers/media/platform/rockchip/aiisp/aiisp.c +++ b/drivers/media/platform/rockchip/aiisp/aiisp.c @@ -174,8 +174,8 @@ static void rkaiisp_dumpreg(struct rkaiisp_device *aidev, u32 start, u32 end) static void rkaiisp_dump_list_reg(struct rkaiisp_device *aidev) { - dev_info(aidev->dev, "frame_id: %d, run_idx: %d\n", - aidev->frame_id, aidev->run_idx); + dev_info(aidev->dev, "frame_id: %d, run_idx: %d, parthdl %d\n", + aidev->frame_id, aidev->run_idx, aidev->parthdl_idx); rkaiisp_dumpreg(aidev, AIISP_CORE_CTRL, AIISP_CORE_NOISE_LMT); rkaiisp_dumpreg(aidev, AIISP_CORE_COMP0, AIISP_CORE_DECOMP16); @@ -669,6 +669,7 @@ static int rkaiisp_init_pool(struct rkaiisp_device *aidev, struct rkaiisp_ispbuf aidev->ispbuf = *ispbuf; aidev->outbuf_idx = 0; + aidev->parthdl_num = 1; aidev->init_buf = true; v4l2_dbg(1, rkaiisp_debug, &aidev->v4l2_dev, "init buf poll\n"); @@ -720,7 +721,25 @@ static int rkaiisp_init_airms_pool(struct rkaiisp_device *aidev, struct rkaiisp_ rmsbuf->inbuf_fd[i] = aidev->rms_inbuf[i].dma_fd; } - size = rmsbuf->image_width * rmsbuf->image_height * 2; + aidev->rmsbuf = *rmsbuf; + aidev->part_rmsbuf = aidev->rmsbuf; + if (rmsbuf->image_width > RKAIISP_AIRMS_MAX_WIDTH) { + int proc_width; + + aidev->is_parthdl = true; + aidev->parthdl_num = 2; + proc_width = aidev->part_rmsbuf.image_width / 2 + RKAIISP_AIRMS_EXTEND_PIXEL; + aidev->part_rmsbuf.image_width = CEIL_BY(proc_width, 16); + aidev->part_rmsbuf.sigma_width = aidev->part_rmsbuf.image_width / 2; + aidev->part_rmsbuf.narmap_width = (aidev->part_rmsbuf.image_width + 7) / 8 * 2; + aidev->parthdl_image_oft = aidev->rmsbuf.image_width - aidev->part_rmsbuf.image_width; + size = (CEIL_BY(rmsbuf->image_width, 2) + 2 * RKAIISP_AIRMS_EXTEND_PIXEL) * rmsbuf->image_height * 2; + } else { + aidev->is_parthdl = false; + aidev->parthdl_num = 1; + size = rmsbuf->image_width * rmsbuf->image_height * 2; + } + rmsbuf->outbuf_num = RKAIISP_MIN(rmsbuf->outbuf_num, RKAIISP_AIRMS_BUF_MAXCNT); for (i = 0; i < rmsbuf->outbuf_num; i++) { aidev->rms_outbuf[i].size = size; @@ -736,13 +755,12 @@ static int rkaiisp_init_airms_pool(struct rkaiisp_device *aidev, struct rkaiisp_ rmsbuf->outbuf_fd[i] = aidev->rms_outbuf[i].dma_fd; } - aidev->narmap_buf.size = rmsbuf->narmap_width * rmsbuf->narmap_height; + aidev->narmap_buf.size = aidev->rmsbuf.narmap_width * aidev->rmsbuf.narmap_height; aidev->narmap_buf.is_need_vaddr = false; aidev->narmap_buf.is_need_dbuf = false; aidev->narmap_buf.is_need_dmafd = false; rkaiisp_allow_buffer(aidev, &aidev->narmap_buf); - aidev->rmsbuf = *rmsbuf; aidev->init_buf = true; v4l2_dbg(1, rkaiisp_debug, &aidev->v4l2_dev, "init buf poll\n"); @@ -896,6 +914,13 @@ static void rkaiisp_gen_slice_param(struct rkaiisp_device *aidev, } } + if (slice_idx > 8) { + aidev->is_state_err = true; + v4l2_err(&aidev->v4l2_dev, + "slice num %d is too big, input width %d\n", slice_idx, width); + return; + } + if (slice_idx >= 1) slice_num = slice_idx - 1; value = slice_mode[0] | @@ -1006,6 +1031,9 @@ static int rkaiisp_determine_size(struct rkaiisp_device *aidev, if (n == 3 && model_cfg->sw_mi_chn3_sel == 0) bits = 8; + if (aidev->chn_size[n].stride != 0 && aidev->exealgo == AIRMS) + cols = aidev->chn_size[n].stride; + sw_mi_chn_stride[n] = CEIL_BY(cols * chns * bits, 16 * 8) / 32; } @@ -1146,6 +1174,7 @@ static u32 rkaiisp_config_rdchannel(struct rkaiisp_device *aidev, { struct rkaiisp_ispbuf_info *ispbuf = &aidev->ispbuf; struct rkaiisp_rmsbuf_info *rmsbuf = &aidev->rmsbuf; + struct rkaiisp_rmsbuf_info *part_rmsbuf = &aidev->part_rmsbuf; struct rkaiisp_dummy_buffer *vpsl_buf; dma_addr_t dma_addr; u32 width, height, stride; @@ -1255,14 +1284,29 @@ static u32 rkaiisp_config_rdchannel(struct rkaiisp_device *aidev, dma_addr = aidev->lastout_buf[aidev->outbuf_idx]->dma_addr; break; case VICAP_BAYER_RAW: - width = rmsbuf->image_width; - height = rmsbuf->image_height; - buffer_index = aidev->curr_idxbuf.airms_st.inbuf_idx; - dma_addr = aidev->rms_inbuf[buffer_index].dma_addr; + if (aidev->is_parthdl) { + width = part_rmsbuf->image_width; + height = part_rmsbuf->image_height; + buffer_index = aidev->curr_idxbuf.airms_st.inbuf_idx; + dma_addr = aidev->rms_inbuf[buffer_index].dma_addr; + if (aidev->parthdl_idx == 1) + dma_addr += aidev->parthdl_image_oft * 2; + stride = rmsbuf->image_width; + } else { + width = rmsbuf->image_width; + height = rmsbuf->image_height; + buffer_index = aidev->curr_idxbuf.airms_st.inbuf_idx; + dma_addr = aidev->rms_inbuf[buffer_index].dma_addr; + } break; case ALLZERO_NARMAP: - width = rmsbuf->narmap_width; - height = rmsbuf->narmap_height; + if (aidev->is_parthdl) { + width = part_rmsbuf->narmap_width; + height = part_rmsbuf->narmap_height; + } else { + width = rmsbuf->narmap_width; + height = rmsbuf->narmap_height; + } dma_addr = aidev->narmap_buf.dma_addr; break; case ISP_FINAL_Y: @@ -1272,13 +1316,26 @@ static u32 rkaiisp_config_rdchannel(struct rkaiisp_device *aidev, dma_addr = aidev->ynrinbuf[buffer_index].dma_addr; break; case VICAP_BAYER_RAW_DOWN: - width = rmsbuf->image_width; - height = rmsbuf->image_height; - buffer_index = aidev->curr_idxbuf.airms_st.inbuf_idx; - dma_addr = aidev->rms_inbuf[buffer_index].dma_addr + width * height * 2; - width = CEIL_BY(CEIL_DOWN(rmsbuf->image_width, 2), 2); - height = CEIL_BY(CEIL_DOWN(rmsbuf->image_height, 2), 2); - sig_width = width; + if (aidev->is_parthdl) { + width = rmsbuf->image_width; + height = rmsbuf->image_height; + buffer_index = aidev->curr_idxbuf.airms_st.inbuf_idx; + dma_addr = aidev->rms_inbuf[buffer_index].dma_addr + width * height * 2; + if (aidev->parthdl_idx == 1) + dma_addr += aidev->parthdl_image_oft / 2; + width = CEIL_BY(CEIL_DOWN(part_rmsbuf->image_width, 2), 2); + height = CEIL_BY(CEIL_DOWN(part_rmsbuf->image_height, 2), 2); + sig_width = width; + stride = CEIL_BY(CEIL_DOWN(rmsbuf->image_width, 2), 2); + } else { + width = rmsbuf->image_width; + height = rmsbuf->image_height; + buffer_index = aidev->curr_idxbuf.airms_st.inbuf_idx; + dma_addr = aidev->rms_inbuf[buffer_index].dma_addr + width * height * 2; + width = CEIL_BY(CEIL_DOWN(rmsbuf->image_width, 2), 2); + height = CEIL_BY(CEIL_DOWN(rmsbuf->image_height, 2), 2); + sig_width = width; + } break; default: width = 0; @@ -1290,7 +1347,7 @@ static u32 rkaiisp_config_rdchannel(struct rkaiisp_device *aidev, if (width > 0) { aidev->chn_size[i].width = width; aidev->chn_size[i].height = height; - aidev->chn_size[i].stride = stride; + aidev->chn_size[i].stride = stride > 0 ? stride : width; rkaiisp_write(aidev, AIISP_MI_RD_CH0_BASE + 0x100 * i, dma_addr, false); rkaiisp_write(aidev, AIISP_MI_RD_CH0_HEIGHT + 0x100 * i, height, false); @@ -1308,6 +1365,7 @@ static u32 rkaiisp_config_rdchannel(struct rkaiisp_device *aidev, static void rkaiisp_run_cfg(struct rkaiisp_device *aidev, u32 run_idx) { struct rkaiisp_ispbuf_info *ispbuf = &aidev->ispbuf; + struct rkaiisp_rmsbuf_info *rmsbuf = &aidev->rmsbuf; struct rkaiisp_params *cur_params; struct rkaiisp_model_cfg *model_cfg; int lastlv, lv_mode, out_chns, i; @@ -1329,6 +1387,7 @@ static void rkaiisp_run_cfg(struct rkaiisp_device *aidev, u32 run_idx) "run frame id: %d, run_idx: %d, model_mode %d\n", sequence, run_idx, aidev->model_mode); + aidev->is_state_err = false; cur_params = (struct rkaiisp_params *)aidev->cur_params->vaddr[0]; model_cfg = &cur_params->model_cfg[run_idx]; @@ -1370,10 +1429,17 @@ static void rkaiisp_run_cfg(struct rkaiisp_device *aidev, u32 run_idx) sig_width = rkaiisp_config_rdchannel(aidev, model_cfg, run_idx); dma_addr = aidev->rms_outbuf[aidev->curr_idxbuf.airms_st.outbuf_idx].dma_addr; + if (aidev->parthdl_idx == 1) + dma_addr += 2 * (CEIL_BY(rmsbuf->image_width, 2) / 2 + RKAIISP_AIRMS_EXTEND_PIXEL); rkaiisp_write(aidev, AIISP_MI_CHN0_WR_BASE, dma_addr, false); rkaiisp_gen_slice_param(aidev, model_cfg, sig_width); rkaiisp_determine_size(aidev, model_cfg); + + iir_stride = CEIL_BY(rmsbuf->image_width, 2); + if (aidev->is_parthdl) + iir_stride += 2 * RKAIISP_AIRMS_EXTEND_PIXEL; + rkaiisp_write(aidev, AIISP_MI_CHN0_WR_STRIDE, iir_stride / 2, false); } else if (aidev->model_mode == SINGLEX2_MODE) { if (run_idx == 0) { sig_width = rkaiisp_config_rdchannel(aidev, model_cfg, run_idx); @@ -1529,16 +1595,25 @@ static void rkaiisp_run_start(struct rkaiisp_device *aidev) { struct rkaiisp_hw_dev *hw_dev = aidev->hw_dev; + if (aidev->is_state_err) { + v4l2_err(&aidev->v4l2_dev, + "aiisp status is error!\n"); + rkaiisp_dump_list_reg(aidev); + return; + } + rkaiisp_write(aidev, AIISP_MI_IMSC, AIISP_MI_ISR_ALL, false); rkaiisp_write(aidev, AIISP_MI_WR_INIT, AIISP_MI_CHN0SELF_FORCE_UPD, false); - if ((aidev->run_idx == 0) && (rkaiisp_showreg != 0)) + if ((aidev->run_idx == 0) && (aidev->parthdl_idx == 0) && (rkaiisp_showreg != 0)) aidev->showreg = true; if (aidev->showreg) rkaiisp_dump_list_reg(aidev); - if ((aidev->run_idx == aidev->model_runcnt - 1) && aidev->showreg) { + if ((aidev->run_idx + 1 == aidev->model_runcnt) && + (aidev->parthdl_idx + 1 == aidev->parthdl_num) && + aidev->showreg) { aidev->showreg = false; rkaiisp_showreg = 0; } @@ -1613,6 +1688,7 @@ void rkaiisp_trigger(struct rkaiisp_device *aidev) if (!rkaiisp_update_buf(aidev)) { aidev->run_idx = 0; + aidev->parthdl_idx = 0; aidev->frame_id = sequence; aidev->pre_frm_st = aidev->frm_st; aidev->frm_st = ktime_get_ns(); @@ -1663,8 +1739,9 @@ enum rkaiisp_irqhdl_ret rkaiisp_irq_hdl(struct rkaiisp_device *aidev, u32 mi_mis u64 frm_hdntim = 0; v4l2_dbg(1, rkaiisp_debug, &aidev->v4l2_dev, - "irq val: 0x%x, run_idx %d, model_runcnt %d\n", - mi_mis, aidev->run_idx, aidev->model_runcnt); + "irq val: 0x%x, run_idx %d, model_runcnt %d, parthdl %d, %d\n", + mi_mis, aidev->run_idx, aidev->model_runcnt, + aidev->parthdl_idx, aidev->parthdl_num); if (mi_mis & AIISP_MI_ISR_BUSERR) { v4l2_err(&aidev->v4l2_dev, "buserr 0x%x\n", mi_mis); @@ -1677,11 +1754,17 @@ enum rkaiisp_irqhdl_ret rkaiisp_irq_hdl(struct rkaiisp_device *aidev, u32 mi_mis rkaiisp_write(aidev, AIISP_MI_ICR, AIISP_MI_ISR_WREND, true); aidev->isr_wrend_cnt++; - if (aidev->run_idx < aidev->model_runcnt - 1) { + if (aidev->run_idx + 1 < aidev->model_runcnt) { aidev->run_idx++; rkaiisp_run_cfg(aidev, aidev->run_idx); rkaiisp_run_start(aidev); return CONTINUE_RUN; + } else if (aidev->is_parthdl && (aidev->parthdl_idx + 1 < aidev->parthdl_num)) { + aidev->parthdl_idx++; + aidev->run_idx = 0; + rkaiisp_run_cfg(aidev, aidev->run_idx); + rkaiisp_run_start(aidev); + return CONTINUE_RUN; } aidev->frm_ed = ktime_get_ns(); diff --git a/drivers/media/platform/rockchip/aiisp/aiisp.h b/drivers/media/platform/rockchip/aiisp/aiisp.h index 37bd8b44e35b..7ee816c91a6c 100644 --- a/drivers/media/platform/rockchip/aiisp/aiisp.h +++ b/drivers/media/platform/rockchip/aiisp/aiisp.h @@ -37,6 +37,8 @@ #define RKAIISP_SW_REG_SIZE 0x3000 #define RKAIISP_SW_MAX_SIZE (RKAIISP_SW_REG_SIZE * 2) #define RKAIISP_AIRMS_BUF_MAXCNT 8 +#define RKAIISP_AIRMS_MAX_WIDTH 4096 +#define RKAIISP_AIRMS_EXTEND_PIXEL 16 #define RKAIISP_MIN(a, b) ((a) < (b) ? (a) : (b)) enum rkaiisp_irqhdl_ret { @@ -121,7 +123,9 @@ struct rkaiisp_device { struct rkaiisp_dummy_buffer *lastout_buf[RKAIISP_LASTOUT_BUF_CNT]; u32 outbuf_idx; + bool is_parthdl; struct rkaiisp_rmsbuf_info rmsbuf; + struct rkaiisp_rmsbuf_info part_rmsbuf; struct rkaiisp_dummy_buffer rms_inbuf[RKAIISP_AIRMS_BUF_MAXCNT]; struct rkaiisp_dummy_buffer rms_outbuf[RKAIISP_AIRMS_BUF_MAXCNT]; struct rkaiisp_dummy_buffer narmap_buf; @@ -149,6 +153,10 @@ struct rkaiisp_device { u32 run_idx; u32 frame_id; + u32 parthdl_idx; + u32 parthdl_num; + u32 parthdl_image_oft; + u64 pre_frm_st; u64 frm_st; u64 frm_ed; @@ -160,6 +168,7 @@ struct rkaiisp_device { bool streamon; bool showreg; bool init_buf; + bool is_state_err; }; extern int rkaiisp_debug; From dcb85d8d3470cb4f1a92ad3fb25d4cb20e7dbdd5 Mon Sep 17 00:00:00 2001 From: Xuhui Lin Date: Tue, 24 Jun 2025 15:18:05 +0800 Subject: [PATCH 20/23] spi: rockchip-slave: Support dma cyclic for misc devices Change-Id: I46ad77c9879f1d89dcc682ac201ff6aac5f46bbe Signed-off-by: Xuhui Lin --- drivers/spi/Kconfig | 10 + drivers/spi/spi-rockchip-slave.c | 305 +++++++++++++++++++++++++- include/uapi/linux/spi/rk-spi-slave.h | 15 ++ 3 files changed, 322 insertions(+), 8 deletions(-) create mode 100644 include/uapi/linux/spi/rk-spi-slave.h diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig index 98ecebb135ad..a3ae9a808e8e 100644 --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig @@ -816,6 +816,16 @@ config SPI_ROCKCHIP_SLAVE SPI Slave controller. Rockchip SPI Slave controller support DMA transport and IRQ mode. +config SPI_ROCKCHIP_SLAVE_MISCDEV + bool "Rockchip SPI controller Slave misc devices" + depends on SPI_ROCKCHIP_SLAVE + help + This selects a misc driver for Rockchip SPI Slave controller. + + If you say yes to this option, It will register rkspi-slave-devN misc device + for each spi controller slave and support to get the controller register + resource by calling mmap. + config SPI_RB4XX tristate "Mikrotik RB4XX SPI master" depends on SPI_MASTER && ATH79 diff --git a/drivers/spi/spi-rockchip-slave.c b/drivers/spi/spi-rockchip-slave.c index 4ce660fc734c..cab98219196f 100644 --- a/drivers/spi/spi-rockchip-slave.c +++ b/drivers/spi/spi-rockchip-slave.c @@ -12,11 +12,13 @@ #include #include #include +#include #include #include #include #include #include +#include #include #include #include @@ -161,16 +163,19 @@ enum rockchip_spi_slave_xfer_mode { }; struct rockchip_spi { + struct spi_controller *ctlr; struct device *dev; struct clk_bulk_data *clks; unsigned int clk_cnt; + struct dma_async_tx_descriptor *rx_cyclic_desc; void __iomem *regs; dma_addr_t dma_addr_rx; dma_addr_t dma_addr_tx; u32 *dma_buf; dma_addr_t dma_phys; + u32 dma_cyclic_period_count; const void *tx; void *rx; @@ -183,6 +188,7 @@ struct rockchip_spi { u32 version; /*depth of the FIFO buffer */ u32 fifo_len; + int transfer_size; int max_transfer_size; u32 fixed_burst_size; u8 tx_idle_type; /* 0-SR_TF_EMPTY 1-SR_SLAVE_TX_BUSY */ @@ -190,6 +196,7 @@ struct rockchip_spi { u8 n_bytes; u32 speed_hz; + u32 mode; bool slave_aborted; bool cs_inactive; /* spi slave tansmition stop when cs inactive */ @@ -198,6 +205,11 @@ struct rockchip_spi { enum rockchip_spi_slave_xfer_mode xfer_mode; bool ext_spi_clk; + /* misc */ + struct miscdevice miscdev; + struct mutex lock; + size_t write_pos; + size_t read_pos; bool verbose; ktime_t dbg_time; }; @@ -329,12 +341,17 @@ static irqreturn_t rockchip_spi_slave_isr(int irq, void *dev_id) } /* When int_cs_inactive comes, spi slave abort */ - if (rs->cs_inactive && readl_relaxed(rs->regs + ROCKCHIP_SPI_ISR) & INT_CS_INACTIVE) { - - rs->slave_aborted = true; - writel_relaxed(0, rs->regs + ROCKCHIP_SPI_IMR); - writel_relaxed(0xffffffff, rs->regs + ROCKCHIP_SPI_ICR); - complete(&rs->xfer_done); + if (rs->cs_inactive && + readl_relaxed(rs->regs + ROCKCHIP_SPI_ISR) & INT_CS_INACTIVE) { + /* Means using dma cyclic now */ + if (rs->rx_cyclic_desc) { + writel_relaxed(0xffffffff, rs->regs + ROCKCHIP_SPI_ICR); + } else { + rs->slave_aborted = true; + writel_relaxed(0, rs->regs + ROCKCHIP_SPI_IMR); + writel_relaxed(0xffffffff, rs->regs + ROCKCHIP_SPI_ICR); + complete(&rs->xfer_done); + } } return IRQ_HANDLED; @@ -473,6 +490,46 @@ static int rockchip_spi_slave_prepare_dma(struct rockchip_spi *rs, return 1; } +static int rockchip_spi_slave_prepare_cyclic_dma(struct rockchip_spi *rs, + struct spi_controller *ctlr, + struct spi_transfer *xfer) +{ + struct dma_async_tx_descriptor *rxdesc = NULL; + + atomic_set(&rs->state, 0); + + if (xfer->rx_buf) { + struct dma_slave_config rxconf = { + .direction = DMA_DEV_TO_MEM, + .src_addr = rs->dma_addr_rx, + .src_addr_width = rs->n_bytes, + .src_maxburst = + rockchip_spi_slave_calc_burst_size(rs, xfer->len / rs->n_bytes), + }; + + dmaengine_slave_config(ctlr->dma_rx, &rxconf); + rxdesc = dmaengine_prep_dma_cyclic(ctlr->dma_rx, rs->dma_phys, xfer->len, + xfer->len > rs->dma_cyclic_period_count ? + xfer->len / rs->dma_cyclic_period_count : xfer->len, + DMA_DEV_TO_MEM, DMA_PREP_INTERRUPT); + if (!rxdesc) + return -EINVAL; + + rxdesc->callback = NULL; + rxdesc->callback_param = ctlr; + } + + /* rx must be started before tx due to spi instinct */ + if (rxdesc) { + atomic_or(RXDMA, &rs->state); + ctlr->dma_rx->cookie = dmaengine_submit(rxdesc); + dma_async_issue_pending(ctlr->dma_rx); + rs->rx_cyclic_desc = rxdesc; + } + + return 0; +} + static bool rockchip_spi_slave_can_dma(struct spi_controller *ctlr, struct spi_device *spi, struct spi_transfer *xfer) @@ -497,6 +554,7 @@ static int rockchip_spi_slave_config(struct rockchip_spi *rs, u32 cr1; u32 dmacr = 0; u32 val = 0; + u32 mode = 0; rs->slave_aborted = false; if (xfer->speed_hz) @@ -504,8 +562,12 @@ static int rockchip_spi_slave_config(struct rockchip_spi *rs, else rs->speed_hz = 100000; - cr0 |= (spi->mode & 0x3U) << CR0_SCPH_OFFSET; - if (spi->mode & SPI_LSB_FIRST) + if (spi) + mode = spi->mode; + else + mode = rs->ctlr->mode_bits; + cr0 |= (mode & 0x3U) << CR0_SCPH_OFFSET; + if (mode & SPI_LSB_FIRST) cr0 |= CR0_FBM_LSB << CR0_FBM_OFFSET; if (xfer->rx_buf && xfer->tx_buf) { @@ -751,11 +813,211 @@ static int rockchip_spi_slave_setup(struct spi_device *spi) cr0 |= ((spi->mode & 0x3) << CR0_SCPH_OFFSET) | CR0_OPM_SLAVE << CR0_OPM_OFFSET; writel_relaxed(cr0, rs->regs + ROCKCHIP_SPI_CTRLR0); + rs->mode = spi->mode; + pm_runtime_put(rs->dev); return 0; } +static int rockchip_spi_slave_misc_open(struct inode *inode, struct file *file) +{ + struct miscdevice *miscdev = file->private_data; + struct rockchip_spi *rs; + + rs = container_of(miscdev, struct rockchip_spi, miscdev); + file->private_data = rs; + + pm_runtime_get_sync(rs->dev); + + return 0; +} + +static int rockchip_spi_slave_misc_init_cyclic(struct rockchip_spi *rs, int length) +{ + struct spi_transfer *xfer; + int ret = 0; + u32 status; + + if (length > rs->max_transfer_size) { + dev_err(rs->dev, "Transfer is too long (%d)\n", length); + return -EINVAL; + } + + if (rs->cs_inactive) { + ret = readl_poll_timeout(rs->regs + ROCKCHIP_SPI_SR, status, + status & SR_SS_IN_N, 20, + ROCKCHIP_SPI_CLK_TO_CS_DEASSERT_US); + if (ret) { + dev_err(rs->dev, "The cs of spi master is still asserted\n"); + return -EIO; + } + } + + xfer = kzalloc(sizeof(struct spi_transfer), GFP_KERNEL); + if (!xfer) + return -ENOMEM; + + xfer->rx_buf = rs->dma_buf; + xfer->tx_buf = NULL; + xfer->len = length; + xfer->bits_per_word = 8; + xfer->speed_hz = 1000000; + rs->n_bytes = xfer->bits_per_word <= 8 ? 1 : 2; + rs->xfer_mode = ROCKCHIP_SPI_DMA; + + ret = rockchip_spi_slave_config(rs, NULL, xfer); + if (ret) + goto free_spi_transfer; + + rockchip_spi_slave_prepare_cyclic_dma(rs, rs->ctlr, xfer); + + /* Record for check */ + rs->transfer_size = xfer->len; + + if (rs->cs_inactive) + writel_relaxed(INT_CS_INACTIVE, rs->regs + ROCKCHIP_SPI_IMR); + + spi_enable_chip(rs, true); + + if (rs->ready) { + gpiod_set_value(rs->ready, 0); + gpiod_set_value(rs->ready, 1); + } + +free_spi_transfer: + kfree(xfer); + + return ret; +} + +static int rockchip_spi_slave_misc_deinit_cyclic(struct rockchip_spi *rs) +{ + struct spi_controller *ctlr = rs->ctlr; + + if (rs->rx_cyclic_desc) { + dmaengine_terminate_async(ctlr->dma_rx); + dmaengine_desc_free(rs->rx_cyclic_desc); + rs->rx_cyclic_desc = NULL; + } + + rockchip_spi_slave_stop(ctlr); + + rs->read_pos = 0; + rs->write_pos = 0; + + return 0; +} + +static long rockchip_spi_slave_misc_ioctl(struct file *file, unsigned int cmd, + unsigned long args) +{ + struct rockchip_spi *rs = file->private_data; + int length = (int)args; + int ret = 0; + + mutex_lock(&rs->lock); + + switch (cmd) { + case SPI_SLAVE_INIT_CYCLIC: + ret = rockchip_spi_slave_misc_init_cyclic(rs, length); + if (ret) + dev_err(rs->dev, "DMA cyclic init failed: %d\n", ret); + break; + case SPI_SLAVE_DEINIT_CYCLIC: + ret = rockchip_spi_slave_misc_deinit_cyclic(rs); + if (ret) + dev_err(rs->dev, "DMA cyclic deinit failed: %d\n", ret); + break; + default: + break; + } + + mutex_unlock(&rs->lock); + + return 0; +} + +static ssize_t rockchip_spi_slave_misc_read(struct file *file, char __user *buf, + size_t n, loff_t *offset) +{ + struct rockchip_spi *rs = file->private_data; + struct spi_controller *ctlr = rs->ctlr; + size_t to_copy, copied = 0; + int ret = 0; + size_t period_size = n > rs->dma_cyclic_period_count ? + n / rs->dma_cyclic_period_count : n; + size_t cur_index; + struct dma_tx_state state; + size_t data_available; + + mutex_lock(&rs->lock); + + if (n + (size_t)(*offset) > rs->transfer_size) { + dev_err(rs->dev, "Exceed the expected length: %zu + %lld > %d\n", + n, *offset, rs->transfer_size); + ret = -EINVAL; + goto out; + } + + dmaengine_tx_status(ctlr->dma_rx, ctlr->dma_rx->cookie, &state); + + cur_index = (period_size - state.residue) % period_size; + if (cur_index < rs->read_pos) + data_available = period_size - rs->read_pos + cur_index; + else + data_available = cur_index - rs->read_pos; + + to_copy = min(n, data_available); + + if (rs->read_pos + to_copy > period_size) { + + if (copy_to_user(buf, rs->dma_buf + rs->read_pos, + period_size - rs->read_pos)) { + ret = -EFAULT; + goto out; + } + + if (copy_to_user(buf + period_size - rs->read_pos, rs->dma_buf, + to_copy - period_size + rs->read_pos)) { + ret = -EFAULT; + goto out; + } + } else { + if (copy_to_user(buf, rs->dma_buf + rs->read_pos, to_copy)) { + ret = -EFAULT; + goto out; + } + } + + rs->read_pos = (rs->read_pos + to_copy) % period_size; + copied = to_copy; + +out: + mutex_unlock(&rs->lock); + return copied ? copied : ret; +} + +static int rockchip_spi_slave_misc_release(struct inode *inode, struct file *file) +{ + struct rockchip_spi *rs = file->private_data; + + mutex_lock(&rs->lock); + rockchip_spi_slave_misc_deinit_cyclic(rs); + mutex_unlock(&rs->lock); + + pm_runtime_put(rs->dev); + + return 0; +} + +static const struct file_operations rockchip_spi_slave_misc_fops = { + .open = rockchip_spi_slave_misc_open, + .release = rockchip_spi_slave_misc_release, + .unlocked_ioctl = rockchip_spi_slave_misc_ioctl, + .read = rockchip_spi_slave_misc_read, +}; + static int rockchip_spi_slave_probe(struct platform_device *pdev) { int ret = 0; @@ -774,6 +1036,8 @@ static int rockchip_spi_slave_probe(struct platform_device *pdev) platform_set_drvdata(pdev, ctlr); rs = spi_controller_get_devdata(ctlr); + rs->ctlr = ctlr; + mutex_init(&rs->lock); /* Get basic io resource and map it */ mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); @@ -924,6 +1188,12 @@ static int rockchip_spi_slave_probe(struct platform_device *pdev) if (!device_property_read_bool(&pdev->dev, "rockchip,dma-support-req-mix")) rs->dma_timeout = 0; + if (!device_property_read_u32(&pdev->dev, "rockchip,dma-cyclic-period-count", &val)) + /* DMA cyclic period count can't be zero */ + rs->dma_cyclic_period_count = val ? val : 1; + else + rs->dma_cyclic_period_count = 1; + rs->ready = devm_gpiod_get_optional(&pdev->dev, "ready", GPIOD_OUT_HIGH); if (IS_ERR(rs->ready)) { ret = PTR_ERR(rs->ready); @@ -937,6 +1207,22 @@ static int rockchip_spi_slave_probe(struct platform_device *pdev) goto err_free_dma_rx; } + if (IS_ENABLED(CONFIG_SPI_ROCKCHIP_SLAVE_MISCDEV)) { + char misc_name[20]; + + snprintf(misc_name, sizeof(misc_name), "rkspi-slv-dev%d", ctlr->bus_num); + rs->miscdev.minor = MISC_DYNAMIC_MINOR; + rs->miscdev.name = misc_name; + rs->miscdev.fops = &rockchip_spi_slave_misc_fops; + rs->miscdev.parent = &pdev->dev; + + ret = misc_register(&rs->miscdev); + if (ret) + dev_err(&pdev->dev, "failed to register misc device %s\n", misc_name); + else + dev_info(&pdev->dev, "register misc device %s\n", misc_name); + } + dev_info(rs->dev, "slave probed, cs-inactive=%d, ready=%d, ext=%d, dam_buf=%x\n", rs->cs_inactive, rs->ready ? 1 : 0, rs->ext_spi_clk, (u32)rs->dma_phys); @@ -961,6 +1247,9 @@ static int rockchip_spi_slave_remove(struct platform_device *pdev) struct spi_controller *ctlr = spi_controller_get(platform_get_drvdata(pdev)); struct rockchip_spi *rs = spi_controller_get_devdata(ctlr); + if (IS_ENABLED(CONFIG_SPI_ROCKCHIP_SLAVE_MISCDEV)) + misc_deregister(&rs->miscdev); + pm_runtime_get_sync(&pdev->dev); clk_bulk_disable_unprepare(rs->clk_cnt, rs->clks); diff --git a/include/uapi/linux/spi/rk-spi-slave.h b/include/uapi/linux/spi/rk-spi-slave.h new file mode 100644 index 000000000000..9a46703a91cf --- /dev/null +++ b/include/uapi/linux/spi/rk-spi-slave.h @@ -0,0 +1,15 @@ +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ +/* + * Copyright (c) 2025 Rockchip Electronics Co., Ltd. + */ + +#ifndef RK_SPI_SLAVE_H +#define RK_SPI_SLAVE_H + +#include + +#define SPI_SLAVE_BASE 's' +#define SPI_SLAVE_INIT_CYCLIC _IOW(SPI_SLAVE_BASE, 0, int) +#define SPI_SLAVE_DEINIT_CYCLIC _IOW(SPI_SLAVE_BASE, 1, int) + +#endif From 542f74d59052e27390d50fae644576cbf0c22f05 Mon Sep 17 00:00:00 2001 From: Chen Shunqing Date: Tue, 17 Jun 2025 15:40:02 +0800 Subject: [PATCH 21/23] media: i2c: rk628: reconfigure cec state when hdmirx reset Signed-off-by: Chen Shunqing Change-Id: I22b9f97b0e39874ecc926b618f0f8147209a40e3 --- drivers/media/i2c/rk628/rk628_bt1120_v4l2.c | 4 ++-- drivers/media/i2c/rk628/rk628_csi_v4l2.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/media/i2c/rk628/rk628_bt1120_v4l2.c b/drivers/media/i2c/rk628/rk628_bt1120_v4l2.c index 6c92a221257a..637028a2cf59 100644 --- a/drivers/media/i2c/rk628/rk628_bt1120_v4l2.c +++ b/drivers/media/i2c/rk628/rk628_bt1120_v4l2.c @@ -335,6 +335,8 @@ static void rk628_bt1120_hdmirx_reset(struct v4l2_subdev *sd) bt1120->hdcp.hdcp_start = false; enable_irq(bt1120->plugin_irq); enable_irq(bt1120->hdmirx_irq); + if (bt1120->cec && bt1120->cec->adap) + rk628_hdmirx_cec_state_reconfiguration(bt1120->rk628, bt1120->cec); } static void rk628_hdmirx_plugout(struct v4l2_subdev *sd) @@ -438,8 +440,6 @@ static void rk628_bt1120_delayed_work_enable_hotplug(struct work_struct *work) rk628_hdmirx_controller_setup(bt1120->rk628); rk628_hdmirx_hpd_ctrl(sd, true); rk628_hdmirx_config_all(sd); - if (bt1120->cec && bt1120->cec->adap) - rk628_hdmirx_cec_state_reconfiguration(bt1120->rk628, bt1120->cec); rk628_bt1120_enable_interrupts(sd, true); } else { bt1120->nosignal = true; diff --git a/drivers/media/i2c/rk628/rk628_csi_v4l2.c b/drivers/media/i2c/rk628/rk628_csi_v4l2.c index 6d26da0db4ab..f424a3cec945 100644 --- a/drivers/media/i2c/rk628/rk628_csi_v4l2.c +++ b/drivers/media/i2c/rk628/rk628_csi_v4l2.c @@ -498,6 +498,8 @@ static void rk628_csi_hdmirx_reset(struct v4l2_subdev *sd) csi->hdcp.hdcp_start = false; enable_irq(csi->plugin_irq); enable_irq(csi->hdmirx_irq); + if (csi->cec && csi->cec->adap) + rk628_hdmirx_cec_state_reconfiguration(csi->rk628, csi->cec); } static void rk628_hdmirx_plugout(struct v4l2_subdev *sd) @@ -574,8 +576,6 @@ static void rk628_csi_delayed_work_enable_hotplug(struct work_struct *work) rk628_hdmirx_controller_setup(csi->rk628); rk628_hdmirx_hpd_ctrl(sd, true); rk628_hdmirx_config_all(sd); - if (csi->cec && csi->cec->adap) - rk628_hdmirx_cec_state_reconfiguration(csi->rk628, csi->cec); rk628_csi_enable_interrupts(sd, true); } else { extcon_set_state_sync(csi->extcon, EXTCON_JACK_VIDEO_IN, false); From fe5312f2aacdf2c221dad0b06f7b833514290420 Mon Sep 17 00:00:00 2001 From: Chen Shunqing Date: Sat, 12 Jul 2025 15:36:04 +0800 Subject: [PATCH 22/23] media: rockchip: hdmirx: add RK_HDMIRX_CMD_GET_SCAN_MODE Signed-off-by: Chen Shunqing Change-Id: I549c04189564cd90698efae73549f15499da0a96 --- drivers/media/platform/rockchip/hdmirx/rk_hdmirx.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/drivers/media/platform/rockchip/hdmirx/rk_hdmirx.c b/drivers/media/platform/rockchip/hdmirx/rk_hdmirx.c index c0e48799014a..afff5b3addb3 100644 --- a/drivers/media/platform/rockchip/hdmirx/rk_hdmirx.c +++ b/drivers/media/platform/rockchip/hdmirx/rk_hdmirx.c @@ -2485,6 +2485,8 @@ static long hdmirx_ioctl_default(struct file *file, void *fh, { struct hdmirx_stream *stream = video_drvdata(file); struct rk_hdmirx_dev *hdmirx_dev = stream->hdmirx_dev; + struct v4l2_dv_timings timings = hdmirx_dev->timings; + struct v4l2_bt_timings *bt = &timings.bt; long ret = 0; bool hpd; enum mute_type type; @@ -2497,6 +2499,14 @@ static long hdmirx_ioctl_default(struct file *file, void *fh, case RK_HDMIRX_CMD_GET_FPS: *(int *)arg = hdmirx_dev->get_timing ? hdmirx_dev->fps : 0; break; + case RK_HDMIRX_CMD_GET_SCAN_MODE: + if (!hdmirx_dev->get_timing) + *(int *)arg = HDMIRX_PROGRESSIVE; + else if (bt->interlaced == V4L2_DV_INTERLACED) + *(int *)arg = HDMIRX_INTERLACED; + else + *(int *)arg = HDMIRX_PROGRESSIVE; + break; case RK_HDMIRX_CMD_GET_SIGNAL_STABLE_STATUS: *(int *)arg = hdmirx_dev->get_timing; break; From 3fc5e850f4018da7d2c6bacadfc77267a428abec Mon Sep 17 00:00:00 2001 From: Simon Xue Date: Fri, 11 Jul 2025 14:39:07 +0800 Subject: [PATCH 23/23] arm64: dts: rockchip: rv1126b: Add decom_mmu clk to decom Since the decom_mmu uses a dedicated clock, its clk must be included in the decom's clk management to ensure proper operation. Change-Id: Id95c4563c092dcf1cab09c190fa82d24018b6a1d Signed-off-by: Simon Xue --- arch/arm64/boot/dts/rockchip/rv1126b.dtsi | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm64/boot/dts/rockchip/rv1126b.dtsi b/arch/arm64/boot/dts/rockchip/rv1126b.dtsi index 76a69b31842d..fa046cdc5f6f 100644 --- a/arch/arm64/boot/dts/rockchip/rv1126b.dtsi +++ b/arch/arm64/boot/dts/rockchip/rv1126b.dtsi @@ -3377,8 +3377,8 @@ compatible = "rockchip,hw-decompress"; reg = <0x22100000 0x1000>; interrupts = ; - clocks = <&cru ACLK_DECOM>, <&cru DCLK_DECOM>, <&cru PCLK_DECOM>; - clock-names = "aclk", "dclk", "pclk"; + clocks = <&cru ACLK_DECOM>, <&cru DCLK_DECOM>, <&cru PCLK_DECOM>, <&cru ACLK_RKMMU_DECOM>, <&cru HCLK_RKMMU_DECOM>; + clock-names = "aclk", "dclk", "pclk", "aclk_mmu", "hclk_mmu"; resets = <&cru SRST_DRESETN_DECOM>; reset-names = "dresetn"; status = "disabled";