Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

drm/msm/dpu: fix WD timer handling on DPU 8.x

Since DPU 8.x Watchdog timer settings were moved from the TOP to the
INTF block. Support programming the timer in the INTF block. Fixes tag
points to the commit which removed register access to those registers on
DPU 8.x+ (and which also should have added proper support for WD timer
on those devices).

Fixes: 43e3293fc614 ("drm/msm/dpu: add support for MDP_TOP blackhole")
Reviewed-by: Marijn Suijten <marijn.suijten@somainline.org>
Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
Patchwork: https://patchwork.freedesktop.org/patch/696586/
Link: https://lore.kernel.org/r/20251230-intf-fix-wd-v6-2-98203d150611@oss.qualcomm.com

+57 -13
+2 -2
drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
··· 786 786 } 787 787 788 788 vsync_cfg.vsync_source = disp_info->vsync_source; 789 + vsync_cfg.frame_rate = drm_mode_vrefresh(&dpu_enc->base.crtc->state->adjusted_mode); 789 790 790 791 if (hw_mdptop->ops.setup_vsync_source) { 791 792 for (i = 0; i < dpu_enc->num_phys_encs; i++) 792 793 vsync_cfg.ppnumber[i] = dpu_enc->hw_pp[i]->idx; 793 794 794 795 vsync_cfg.pp_count = dpu_enc->num_phys_encs; 795 - vsync_cfg.frame_rate = drm_mode_vrefresh(&dpu_enc->base.crtc->state->adjusted_mode); 796 796 797 797 hw_mdptop->ops.setup_vsync_source(hw_mdptop, &vsync_cfg); 798 798 } ··· 802 802 803 803 if (phys_enc->has_intf_te && phys_enc->hw_intf->ops.vsync_sel) 804 804 phys_enc->hw_intf->ops.vsync_sel(phys_enc->hw_intf, 805 - vsync_cfg.vsync_source); 805 + &vsync_cfg); 806 806 } 807 807 } 808 808
+46 -3
drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c
··· 67 67 #define INTF_MISR_CTRL 0x180 68 68 #define INTF_MISR_SIGNATURE 0x184 69 69 70 + #define INTF_WD_TIMER_0_CTL 0x230 71 + #define INTF_WD_TIMER_0_CTL2 0x234 72 + #define INTF_WD_TIMER_0_LOAD_VALUE 0x238 73 + 70 74 #define INTF_MUX 0x25C 71 75 #define INTF_STATUS 0x26C 72 76 #define INTF_AVR_CONTROL 0x270 ··· 479 475 } 480 476 481 477 static void dpu_hw_intf_vsync_sel(struct dpu_hw_intf *intf, 482 - enum dpu_vsync_source vsync_source) 478 + struct dpu_vsync_source_cfg *cfg) 483 479 { 484 480 struct dpu_hw_blk_reg_map *c; 485 481 ··· 488 484 489 485 c = &intf->hw; 490 486 491 - DPU_REG_WRITE(c, INTF_TEAR_MDP_VSYNC_SEL, (vsync_source & 0xf)); 487 + DPU_REG_WRITE(c, INTF_TEAR_MDP_VSYNC_SEL, (cfg->vsync_source & 0xf)); 488 + } 489 + 490 + static void dpu_hw_intf_vsync_sel_v8(struct dpu_hw_intf *intf, 491 + struct dpu_vsync_source_cfg *cfg) 492 + { 493 + struct dpu_hw_blk_reg_map *c; 494 + 495 + if (!intf) 496 + return; 497 + 498 + c = &intf->hw; 499 + 500 + if (cfg->vsync_source >= DPU_VSYNC_SOURCE_WD_TIMER_4 && 501 + cfg->vsync_source <= DPU_VSYNC_SOURCE_WD_TIMER_1) { 502 + pr_warn_once("DPU 8.x supports only GPIOs and timer0 as TE sources\n"); 503 + return; 504 + } 505 + 506 + if (cfg->vsync_source == DPU_VSYNC_SOURCE_WD_TIMER_0) { 507 + u32 reg; 508 + 509 + DPU_REG_WRITE(c, INTF_WD_TIMER_0_LOAD_VALUE, 510 + CALCULATE_WD_LOAD_VALUE(cfg->frame_rate)); 511 + 512 + DPU_REG_WRITE(c, INTF_WD_TIMER_0_CTL, BIT(0)); /* clear timer */ 513 + 514 + reg = BIT(8); /* enable heartbeat timer */ 515 + reg |= BIT(0); /* enable WD timer */ 516 + reg |= BIT(1); /* select default 16 clock ticks */ 517 + DPU_REG_WRITE(c, INTF_WD_TIMER_0_CTL2, reg); 518 + 519 + /* make sure that timers are enabled/disabled for vsync state */ 520 + wmb(); 521 + } 522 + 523 + dpu_hw_intf_vsync_sel(intf, cfg); 492 524 } 493 525 494 526 static void dpu_hw_intf_disable_autorefresh(struct dpu_hw_intf *intf, ··· 638 598 c->ops.enable_tearcheck = dpu_hw_intf_enable_te; 639 599 c->ops.disable_tearcheck = dpu_hw_intf_disable_te; 640 600 c->ops.connect_external_te = dpu_hw_intf_connect_external_te; 641 - c->ops.vsync_sel = dpu_hw_intf_vsync_sel; 601 + if (mdss_rev->core_major_ver >= 8) 602 + c->ops.vsync_sel = dpu_hw_intf_vsync_sel_v8; 603 + else 604 + c->ops.vsync_sel = dpu_hw_intf_vsync_sel; 642 605 c->ops.disable_autorefresh = dpu_hw_intf_disable_autorefresh; 643 606 } 644 607
+2 -1
drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.h
··· 12 12 #include "dpu_hw_util.h" 13 13 14 14 struct dpu_hw_intf; 15 + struct dpu_vsync_source_cfg; 15 16 16 17 /* intf timing settings */ 17 18 struct dpu_hw_intf_timing_params { ··· 105 104 106 105 int (*connect_external_te)(struct dpu_hw_intf *intf, bool enable_external_te); 107 106 108 - void (*vsync_sel)(struct dpu_hw_intf *intf, enum dpu_vsync_source vsync_source); 107 + void (*vsync_sel)(struct dpu_hw_intf *intf, struct dpu_vsync_source_cfg *cfg); 109 108 110 109 void (*disable_autorefresh)(struct dpu_hw_intf *intf, uint32_t encoder_id, u16 vdisplay); 111 110
-7
drivers/gpu/drm/msm/disp/dpu1/dpu_hw_top.c
··· 22 22 #define TRAFFIC_SHAPER_WR_CLIENT(num) (0x060 + (num * 4)) 23 23 #define TRAFFIC_SHAPER_FIXPOINT_FACTOR 4 24 24 25 - #define MDP_TICK_COUNT 16 26 - #define XO_CLK_RATE 19200 27 - #define MS_TICKS_IN_SEC 1000 28 - 29 - #define CALCULATE_WD_LOAD_VALUE(fps) \ 30 - ((uint32_t)((MS_TICKS_IN_SEC * XO_CLK_RATE)/(MDP_TICK_COUNT * fps))) 31 - 32 25 static void dpu_hw_setup_split_pipe(struct dpu_hw_mdp *mdp, 33 26 struct split_pipe_cfg *cfg) 34 27 {
+7
drivers/gpu/drm/msm/disp/dpu1/dpu_hw_util.h
··· 21 21 22 22 #define TO_S15D16(_x_)((_x_) << 7) 23 23 24 + #define MDP_TICK_COUNT 16 25 + #define XO_CLK_RATE 19200 26 + #define MS_TICKS_IN_SEC 1000 27 + 28 + #define CALCULATE_WD_LOAD_VALUE(fps) \ 29 + ((uint32_t)((MS_TICKS_IN_SEC * XO_CLK_RATE)/(MDP_TICK_COUNT * fps))) 30 + 24 31 extern const struct dpu_csc_cfg dpu_csc_YUV2RGB_601L; 25 32 extern const struct dpu_csc_cfg dpu_csc10_YUV2RGB_601L; 26 33 extern const struct dpu_csc_cfg dpu_csc10_rgb2yuv_601l;