From 3b55829f9f5179cefecde44bff186a70060b5cb7 Mon Sep 17 00:00:00 2001 From: Weiwen Chen Date: Thu, 21 Aug 2025 14:27:24 +0800 Subject: [PATCH 01/14] arm64: config: rv1126b: Enable CONFIG_SQUASHFS Signed-off-by: Weiwen Chen Change-Id: I9571f0acb3ef6dcfc7740c22f6a7fa15e0ed6eba --- arch/arm64/configs/rv1126b_defconfig | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/arch/arm64/configs/rv1126b_defconfig b/arch/arm64/configs/rv1126b_defconfig index 8cc703a64fa2..f5f028a613af 100644 --- a/arch/arm64/configs/rv1126b_defconfig +++ b/arch/arm64/configs/rv1126b_defconfig @@ -342,6 +342,10 @@ CONFIG_EXT4_FS=y CONFIG_AUTOFS4_FS=y CONFIG_VFAT_FS=y CONFIG_TMPFS=y +CONFIG_SQUASHFS=y +CONFIG_SQUASHFS_DECOMP_MULTI=y +CONFIG_SQUASHFS_XZ=y +CONFIG_SQUASHFS_4K_DEVBLK_SIZE=y CONFIG_PSTORE=y CONFIG_PSTORE_CONSOLE=y CONFIG_PSTORE_RAM=y From c820efabce9874275e6af7c720558930e29bacbd Mon Sep 17 00:00:00 2001 From: Yu Qiaowei Date: Thu, 21 Aug 2025 11:30:53 +0800 Subject: [PATCH 02/14] video: rockchip: rga3: mpi_commit: support modify width/height in rotate 90/270 Change-Id: I20372e8b4b12ebc10ad3b9d89d9ef67c04edbdd5 Signed-off-by: Yu Qiaowei --- drivers/video/rockchip/rga3/rga_drv.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/drivers/video/rockchip/rga3/rga_drv.c b/drivers/video/rockchip/rga3/rga_drv.c index b764ae6ed460..8a270a75b1c7 100644 --- a/drivers/video/rockchip/rga3/rga_drv.c +++ b/drivers/video/rockchip/rga3/rga_drv.c @@ -159,13 +159,24 @@ int rga_mpi_commit(struct rga_mpi_job_t *mpi_job) &mpi_cmd.pat, &cached_cmd->pat); - if ((mpi_job->dst != NULL) && (request->flags & RGA_CONTEXT_DST_MASK)) + if ((mpi_job->dst != NULL) && (request->flags & RGA_CONTEXT_DST_MASK)) { rga_mpi_set_channel_info(RGA_CONTEXT_DST_MASK, request->flags, mpi_job->dst, &mpi_cmd.dst, &cached_cmd->dst); + /* rotate 90/270 */ + if (((mpi_cmd.rotate_mode & 0xf) == 1) && + ((mpi_cmd.sina == 65536 && mpi_cmd.cosa == 0) || + (mpi_cmd.sina == -65536 && mpi_cmd.cosa == 0))) { + swap(mpi_cmd.dst.act_w, mpi_cmd.dst.act_h); + + if (request->flags & RGA_CONTEXT_DST_CACHE_INFO) + swap(cached_cmd->dst.act_w, cached_cmd->dst.act_h); + } + } + /* set buffer handle */ if (mpi_job->dma_buf_src0 != NULL) { ret = rga_mpi_set_channel_buffer(mpi_job->dma_buf_src0, From 8fa42a17cfadcefe395e2e02b46e2249a822910d Mon Sep 17 00:00:00 2001 From: Weiwen Chen Date: Fri, 22 Aug 2025 11:24:53 +0800 Subject: [PATCH 03/14] arm64: config: rv1126b: Enable CONFIG_VIDEO_ROCKCHIP_AIISP Signed-off-by: Weiwen Chen Change-Id: I1c0cfae2b3044f733163fe0a538559a5857d2fd6 --- arch/arm64/configs/rv1126b_defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/configs/rv1126b_defconfig b/arch/arm64/configs/rv1126b_defconfig index f5f028a613af..c5fe46abb8c6 100644 --- a/arch/arm64/configs/rv1126b_defconfig +++ b/arch/arm64/configs/rv1126b_defconfig @@ -205,6 +205,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_ISP=y CONFIG_VIDEO_ROCKCHIP_VPSS=y From 308d91769707edc9898ea26edc5e8fa81661e263 Mon Sep 17 00:00:00 2001 From: Wei Dun Date: Thu, 21 Aug 2025 16:24:29 +0800 Subject: [PATCH 04/14] media: rockchip: vpss: add FBC format alignment check for width/height Change-Id: Ia35e17fd0c825b694f609c2a8f3636d261465c7c Signed-off-by: Wei Dun --- .../platform/rockchip/vpss/vpss_offline_v20.c | 68 +++++++++++++++---- 1 file changed, 56 insertions(+), 12 deletions(-) diff --git a/drivers/media/platform/rockchip/vpss/vpss_offline_v20.c b/drivers/media/platform/rockchip/vpss/vpss_offline_v20.c index 55afee3a99f7..97b8647a8f71 100644 --- a/drivers/media/platform/rockchip/vpss/vpss_offline_v20.c +++ b/drivers/media/platform/rockchip/vpss/vpss_offline_v20.c @@ -946,11 +946,6 @@ static int read_config(struct rkvpss_offline_dev *ofl, u32 in_ctrl, in_size, in_c_offs, unite_r_offs, val, mask, unite_off = 0, enlarge = 0, header_size = 0, payload_size = 0; - if (!IS_ALIGNED(cfg->input.stride, 4)) { - v4l2_err(&ofl->v4l2_dev, "input stride %d is not 4-byte aligned\n", cfg->input.stride); - return -EINVAL; - } - in_c_offs = 0; in_ctrl = 0; switch (cfg->input.format) { @@ -1348,17 +1343,10 @@ static int write_config(struct rkvpss_offline_dev *ofl, cfg->dev_id, i); cfg->output[i].enable = 0; } - if (!cfg->output[i].enable) continue; ch_en = true; - if (!IS_ALIGNED(cfg->output[i].stride, 4)) { - v4l2_err(&ofl->v4l2_dev, "output stride %d is not 4-byte aligned for ch%d\n", - cfg->output[i].stride, i); - return -EINVAL; - } - if (cfg->output[i].aspt.enable) { w = cfg->output[i].aspt.width; h = cfg->output[i].aspt.height; @@ -2028,6 +2016,34 @@ int rkvpss_check_params(struct rkvpss_offline_dev *ofl, goto end; } + /* check input format alignment */ + if (cfg->input.format == V4L2_PIX_FMT_FBC0 || + cfg->input.format == V4L2_PIX_FMT_FBC2 || + cfg->input.format == V4L2_PIX_FMT_FBC4) { + if (!IS_ALIGNED(cfg->input.width, 64)) { + v4l2_err(&ofl->v4l2_dev, + "dev_id:%d fbc input width %d is not 64 aligned\n", + cfg->dev_id, cfg->input.width); + ret = -EINVAL; + goto end; + } + if (!IS_ALIGNED(cfg->input.height, 4)) { + v4l2_err(&ofl->v4l2_dev, + "dev_id:%d fbc input height %d is not 4 aligned\n", + cfg->dev_id, cfg->input.height); + ret = -EINVAL; + goto end; + } + } else { + if (!IS_ALIGNED(cfg->input.stride, 4)) { + v4l2_err(&ofl->v4l2_dev, + "dev_id:%d input stride %d is not 4-byte aligned\n", + cfg->dev_id, cfg->input.stride); + ret = -EINVAL; + goto end; + } + } + *unite = false; if (cfg->input.width > RKVPSS_MAX_WIDTH_V20) { *unite = true; @@ -2107,6 +2123,34 @@ int rkvpss_check_params(struct rkvpss_offline_dev *ofl, goto end; } + /* check output format alignment */ + if (cfg->output[i].format == V4L2_PIX_FMT_FBC0 || + cfg->output[i].format == V4L2_PIX_FMT_FBC2 || + cfg->output[i].format == V4L2_PIX_FMT_FBC4) { + if (!IS_ALIGNED(cfg->input.width, 64)) { + v4l2_err(&ofl->v4l2_dev, + "dev_id:%d ch:%d fbc output width %d is not 64 aligned\n", + cfg->dev_id, i, cfg->input.width); + ret = -EINVAL; + goto end; + } + if (!IS_ALIGNED(cfg->input.height, 4)) { + v4l2_err(&ofl->v4l2_dev, + "dev_id:%d ch:%d fbc output height %d is not 4 aligned\n", + cfg->dev_id, i, cfg->input.height); + ret = -EINVAL; + goto end; + } + } else { + if (!IS_ALIGNED(cfg->output[i].stride, 4)) { + v4l2_err(&ofl->v4l2_dev, + "dev_id:%d ch:%d output stride %d is not 4-byte aligned\n", + cfg->dev_id, i, cfg->output[i].stride); + ret = -EINVAL; + goto end; + } + } + /* check output size */ if (cfg->output[i].aspt.enable) { out_width = cfg->output[i].aspt.width; From 702cba79f028f799cf4eea93f2e71eec576df4ef Mon Sep 17 00:00:00 2001 From: XiaoDong Huang Date: Wed, 23 Jul 2025 17:34:40 +0800 Subject: [PATCH 05/14] dt-bindings: suspend: rv1126b: add RKPM_SLP_32K_IO macro Signed-off-by: XiaoDong Huang Change-Id: I1c6b01d8023db0c82aaac0fcf6c23b054b676d4a --- include/dt-bindings/suspend/rockchip-rv1126b.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/dt-bindings/suspend/rockchip-rv1126b.h b/include/dt-bindings/suspend/rockchip-rv1126b.h index 3b51c78d626d..04da220a35fa 100644 --- a/include/dt-bindings/suspend/rockchip-rv1126b.h +++ b/include/dt-bindings/suspend/rockchip-rv1126b.h @@ -24,6 +24,7 @@ #define RKPM_SLP_CLK_GT BIT(16) #define RKPM_SLP_PMIC_LP BIT(17) +#define RKPM_SLP_32K_IO BIT(23) #define RKPM_SLP_32K_EXT BIT(24) #define RKPM_SLP_TIME_OUT_WKUP BIT(25) #define RKPM_SLP_PMU_DBG BIT(26) From 1ef5a401b94cbca88f13ee9e727ffa97c140ff8f Mon Sep 17 00:00:00 2001 From: Xu Xuehui Date: Mon, 19 May 2025 11:07:12 +0800 Subject: [PATCH 06/14] Revert "PCI: disable L0s for CYW989459 Wireless Module" This reverts commit fa17e4b1d3ce6498d7864b3aac1706f1bc1efbc1. Signed-off-by: Xu Xuehui Change-Id: I5b7ee55610cfc0861e637f6234229f95b23bc44a --- drivers/pci/quirks.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index 3cb8a6856c7a..ffb8cac4dc14 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c @@ -2398,7 +2398,6 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x10ec, quirk_disable_aspm_l0s); DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x10f1, quirk_disable_aspm_l0s); DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x10f4, quirk_disable_aspm_l0s); DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x1508, quirk_disable_aspm_l0s); -DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_BROADCOM, 0x4415, quirk_disable_aspm_l0s); static void quirk_disable_aspm_l0s_l1(struct pci_dev *dev) { From 52a34e877ed9a6c978fc9e5a8263a34a7f08a8b0 Mon Sep 17 00:00:00 2001 From: Xu Xuehui Date: Mon, 19 May 2025 11:07:12 +0800 Subject: [PATCH 07/14] PCI/ASPM: Disable ASPM L0s/L1 on CYW989459 Wireless Module Signed-off-by: Xu Xuehui Change-Id: Ib4b93edaa9161e4ebd46243561014bdbb87c43ca --- drivers/pci/quirks.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index ffb8cac4dc14..d0f1f96dccce 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c @@ -2411,6 +2411,7 @@ static void quirk_disable_aspm_l0s_l1(struct pci_dev *dev) * disable both L0s and L1 for now to be safe. */ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ASMEDIA, 0x1080, quirk_disable_aspm_l0s_l1); +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_BROADCOM, 0x4415, quirk_disable_aspm_l0s_l1); /* * Micron 2100AI NVMe doesn't work reliably when ASPM is enabled. Disable From 9d7731c347fce3c51f45800ebb1b263532e2f6ee Mon Sep 17 00:00:00 2001 From: Yifeng Zhao Date: Fri, 22 Aug 2025 10:37:41 +0800 Subject: [PATCH 08/14] soc: rockchip: thunderboot_mmc: disable DMA upon transfer completion Signed-off-by: Yifeng Zhao Change-Id: I8f61eae3acdef85157452a29124e95e7fc4cf1fb --- drivers/soc/rockchip/rockchip_thunderboot_mmc.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/soc/rockchip/rockchip_thunderboot_mmc.c b/drivers/soc/rockchip/rockchip_thunderboot_mmc.c index 4c73ae4613fe..3ca747066a6b 100644 --- a/drivers/soc/rockchip/rockchip_thunderboot_mmc.c +++ b/drivers/soc/rockchip/rockchip_thunderboot_mmc.c @@ -16,8 +16,11 @@ #include #include +#define SDMMC_CTRL 0x000 #define SDMMC_RINTSTS 0x044 #define SDMMC_STATUS 0x048 +#define SDMMC_BMOD 0x080 +#define SDMMC_DBADDR 0x088 #define SDMMC_IDSTS 0x08c #define SDMMC_INTR_ERROR 0xB7C2 @@ -76,6 +79,11 @@ static int rk_tb_mmc_thread(void *p) goto out; } + /* Disable the DMA of the MMC controller */ + writel(0, regs + SDMMC_CTRL); + writel(0, regs + SDMMC_BMOD); + writel(0, regs + SDMMC_DBADDR); + /* Parse ramdisk addr and help start decompressing */ if (rds && rdd) { struct resource src, dst; From 5a0dd5d2ca6c74cd72c5853638abbd44be4125fa Mon Sep 17 00:00:00 2001 From: Ziyuan Xu Date: Sat, 23 Aug 2025 17:43:02 +0800 Subject: [PATCH 09/14] ARM: dts: rockchip: Fixes mmc_ecsd address for rv1126b-thunder-boot-emmc Fixes: 327f2160651 ("ARM: dts: rockchip: Add rv1126b-evb2-v10-tb-400w-spi-nor support") Signed-off-by: Ziyuan Xu Change-Id: Id10e07c350f146e5c75f4657e3fa2b491e8c417c --- arch/arm/boot/dts/rv1126b-thunder-boot-emmc.dtsi | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm/boot/dts/rv1126b-thunder-boot-emmc.dtsi b/arch/arm/boot/dts/rv1126b-thunder-boot-emmc.dtsi index 1d5b33308f53..da03f4fcbe13 100644 --- a/arch/arm/boot/dts/rv1126b-thunder-boot-emmc.dtsi +++ b/arch/arm/boot/dts/rv1126b-thunder-boot-emmc.dtsi @@ -23,8 +23,8 @@ }; &reserved_memory { - mmc_ecsd: mmc@47fffe00 { - reg = <0x47fffe00 0x00001000>; + mmc_ecsd: mmc@47fff000 { + reg = <0x47fff000 0x00001000>; }; mmc_idmac: mmc@48000000 { From ea06a72307595ef10e34fd654f0e7d3bf151da67 Mon Sep 17 00:00:00 2001 From: Ziyuan Xu Date: Sat, 23 Aug 2025 17:45:40 +0800 Subject: [PATCH 10/14] arm64: dts: rockchip: Fixes mmc_ecsd address for rv1126b-fastboot-emmc Fixes: dbdfcd9a914 ("arm64: dts: rockchip: Add rv1126b fastboot for emmc/spi nand/spi nor") Signed-off-by: Ziyuan Xu Change-Id: I2797f7c9552c5ce4306858f59078f544fffa037b --- arch/arm64/boot/dts/rockchip/rv1126b-fastboot-emmc.dtsi | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm64/boot/dts/rockchip/rv1126b-fastboot-emmc.dtsi b/arch/arm64/boot/dts/rockchip/rv1126b-fastboot-emmc.dtsi index 698e5b2148a4..07c85f1b11f2 100644 --- a/arch/arm64/boot/dts/rockchip/rv1126b-fastboot-emmc.dtsi +++ b/arch/arm64/boot/dts/rockchip/rv1126b-fastboot-emmc.dtsi @@ -36,8 +36,8 @@ reg = <0x48000000 0x00400000>; }; - mmc_ecsd: mmc@47FFFE00{ - reg = <0x47FFFE00 0x00001000>; + mmc_ecsd: mmc@47FFF000{ + reg = <0x47FFF000 0x00001000>; }; ramdisk_r: ramdisk_r { From 6b47e41786d831c4ebcb3393133876cc2f4a07c9 Mon Sep 17 00:00:00 2001 From: Yandong Lin Date: Tue, 19 Aug 2025 16:16:47 +0800 Subject: [PATCH 11/14] video: rockchip: mpp: rkvenc2: Fix the timeout threshold config issue Change-Id: If08868806b167fa7d6b2dfd75b6ad0f44fde70a7 Signed-off-by: Yandong Lin --- drivers/video/rockchip/mpp/mpp_rkvenc2.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/drivers/video/rockchip/mpp/mpp_rkvenc2.c b/drivers/video/rockchip/mpp/mpp_rkvenc2.c index 61abd0cb6875..9e038d806e22 100644 --- a/drivers/video/rockchip/mpp/mpp_rkvenc2.c +++ b/drivers/video/rockchip/mpp/mpp_rkvenc2.c @@ -1474,13 +1474,10 @@ static void rkvenc2_calc_timeout_thd(struct mpp_dev *mpp) } /* - * When vepu_type is RKVENC_VEPU_510, multiplied by 256 core clock cycles, - * else use x1024 core clk cycles + * The frame timeout threshold is *1024 core clock cycles, + * but the sub module timeout threshold is 1/4 frame timeout. */ - if (hw->vepu_type == RKVENC_VEPU_510) - timeout_thd |= timeout_ms * (clk_get_rate(enc->core_clk_info.clk) / 256000); - else - timeout_thd |= timeout_ms * (clk_get_rate(enc->core_clk_info.clk) / 1024000); + timeout_thd |= timeout_ms * (clk_get_rate(enc->core_clk_info.clk) / 256000); mpp_write(mpp, RKVENC_WDG, timeout_thd); } From c79104d97229338effc16500da10bf9a03ef0b06 Mon Sep 17 00:00:00 2001 From: Yandong Lin Date: Fri, 22 Aug 2025 15:39:01 +0800 Subject: [PATCH 12/14] video: rockchip: mpp: Fix load info not clear issue The default is to clear mpp load info during suspend, but suspend config may be turned off, resulting in load info not being cleared. Change-Id: Ic930d3f691dc2f1694acfdc7ac1cbe4f022b4e62 Signed-off-by: Yandong Lin --- drivers/video/rockchip/mpp/mpp_service.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/drivers/video/rockchip/mpp/mpp_service.c b/drivers/video/rockchip/mpp/mpp_service.c index 4ae409738685..5cb9056acb50 100644 --- a/drivers/video/rockchip/mpp/mpp_service.c +++ b/drivers/video/rockchip/mpp/mpp_service.c @@ -335,6 +335,17 @@ static int mpp_show_device_load(struct seq_file *file, void *v) if (!mpp) continue; + + if (mpp->load_info.load_time) { + s64 time_diff_us; + + time_diff_us = ktime_us_delta(ktime_get(), + mpp->load_info.load_time); + if ((time_diff_us > 2 * srv->load_interval * 1000) || + list_empty(&queue->session_attach)) + mpp_dev_load_clear(mpp); + } + seq_printf(file, "%-25s load: %3d.%02d%% utilization: %3d.%02d%%\n", dev_name(mpp->dev), mpp->load_info.load, mpp->load_info.load_frac, From 949befa2e728b18654e0fcc217fc480ac2cf52de Mon Sep 17 00:00:00 2001 From: Algea Cao Date: Tue, 12 Aug 2025 11:09:17 +0800 Subject: [PATCH 13/14] drm/bridge: synopsys: dw-hdmi-qp: Independently configure color and infoframe When the HDMI status changes, there is no need to call dw_hdmi_qp_setup() function every time. The configuration can be carried out independently for specific changed parts. This can reduce delays and avoid mutual interference. Change-Id: I5999961893d517cba04c58ca0c96fe201d413ee0 Signed-off-by: Algea Cao --- drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c | 140 ++++++++----------- include/drm/bridge/dw_hdmi.h | 5 + 2 files changed, 67 insertions(+), 78 deletions(-) diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c index 4f3602d98d35..118153b0572d 100644 --- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c +++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c @@ -302,7 +302,6 @@ struct dw_hdmi_qp { bool sink_is_hdmi; bool sink_has_audio; bool dclk_en; - bool frl_switch; /* when frl mode switch color and freq is equal set true */ bool cec_enable; bool allm_enable; bool support_hdmi; @@ -321,6 +320,7 @@ struct dw_hdmi_qp { u8 phy_mask; /* desired phy int mask settings */ u8 mc_clkdis; /* clock disable register */ u8 hdcp_status; + u8 hdmi_changed_status; u32 max_ffe_lv; bool update; @@ -2263,9 +2263,6 @@ static int dw_hdmi_qp_flt_ltsp(struct dw_hdmi_qp *hdmi) /* exit frl mode, maybe it was a training failure or hdmi was disabled */ static int dw_hdmi_qp_flt_ltsl(struct dw_hdmi_qp *hdmi) { - if (hdmi->frl_switch) - return -EINVAL; - drm_scdc_writeb(hdmi->ddc, SCDC_CONFIG_1, 0); drm_scdc_writeb(hdmi->ddc, SCDC_UPDATE_0, BIT(5)); @@ -2280,9 +2277,6 @@ static int hdmi_set_op_mode(struct dw_hdmi_qp *hdmi, { int ret = 0; - if (hdmi->frl_switch) - return 0; - if (!link_cfg->frl_mode) { dev_info(hdmi->dev, "dw hdmi qp use tmds mode\n"); hdmi_modb(hdmi, 0, AVP_DATAPATH_VIDEO_SWDISABLE, GLOBAL_SWDISABLE); @@ -2420,9 +2414,6 @@ static void dw_hdmi_qp_flt_work(struct work_struct *p_work) u8 frl_rate; int state = LTS1; - if (hdmi->frl_switch) - return; - frl_rate = link_cfg->frl_lanes * link_cfg->rate_per_lane; while (1) { @@ -2532,7 +2523,7 @@ static int dw_hdmi_qp_setup(struct dw_hdmi_qp *hdmi, hdmi->phy.ops->set_mode(hdmi, hdmi->phy.data, HDMI_MODE_FRL_MASK, link_cfg->frl_mode); - if (!hdmi->update && !hdmi->frl_switch && hdmi->plat_data->link_clk_set) + if (!hdmi->update && hdmi->plat_data->link_clk_set) hdmi->plat_data->link_clk_set(data, true); /* @@ -2601,7 +2592,6 @@ static int dw_hdmi_qp_setup(struct dw_hdmi_qp *hdmi, ret = hdmi_set_op_mode(hdmi, link_cfg, connector); if (ret) { dev_err(hdmi->dev, "%s hdmi set operation mode failed\n", __func__); - hdmi->frl_switch = false; return ret; } } else { @@ -2613,7 +2603,6 @@ static int dw_hdmi_qp_setup(struct dw_hdmi_qp *hdmi, dev_info(hdmi->dev, "%s DVI mode\n", __func__); } - hdmi->frl_switch = false; return 0; } @@ -3158,27 +3147,6 @@ dw_hdmi_connector_best_encoder(struct drm_connector *connector) return hdmi->bridge.encoder; } -static bool dw_hdmi_color_changed(struct drm_connector *connector, - struct drm_atomic_state *state) -{ - struct dw_hdmi_qp *hdmi = - container_of(connector, struct dw_hdmi_qp, connector); - void *data = hdmi->plat_data->phy_data; - struct drm_connector_state *old_state = - drm_atomic_get_old_connector_state(state, connector); - struct drm_connector_state *new_state = - drm_atomic_get_new_connector_state(state, connector); - bool ret = false; - - if (hdmi->plat_data->get_color_changed) - ret = hdmi->plat_data->get_color_changed(data); - - if (new_state->colorspace != old_state->colorspace) - ret = true; - - return ret; -} - static bool hdr_metadata_equal(struct dw_hdmi_qp *hdmi, const struct drm_connector_state *old_state, const struct drm_connector_state *new_state) { @@ -3231,20 +3199,6 @@ static bool hdr_metadata_equal(struct dw_hdmi_qp *hdmi, const struct drm_connect return ret; } -static bool check_hdr_color_change(struct drm_connector_state *old_state, - struct drm_connector_state *new_state, - struct dw_hdmi_qp *hdmi) -{ - void *data = hdmi->plat_data->phy_data; - - if (!hdr_metadata_equal(hdmi, old_state, new_state)) { - hdmi->plat_data->check_hdr_color_change(new_state, data); - return true; - } - - return false; -} - static void dw_hdmi_qp_hdcp_disable(struct dw_hdmi_qp *hdmi, const struct drm_connector_state *conn_state) { @@ -3311,6 +3265,53 @@ static bool dovi_vsif_equal(struct dw_hdmi_qp *hdmi) } } +static u8 dw_hdmi_qp_state_changed(struct dw_hdmi_qp *hdmi, struct drm_connector *connector, + struct drm_atomic_state *state) +{ + struct drm_connector_state *old_state = + drm_atomic_get_old_connector_state(state, connector); + struct drm_connector_state *new_state = + drm_atomic_get_new_connector_state(state, connector); + void *data = hdmi->plat_data->phy_data; + u32 old_enc_in_encoding = hdmi->hdmi_data.enc_in_encoding; + u32 old_enc_out_encoding = hdmi->hdmi_data.enc_out_encoding; + u32 old_enc_in_bus_format = hdmi->hdmi_data.enc_in_bus_format; + u32 old_enc_out_bus_format = hdmi->hdmi_data.enc_out_bus_format; + + if (hdmi->plat_data->update_color_format) + hdmi->plat_data->update_color_format(new_state, data); + if (hdmi->plat_data->get_enc_in_encoding) + hdmi->hdmi_data.enc_in_encoding = hdmi->plat_data->get_enc_in_encoding(data); + if (hdmi->plat_data->get_enc_out_encoding) + hdmi->hdmi_data.enc_out_encoding = hdmi->plat_data->get_enc_out_encoding(data); + if (hdmi->plat_data->get_input_bus_format) + hdmi->hdmi_data.enc_in_bus_format = hdmi->plat_data->get_input_bus_format(data); + if (hdmi->plat_data->get_output_bus_format) + hdmi->hdmi_data.enc_out_bus_format = hdmi->plat_data->get_output_bus_format(data); + + hdmi->hdmi_changed_status = 0; + + if (!dovi_vsif_equal(hdmi)) + hdmi->hdmi_changed_status |= HDMI_VSIF_CHANGED; + + if (!hdr_metadata_equal(hdmi, old_state, new_state)) + hdmi->hdmi_changed_status |= HDMI_HDR_STATUS_CHANGED; + + if (old_enc_in_bus_format != hdmi->hdmi_data.enc_in_bus_format || + old_enc_out_bus_format != hdmi->hdmi_data.enc_out_bus_format || + old_enc_in_encoding != hdmi->hdmi_data.enc_in_encoding || + old_enc_out_encoding != hdmi->hdmi_data.enc_out_encoding) { + hdmi->hdmi_changed_status |= HDMI_COLOR_FMT_CHANGED; + if (hdmi->plat_data->set_prev_bus_format) + hdmi->plat_data->set_prev_bus_format(data, old_enc_out_bus_format); + } + + if (dw_hdmi_qp_check_output_type_changed(hdmi)) + hdmi->hdmi_changed_status |= HDMI_OUTPUT_MODE_CHANGED; + + return hdmi->hdmi_changed_status; +} + static int dw_hdmi_connector_atomic_check(struct drm_connector *connector, struct drm_atomic_state *state) { @@ -3414,44 +3415,25 @@ static int dw_hdmi_connector_atomic_check(struct drm_connector *connector, hdmi->logo_plug_out = true; } - if (check_hdr_color_change(old_state, new_state, hdmi) || hdmi->logo_plug_out || - dw_hdmi_color_changed(connector, state) || - dw_hdmi_qp_check_output_type_changed(hdmi)) { + if (dw_hdmi_qp_state_changed(hdmi, connector, state) || hdmi->logo_plug_out) { u32 mtmdsclk; crtc_state = drm_atomic_get_crtc_state(state, crtc); if (IS_ERR(crtc_state)) return PTR_ERR(crtc_state); - if (hdmi->plat_data->update_color_format) - hdmi->plat_data->update_color_format(new_state, data); - if (hdmi->plat_data->get_enc_in_encoding) - hdmi->hdmi_data.enc_in_encoding = - hdmi->plat_data->get_enc_in_encoding(data); - if (hdmi->plat_data->get_enc_out_encoding) - hdmi->hdmi_data.enc_out_encoding = - hdmi->plat_data->get_enc_out_encoding(data); - if (hdmi->plat_data->get_input_bus_format) - hdmi->hdmi_data.enc_in_bus_format = - hdmi->plat_data->get_input_bus_format(data); - if (hdmi->plat_data->get_output_bus_format) - hdmi->hdmi_data.enc_out_bus_format = - hdmi->plat_data->get_output_bus_format(data); - mtmdsclk = hdmi_get_tmdsclock(hdmi, mode.clock); if (hdmi_bus_fmt_is_yuv420(hdmi->hdmi_data.enc_out_bus_format)) mtmdsclk /= 2; if (hdmi->hdmi_data.video_mode.mpixelclock == (mode.clock * 1000) && hdmi->hdmi_data.video_mode.mtmdsclock == (mtmdsclk * 1000) && - mode.clock <= 600000 && !hdmi->disabled && !hdmi->logo_plug_out) { + !hdmi->disabled && !hdmi->logo_plug_out) { hdmi->update = true; hdmi_writel(hdmi, 1, PKTSCHED_PKT_CONTROL0); hdmi_modb(hdmi, PKTSCHED_GCP_TX_EN, PKTSCHED_GCP_TX_EN, PKTSCHED_PKT_EN); mdelay(50); } else if (!hdmi->disabled) { - if (hdmi->previous_mode.clock > 600000 && mode.clock > 600000) - hdmi->frl_switch = true; hdmi->update = false; crtc_state->mode_changed = true; hdmi->logo_plug_out = false; @@ -3468,7 +3450,14 @@ static void dw_hdmi_connector_atomic_commit(struct drm_connector *connector, container_of(connector, struct dw_hdmi_qp, connector); if (hdmi->update) { - dw_hdmi_qp_setup(hdmi, hdmi->curr_conn, &hdmi->previous_mode); + if (hdmi->hdmi_changed_status & HDMI_COLOR_FMT_CHANGED) { + if (hdmi->plat_data->set_grf_cfg) + hdmi->plat_data->set_grf_cfg(hdmi->plat_data->phy_data); + hdmi_config_AVI(hdmi, connector, &hdmi->previous_mode); + } + if (hdmi->hdmi_changed_status & HDMI_HDR_STATUS_CHANGED) + hdmi_config_drm_infoframe(hdmi, connector); + msleep(50); hdmi_writel(hdmi, 2, PKTSCHED_PKT_CONTROL0); hdmi->update = false; @@ -3476,7 +3465,7 @@ static void dw_hdmi_connector_atomic_commit(struct drm_connector *connector, if (!hdmi->disabled) { set_dw_hdmi_hdcp_enable(hdmi, connector, state); - if (!dovi_vsif_equal(hdmi)) + if (hdmi->hdmi_changed_status & HDMI_VSIF_CHANGED) hdmi_config_vendor_specific_infoframe(hdmi, hdmi->curr_conn, &hdmi->previous_mode); } @@ -3658,8 +3647,6 @@ static void dw_hdmi_qp_bridge_mode_set(struct drm_bridge *bridge, mutex_lock(&hdmi->mutex); - if (!drm_mode_equal(orig_mode, mode)) - hdmi->frl_switch = false; /* Store the display mode for plugin/DKMS poweron events */ drm_mode_copy(&hdmi->previous_mode, mode); if (hdmi->plat_data->split_mode || hdmi->plat_data->dual_connector_split) @@ -3687,9 +3674,6 @@ static void dw_hdmi_qp_bridge_atomic_disable(struct drm_bridge *bridge, return; } - if (link_cfg->dsc_mode) - hdmi->frl_switch = false; - /* set avmute */ hdmi_writel(hdmi, 1, PKTSCHED_PKT_CONTROL0); mdelay(50); @@ -3708,7 +3692,7 @@ static void dw_hdmi_qp_bridge_atomic_disable(struct drm_bridge *bridge, mutex_unlock(&hdmi->audio_mutex); }; - if (hdmi->phy.ops->disable && !hdmi->frl_switch) { + if (hdmi->phy.ops->disable) { hdmi_writel(hdmi, 0, FLT_CONFIG0); hdmi_writel(hdmi, 0, SCRAMB_CONFIG0); @@ -3756,7 +3740,7 @@ static void dw_hdmi_qp_bridge_atomic_enable(struct drm_bridge *bridge, dw_hdmi_qp_setup(hdmi, hdmi->curr_conn, &hdmi->previous_mode); - if ((link_cfg && !link_cfg->frl_mode) || hdmi->frl_switch) { + if (link_cfg && !link_cfg->frl_mode) { hdmi_writel(hdmi, 2, PKTSCHED_PKT_CONTROL0); hdmi_modb(hdmi, PKTSCHED_GCP_TX_EN, PKTSCHED_GCP_TX_EN, PKTSCHED_PKT_EN); } diff --git a/include/drm/bridge/dw_hdmi.h b/include/drm/bridge/dw_hdmi.h index 796c146c2555..820a3c24c209 100644 --- a/include/drm/bridge/dw_hdmi.h +++ b/include/drm/bridge/dw_hdmi.h @@ -82,6 +82,11 @@ struct platform_device; #define SUPPORT_HDMI_ALLM BIT(1) #define DOVI_VSIF_LEN 8 +#define HDMI_HDR_STATUS_CHANGED BIT(0) +#define HDMI_COLOR_FMT_CHANGED BIT(1) +#define HDMI_OUTPUT_MODE_CHANGED BIT(2) +#define HDMI_VSIF_CHANGED BIT(3) + enum { DW_HDMI_RES_8, DW_HDMI_RES_10, From 83950944033f768197600e90b37468f7e38cd388 Mon Sep 17 00:00:00 2001 From: Algea Cao Date: Mon, 18 Aug 2025 17:59:14 +0800 Subject: [PATCH 14/14] drm/bridge: synopsys: dw-hdmi: Fix hdmi color can't be switched when entering kernel In scenarios where U-boot can read EDID but the kernel cannot, HDMI color of U-boot and the kernel may differ. The current color switching process causes this scenario where HDMI enters the kernel but fails to switch to the correct color. Optimize process of switching colors to solve this problem. Change-Id: I36c7d7e68e438bd33f9d2804d4a5a34edda9ba4a Signed-off-by: Algea Cao --- drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 96 +++++++++------------ drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c | 26 ------ include/drm/bridge/dw_hdmi.h | 1 - 3 files changed, 41 insertions(+), 82 deletions(-) diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c index 0fcb06c19297..d546a3632c63 100644 --- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c +++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c @@ -304,6 +304,7 @@ struct dw_hdmi { bool rxsense; /* rxsense state */ u8 phy_mask; /* desired phy int mask settings */ u8 mc_clkdis; /* clock disable register */ + u8 hdmi_changed_status; spinlock_t audio_lock; struct mutex audio_mutex; @@ -3303,19 +3304,6 @@ dw_hdmi_connector_best_encoder(struct drm_connector *connector) return hdmi->bridge.encoder; } -static bool dw_hdmi_color_changed(struct drm_connector *connector) -{ - struct dw_hdmi *hdmi = container_of(connector, struct dw_hdmi, - connector); - void *data = hdmi->plat_data->phy_data; - bool ret = false; - - if (hdmi->plat_data->get_color_changed) - ret = hdmi->plat_data->get_color_changed(data); - - return ret; -} - static bool hdr_metadata_equal(struct dw_hdmi *hdmi, const struct drm_connector_state *old_state, const struct drm_connector_state *new_state) { @@ -3368,25 +3356,50 @@ static bool hdr_metadata_equal(struct dw_hdmi *hdmi, const struct drm_connector_ return ret; } -static bool check_hdr_color_change(struct drm_connector_state *old_state, - struct drm_connector_state *new_state, - struct dw_hdmi *hdmi) +static u8 dw_hdmi_state_changed(struct dw_hdmi *hdmi, struct drm_connector *connector, + struct drm_atomic_state *state) { + struct drm_connector_state *old_state = + drm_atomic_get_old_connector_state(state, connector); + struct drm_connector_state *new_state = + drm_atomic_get_new_connector_state(state, connector); void *data = hdmi->plat_data->phy_data; + u32 old_enc_in_encoding = hdmi->hdmi_data.enc_in_encoding; + u32 old_enc_out_encoding = hdmi->hdmi_data.enc_out_encoding; + u32 old_enc_in_bus_format = hdmi->hdmi_data.enc_in_bus_format; + u32 old_enc_out_bus_format = hdmi->hdmi_data.enc_out_bus_format; - if (!hdr_metadata_equal(hdmi, old_state, new_state)) { - hdmi->plat_data->check_hdr_color_change(new_state, data); - return true; + if (hdmi->plat_data->update_color_format) + hdmi->plat_data->update_color_format(new_state, data); + if (hdmi->plat_data->get_enc_in_encoding) + hdmi->hdmi_data.enc_in_encoding = hdmi->plat_data->get_enc_in_encoding(data); + if (hdmi->plat_data->get_enc_out_encoding) + hdmi->hdmi_data.enc_out_encoding = hdmi->plat_data->get_enc_out_encoding(data); + if (hdmi->plat_data->get_input_bus_format) + hdmi->hdmi_data.enc_in_bus_format = hdmi->plat_data->get_input_bus_format(data); + if (hdmi->plat_data->get_output_bus_format) + hdmi->hdmi_data.enc_out_bus_format = hdmi->plat_data->get_output_bus_format(data); + + hdmi->hdmi_changed_status = 0; + + if (!hdr_metadata_equal(hdmi, old_state, new_state)) + hdmi->hdmi_changed_status |= HDMI_HDR_STATUS_CHANGED; + + if (old_enc_in_bus_format != hdmi->hdmi_data.enc_in_bus_format || + old_enc_out_bus_format != hdmi->hdmi_data.enc_out_bus_format || + old_enc_in_encoding != hdmi->hdmi_data.enc_in_encoding || + old_enc_out_encoding != hdmi->hdmi_data.enc_out_encoding) { + hdmi->hdmi_changed_status |= HDMI_COLOR_FMT_CHANGED; + if (hdmi->plat_data->set_prev_bus_format) + hdmi->plat_data->set_prev_bus_format(data, old_enc_out_bus_format); } - return false; + return hdmi->hdmi_changed_status; } static int dw_hdmi_connector_atomic_check(struct drm_connector *connector, struct drm_atomic_state *state) { - struct drm_connector_state *old_state = - drm_atomic_get_old_connector_state(state, connector); struct drm_connector_state *new_state = drm_atomic_get_new_connector_state(state, connector); struct drm_crtc *crtc = new_state->crtc; @@ -3394,7 +3407,6 @@ static int dw_hdmi_connector_atomic_check(struct drm_connector *connector, struct dw_hdmi *hdmi = container_of(connector, struct dw_hdmi, connector); struct drm_display_mode *mode = NULL; - void *data = hdmi->plat_data->phy_data; struct hdmi_vmode *vmode = &hdmi->hdmi_data.video_mode; if (!crtc) @@ -3415,19 +3427,6 @@ static int dw_hdmi_connector_atomic_check(struct drm_connector *connector, hdmi->curr_conn = connector; - if (hdmi->plat_data->get_enc_in_encoding) - hdmi->hdmi_data.enc_in_encoding = - hdmi->plat_data->get_enc_in_encoding(data); - if (hdmi->plat_data->get_enc_out_encoding) - hdmi->hdmi_data.enc_out_encoding = - hdmi->plat_data->get_enc_out_encoding(data); - if (hdmi->plat_data->get_input_bus_format) - hdmi->hdmi_data.enc_in_bus_format = - hdmi->plat_data->get_input_bus_format(data); - if (hdmi->plat_data->get_output_bus_format) - hdmi->hdmi_data.enc_out_bus_format = - hdmi->plat_data->get_output_bus_format(data); - drm_mode_copy(&hdmi->previous_mode, mode); vmode->mpixelclock = mode->crtc_clock * 1000; vmode->previous_pixelclock = mode->clock * 1000; @@ -3441,30 +3440,14 @@ static int dw_hdmi_connector_atomic_check(struct drm_connector *connector, drm_scdc_readb(hdmi->ddc, SCDC_TMDS_CONFIG, &val); /* if plug out before hdmi bind, reset hdmi */ - if (vmode->mtmdsclock >= 340000000 && !(val & SCDC_TMDS_BIT_CLOCK_RATIO_BY_40) - && !hdmi->force_kernel_output) + if ((vmode->mtmdsclock >= 340000000 && !(val & SCDC_TMDS_BIT_CLOCK_RATIO_BY_40)) && + !hdmi->force_kernel_output) hdmi->logo_plug_out = true; } - if (check_hdr_color_change(old_state, new_state, hdmi) || hdmi->logo_plug_out || - dw_hdmi_color_changed(connector)) { + if (dw_hdmi_state_changed(hdmi, connector, state) || hdmi->logo_plug_out) { u32 mtmdsclk; - if (hdmi->plat_data->update_color_format) - hdmi->plat_data->update_color_format(new_state, data); - if (hdmi->plat_data->get_enc_in_encoding) - hdmi->hdmi_data.enc_in_encoding = - hdmi->plat_data->get_enc_in_encoding(data); - if (hdmi->plat_data->get_enc_out_encoding) - hdmi->hdmi_data.enc_out_encoding = - hdmi->plat_data->get_enc_out_encoding(data); - if (hdmi->plat_data->get_input_bus_format) - hdmi->hdmi_data.enc_in_bus_format = - hdmi->plat_data->get_input_bus_format(data); - if (hdmi->plat_data->get_output_bus_format) - hdmi->hdmi_data.enc_out_bus_format = - hdmi->plat_data->get_output_bus_format(data); - mtmdsclk = hdmi_get_tmdsclock(hdmi, mode->clock); if (hdmi_bus_fmt_is_yuv420(hdmi->hdmi_data.enc_out_bus_format)) @@ -4053,6 +4036,9 @@ static int dw_hdmi_bridge_atomic_check(struct drm_bridge *bridge, struct dw_hdmi *hdmi = bridge->driver_private; void *data = hdmi->plat_data->phy_data; + if (!hdmi->next_bridge) + return 0; + if (bridge_state->output_bus_cfg.format == MEDIA_BUS_FMT_FIXED) { if (hdmi->plat_data->get_output_bus_format) hdmi->hdmi_data.enc_out_bus_format = diff --git a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c index e34174fa19c5..9eebcfaa85cb 100644 --- a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c +++ b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c @@ -3110,21 +3110,6 @@ static int dw_hdmi_link_clk_set(void *data, bool enable) return 0; } -static bool -dw_hdmi_rockchip_check_hdr_color_change(struct drm_connector_state *conn_state, - void *data) -{ - struct rockchip_hdmi *hdmi = (struct rockchip_hdmi *)data; - - if (!conn_state || !data) - return false; - - if (dw_hdmi_rockchip_check_color(conn_state, hdmi)) - return true; - - return false; -} - static void dw_hdmi_rockchip_set_prev_bus_format(void *data, unsigned long bus_format) { struct rockchip_hdmi *hdmi = (struct rockchip_hdmi *)data; @@ -3713,18 +3698,9 @@ dw_hdmi_rockchip_set_property(struct drm_connector *connector, if (property == hdmi->color_depth_property) { hdmi->colordepth = val; - /* If hdmi is disconnected, state->crtc is null */ - if (!state->crtc) - return 0; - if (dw_hdmi_rockchip_check_color(state, hdmi)) - hdmi->color_changed++; return 0; } else if (property == hdmi->hdmi_output_property) { hdmi->hdmi_output = val; - if (!state->crtc) - return 0; - if (dw_hdmi_rockchip_check_color(state, hdmi)) - hdmi->color_changed++; return 0; } else if (property == hdmi->quant_range) { u64 quant_range = hdmi->hdmi_quant_range; @@ -4590,8 +4566,6 @@ static int dw_hdmi_rockchip_bind(struct device *dev, struct device *master, plat_data->get_vp_id = dw_hdmi_rockchip_get_vp_id; plat_data->update_color_format = dw_hdmi_rockchip_update_color_format; - plat_data->check_hdr_color_change = - dw_hdmi_rockchip_check_hdr_color_change; plat_data->set_prev_bus_format = dw_hdmi_rockchip_set_prev_bus_format; plat_data->set_ddc_io = diff --git a/include/drm/bridge/dw_hdmi.h b/include/drm/bridge/dw_hdmi.h index 820a3c24c209..a568cc4008c0 100644 --- a/include/drm/bridge/dw_hdmi.h +++ b/include/drm/bridge/dw_hdmi.h @@ -284,7 +284,6 @@ struct dw_hdmi_plat_data { int (*link_clk_set)(void *data, bool enable); int (*get_vp_id)(struct drm_crtc_state *crtc_state); void (*update_color_format)(struct drm_connector_state *conn_state, void *data); - bool (*check_hdr_color_change)(struct drm_connector_state *conn_state, void *data); void (*set_prev_bus_format)(void *data, unsigned long bus_format); int (*get_colorimetry)(void *data, const struct edid *edid); void (*set_ddc_io)(void *data, bool enable);