From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mail-wm1-f45.google.com (mail-wm1-f45.google.com [209.85.128.45]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 66D9B402B8C for ; Wed, 12 Aug 2026 10:49:34 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.128.45 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1786531776; cv=none; b=KNXCYyduYbzHMGQPXUcklwQqbMvenGxOyiVqmhtEdmiJ223Psjugo1JGN6p0697cYta4DhQ3/65QdK9AhVdpOTecaWH5BKsoddF+aCaK8a8hOUyXERWTmvdxLv6GRIz4c7SWkEAttKfmu4YnxN/T//PGnP9B/F8zGAMKN7rnUak= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1786531776; c=relaxed/simple; bh=hvIhIWIN1w88GwNbmooD4hIJGJFlP1m6ByocAO8PKuM=; h=From:To:Cc:Subject:Date:Message-ID:MIME-Version; b=Wa8Sw++IduYEfq6T0Yxrsx1pgq+Px7bxMYHCH03unb54XI+PEwf5BwCHNygVfJ+caZnJ6rNr0R2AOcK5tgaUzYelDCPAM1yNvL4OIfYkUhuSaOE7tNR+tG7qbbRiPF0LNtINdjIrcWlp6r+BVN2AcL7UlNYphYL+M13vR9JUkgU= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=MFKO6NV3; arc=none smtp.client-ip=209.85.128.45 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="MFKO6NV3" Received: by mail-wm1-f45.google.com with SMTP id 5b1f17b1804b1-4954c08a7c8so573665e9.3 for ; Wed, 12 Aug 2026 03:49:34 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1786531773; x=1787136573; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:from:to:cc:subject:date:message-id:reply-to:content-type; bh=2htw98TlVcP+RIDb3b8KEcHym617Hw0Z8IMjX67kKx8=; b=MFKO6NV3o+6zBNNNQsnwK61Xnia9O/MKajyTbCGhBmFsDORn2rNzSXBUAIHCViqFWx HNApdxSt1VlEE+DL3ClGDSwpJxH2mGQ2aaJ3GtefEaSG03ankCFaKDbucButBdEugK/Z maRthD8LnMXVfrEdQiS0TyQDUvjnLXMwkx/WMVwUubAuH/U2hDxO+7IrgbRxvJbpoTfY 27Aw9F34jdzUe2qncop6yE7fkvfNXxSfQEs8O7uOk3ds0XHNf2qIwR4Yjjz62GxjaGiz Hfw5NJOaBSto3TUYe3mPqDeRzm72KLA6pmi/pdX8iFW65AuIls25YTQG9DJJTBg+orMx +fYg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1786531773; x=1787136573; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:x-gm-gg:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to:content-type; bh=2htw98TlVcP+RIDb3b8KEcHym617Hw0Z8IMjX67kKx8=; b=BX2UQC9r21zRy3dJ3OQ5XnV0blD/hH/LLHMIxSckILwC4WtHaC4pHWUTtsp1ikEsER 0RFap3UXLuiryg+KSLr0zhrlGG3GueMrqokagmlLChuwDoDIMpOHAEk+cun1b7t65fKY zY+SRt64P1LCfVue7vfcHxVXMndn0e6ZBPtYOg7kZXUjIFnT8JnKaPFHG6yGK9GNP2D1 YBcsjzVmRSe9eQ5Cclnrfwthwc5uDUu905dtKaRfGSrGbkEmKSd6riPyFlxTMeizMJx4 eh5JXNdPOdJgjlxpBEaRsnf+FvadcS4M2jJLK4PR83Xl4BtYnzAPmMavkh8mgRDNloQn Usgw== X-Forwarded-Encrypted: i=1; AHgh+RoU7pcJ+J8eYDFjKfL0lcPsyhuyFmYbnqXXy0mauC9MbXPLn0TCIMhFIiKPv/W3MH8JvLpLhBNXvTN+FsE=@vger.kernel.org X-Gm-Message-State: AOJu0YwNpqvd7hIMCCThOXWKQAL9OeBJB72lyN22Zw6kwgFASUn55Skt hfo5W2KLpglfsJQ6Ktu0ZqlKyDM2PLI+C5Hk+SmUUrovxRovnK1Jwxav X-Gm-Gg: AR+sD12jtIS/8mQXEAowzXQLR3wIMfm0ePJR5jD85RJ9q5t9TXwC5MGL5K4xITUdxBr e6g1DLo0G1N4OjDnJJeu5xkS30EewT9fuTF9AbUhf7KOJd59uYJJLG24AO1y0EBn+Cp9mOuUXyh 2OTzkNQs9hjXS88C9VmJVpDDKx8H3ufvIjQ46QUi13XPDJ5qmbf7HyJZvQW2swfJ0rLV3+X5+4p arw094AIPVPnN22RxbMKlh4dYrqPsySEk/w6is91CumixkaCzMipmGKjLF6p0Bpf1QOvVrLmd/s buAex4KT10D4yARDLFEjEvAk7OXSxcwomwlmmse6p2tXcHOqAS1uyEeO00nfY5WLpGMFZZkpyiy Q21/4gz5BXTFEpSvDwgMCeIS42LrP91s/8cJhmqDU7SOtRD/ehDbOBjxLIo2rII1sfaKxsQvRIw bwxJyPdhDTs6sHrpaFhtwafSaIHcWglYF8a9M27Xj5qypHra5BC7HY6VDtL/oIbq+yCbcTsHP+M 8heIf7zomWfRwEIvnftCtnnaGzTKAQplY6SC73NrVQfDjxBD13bTCRjLxf6Rfiu9TW1zDAjFFP7 NXYx X-Received: by 2002:a05:600c:1d02:b0:493:f42e:1b3f with SMTP id 5b1f17b1804b1-4997c1412a8mr27209975e9.3.1786531772439; Wed, 12 Aug 2026 03:49:32 -0700 (PDT) Received: from OrangePi5-Plus.BB-HOME (20014C4E1B84A600F9E120266BE3CC9B.dsl.pool.telekom.hu. [2001:4c4e:1b84:a600:f9e1:2026:6be3:cc9b]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-4997abf94c1sm60999775e9.14.2026.08.12.03.49.30 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 12 Aug 2026 03:49:31 -0700 (PDT) From: Igor Paunovic To: Sandy Huang , Heiko Stuebner , Andy Yan Cc: Igor Paunovic , Cristian Ciocaltea , Sebastian Reichel , Chaoyi Chen , Alexey Charkov , Maarten Lankhorst , Maxime Ripard , Thomas Zimmermann , David Airlie , Simona Vetter , dri-devel@lists.freedesktop.org, linux-rockchip@lists.infradead.org, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org Subject: [PATCH] drm/rockchip: vop2: Scale the AXI clock to the bandwidth the mode needs Date: Wed, 12 Aug 2026 12:49:04 +0200 Message-ID: <20260812104909.6390-1-royalnet026@gmail.com> X-Mailer: git-send-email 2.53.0 Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit VOP2 fetches the scanout data for all of its video ports over a single AXI clock. On RK3588 that clock is pinned to 500 MHz by the device tree and nothing ever raises it, so a mode whose pixel rate outruns what the AXI clock can deliver underruns the internal scanout FIFO. The hardware reports this as POST_BUF_EMPTY and the picture is corrupted. 3840x2160@120 over DisplayPort is such a mode. Measured on an Orange Pi 5 Plus by moving the rate at runtime while the mode was up, with dclk unchanged at 594 MHz throughout, so that the AXI rate was the only variable: 500 MHz: ~594000 suppressed vop2_isr callbacks per 5 s, corrupted 750 MHz: no POST_BUF_EMPTY at all for the 42 s the phase lasted, clean 500 MHz: ~607000 suppressed callbacks per 5 s, corrupted again Both transitions are immediate. Heiko Stuebner reports the same starvation on different hardware [1]. The requirement follows each port's pixel rate rather than its interface clock, and it is per port rather than aggregate. Two measurements at 500 MHz pin that down: - a single port scanning out 3840x2160@120 underruns, while the same composed pixel rate spread over three ports - 3840x2160@60 on one and 3840x2160@30 on two others - is clean for a minute with no underrun on any of them. The totals are equal to the pixel: 3840*2160*120 == 3840*2160*(60+30+30). - 3840x2160@60 is clean where 3840x2160@120 is not, although both run dclk at 594 MHz on this board: the 120 Hz link is YCbCr 4:2:0, which halves dclk without halving the rate at which the port consumes pixels. So the condition belongs on each video port's own crtc_clock. Summing across ports would be wrong, and keying on dclk would miss 4:2:0 entirely. The threshold sits between the measured points: 3840x2160@60 (594000 kHz) and 2560x1440@144 (about 586000 kHz) are both clean at the default rate, 3840x2160@120 (1188000 kHz) is not. Take the maximum over the video ports that are scanning out rather than counting them, so that disabling one port cannot drop the rate below what a port that is still scanning needs. The rate the platform set up is used as the lower bound, so a board that already configures a higher rate keeps it. Tested on the same board on drm-misc-next plus the dw-dp and Rockchip USBDP PHY series, which DisplayPort Alt Mode needs in order to come up at all: 3840x2160@120 selects 750 MHz and runs with no underrun, dropping to 3840x2160@60 returns the clock to 500 MHz and stays clean, and going back raises it again. On that same kernel without this patch the output shows no picture at any mode. Link: https://lore.kernel.org/all/20260808104240.13776-1-royalnet026@gmail.com/ Link: https://lore.kernel.org/all/20767137.geO5KgaWL5@diego/ [1] Signed-off-by: Igor Paunovic --- Cristian, this overlaps with your ACLK work: the condition here is not FRL-specific, so it also covers the HDMI FRL case that 7e580d1cc3aa handles in the rockchip-3588 branch. I did not want to queue this behind a series that is itself blocked, but I am equally happy to rebase on top of yours, or to drop this if you would rather carry it. Whatever shape it takes should keep the FRL case working rather than replace it. Chaoyi, thank you for the FIFO description and the downstream decision flow - the per-port measurement above came directly out of that. Based on drm-misc-next at c8d3d795dd40. Tested on an Orange Pi 5 Plus; DisplayPort Alt Mode there additionally needs the dw-dp series and the Rockchip USBDP PHY series, neither of which is merged yet, so the test kernel carried both. drivers/gpu/drm/rockchip/rockchip_drm_vop2.c | 46 ++++++++++++++++++++ drivers/gpu/drm/rockchip/rockchip_drm_vop2.h | 2 + 2 files changed, 48 insertions(+) diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c index 4cce3e336f5b..5dda1fc1c8a1 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c @@ -104,6 +104,20 @@ enum vop2_afbc_format { #define VOP2_MAX_DCLK_RATE 600000000UL +/* + * All video ports fetch their scanout data over a single AXI clock. The + * hardware buffers that data in an internal FIFO which is drained at the + * pixel rate, so a mode whose pixel rate outruns the fill rate underruns the + * FIFO, which the hardware reports as POST_BUF_EMPTY and which shows up as a + * corrupted image. Raise the AXI clock for modes that need it. + * + * The requirement follows the pixel rate rather than the interface clock: a + * YCbCr 4:2:0 link halves dclk but not the rate at which the video port + * consumes pixels. + */ +#define VOP2_ACLK_RATE_HIGH 750000000UL +#define VOP2_HIGH_BW_PIXCLK_KHZ 1000000 + /* * bus-format types. */ @@ -1008,6 +1022,32 @@ static bool vop2_gamma_lut_in_use(struct vop2 *vop2, struct vop2_video_port *vp) return gamma_en_vp_id != nr_vps && gamma_en_vp_id != vp->id; } +/* + * Pick the AXI clock rate that satisfies every video port that is scanning + * out. Taking the maximum over the active ports rather than counting them + * means a port being disabled can never drop the rate below what a port that + * is still scanning needs. + */ +static void vop2_update_aclk_rate(struct vop2 *vop2) +{ + unsigned long rate = vop2->aclk_rate_normal; + struct drm_crtc *crtc; + + if (vop2->version != VOP_VERSION_RK3588) + return; + + drm_for_each_crtc(crtc, vop2->drm) { + if (!crtc->state->active) + continue; + + if (crtc->state->adjusted_mode.crtc_clock > VOP2_HIGH_BW_PIXCLK_KHZ && + rate < VOP2_ACLK_RATE_HIGH) + rate = VOP2_ACLK_RATE_HIGH; + } + + clk_set_rate(vop2->aclk, rate); +} + static void vop2_crtc_atomic_disable(struct drm_crtc *crtc, struct drm_atomic_commit *state) { @@ -1053,6 +1093,8 @@ static void vop2_crtc_atomic_disable(struct drm_crtc *crtc, if (!vop2->enable_count) vop2_disable(vop2); + vop2_update_aclk_rate(vop2); + vop2_unlock(vop2); if (crtc->state->event && !crtc->state->active) { @@ -1780,6 +1822,8 @@ static void vop2_crtc_atomic_enable(struct drm_crtc *crtc, vop2_lock(vop2); + vop2_update_aclk_rate(vop2); + ret = clk_prepare_enable(vp->dclk); if (ret < 0) { drm_err(vop2->drm, "failed to enable dclk for video port%d - %d\n", @@ -2875,6 +2919,8 @@ static int vop2_bind(struct device *dev, struct device *master, void *data) return dev_err_probe(drm->dev, PTR_ERR(vop2->aclk), "failed to get aclk source\n"); + vop2->aclk_rate_normal = clk_get_rate(vop2->aclk); + vop2->pclk = devm_clk_get_optional(vop2->dev, "pclk_vop"); if (IS_ERR(vop2->pclk)) return dev_err_probe(drm->dev, PTR_ERR(vop2->pclk), diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.h b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.h index ffcb39c130aa..50a3513c89ab 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.h +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.h @@ -326,6 +326,8 @@ struct vop2 { unsigned int enable_count; struct clk *hclk; struct clk *aclk; + /* AXI clock rate set up by the platform, used as the lower bound. */ + unsigned long aclk_rate_normal; struct clk *pclk; struct clk *pll_hdmiphy0; struct clk *pll_hdmiphy1; -- 2.43.0