FAILED: patch "[PATCH] drm/msm/dsi: round 6G byte clock rate to the PLL-achievable" failed to apply to 5.10-stable tree
Subsystems (3)
[email protected]
maintainerThe patch below does not apply to the 5.10-stable tree.
If someone wants it applied there, or to any other stable or longterm tree, then please email the backport, including the original git commit id to <[email protected]>.
To reproduce the conflict and resubmit, you may use the following commands:
git fetch https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/ linux-5.10.y
git checkout FETCH_HEAD
git cherry-pick -x 6cd33b6f4155efc20485929fd0b56bb704641db9
# <resolve conflicts, build, test, etc.>
git commit -s
git send-email --to '<[email protected]>' --in-reply-to '2026090910-activist-busily-77c5@gregkh' --subject-prefix 'PATCH 5.10.y' 'HEAD^..'
Possible dependencies:
thanks,
greg k-h
------------------ original commit in Linus's tree ------------------
From 6cd33b6f4155efc20485929fd0b56bb704641db9 Mon Sep 17 00:00:00 2001
From: Kavan Smith <[email protected]>
Date: Mon, 6 Jul 2026 18:32:40 -0700
Subject: [PATCH] drm/msm/dsi: round 6G byte clock rate to the PLL-achievable
value
MSM8916 runtime DSI commands still go through msm_dsi_host_xfer_prepare(), which re-applies the link clock rate before enabling the link clocks. That is fine in principle, but on DSI 6G the requested byte clock rate often does not exactly match the DSI PHY PLL's realizable rate. For example, the driver can request 56250000 Hz while the PLL actually runs at 56246337 Hz.
Because the requested and actual rates differ slightly, every later link_clk_set_rate() call is treated as a real clock change and re-locks the PLL. On a video-mode panel without an internal timing generator, such as samsung,s6d7aa0 / lsl080al03 on MSM8916, that live-clock glitch makes the panel lose pixel lock and visibly corrupts scanout on each runtime DCS command, including backlight writes.
Fix this by rounding the computed 6G byte clock rate up front, before it is stored in msm_host->byte_clk_rate and reused by later transfers. Once the host carries the PLL-achievable rate instead of the idealized one, repeated link_clk_set_rate() calls become no-ops in the common clock framework and no longer re-lock the PLL.
This keeps the normal transfer callback sequencing intact, preserves the OPP vote path in link_clk_set_rate(), and matches the fix direction suggested in the original 2018 discussion.
Patchwork: https://patchwork.freedesktop.org/patch/738234/
drivers/gpu/drm/msm/dsi/dsi_host.c +12 -0
@@ -670,12 +670,24 @@ static void dsi_calc_pclk(struct msm_dsi_host *msm_host, bool is_bonded_dsi)int dsi_calc_clk_rate_6g (struct msm_dsi_host *msm_host,bool is_bonded_dsi) { +long rounded_byte_clk_rate; +if (!msm_host->mode) {pr_err ("%s: mode not set\n" , __func__);return -EINVAL ; }dsi_calc_pclk (msm_host, is_bonded_dsi); + + rounded_byte_clk_rate =clk_round_rate (msm_host->byte_clk, + msm_host->byte_clk_rate); +if (rounded_byte_clk_rate <0 ) { +pr_err ("%s: failed to round byte clock rate, %ld\n" , + __func__, rounded_byte_clk_rate); +return rounded_byte_clk_rate; + } + + msm_host->byte_clk_rate = rounded_byte_clk_rate; msm_host->esc_clk_rate =clk_get_rate (msm_host->esc_clk);return 0 ; }
Sasha Levin
maintainerPATCH 1/3 drm/msm/dsi: do not enable PHYs when called for the slave DSI interface
From: Dmitry Baryshkov <[email protected]>
[ Upstream commit a14440042fe8dac6b7c507a946f46a6f50c9c05d ]
Move the call to dsi_mgr_phy_enable after checking whether the DSI interface is slave, so that PHY enablement happens together with the host enablement.
Stable-dep-of: 6cd33b6f4155 ("drm/msm/dsi: round 6G byte clock rate to the PLL-achievable value")
--- drivers/gpu/drm/msm/dsi/dsi_manager.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-)
drivers/gpu/drm/msm/dsi/dsi_manager.c +4 -4
@@ -381,14 +381,14 @@ static void dsi_mgr_bridge_pre_enable(struct drm_bridge *bridge)if (!msm_dsi_device_connected (msm_dsi))return ; - ret =dsi_mgr_phy_enable (id, phy_shared_timings); -if (ret) - goto phy_en_fail; -/* Do nothing with the host if it is slave-DSI in case of dual DSI */ if (is_dual_dsi && !IS_MASTER_DSI_LINK (id))return ; + ret =dsi_mgr_phy_enable (id, phy_shared_timings); +if (ret) + goto phy_en_fail; + ret =msm_dsi_host_power_on (host, &phy_shared_timings[id], is_dual_dsi);if (ret) {pr_err ("%s: power on host %d failed, %d\n" , __func__, id, ret);
Signature · 1 line
2.53.0
Sasha Levin
maintainerPATCH 2/3 drm/msm/dsi: rename dual DSI to bonded DSI
From: Dmitry Baryshkov <[email protected]>
[ Upstream commit 6183606da324b934166e7b47c3be6176fa86f9ff ]
We are preparing to support two independent DSI hosts in the DSI/DPU code. To remove possible confusion (as both configurations can be referenced as dual DSI) let's rename old "dual DSI" (two DSI hosts driving single device, with clocks being locked) to "bonded DSI".
[5.10 dependency adaptation: keep the existing PHY/PLL interfaces and rename the stable-only source PLL selection to IS_BONDED_DSI(). Apply the 10nm, 14nm and 7nm PLL comment changes in dsi/pll/, where that code lives in this tree. Omit the test-pattern hunk and newer host declarations, which have no implementation here. No functions or clock behavior are added. The resulting host names let the target byte-clock rounding patch apply without further changes.]
[ sashal: Reduced backport -- upstream 6183606da324b touches 8 file(s), this
backport carries 8. Not backported here:
drivers/gpu/drm/msm/dsi/phy/dsi_phy_10nm.c drivers/gpu/drm/msm/dsi/phy/dsi_phy_14nm.c drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c
This note is generated from the file lists only; see the resolution record for the reasoning. ]
Stable-dep-of: 6cd33b6f4155 ("drm/msm/dsi: round 6G byte clock rate to the PLL-achievable value")
--- drivers/gpu/drm/msm/disp/mdp5/mdp5_ctl.c | 2 +- drivers/gpu/drm/msm/dsi/dsi.h | 8 +- drivers/gpu/drm/msm/dsi/dsi_cfg.h | 2 +- drivers/gpu/drm/msm/dsi/dsi_host.c | 34 +++---- drivers/gpu/drm/msm/dsi/dsi_manager.c | 103 ++++++++++----------- drivers/gpu/drm/msm/dsi/pll/dsi_pll_10nm.c | 2 +- drivers/gpu/drm/msm/dsi/pll/dsi_pll_14nm.c | 6 +- drivers/gpu/drm/msm/dsi/pll/dsi_pll_7nm.c | 2 +- 8 files changed, 79 insertions(+), 80 deletions(-)
drivers/gpu/drm/msm/disp/mdp5/mdp5_ctl.c +1 -1
@@ -728,7 +728,7 @@ struct mdp5_ctl_manager *mdp5_ctlm_init(struct drm_device *dev, }/* -* In Dual DSI case, CTL0 and CTL1 are always assigned to two DSI +* In bonded DSI case, CTL0 and CTL1 are always assigned to two DSI * interfaces to support single FLUSH feature (Flush CTL0 and CTL1 when * only write into CTL0's FLUSH register) to keep two DSI pipes in sync. * Single FLUSH is supported from hw rev v3.0.
drivers/gpu/drm/msm/dsi/dsi.h +4 -4
@@ -159,7 +159,7 @@ int msm_dsi_host_enable(struct mipi_dsi_host *host);int msm_dsi_host_disable (struct mipi_dsi_host *host);int msm_dsi_host_power_on (struct mipi_dsi_host *host,struct msm_dsi_phy_shared_timings *phy_shared_timings, -bool is_dual_dsi); +bool is_bonded_dsi);int msm_dsi_host_power_off (struct mipi_dsi_host *host);int msm_dsi_host_set_display_mode (struct mipi_dsi_host *host,const struct drm_display_mode *mode);
@@ -173,7 +173,7 @@ int msm_dsi_host_set_src_pll(struct mipi_dsi_host *host,void msm_dsi_host_reset_phy (struct mipi_dsi_host *host);void msm_dsi_host_get_phy_clk_req (struct mipi_dsi_host *host,struct msm_dsi_phy_clk_request *clk_req, -bool is_dual_dsi); +bool is_bonded_dsi);void msm_dsi_host_destroy (struct mipi_dsi_host *host);int msm_dsi_host_modeset_init (struct mipi_dsi_host *host,struct drm_device *dev);
@@ -195,8 +195,8 @@ int dsi_dma_base_get_6g(struct msm_dsi_host *msm_host, uint64_t *iova);int dsi_dma_base_get_v2 (struct msm_dsi_host *msm_host,uint64_t *iova);int dsi_clk_init_v2 (struct msm_dsi_host *msm_host);int dsi_clk_init_6g_v2 (struct msm_dsi_host *msm_host); -int dsi_calc_clk_rate_v2 (struct msm_dsi_host *msm_host,bool is_dual_dsi); -int dsi_calc_clk_rate_6g (struct msm_dsi_host *msm_host,bool is_dual_dsi); +int dsi_calc_clk_rate_v2 (struct msm_dsi_host *msm_host,bool is_bonded_dsi); +int dsi_calc_clk_rate_6g (struct msm_dsi_host *msm_host,bool is_bonded_dsi);/* dsi phy */ struct msm_dsi_phy ;
drivers/gpu/drm/msm/dsi/dsi_cfg.h +1 -1
@@ -47,7 +47,7 @@ struct msm_dsi_host_cfg_ops {void * (*tx_buf_get)(struct msm_dsi_host *msm_host);void (*tx_buf_put)(struct msm_dsi_host *msm_host);int (*dma_base_get)(struct msm_dsi_host *msm_host,uint64_t *iova); -int (*calc_clk_rate)(struct msm_dsi_host *msm_host,bool is_dual_dsi); +int (*calc_clk_rate)(struct msm_dsi_host *msm_host,bool is_bonded_dsi); };struct msm_dsi_cfg_handler {
drivers/gpu/drm/msm/dsi/dsi_host.c +17 -17
@@ -680,7 +680,7 @@ void dsi_link_clk_disable_v2(struct msm_dsi_host *msm_host)clk_disable_unprepare (msm_host->byte_clk); } -static u32 dsi_get_pclk_rate (struct msm_dsi_host *msm_host,bool is_dual_dsi) +static u32 dsi_get_pclk_rate (struct msm_dsi_host *msm_host,bool is_bonded_dsi) {struct drm_display_mode *mode = msm_host->mode;u32 pclk_rate;
@@ -688,22 +688,22 @@ static u32 dsi_get_pclk_rate(struct msm_dsi_host *msm_host, bool is_dual_dsi) pclk_rate = mode->clock *1000u ;/* -* For dual DSI mode, the current DRM mode has the complete width of the +* For bonded DSI mode, the current DRM mode has the complete width of the * panel. Since, the complete panel is driven by two DSI controllers, * the clock rates have to be split between the two dsi controllers. * Adjust the byte and pixel clock rates for each dsi host accordingly. */ -if (is_dual_dsi) +if (is_bonded_dsi) pclk_rate /=2 ;return pclk_rate; } -static void dsi_calc_pclk (struct msm_dsi_host *msm_host,bool is_dual_dsi) +static void dsi_calc_pclk (struct msm_dsi_host *msm_host,bool is_bonded_dsi) {u8 lanes = msm_host->lanes;u32 bpp =dsi_get_bpp (msm_host->format); -u32 pclk_rate =dsi_get_pclk_rate (msm_host, is_dual_dsi); +u32 pclk_rate =dsi_get_pclk_rate (msm_host, is_bonded_dsi);u64 pclk_bpp = (u64 )pclk_rate * bpp;if (lanes ==0 ) {
@@ -721,28 +721,28 @@ static void dsi_calc_pclk(struct msm_dsi_host *msm_host, bool is_dual_dsi) } -int dsi_calc_clk_rate_6g (struct msm_dsi_host *msm_host,bool is_dual_dsi) +int dsi_calc_clk_rate_6g (struct msm_dsi_host *msm_host,bool is_bonded_dsi) {if (!msm_host->mode) {pr_err ("%s: mode not set\n" , __func__);return -EINVAL ; } -dsi_calc_pclk (msm_host, is_dual_dsi); +dsi_calc_pclk (msm_host, is_bonded_dsi); msm_host->esc_clk_rate =clk_get_rate (msm_host->esc_clk);return 0 ; } -int dsi_calc_clk_rate_v2 (struct msm_dsi_host *msm_host,bool is_dual_dsi) +int dsi_calc_clk_rate_v2 (struct msm_dsi_host *msm_host,bool is_bonded_dsi) {u32 bpp =dsi_get_bpp (msm_host->format);u64 pclk_bpp;unsigned int esc_mhz, esc_div;unsigned long byte_mhz; -dsi_calc_pclk (msm_host, is_dual_dsi); +dsi_calc_pclk (msm_host, is_bonded_dsi); - pclk_bpp = (u64 )dsi_get_pclk_rate (msm_host, is_dual_dsi) * bpp; + pclk_bpp = (u64 )dsi_get_pclk_rate (msm_host, is_bonded_dsi) * bpp;do_div (pclk_bpp,8 ); msm_host->src_clk_rate = pclk_bpp;
@@ -939,7 +939,7 @@ static void dsi_ctrl_config(struct msm_dsi_host *msm_host, bool enable,dsi_write (msm_host,REG_DSI_CTRL , data); } -static void dsi_timing_setup (struct msm_dsi_host *msm_host,bool is_dual_dsi) +static void dsi_timing_setup (struct msm_dsi_host *msm_host,bool is_bonded_dsi) {struct drm_display_mode *mode = msm_host->mode;u32 hs_start =0 , vs_start =0 ;/* take sync start as 0 */
@@ -957,13 +957,13 @@ static void dsi_timing_setup(struct msm_dsi_host *msm_host, bool is_dual_dsi)DBG ("" );/* -* For dual DSI mode, the current DRM mode has +* For bonded DSI mode, the current DRM mode has * the complete width of the panel. Since, the complete * panel is driven by two DSI controllers, the horizontal * timings have to be split between the two dsi controllers. * Adjust the DSI host timing values accordingly. */ -if (is_dual_dsi) { +if (is_bonded_dsi) { h_total /=2 ; hs_end /=2 ; ha_start /=2 ;
@@ -2318,13 +2318,13 @@ void msm_dsi_host_reset_phy(struct mipi_dsi_host *host)void msm_dsi_host_get_phy_clk_req (struct mipi_dsi_host *host,struct msm_dsi_phy_clk_request *clk_req, -bool is_dual_dsi) +bool is_bonded_dsi) {struct msm_dsi_host *msm_host =to_msm_dsi_host (host);const struct msm_dsi_cfg_handler *cfg_hnd = msm_host->cfg_hnd;int ret; - ret = cfg_hnd->ops->calc_clk_rate (msm_host, is_dual_dsi); + ret = cfg_hnd->ops->calc_clk_rate (msm_host, is_bonded_dsi);if (ret) {pr_err ("%s: unable to calc clk rate, %d\n" , __func__, ret);return ;
@@ -2387,7 +2387,7 @@ static void msm_dsi_sfpb_config(struct msm_dsi_host *msm_host, bool enable)int msm_dsi_host_power_on (struct mipi_dsi_host *host,struct msm_dsi_phy_shared_timings *phy_shared_timings, -bool is_dual_dsi) +bool is_bonded_dsi) {struct msm_dsi_host *msm_host =to_msm_dsi_host (host);const struct msm_dsi_cfg_handler *cfg_hnd = msm_host->cfg_hnd;
@@ -2425,7 +2425,7 @@ int msm_dsi_host_power_on(struct mipi_dsi_host *host, goto fail_disable_clk; } -dsi_timing_setup (msm_host, is_dual_dsi); +dsi_timing_setup (msm_host, is_bonded_dsi);dsi_sw_reset (msm_host);dsi_ctrl_config (msm_host, true, phy_shared_timings);
drivers/gpu/drm/msm/dsi/dsi_manager.c +51 -52
319 lines not on this page · raw message
drivers/gpu/drm/msm/dsi/pll/dsi_pll_10nm.c +1 -1
@@ -124,7 +124,7 @@ struct dsi_pll_10nm {#define to_pll_10nm (x) container_of(x, struct dsi_pll_10nm, base)/* -* Global list of private DSI PLL struct pointers. We need this for Dual DSI +* Global list of private DSI PLL struct pointers. We need this for bonded DSI * mode, where the master PLL's clk_ops needs access the slave's private data */ static struct dsi_pll_10nm *pll_10nm_list[DSI_MAX ];
drivers/gpu/drm/msm/dsi/pll/dsi_pll_14nm.c +3 -3
@@ -152,7 +152,7 @@ struct dsi_pll_14nm {/* * Private struct for N1/N2 post-divider clocks. These clocks are similar to * the generic clk_divider class of clocks. The only difference is that it -* also sets the slave DSI PLL's post-dividers if in Dual DSI mode +* also sets the slave DSI PLL's post-dividers if in bonded DSI mode */ struct dsi_pll_14nm_postdiv {struct clk_hw hw;
@@ -168,7 +168,7 @@ struct dsi_pll_14nm_postdiv {#define to_pll_14nm_postdiv (_hw) container_of(_hw, struct dsi_pll_14nm_postdiv, hw)/* -* Global list of private DSI PLL struct pointers. We need this for Dual DSI +* Global list of private DSI PLL struct pointers. We need this for bonded DSI * mode, where the master PLL's clk_ops needs access the slave's private data */ static struct dsi_pll_14nm *pll_14nm_list[DSI_MAX ];
@@ -734,7 +734,7 @@ static int dsi_pll_14nm_postdiv_set_rate(struct clk_hw *hw, unsigned long rate, val |= value << shift;pll_write (base + REG_DSI_14nm_PHY_CMN_CLK_CFG0, val); -/* If we're master in dual DSI mode, then the slave PLL's post-dividers +/* If we're master in bonded DSI mode, then the slave PLL's post-dividers * follow the master's post dividers */ if (pll_14nm->uc ==MSM_DSI_PHY_MASTER ) {
drivers/gpu/drm/msm/dsi/pll/dsi_pll_7nm.c +1 -1
@@ -124,7 +124,7 @@ struct dsi_pll_7nm {#define to_pll_7nm (x) container_of(x, struct dsi_pll_7nm, base)/* -* Global list of private DSI PLL struct pointers. We need this for Dual DSI +* Global list of private DSI PLL struct pointers. We need this for bonded DSI * mode, where the master PLL's clk_ops needs access the slave's private data */ static struct dsi_pll_7nm *pll_7nm_list[DSI_MAX ];
Signature · 1 line
2.53.0
Sasha Levin
maintainerPATCH 3/3 drm/msm/dsi: round 6G byte clock rate to the PLL-achievable value
In reply to Sasha LevinFrom: Kavan Smith <[email protected]>
[ Upstream commit 6cd33b6f4155efc20485929fd0b56bb704641db9 ]
MSM8916 runtime DSI commands still go through msm_dsi_host_xfer_prepare(), which re-applies the link clock rate before enabling the link clocks. That is fine in principle, but on DSI 6G the requested byte clock rate often does not exactly match the DSI PHY PLL's realizable rate. For example, the driver can request 56250000 Hz while the PLL actually runs at 56246337 Hz.
Because the requested and actual rates differ slightly, every later link_clk_set_rate() call is treated as a real clock change and re-locks the PLL. On a video-mode panel without an internal timing generator, such as samsung,s6d7aa0 / lsl080al03 on MSM8916, that live-clock glitch makes the panel lose pixel lock and visibly corrupts scanout on each runtime DCS command, including backlight writes.
Fix this by rounding the computed 6G byte clock rate up front, before it is stored in msm_host->byte_clk_rate and reused by later transfers. Once the host carries the PLL-achievable rate instead of the idealized one, repeated link_clk_set_rate() calls become no-ops in the common clock framework and no longer re-lock the PLL.
This keeps the normal transfer callback sequencing intact, preserves the OPP vote path in link_clk_set_rate(), and matches the fix direction suggested in the original 2018 discussion.
Patchwork: https://patchwork.freedesktop.org/patch/738234/
--- drivers/gpu/drm/msm/dsi/dsi_host.c | 12 ++++++++++++ 1 file changed, 12 insertions(+)
drivers/gpu/drm/msm/dsi/dsi_host.c +12 -0
@@ -723,12 +723,24 @@ static void dsi_calc_pclk(struct msm_dsi_host *msm_host, bool is_bonded_dsi)int dsi_calc_clk_rate_6g (struct msm_dsi_host *msm_host,bool is_bonded_dsi) { +long rounded_byte_clk_rate; +if (!msm_host->mode) {pr_err ("%s: mode not set\n" , __func__);return -EINVAL ; }dsi_calc_pclk (msm_host, is_bonded_dsi); + + rounded_byte_clk_rate =clk_round_rate (msm_host->byte_clk, + msm_host->byte_clk_rate); +if (rounded_byte_clk_rate <0 ) { +pr_err ("%s: failed to round byte clock rate, %ld\n" , + __func__, rounded_byte_clk_rate); +return rounded_byte_clk_rate; + } + + msm_host->byte_clk_rate = rounded_byte_clk_rate; msm_host->esc_clk_rate =clk_get_rate (msm_host->esc_clk);return 0 ; }
Signature · 1 line
2.53.0