diff --git a/msm/msm_drv.h b/msm/msm_drv.h index 68b0187b31..f97e997688 100644 --- a/msm/msm_drv.h +++ b/msm/msm_drv.h @@ -1260,8 +1260,10 @@ struct drm_framebuffer *msm_framebuffer_init(struct drm_device *dev, struct drm_gem_object **bos); struct drm_framebuffer *msm_framebuffer_create(struct drm_device *dev, struct drm_file *file, const struct drm_mode_fb_cmd2 *mode_cmd); -void msm_framebuffer_set_cache_hint(struct drm_framebuffer *fb, u32 flags, u32 type); -void msm_framebuffer_get_cache_hint(struct drm_framebuffer *fb, u32 *flags, u32 *type); +int msm_framebuffer_set_cache_hint(struct drm_framebuffer *fb, + u32 flags, u32 rd_type, u32 wr_type); +int msm_framebuffer_get_cache_hint(struct drm_framebuffer *fb, + u32 *flags, u32 *rd_type, u32 *wr_type); struct drm_fb_helper *msm_fbdev_init(struct drm_device *dev); void msm_fbdev_free(struct drm_device *dev); diff --git a/msm/msm_fb.c b/msm/msm_fb.c index 4bf614b7cd..ee6a475528 100644 --- a/msm/msm_fb.c +++ b/msm/msm_fb.c @@ -31,7 +31,8 @@ struct msm_framebuffer { struct drm_framebuffer base; const struct msm_format *format; u32 cache_flags; - u32 cache_type; + u32 cache_rd_type; + u32 cache_wr_type; }; #define to_msm_framebuffer(x) container_of(x, struct msm_framebuffer, base) @@ -284,29 +285,34 @@ fail: return ERR_PTR(ret); } -void msm_framebuffer_set_cache_hint(struct drm_framebuffer *fb, u32 flags, u32 type) +int msm_framebuffer_set_cache_hint(struct drm_framebuffer *fb, + u32 flags, u32 rd_type, u32 wr_type) { struct msm_framebuffer *msm_fb; if (!fb) - return; + return -EINVAL; msm_fb = to_msm_framebuffer(fb); msm_fb->cache_flags = flags; - msm_fb->cache_type = type; + msm_fb->cache_rd_type = rd_type; + msm_fb->cache_wr_type = wr_type; + + return 0; } -void msm_framebuffer_get_cache_hint(struct drm_framebuffer *fb, u32 *flags, u32 *type) +int msm_framebuffer_get_cache_hint(struct drm_framebuffer *fb, + u32 *flags, u32 *rd_type, u32 *wr_type) { struct msm_framebuffer *msm_fb; - if (!fb) { - *flags = 0; - *type = 0; - return; - } + if (!fb) + return -EINVAL; msm_fb = to_msm_framebuffer(fb); *flags = msm_fb->cache_flags; - *type = msm_fb->cache_type; + *rd_type = msm_fb->cache_rd_type; + *wr_type = msm_fb->cache_wr_type; + + return 0; } diff --git a/msm/sde/sde_core_perf.c b/msm/sde/sde_core_perf.c index 4544df0206..c50a8e1968 100644 --- a/msm/sde/sde_core_perf.c +++ b/msm/sde/sde_core_perf.c @@ -389,8 +389,7 @@ static void _sde_core_perf_crtc_set_llcc_cache_type(struct sde_kms *kms, u32 llcc_active = 0; if (!test_bit(type, kms->perf.catalog->sde_sys_cache_type_map)) { - SDE_DEBUG("System Cache %d is not enabled!. Won't use\n", - type); + SDE_DEBUG("system cache %d is not enabled!. Won't use\n", type); return; } diff --git a/msm/sde/sde_encoder_phys_wb.c b/msm/sde/sde_encoder_phys_wb.c index 49e0b074e3..7b990adc04 100644 --- a/msm/sde/sde_encoder_phys_wb.c +++ b/msm/sde/sde_encoder_phys_wb.c @@ -1074,7 +1074,7 @@ static int sde_encoder_phys_wb_atomic_check(struct sde_encoder_phys *phys_enc, return rc; } -static void _sde_encoder_phys_wb_setup_cache(struct sde_encoder_phys *phys_enc, +static void _sde_encoder_phys_wb_setup_sys_cache(struct sde_encoder_phys *phys_enc, struct drm_framebuffer *fb) { struct sde_encoder_phys_wb *wb_enc = to_sde_encoder_phys_wb(phys_enc); @@ -1084,17 +1084,32 @@ static void _sde_encoder_phys_wb_setup_cache(struct sde_encoder_phys *phys_enc, struct sde_crtc *sde_crtc = to_sde_crtc(wb_enc->crtc); struct sde_sc_cfg *sc_cfg; struct sde_hw_wb_sc_cfg *cfg = &wb_enc->sc_cfg; - u32 cache_enable, cache_type; + u32 cache_enable, cache_flag, cache_rd_type, cache_wr_type; + + if (!fb) { + SDE_ERROR("invalid fb on wb %d\n", WBID(wb_enc)); + return; + } /* * - use LLCC_DISP for cwb static display + * - use LLCC_DISP_1 for cwb static display read path only * - use LLCC_DISP_WB for 2-pass composition using offline-wb */ - cache_type = phys_enc->in_clone_mode ? SDE_SYS_CACHE_DISP : SDE_SYS_CACHE_DISP_WB; + if (phys_enc->in_clone_mode) { + cache_rd_type = SDE_SYS_CACHE_DISP; + if (test_bit(SDE_SYS_CACHE_DISP_1, hw_wb->catalog->sde_sys_cache_type_map)) + cache_wr_type = SDE_SYS_CACHE_DISP_1; + else + cache_wr_type = SDE_SYS_CACHE_DISP; + } else { + cache_rd_type = SDE_SYS_CACHE_DISP_WB; + cache_wr_type = SDE_SYS_CACHE_DISP_WB; + } - sc_cfg = &hw_wb->catalog->sc_cfg[cache_type]; - if (!test_bit(cache_type, hw_wb->catalog->sde_sys_cache_type_map)) { - SDE_DEBUG("sys cache type %d not enabled\n", cache_type); + sc_cfg = &hw_wb->catalog->sc_cfg[cache_wr_type]; + if (!test_bit(cache_wr_type, hw_wb->catalog->sde_sys_cache_type_map)) { + SDE_DEBUG("sys cache type %d not enabled\n", cache_wr_type); return; } @@ -1113,25 +1128,31 @@ static void _sde_encoder_phys_wb_setup_cache(struct sde_encoder_phys *phys_enc, if (cache_enable) { cfg->wr_scid = sc_cfg->llcc_scid; - cfg->type = cache_type; - msm_framebuffer_set_cache_hint(fb, MSM_FB_CACHE_WRITE_EN, cache_type); + cfg->type = cache_wr_type; + cache_flag = MSM_FB_CACHE_WRITE_EN; } else { cfg->wr_scid = 0x0; cfg->type = SDE_SYS_CACHE_NONE; - msm_framebuffer_set_cache_hint(fb, MSM_FB_CACHE_NONE, SDE_SYS_CACHE_NONE); + cache_flag = MSM_FB_CACHE_NONE; + cache_rd_type = SDE_SYS_CACHE_NONE; + cache_wr_type = SDE_SYS_CACHE_NONE; } + msm_framebuffer_set_cache_hint(fb, cache_flag, cache_rd_type, cache_wr_type); /* * avoid llcc_active reset for crtc while in clone mode as it will reset it for * primary display as well */ if (cache_enable || !phys_enc->in_clone_mode) { - sde_crtc->new_perf.llcc_active[cache_type] = cache_enable; + sde_crtc->new_perf.llcc_active[cache_wr_type] = cache_enable; + sde_crtc->new_perf.llcc_active[cache_rd_type] = cache_enable; sde_core_perf_crtc_update_llcc(wb_enc->crtc); } hw_wb->ops.setup_sys_cache(hw_wb, cfg); - SDE_EVT32(WBID(wb_enc), cfg->wr_scid, cfg->flags, cfg->type, cache_enable); + SDE_EVT32(WBID(wb_enc), cfg->wr_scid, cfg->flags, cfg->type, cache_enable, + phys_enc->in_clone_mode, cache_flag, cache_rd_type, + cache_wr_type, fb->base.id); } static void _sde_encoder_phys_wb_update_cwb_flush_helper( @@ -1493,7 +1514,7 @@ static void sde_encoder_phys_wb_setup(struct sde_encoder_phys *phys_enc) _sde_encoder_phys_wb_setup_ctl(phys_enc, wb_enc->wb_fmt); - _sde_encoder_phys_wb_setup_cache(phys_enc, fb); + _sde_encoder_phys_wb_setup_sys_cache(phys_enc, fb); _sde_encoder_phys_wb_setup_cwb(phys_enc, true); diff --git a/msm/sde/sde_hw_catalog.c b/msm/sde/sde_hw_catalog.c index 55c0e1a0ee..b209d9c596 100644 --- a/msm/sde/sde_hw_catalog.c +++ b/msm/sde/sde_hw_catalog.c @@ -3488,11 +3488,13 @@ static int sde_cache_parse_dt(struct device_node *np, #if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 15, 0)) const u32 sde_sys_cache_usecase_id[SDE_SYS_CACHE_MAX] = { [SDE_SYS_CACHE_DISP] = LLCC_DISP, + [SDE_SYS_CACHE_DISP_1] = LLCC_DISP_1, [SDE_SYS_CACHE_DISP_WB] = LLCC_DISP_WB, }; #else const u32 sde_sys_cache_usecase_id[SDE_SYS_CACHE_MAX] = { [SDE_SYS_CACHE_DISP] = LLCC_DISP, + [SDE_SYS_CACHE_DISP_1] = 0, [SDE_SYS_CACHE_DISP_WB] = 0, }; #endif @@ -5148,6 +5150,7 @@ static int _sde_hardware_pre_caps(struct sde_mdss_cfg *sde_cfg, uint32_t hw_rev) set_bit(SDE_FEATURE_CTL_DONE, sde_cfg->features); set_bit(SDE_FEATURE_TRUSTED_VM, sde_cfg->features); set_bit(SDE_SYS_CACHE_DISP, sde_cfg->sde_sys_cache_type_map); + set_bit(SDE_SYS_CACHE_DISP_1, sde_cfg->sde_sys_cache_type_map); set_bit(SDE_SYS_CACHE_DISP_WB, sde_cfg->sde_sys_cache_type_map); sde_cfg->allowed_dsc_reservation_switch = SDE_DP_DSC_RESERVATION_SWITCH; sde_cfg->autorefresh_disable_seq = AUTOREFRESH_DISABLE_SEQ2; diff --git a/msm/sde/sde_hw_catalog.h b/msm/sde/sde_hw_catalog.h index 76b8eb5962..6be47392e4 100644 --- a/msm/sde/sde_hw_catalog.h +++ b/msm/sde/sde_hw_catalog.h @@ -205,12 +205,15 @@ enum { /** * sde_sys_cache_type: Types of system cache supported - * SDE_SYS_CACHE_DISP: Static img system cache - * SDE_SYS_CACHE_MAX: Maximum number of sys cache users - * SDE_SYS_CACHE_NONE: Sys cache not used + * SDE_SYS_CACHE_DISP: System cache for static display read/write path use case + * SDE_SYS_CACHE_DISP_1: System cache for static display write path use case + * SDE_SYS_CACHE_DISP_WB: System cache for IWE use case + * SDE_SYS_CACHE_MAX: Maximum number of system cache users + * SDE_SYS_CACHE_NONE: System cache not used */ enum sde_sys_cache_type { SDE_SYS_CACHE_DISP, + SDE_SYS_CACHE_DISP_1, SDE_SYS_CACHE_DISP_WB, SDE_SYS_CACHE_MAX, SDE_SYS_CACHE_NONE = SDE_SYS_CACHE_MAX diff --git a/msm/sde/sde_plane.c b/msm/sde/sde_plane.c index dc7128baf2..8b622e4c3b 100644 --- a/msm/sde/sde_plane.c +++ b/msm/sde/sde_plane.c @@ -2852,16 +2852,30 @@ static void _sde_plane_sspp_setup_sys_cache(struct sde_plane *psde, struct sde_sc_cfg *sc_cfg = psde->catalog->sc_cfg; struct sde_hw_pipe_sc_cfg *cfg = &pstate->sc_cfg; bool prev_rd_en = cfg->rd_en; - u32 fb_cache_flag, fb_cache_type; + u32 cache_flag, cache_rd_type, cache_wr_type; - msm_framebuffer_get_cache_hint(state->fb, &fb_cache_flag, &fb_cache_type); + if (!state->fb) { + SDE_ERROR("invalid fb on plane %d\n", DRMID(&psde->base)); + return; + } + + msm_framebuffer_get_cache_hint(state->fb, &cache_flag, &cache_rd_type, &cache_wr_type); cfg->rd_en = false; cfg->rd_scid = 0x0; cfg->flags = SYS_CACHE_EN_FLAG | SYS_CACHE_SCID; cfg->type = SDE_SYS_CACHE_NONE; - if ((test_bit(SDE_SYS_CACHE_DISP, psde->catalog->sde_sys_cache_type_map)) + /* + * if condition handles static display legacy path, where internal state machine is + * transitioning the "static_cache_state" variable to program the LLCC cache through + * SSPP hardware using SDE_SYS_CACHE_DISP SCID. + * else condition handles static display and IWE path, were the frame is programmed to + * LLCC cache through WB/CWB path and read back by SSPP hardware. The FB cache hints are + * used to pass information on which SCID to use during read path and LLCC cache to + * keep active. + */ + if (test_bit(SDE_SYS_CACHE_DISP, psde->catalog->sde_sys_cache_type_map) && ((pstate->static_cache_state == CACHE_STATE_FRAME_WRITE) || (pstate->static_cache_state == CACHE_STATE_FRAME_READ))) { cfg->rd_en = true; @@ -2869,23 +2883,21 @@ static void _sde_plane_sspp_setup_sys_cache(struct sde_plane *psde, cfg->rd_noallocate = (pstate->static_cache_state == CACHE_STATE_FRAME_READ); cfg->flags |= SYS_CACHE_NO_ALLOC; cfg->type = SDE_SYS_CACHE_DISP; - - } else if (test_bit(fb_cache_type, psde->catalog->sde_sys_cache_type_map) - && fb_cache_flag) { + } else if (test_bit(cache_rd_type, psde->catalog->sde_sys_cache_type_map) && cache_flag) { cfg->rd_en = true; - cfg->rd_scid = sc_cfg[fb_cache_type].llcc_scid; + cfg->rd_scid = sc_cfg[cache_rd_type].llcc_scid; cfg->rd_noallocate = true; cfg->flags |= SYS_CACHE_NO_ALLOC; - cfg->type = fb_cache_type; + cache_flag = MSM_FB_CACHE_READ_EN; - msm_framebuffer_set_cache_hint(state->fb, MSM_FB_CACHE_READ_EN, fb_cache_type); + msm_framebuffer_set_cache_hint(state->fb, cache_flag, cache_rd_type, cache_wr_type); } if (!cfg->rd_en && !prev_rd_en) return; SDE_EVT32(DRMID(&psde->base), cfg->rd_scid, cfg->rd_en, cfg->rd_noallocate, cfg->flags, - fb_cache_flag, fb_cache_type); + cache_flag, cache_rd_type, cache_wr_type, state->fb->base.id); psde->pipe_hw->ops.setup_sys_cache(psde->pipe_hw, cfg); } @@ -3585,6 +3597,7 @@ bool sde_plane_is_cache_required(struct drm_plane *plane, enum sde_sys_cache_type type) { struct sde_plane_state *pstate; + u32 cache_flag, cache_rd_type, cache_wr_type; if (!plane || !plane->state) { SDE_ERROR("invalid plane\n"); @@ -3592,12 +3605,20 @@ bool sde_plane_is_cache_required(struct drm_plane *plane, } pstate = to_sde_plane_state(plane->state); + msm_framebuffer_get_cache_hint(plane->state->fb, &cache_flag, &cache_rd_type, + &cache_wr_type); /* check if llcc is required for the plane */ - if (pstate->sc_cfg.rd_en && (pstate->sc_cfg.type == type)) + if (pstate->sc_cfg.rd_en && ((pstate->sc_cfg.type == type) + || (cache_flag && (cache_rd_type == type)) + || (cache_flag && (cache_wr_type == type)))) { + SDE_EVT32_VERBOSE(DRMID(plane), type, pstate->sc_cfg.rd_en, pstate->sc_cfg.type, + cache_flag, cache_rd_type, cache_wr_type, + plane->state->fb->base.id); return true; - else - return false; + } + + return false; } static void _sde_plane_install_master_only_properties(struct sde_plane *psde)