diff options
Diffstat (limited to 'drivers/gpu/drm/msm/disp/dpu1')
19 files changed, 528 insertions, 556 deletions
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c index 967245b8cc02..e7c9fe1a250f 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c @@ -337,7 +337,8 @@ static void _dpu_crtc_program_lm_output_roi(struct drm_crtc *crtc) } static void _dpu_crtc_blend_setup_mixer(struct drm_crtc *crtc, - struct dpu_crtc *dpu_crtc, struct dpu_crtc_mixer *mixer) + struct dpu_crtc *dpu_crtc, struct dpu_crtc_mixer *mixer, + struct dpu_hw_stage_cfg *stage_cfg) { struct drm_plane *plane; struct drm_framebuffer *fb; @@ -346,7 +347,6 @@ static void _dpu_crtc_blend_setup_mixer(struct drm_crtc *crtc, struct dpu_plane_state *pstate = NULL; struct dpu_format *format; struct dpu_hw_ctl *ctl = mixer->lm_ctl; - struct dpu_hw_stage_cfg *stage_cfg = &dpu_crtc->stage_cfg; u32 flush_mask; uint32_t stage_idx, lm_idx; @@ -422,6 +422,7 @@ static void _dpu_crtc_blend_setup(struct drm_crtc *crtc) struct dpu_crtc_mixer *mixer = cstate->mixers; struct dpu_hw_ctl *ctl; struct dpu_hw_mixer *lm; + struct dpu_hw_stage_cfg stage_cfg; int i; DRM_DEBUG_ATOMIC("%s\n", dpu_crtc->name); @@ -435,9 +436,9 @@ static void _dpu_crtc_blend_setup(struct drm_crtc *crtc) } /* initialize stage cfg */ - memset(&dpu_crtc->stage_cfg, 0, sizeof(struct dpu_hw_stage_cfg)); + memset(&stage_cfg, 0, sizeof(struct dpu_hw_stage_cfg)); - _dpu_crtc_blend_setup_mixer(crtc, dpu_crtc, mixer); + _dpu_crtc_blend_setup_mixer(crtc, dpu_crtc, mixer, &stage_cfg); for (i = 0; i < cstate->num_mixers; i++) { ctl = mixer[i].lm_ctl; @@ -458,7 +459,7 @@ static void _dpu_crtc_blend_setup(struct drm_crtc *crtc) mixer[i].flush_mask); ctl->ops.setup_blendstage(ctl, mixer[i].hw_lm->idx, - &dpu_crtc->stage_cfg); + &stage_cfg); } } @@ -923,6 +924,20 @@ static struct drm_crtc_state *dpu_crtc_duplicate_state(struct drm_crtc *crtc) return &cstate->base; } +static void dpu_crtc_atomic_print_state(struct drm_printer *p, + const struct drm_crtc_state *state) +{ + const struct dpu_crtc_state *cstate = to_dpu_crtc_state(state); + int i; + + for (i = 0; i < cstate->num_mixers; i++) { + drm_printf(p, "\tlm[%d]=%d\n", i, cstate->mixers[i].hw_lm->idx - LM_0); + drm_printf(p, "\tctl[%d]=%d\n", i, cstate->mixers[i].lm_ctl->idx - CTL_0); + if (cstate->mixers[i].hw_dspp) + drm_printf(p, "\tdspp[%d]=%d\n", i, cstate->mixers[i].hw_dspp->idx - DSPP_0); + } +} + static void dpu_crtc_disable(struct drm_crtc *crtc, struct drm_atomic_state *state) { @@ -1423,15 +1438,16 @@ DEFINE_SHOW_ATTRIBUTE(dpu_crtc_debugfs_state); static int _dpu_crtc_init_debugfs(struct drm_crtc *crtc) { struct dpu_crtc *dpu_crtc = to_dpu_crtc(crtc); + struct dentry *debugfs_root; - dpu_crtc->debugfs_root = debugfs_create_dir(dpu_crtc->name, + debugfs_root = debugfs_create_dir(dpu_crtc->name, crtc->dev->primary->debugfs_root); debugfs_create_file("status", 0400, - dpu_crtc->debugfs_root, + debugfs_root, dpu_crtc, &_dpu_debugfs_status_fops); debugfs_create_file("state", 0600, - dpu_crtc->debugfs_root, + debugfs_root, &dpu_crtc->base, &dpu_crtc_debugfs_state_fops); @@ -1449,13 +1465,6 @@ static int dpu_crtc_late_register(struct drm_crtc *crtc) return _dpu_crtc_init_debugfs(crtc); } -static void dpu_crtc_early_unregister(struct drm_crtc *crtc) -{ - struct dpu_crtc *dpu_crtc = to_dpu_crtc(crtc); - - debugfs_remove_recursive(dpu_crtc->debugfs_root); -} - static const struct drm_crtc_funcs dpu_crtc_funcs = { .set_config = drm_atomic_helper_set_config, .destroy = dpu_crtc_destroy, @@ -1463,8 +1472,8 @@ static const struct drm_crtc_funcs dpu_crtc_funcs = { .reset = dpu_crtc_reset, .atomic_duplicate_state = dpu_crtc_duplicate_state, .atomic_destroy_state = dpu_crtc_destroy_state, + .atomic_print_state = dpu_crtc_atomic_print_state, .late_register = dpu_crtc_late_register, - .early_unregister = dpu_crtc_early_unregister, .verify_crc_source = dpu_crtc_verify_crc_source, .set_crc_source = dpu_crtc_set_crc_source, .enable_vblank = msm_crtc_enable_vblank, diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.h index ae9546ca1359..b8785c394fcc 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.h @@ -129,8 +129,6 @@ struct dpu_crtc_frame_event { * @drm_requested_vblank : Whether vblanks have been enabled in the encoder * @property_info : Opaque structure for generic property support * @property_defaults : Array of default values for generic property support - * @stage_cfg : H/w mixer stage configuration - * @debugfs_root : Parent of debugfs node * @vblank_cb_count : count of vblank callback since last reset * @play_count : frame count between crtc enable and disable * @vblank_cb_time : ktime at vblank count reset @@ -161,9 +159,6 @@ struct dpu_crtc { struct drm_pending_vblank_event *event; u32 vsync_count; - struct dpu_hw_stage_cfg stage_cfg; - struct dentry *debugfs_root; - u32 vblank_cb_count; u64 play_count; ktime_t vblank_cb_time; diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c index e7ee4cfb8461..1e648db439f9 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c @@ -995,9 +995,6 @@ static void dpu_encoder_virt_mode_set(struct drm_encoder *drm_enc, trace_dpu_enc_mode_set(DRMID(drm_enc)); - if (drm_enc->encoder_type == DRM_MODE_ENCODER_TMDS) - msm_dp_display_mode_set(dpu_enc->dp, drm_enc, mode, adj_mode); - list_for_each_entry(conn_iter, connector_list, head) if (conn_iter->encoder == drm_enc) conn = conn_iter; @@ -1148,10 +1145,6 @@ static void dpu_encoder_virt_enable(struct drm_encoder *drm_enc) struct msm_drm_private *priv; struct drm_display_mode *cur_mode = NULL; - if (!drm_enc) { - DPU_ERROR("invalid encoder\n"); - return; - } dpu_enc = to_dpu_encoder_virt(drm_enc); mutex_lock(&dpu_enc->enc_lock); @@ -1177,14 +1170,6 @@ static void dpu_encoder_virt_enable(struct drm_encoder *drm_enc) _dpu_encoder_virt_enable_helper(drm_enc); - if (drm_enc->encoder_type == DRM_MODE_ENCODER_TMDS) { - ret = msm_dp_display_enable(dpu_enc->dp, drm_enc); - if (ret) { - DPU_ERROR_ENC(dpu_enc, "dp display enable failed: %d\n", - ret); - goto out; - } - } dpu_enc->enabled = true; out: @@ -1197,14 +1182,6 @@ static void dpu_encoder_virt_disable(struct drm_encoder *drm_enc) struct msm_drm_private *priv; int i = 0; - if (!drm_enc) { - DPU_ERROR("invalid encoder\n"); - return; - } else if (!drm_enc->dev) { - DPU_ERROR("invalid dev\n"); - return; - } - dpu_enc = to_dpu_encoder_virt(drm_enc); DPU_DEBUG_ENC(dpu_enc, "\n"); @@ -1218,11 +1195,6 @@ static void dpu_encoder_virt_disable(struct drm_encoder *drm_enc) /* wait for idle */ dpu_encoder_wait_for_event(drm_enc, MSM_ENC_TX_COMPLETE); - if (drm_enc->encoder_type == DRM_MODE_ENCODER_TMDS) { - if (msm_dp_display_pre_disable(dpu_enc->dp, drm_enc)) - DPU_ERROR_ENC(dpu_enc, "dp display push idle failed\n"); - } - dpu_encoder_resource_control(drm_enc, DPU_ENC_RC_EVENT_PRE_STOP); for (i = 0; i < dpu_enc->num_phys_encs; i++) { @@ -1247,11 +1219,6 @@ static void dpu_encoder_virt_disable(struct drm_encoder *drm_enc) DPU_DEBUG_ENC(dpu_enc, "encoder disabled\n"); - if (drm_enc->encoder_type == DRM_MODE_ENCODER_TMDS) { - if (msm_dp_display_disable(dpu_enc->dp, drm_enc)) - DPU_ERROR_ENC(dpu_enc, "dp display disable failed\n"); - } - mutex_unlock(&dpu_enc->enc_lock); } @@ -2128,11 +2095,8 @@ static void dpu_encoder_frame_done_timeout(struct timer_list *t) static const struct drm_encoder_helper_funcs dpu_encoder_helper_funcs = { .mode_set = dpu_encoder_virt_mode_set, .disable = dpu_encoder_virt_disable, - .enable = dpu_kms_encoder_enable, + .enable = dpu_encoder_virt_enable, .atomic_check = dpu_encoder_virt_atomic_check, - - /* This is called by dpu_kms_encoder_enable */ - .commit = dpu_encoder_virt_enable, }; static const struct drm_encoder_funcs dpu_encoder_funcs = { diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c index 185379b18572..ddd9d89cd456 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c @@ -698,17 +698,17 @@ struct dpu_encoder_phys *dpu_encoder_phys_vid_init( { struct dpu_encoder_phys *phys_enc = NULL; struct dpu_encoder_irq *irq; - int i, ret = 0; + int i; if (!p) { - ret = -EINVAL; - goto fail; + DPU_ERROR("failed to create encoder due to invalid parameter\n"); + return ERR_PTR(-EINVAL); } phys_enc = kzalloc(sizeof(*phys_enc), GFP_KERNEL); if (!phys_enc) { - ret = -ENOMEM; - goto fail; + DPU_ERROR("failed to create encoder due to memory allocation error\n"); + return ERR_PTR(-ENOMEM); } phys_enc->hw_mdptop = p->dpu_kms->hw_mdp; @@ -748,11 +748,4 @@ struct dpu_encoder_phys *dpu_encoder_phys_vid_init( DPU_DEBUG_VIDENC(phys_enc, "created intf idx:%d\n", p->intf_idx); return phys_enc; - -fail: - DPU_ERROR("failed to create encoder\n"); - if (phys_enc) - dpu_encoder_phys_vid_destroy(phys_enc); - - return ERR_PTR(ret); } diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c index ce6f32a919e5..aa75991903a6 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c @@ -45,7 +45,7 @@ (PINGPONG_SDM845_MASK | BIT(DPU_PINGPONG_TE2)) #define CTL_SC7280_MASK \ - (BIT(DPU_CTL_ACTIVE_CFG) | BIT(DPU_CTL_FETCH_ACTIVE)) + (BIT(DPU_CTL_ACTIVE_CFG) | BIT(DPU_CTL_FETCH_ACTIVE) | BIT(DPU_CTL_VM_CFG)) #define MERGE_3D_SM8150_MASK (0) @@ -856,9 +856,9 @@ static const struct dpu_intf_cfg sm8150_intf[] = { }; static const struct dpu_intf_cfg sc7280_intf[] = { - INTF_BLK("intf_0", INTF_0, 0x34000, INTF_DP, 0, 24, INTF_SC7280_MASK, MDP_SSPP_TOP0_INTR, 24, 25), + INTF_BLK("intf_0", INTF_0, 0x34000, INTF_DP, MSM_DP_CONTROLLER_0, 24, INTF_SC7280_MASK, MDP_SSPP_TOP0_INTR, 24, 25), INTF_BLK("intf_1", INTF_1, 0x35000, INTF_DSI, 0, 24, INTF_SC7280_MASK, MDP_SSPP_TOP0_INTR, 26, 27), - INTF_BLK("intf_5", INTF_5, 0x39000, INTF_EDP, 0, 24, INTF_SC7280_MASK, MDP_SSPP_TOP0_INTR, 22, 23), + INTF_BLK("intf_5", INTF_5, 0x39000, INTF_DP, MSM_DP_CONTROLLER_1, 24, INTF_SC7280_MASK, MDP_SSPP_TOP0_INTR, 22, 23), }; /************************************************************* diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h index 4ade44bbd37e..31af04afda7d 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h @@ -179,13 +179,16 @@ enum { /** * CTL sub-blocks - * @DPU_CTL_SPLIT_DISPLAY CTL supports video mode split display + * @DPU_CTL_SPLIT_DISPLAY: CTL supports video mode split display + * @DPU_CTL_FETCH_ACTIVE: Active CTL for fetch HW (SSPPs) + * @DPU_CTL_VM_CFG: CTL config to support multiple VMs * @DPU_CTL_MAX */ enum { DPU_CTL_SPLIT_DISPLAY = 0x1, DPU_CTL_ACTIVE_CFG, DPU_CTL_FETCH_ACTIVE, + DPU_CTL_VM_CFG, DPU_CTL_MAX }; diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c index 64740ddb983e..02da9ecf71f1 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c @@ -36,6 +36,7 @@ #define MERGE_3D_IDX 23 #define INTF_IDX 31 #define CTL_INVALID_BIT 0xffff +#define CTL_DEFAULT_GROUP_ID 0xf static const u32 fetch_tbl[SSPP_MAX] = {CTL_INVALID_BIT, 16, 17, 18, 19, CTL_INVALID_BIT, CTL_INVALID_BIT, CTL_INVALID_BIT, CTL_INVALID_BIT, 0, @@ -498,6 +499,13 @@ static void dpu_hw_ctl_intf_cfg_v1(struct dpu_hw_ctl *ctx, u32 intf_active = 0; u32 mode_sel = 0; + /* CTL_TOP[31:28] carries group_id to collate CTL paths + * per VM. Explicitly disable it until VM support is + * added in SW. Power on reset value is not disable. + */ + if ((test_bit(DPU_CTL_VM_CFG, &ctx->caps->features))) + mode_sel = CTL_DEFAULT_GROUP_ID << 28; + if (cfg->intf_mode_sel == DPU_CTL_MODE_SEL_CMD) mode_sel |= BIT(17); diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.c index d2b6dca487e3..a77a5eaa78ad 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.c @@ -30,6 +30,9 @@ #define MDP_AD4_INTR_STATUS_OFF 0x420 #define MDP_INTF_0_OFF_REV_7xxx 0x34000 #define MDP_INTF_1_OFF_REV_7xxx 0x35000 +#define MDP_INTF_2_OFF_REV_7xxx 0x36000 +#define MDP_INTF_3_OFF_REV_7xxx 0x37000 +#define MDP_INTF_4_OFF_REV_7xxx 0x38000 #define MDP_INTF_5_OFF_REV_7xxx 0x39000 /** @@ -111,6 +114,21 @@ static const struct dpu_intr_reg dpu_intr_set[] = { MDP_INTF_1_OFF_REV_7xxx+INTF_INTR_STATUS }, { + MDP_INTF_2_OFF_REV_7xxx+INTF_INTR_CLEAR, + MDP_INTF_2_OFF_REV_7xxx+INTF_INTR_EN, + MDP_INTF_2_OFF_REV_7xxx+INTF_INTR_STATUS + }, + { + MDP_INTF_3_OFF_REV_7xxx+INTF_INTR_CLEAR, + MDP_INTF_3_OFF_REV_7xxx+INTF_INTR_EN, + MDP_INTF_3_OFF_REV_7xxx+INTF_INTR_STATUS + }, + { + MDP_INTF_4_OFF_REV_7xxx+INTF_INTR_CLEAR, + MDP_INTF_4_OFF_REV_7xxx+INTF_INTR_EN, + MDP_INTF_4_OFF_REV_7xxx+INTF_INTR_STATUS + }, + { MDP_INTF_5_OFF_REV_7xxx+INTF_INTR_CLEAR, MDP_INTF_5_OFF_REV_7xxx+INTF_INTR_EN, MDP_INTF_5_OFF_REV_7xxx+INTF_INTR_STATUS diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.h index d50e78c9f148..1ab75cccd145 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.h @@ -26,6 +26,9 @@ enum dpu_hw_intr_reg { MDP_AD4_1_INTR, MDP_INTF0_7xxx_INTR, MDP_INTF1_7xxx_INTR, + MDP_INTF2_7xxx_INTR, + MDP_INTF3_7xxx_INTR, + MDP_INTF4_7xxx_INTR, MDP_INTF5_7xxx_INTR, MDP_INTR_MAX, }; diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.c index f9460672176a..09cdc3576653 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.c @@ -8,6 +8,8 @@ #include "dpu_hw_sspp.h" #include "dpu_kms.h" +#include <drm/drm_file.h> + #define DPU_FETCH_CONFIG_RESET_VALUE 0x00000087 /* DPU_SSPP_SRC */ @@ -75,6 +77,7 @@ #define SSPP_TRAFFIC_SHAPER 0x130 #define SSPP_CDP_CNTL 0x134 #define SSPP_UBWC_ERROR_STATUS 0x138 +#define SSPP_CDP_CNTL_REC1 0x13c #define SSPP_TRAFFIC_SHAPER_PREFILL 0x150 #define SSPP_TRAFFIC_SHAPER_REC1_PREFILL 0x154 #define SSPP_TRAFFIC_SHAPER_REC1 0x158 @@ -413,13 +416,11 @@ static void dpu_hw_sspp_setup_pe_config(struct dpu_hw_pipe *ctx, static void _dpu_hw_sspp_setup_scaler3(struct dpu_hw_pipe *ctx, struct dpu_hw_pipe_cfg *sspp, - struct dpu_hw_pixel_ext *pe, void *scaler_cfg) { u32 idx; struct dpu_hw_scaler3_cfg *scaler3_cfg = scaler_cfg; - (void)pe; if (_sspp_subblk_offset(ctx, DPU_SSPP_SCALER_QSEED3, &idx) || !sspp || !scaler3_cfg) return; @@ -539,7 +540,7 @@ static void dpu_hw_sspp_setup_sourceaddress(struct dpu_hw_pipe *ctx, } static void dpu_hw_sspp_setup_csc(struct dpu_hw_pipe *ctx, - struct dpu_csc_cfg *data) + const struct dpu_csc_cfg *data) { u32 idx; bool csc10 = false; @@ -571,19 +572,20 @@ static void dpu_hw_sspp_setup_solidfill(struct dpu_hw_pipe *ctx, u32 color, enum } static void dpu_hw_sspp_setup_danger_safe_lut(struct dpu_hw_pipe *ctx, - struct dpu_hw_pipe_qos_cfg *cfg) + u32 danger_lut, + u32 safe_lut) { u32 idx; if (_sspp_subblk_offset(ctx, DPU_SSPP_SRC, &idx)) return; - DPU_REG_WRITE(&ctx->hw, SSPP_DANGER_LUT + idx, cfg->danger_lut); - DPU_REG_WRITE(&ctx->hw, SSPP_SAFE_LUT + idx, cfg->safe_lut); + DPU_REG_WRITE(&ctx->hw, SSPP_DANGER_LUT + idx, danger_lut); + DPU_REG_WRITE(&ctx->hw, SSPP_SAFE_LUT + idx, safe_lut); } static void dpu_hw_sspp_setup_creq_lut(struct dpu_hw_pipe *ctx, - struct dpu_hw_pipe_qos_cfg *cfg) + u64 creq_lut) { u32 idx; @@ -591,11 +593,11 @@ static void dpu_hw_sspp_setup_creq_lut(struct dpu_hw_pipe *ctx, return; if (ctx->cap && test_bit(DPU_SSPP_QOS_8LVL, &ctx->cap->features)) { - DPU_REG_WRITE(&ctx->hw, SSPP_CREQ_LUT_0 + idx, cfg->creq_lut); + DPU_REG_WRITE(&ctx->hw, SSPP_CREQ_LUT_0 + idx, creq_lut); DPU_REG_WRITE(&ctx->hw, SSPP_CREQ_LUT_1 + idx, - cfg->creq_lut >> 32); + creq_lut >> 32); } else { - DPU_REG_WRITE(&ctx->hw, SSPP_CREQ_LUT + idx, cfg->creq_lut); + DPU_REG_WRITE(&ctx->hw, SSPP_CREQ_LUT + idx, creq_lut); } } @@ -625,10 +627,12 @@ static void dpu_hw_sspp_setup_qos_ctrl(struct dpu_hw_pipe *ctx, } static void dpu_hw_sspp_setup_cdp(struct dpu_hw_pipe *ctx, - struct dpu_hw_pipe_cdp_cfg *cfg) + struct dpu_hw_pipe_cdp_cfg *cfg, + enum dpu_sspp_multirect_index index) { u32 idx; u32 cdp_cntl = 0; + u32 cdp_cntl_offset = 0; if (!ctx || !cfg) return; @@ -636,6 +640,11 @@ static void dpu_hw_sspp_setup_cdp(struct dpu_hw_pipe *ctx, if (_sspp_subblk_offset(ctx, DPU_SSPP_SRC, &idx)) return; + if (index == DPU_SSPP_RECT_SOLO || index == DPU_SSPP_RECT_0) + cdp_cntl_offset = SSPP_CDP_CNTL; + else + cdp_cntl_offset = SSPP_CDP_CNTL_REC1; + if (cfg->enable) cdp_cntl |= BIT(0); if (cfg->ubwc_meta_enable) @@ -645,7 +654,7 @@ static void dpu_hw_sspp_setup_cdp(struct dpu_hw_pipe *ctx, if (cfg->preload_ahead == DPU_SSPP_CDP_PRELOAD_AHEAD_64) cdp_cntl |= BIT(3); - DPU_REG_WRITE(&ctx->hw, SSPP_CDP_CNTL, cdp_cntl); + DPU_REG_WRITE(&ctx->hw, cdp_cntl_offset, cdp_cntl); } static void _setup_layer_ops(struct dpu_hw_pipe *c, @@ -685,6 +694,71 @@ static void _setup_layer_ops(struct dpu_hw_pipe *c, c->ops.setup_cdp = dpu_hw_sspp_setup_cdp; } +#ifdef CONFIG_DEBUG_FS +int _dpu_hw_sspp_init_debugfs(struct dpu_hw_pipe *hw_pipe, struct dpu_kms *kms, struct dentry *entry) +{ + const struct dpu_sspp_cfg *cfg = hw_pipe->cap; + const struct dpu_sspp_sub_blks *sblk = cfg->sblk; + struct dentry *debugfs_root; + char sspp_name[32]; + + snprintf(sspp_name, sizeof(sspp_name), "%d", hw_pipe->idx); + + /* create overall sub-directory for the pipe */ + debugfs_root = + debugfs_create_dir(sspp_name, entry); + + /* don't error check these */ + debugfs_create_xul("features", 0600, + debugfs_root, (unsigned long *)&hw_pipe->cap->features); + + /* add register dump support */ + dpu_debugfs_create_regset32("src_blk", 0400, + debugfs_root, + sblk->src_blk.base + cfg->base, + sblk->src_blk.len, + kms); + + if (cfg->features & BIT(DPU_SSPP_SCALER_QSEED3) || + cfg->features & BIT(DPU_SSPP_SCALER_QSEED3LITE) || + cfg->features & BIT(DPU_SSPP_SCALER_QSEED2) || + cfg->features & BIT(DPU_SSPP_SCALER_QSEED4)) + dpu_debugfs_create_regset32("scaler_blk", 0400, + debugfs_root, + sblk->scaler_blk.base + cfg->base, + sblk->scaler_blk.len, + kms); + + if (cfg->features & BIT(DPU_SSPP_CSC) || + cfg->features & BIT(DPU_SSPP_CSC_10BIT)) + dpu_debugfs_create_regset32("csc_blk", 0400, + debugfs_root, + sblk->csc_blk.base + cfg->base, + sblk->csc_blk.len, + kms); + + debugfs_create_u32("xin_id", + 0400, + debugfs_root, + (u32 *) &cfg->xin_id); + debugfs_create_u32("clk_ctrl", + 0400, + debugfs_root, + (u32 *) &cfg->clk_ctrl); + debugfs_create_x32("creq_vblank", + 0600, + debugfs_root, + (u32 *) &sblk->creq_vblank); + debugfs_create_x32("danger_vblank", + 0600, + debugfs_root, + (u32 *) &sblk->danger_vblank); + + return 0; +} +#endif + + static const struct dpu_sspp_cfg *_sspp_offset(enum dpu_sspp sspp, void __iomem *addr, struct dpu_mdss_cfg *catalog, diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.h index fdfd4b46e2c6..92b071b78fdb 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.h @@ -25,11 +25,17 @@ struct dpu_hw_pipe; /** * Define all scaler feature bits in catalog */ -#define DPU_SSPP_SCALER ((1UL << DPU_SSPP_SCALER_RGB) | \ - (1UL << DPU_SSPP_SCALER_QSEED2) | \ - (1UL << DPU_SSPP_SCALER_QSEED3) | \ - (1UL << DPU_SSPP_SCALER_QSEED3LITE) | \ - (1UL << DPU_SSPP_SCALER_QSEED4)) +#define DPU_SSPP_SCALER (BIT(DPU_SSPP_SCALER_RGB) | \ + BIT(DPU_SSPP_SCALER_QSEED2) | \ + BIT(DPU_SSPP_SCALER_QSEED3) | \ + BIT(DPU_SSPP_SCALER_QSEED3LITE) | \ + BIT(DPU_SSPP_SCALER_QSEED4)) + +/* + * Define all CSC feature bits in catalog + */ +#define DPU_SSPP_CSC_ANY (BIT(DPU_SSPP_CSC) | \ + BIT(DPU_SSPP_CSC_10BIT)) /** * Component indices @@ -166,18 +172,12 @@ struct dpu_hw_pipe_cfg { /** * struct dpu_hw_pipe_qos_cfg : Source pipe QoS configuration - * @danger_lut: LUT for generate danger level based on fill level - * @safe_lut: LUT for generate safe level based on fill level - * @creq_lut: LUT for generate creq level based on fill level * @creq_vblank: creq value generated to vbif during vertical blanking * @danger_vblank: danger value generated during vertical blanking * @vblank_en: enable creq_vblank and danger_vblank during vblank * @danger_safe_en: enable danger safe generation */ struct dpu_hw_pipe_qos_cfg { - u32 danger_lut; - u32 safe_lut; - u64 creq_lut; u32 creq_vblank; u32 danger_vblank; bool vblank_en; @@ -268,7 +268,7 @@ struct dpu_hw_sspp_ops { * @ctx: Pointer to pipe context * @data: Pointer to config structure */ - void (*setup_csc)(struct dpu_hw_pipe *ctx, struct dpu_csc_cfg *data); + void (*setup_csc)(struct dpu_hw_pipe *ctx, const struct dpu_csc_cfg *data); /** * setup_solidfill - enable/disable colorfill @@ -302,20 +302,22 @@ struct dpu_hw_sspp_ops { /** * setup_danger_safe_lut - setup danger safe LUTs * @ctx: Pointer to pipe context - * @cfg: Pointer to pipe QoS configuration + * @danger_lut: LUT for generate danger level based on fill level + * @safe_lut: LUT for generate safe level based on fill level * */ void (*setup_danger_safe_lut)(struct dpu_hw_pipe *ctx, - struct dpu_hw_pipe_qos_cfg *cfg); + u32 danger_lut, + u32 safe_lut); /** * setup_creq_lut - setup CREQ LUT * @ctx: Pointer to pipe context - * @cfg: Pointer to pipe QoS configuration + * @creq_lut: LUT for generate creq level based on fill level * */ void (*setup_creq_lut)(struct dpu_hw_pipe *ctx, - struct dpu_hw_pipe_qos_cfg *cfg); + u64 creq_lut); /** * setup_qos_ctrl - setup QoS control @@ -338,12 +340,10 @@ struct dpu_hw_sspp_ops { * setup_scaler - setup scaler * @ctx: Pointer to pipe context * @pipe_cfg: Pointer to pipe configuration - * @pe_cfg: Pointer to pixel extension configuration * @scaler_cfg: Pointer to scaler configuration */ void (*setup_scaler)(struct dpu_hw_pipe *ctx, struct dpu_hw_pipe_cfg *pipe_cfg, - struct dpu_hw_pixel_ext *pe_cfg, void *scaler_cfg); /** @@ -356,9 +356,11 @@ struct dpu_hw_sspp_ops { * setup_cdp - setup client driven prefetch * @ctx: Pointer to pipe context * @cfg: Pointer to cdp configuration + * @index: rectangle index in multirect */ void (*setup_cdp)(struct dpu_hw_pipe *ctx, - struct dpu_hw_pipe_cdp_cfg *cfg); + struct dpu_hw_pipe_cdp_cfg *cfg, + enum dpu_sspp_multirect_index index); }; /** @@ -385,6 +387,7 @@ struct dpu_hw_pipe { struct dpu_hw_sspp_ops ops; }; +struct dpu_kms; /** * dpu_hw_sspp_init - initializes the sspp hw driver object. * Should be called once before accessing every pipe. @@ -404,5 +407,8 @@ struct dpu_hw_pipe *dpu_hw_sspp_init(enum dpu_sspp idx, */ void dpu_hw_sspp_destroy(struct dpu_hw_pipe *ctx); +void dpu_debugfs_sspp_init(struct dpu_kms *dpu_kms, struct dentry *debugfs_root); +int _dpu_hw_sspp_init_debugfs(struct dpu_hw_pipe *hw_pipe, struct dpu_kms *kms, struct dentry *entry); + #endif /*_DPU_HW_SSPP_H */ diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_util.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_util.c index f94584c982cd..aad85116b0a0 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_util.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_util.c @@ -374,7 +374,7 @@ u32 dpu_hw_get_scaler3_ver(struct dpu_hw_blk_reg_map *c, void dpu_hw_csc_setup(struct dpu_hw_blk_reg_map *c, u32 csc_reg_off, - struct dpu_csc_cfg *data, bool csc10) + const struct dpu_csc_cfg *data, bool csc10) { static const u32 matrix_shift = 7; u32 clamp_shift = csc10 ? 16 : 8; diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_util.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_util.h index 6d4911957e33..39134754579e 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_util.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_util.h @@ -322,6 +322,6 @@ u32 dpu_hw_get_scaler3_ver(struct dpu_hw_blk_reg_map *c, void dpu_hw_csc_setup(struct dpu_hw_blk_reg_map *c, u32 csc_reg_off, - struct dpu_csc_cfg *data, bool csc10); + const struct dpu_csc_cfg *data, bool csc10); #endif /* _DPU_HW_UTIL_H */ diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c index a15b26428280..47fe11a84a77 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c @@ -21,14 +21,14 @@ #include "msm_gem.h" #include "disp/msm_disp_snapshot.h" -#include "dpu_kms.h" #include "dpu_core_irq.h" +#include "dpu_crtc.h" +#include "dpu_encoder.h" #include "dpu_formats.h" #include "dpu_hw_vbif.h" -#include "dpu_vbif.h" -#include "dpu_encoder.h" +#include "dpu_kms.h" #include "dpu_plane.h" -#include "dpu_crtc.h" +#include "dpu_vbif.h" #define CREATE_TRACE_POINTS #include "dpu_trace.h" @@ -73,8 +73,8 @@ static int _dpu_danger_signal_status(struct seq_file *s, &status); } else { seq_puts(s, "\nSafe signal status:\n"); - if (kms->hw_mdp->ops.get_danger_status) - kms->hw_mdp->ops.get_danger_status(kms->hw_mdp, + if (kms->hw_mdp->ops.get_safe_status) + kms->hw_mdp->ops.get_safe_status(kms->hw_mdp, &status); } pm_runtime_put_sync(&kms->pdev->dev); @@ -82,7 +82,7 @@ static int _dpu_danger_signal_status(struct seq_file *s, seq_printf(s, "MDP : 0x%x\n", status.mdp); for (i = SSPP_VIG0; i < SSPP_MAX; i++) - seq_printf(s, "SSPP%d : 0x%x \t", i - SSPP_VIG0, + seq_printf(s, "SSPP%d : 0x%x \n", i - SSPP_VIG0, status.sspp[i]); seq_puts(s, "\n"); @@ -101,6 +101,73 @@ static int dpu_debugfs_safe_stats_show(struct seq_file *s, void *v) } DEFINE_SHOW_ATTRIBUTE(dpu_debugfs_safe_stats); +static ssize_t _dpu_plane_danger_read(struct file *file, + char __user *buff, size_t count, loff_t *ppos) +{ + struct dpu_kms *kms = file->private_data; + int len; + char buf[40]; + + len = scnprintf(buf, sizeof(buf), "%d\n", !kms->has_danger_ctrl); + + return simple_read_from_buffer(buff, count, ppos, buf, len); +} + +static void _dpu_plane_set_danger_state(struct dpu_kms *kms, bool enable) +{ + struct drm_plane *plane; + + drm_for_each_plane(plane, kms->dev) { + if (plane->fb && plane->state) { + dpu_plane_danger_signal_ctrl(plane, enable); + DPU_DEBUG("plane:%d img:%dx%d ", + plane->base.id, plane->fb->width, + plane->fb->height); + DPU_DEBUG("src[%d,%d,%d,%d] dst[%d,%d,%d,%d]\n", + plane->state->src_x >> 16, + plane->state->src_y >> 16, + plane->state->src_w >> 16, + plane->state->src_h >> 16, + plane->state->crtc_x, plane->state->crtc_y, + plane->state->crtc_w, plane->state->crtc_h); + } else { + DPU_DEBUG("Inactive plane:%d\n", plane->base.id); + } + } +} + +static ssize_t _dpu_plane_danger_write(struct file *file, + const char __user *user_buf, size_t count, loff_t *ppos) +{ + struct dpu_kms *kms = file->private_data; + int disable_panic; + int ret; + + ret = kstrtouint_from_user(user_buf, count, 0, &disable_panic); + if (ret) + return ret; + + if (disable_panic) { + /* Disable panic signal for all active pipes */ + DPU_DEBUG("Disabling danger:\n"); + _dpu_plane_set_danger_state(kms, false); + kms->has_danger_ctrl = false; + } else { + /* Enable panic signal for all active pipes */ + DPU_DEBUG("Enabling danger:\n"); + kms->has_danger_ctrl = true; + _dpu_plane_set_danger_state(kms, true); + } + + return count; +} + +static const struct file_operations dpu_plane_danger_enable = { + .open = simple_open, + .read = _dpu_plane_danger_read, + .write = _dpu_plane_danger_write, +}; + static void dpu_debugfs_danger_init(struct dpu_kms *dpu_kms, struct dentry *parent) { @@ -110,8 +177,20 @@ static void dpu_debugfs_danger_init(struct dpu_kms *dpu_kms, dpu_kms, &dpu_debugfs_danger_stats_fops); debugfs_create_file("safe_status", 0600, entry, dpu_kms, &dpu_debugfs_safe_stats_fops); + debugfs_create_file("disable_danger", 0600, entry, + dpu_kms, &dpu_plane_danger_enable); + } +/* + * Companion structure for dpu_debugfs_create_regset32. + */ +struct dpu_debugfs_regset32 { + uint32_t offset; + uint32_t blk_len; + struct dpu_kms *dpu_kms; +}; + static int _dpu_debugfs_show_regset32(struct seq_file *s, void *data) { struct dpu_debugfs_regset32 *regset = s->private; @@ -159,24 +238,23 @@ static const struct file_operations dpu_fops_regset32 = { .release = single_release, }; -void dpu_debugfs_setup_regset32(struct dpu_debugfs_regset32 *regset, +void dpu_debugfs_create_regset32(const char *name, umode_t mode, + void *parent, uint32_t offset, uint32_t length, struct dpu_kms *dpu_kms) { - if (regset) { - regset->offset = offset; - regset->blk_len = length; - regset->dpu_kms = dpu_kms; - } -} + struct dpu_debugfs_regset32 *regset; -void dpu_debugfs_create_regset32(const char *name, umode_t mode, - void *parent, struct dpu_debugfs_regset32 *regset) -{ - if (!name || !regset || !regset->dpu_kms || !regset->blk_len) + if (WARN_ON(!name || !dpu_kms || !length)) + return; + + regset = devm_kzalloc(&dpu_kms->pdev->dev, sizeof(*regset), GFP_KERNEL); + if (!regset) return; /* make sure offset is a multiple of 4 */ - regset->offset = round_down(regset->offset, 4); + regset->offset = round_down(offset, 4); + regset->blk_len = length; + regset->dpu_kms = dpu_kms; debugfs_create_file(name, mode, parent, regset, &dpu_fops_regset32); } @@ -203,6 +281,7 @@ static int dpu_kms_debugfs_init(struct msm_kms *kms, struct drm_minor *minor) dpu_debugfs_danger_init(dpu_kms, entry); dpu_debugfs_vbif_init(dpu_kms, entry); dpu_debugfs_core_irq_init(dpu_kms, entry); + dpu_debugfs_sspp_init(dpu_kms, entry); for (i = 0; i < ARRAY_SIZE(priv->dp); i++) { if (priv->dp[i]) @@ -384,28 +463,6 @@ static void dpu_kms_flush_commit(struct msm_kms *kms, unsigned crtc_mask) } } -/* - * Override the encoder enable since we need to setup the inline rotator and do - * some crtc magic before enabling any bridge that might be present. - */ -void dpu_kms_encoder_enable(struct drm_encoder *encoder) -{ - const struct drm_encoder_helper_funcs *funcs = encoder->helper_private; - struct drm_device *dev = encoder->dev; - struct drm_crtc *crtc; - - /* Forward this enable call to the commit hook */ - if (funcs && funcs->commit) - funcs->commit(encoder); - - drm_for_each_crtc(crtc, dev) { - if (!(crtc->state->encoder_mask & drm_encoder_mask(encoder))) - continue; - - trace_dpu_kms_enc_enable(DRMID(crtc)); - } -} - static void dpu_kms_complete_commit(struct msm_kms *kms, unsigned crtc_mask) { struct dpu_kms *dpu_kms = to_dpu_kms(kms); @@ -863,6 +920,11 @@ static void dpu_kms_mdp_snapshot(struct msm_disp_state *disp_state, struct msm_k msm_disp_snapshot_add_block(disp_state, cat->sspp[i].len, dpu_kms->mmio + cat->sspp[i].base, "sspp_%d", i); + /* dump LM sub-blocks HW regs info */ + for (i = 0; i < cat->mixer_count; i++) + msm_disp_snapshot_add_block(disp_state, cat->mixer[i].len, + dpu_kms->mmio + cat->mixer[i].base, "lm_%d", i); + msm_disp_snapshot_add_block(disp_state, top->hw.length, dpu_kms->mmio + top->hw.blk_off, "top"); @@ -1153,9 +1215,9 @@ struct msm_kms *dpu_kms_init(struct drm_device *dev) static int dpu_bind(struct device *dev, struct device *master, void *data) { - struct drm_device *ddev = dev_get_drvdata(master); + struct msm_drm_private *priv = dev_get_drvdata(master); struct platform_device *pdev = to_platform_device(dev); - struct msm_drm_private *priv = ddev->dev_private; + struct drm_device *ddev = priv->dev; struct dpu_kms *dpu_kms; struct dss_module_power *mp; int ret = 0; @@ -1285,7 +1347,7 @@ static const struct dev_pm_ops dpu_pm_ops = { pm_runtime_force_resume) }; -static const struct of_device_id dpu_dt_match[] = { +const struct of_device_id dpu_dt_match[] = { { .compatible = "qcom,sdm845-dpu", }, { .compatible = "qcom,sc7180-dpu", }, { .compatible = "qcom,sc7280-dpu", }, diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h index 775bcbda860f..2d385b4b7f5e 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h @@ -160,34 +160,10 @@ struct dpu_global_state * * Documentation/filesystems/debugfs.rst * - * @dpu_debugfs_setup_regset32: Initialize data for dpu_debugfs_create_regset32 * @dpu_debugfs_create_regset32: Create 32-bit register dump file - * @dpu_debugfs_get_root: Get root dentry for DPU_KMS's debugfs node */ /** - * Companion structure for dpu_debugfs_create_regset32. Do not initialize the - * members of this structure explicitly; use dpu_debugfs_setup_regset32 instead. - */ -struct dpu_debugfs_regset32 { - uint32_t offset; - uint32_t blk_len; - struct dpu_kms *dpu_kms; -}; - -/** - * dpu_debugfs_setup_regset32 - Initialize register block definition for debugfs - * This function is meant to initialize dpu_debugfs_regset32 structures for use - * with dpu_debugfs_create_regset32. - * @regset: opaque register definition structure - * @offset: sub-block offset - * @length: sub-block length, in bytes - * @dpu_kms: pointer to dpu kms structure - */ -void dpu_debugfs_setup_regset32(struct dpu_debugfs_regset32 *regset, - uint32_t offset, uint32_t length, struct dpu_kms *dpu_kms); - -/** * dpu_debugfs_create_regset32 - Create register read back file for debugfs * * This function is almost identical to the standard debugfs_create_regset32() @@ -195,20 +171,16 @@ void dpu_debugfs_setup_regset32(struct dpu_debugfs_regset32 *regset, * names/offsets do not need to be provided. The 'read' function simply outputs * sequential register values over a specified range. * - * Similar to the related debugfs_create_regset32 API, the structure pointed to - * by regset needs to persist for the lifetime of the created file. The calling - * code is responsible for initialization/management of this structure. - * - * The structure pointed to by regset is meant to be opaque. Please use - * dpu_debugfs_setup_regset32 to initialize it. - * * @name: File name within debugfs * @mode: File mode within debugfs * @parent: Parent directory entry within debugfs, can be NULL - * @regset: Pointer to persistent register block definition + * @offset: sub-block offset + * @length: sub-block length, in bytes + * @dpu_kms: pointer to dpu kms structure */ void dpu_debugfs_create_regset32(const char *name, umode_t mode, - void *parent, struct dpu_debugfs_regset32 *regset); + void *parent, + uint32_t offset, uint32_t length, struct dpu_kms *dpu_kms); /** * dpu_debugfs_get_root - Return root directory entry for KMS's debugfs @@ -235,8 +207,6 @@ void *dpu_debugfs_get_root(struct dpu_kms *dpu_kms); int dpu_enable_vblank(struct msm_kms *kms, struct drm_crtc *crtc); void dpu_disable_vblank(struct msm_kms *kms, struct drm_crtc *crtc); -void dpu_kms_encoder_enable(struct drm_encoder *encoder); - /** * dpu_kms_get_clk_rate() - get the clock rate * @dpu_kms: pointer to dpu_kms structure diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_mdss.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_mdss.c index b466784d9822..131c1f1a869c 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_mdss.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_mdss.c @@ -111,7 +111,7 @@ static int _dpu_mdss_irq_domain_add(struct dpu_mdss *dpu_mdss) struct device *dev; struct irq_domain *domain; - dev = dpu_mdss->base.dev->dev; + dev = dpu_mdss->base.dev; domain = irq_domain_add_linear(dev->of_node, 32, &dpu_mdss_irqdomain_ops, dpu_mdss); @@ -184,16 +184,15 @@ static int dpu_mdss_disable(struct msm_mdss *mdss) return ret; } -static void dpu_mdss_destroy(struct drm_device *dev) +static void dpu_mdss_destroy(struct msm_mdss *mdss) { - struct platform_device *pdev = to_platform_device(dev->dev); - struct msm_drm_private *priv = dev->dev_private; - struct dpu_mdss *dpu_mdss = to_dpu_mdss(priv->mdss); + struct platform_device *pdev = to_platform_device(mdss->dev); + struct dpu_mdss *dpu_mdss = to_dpu_mdss(mdss); struct dss_module_power *mp = &dpu_mdss->mp; int irq; - pm_runtime_suspend(dev->dev); - pm_runtime_disable(dev->dev); + pm_runtime_suspend(mdss->dev); + pm_runtime_disable(mdss->dev); _dpu_mdss_irq_domain_fini(dpu_mdss); irq = platform_get_irq(pdev, 0); irq_set_chained_handler_and_data(irq, NULL, NULL); @@ -203,7 +202,6 @@ static void dpu_mdss_destroy(struct drm_device *dev) if (dpu_mdss->mmio) devm_iounmap(&pdev->dev, dpu_mdss->mmio); dpu_mdss->mmio = NULL; - priv->mdss = NULL; } static const struct msm_mdss_funcs mdss_funcs = { @@ -212,16 +210,15 @@ static const struct msm_mdss_funcs mdss_funcs = { .destroy = dpu_mdss_destroy, }; -int dpu_mdss_init(struct drm_device *dev) +int dpu_mdss_init(struct platform_device *pdev) { - struct platform_device *pdev = to_platform_device(dev->dev); - struct msm_drm_private *priv = dev->dev_private; + struct msm_drm_private *priv = platform_get_drvdata(pdev); struct dpu_mdss *dpu_mdss; struct dss_module_power *mp; int ret; int irq; - dpu_mdss = devm_kzalloc(dev->dev, sizeof(*dpu_mdss), GFP_KERNEL); + dpu_mdss = devm_kzalloc(&pdev->dev, sizeof(*dpu_mdss), GFP_KERNEL); if (!dpu_mdss) return -ENOMEM; @@ -238,7 +235,7 @@ int dpu_mdss_init(struct drm_device *dev) goto clk_parse_err; } - dpu_mdss->base.dev = dev; + dpu_mdss->base.dev = &pdev->dev; dpu_mdss->base.funcs = &mdss_funcs; ret = _dpu_mdss_irq_domain_add(dpu_mdss); @@ -256,7 +253,7 @@ int dpu_mdss_init(struct drm_device *dev) priv->mdss = &dpu_mdss->base; - pm_runtime_enable(dev->dev); + pm_runtime_enable(&pdev->dev); return 0; diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c index a3e3b9d1b82e..ca75089c9d61 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c @@ -13,7 +13,6 @@ #include <drm/drm_atomic.h> #include <drm/drm_atomic_uapi.h> #include <drm/drm_damage_helper.h> -#include <drm/drm_file.h> #include <drm/drm_gem_atomic_helper.h> #include "msm_drv.h" @@ -90,7 +89,6 @@ enum dpu_plane_qos { /* * struct dpu_plane - local dpu plane structure * @aspace: address space pointer - * @csc_ptr: Points to dpu_csc_cfg structure to use for current * @mplane_list: List of multirect planes of the same pipe * @catalog: Points to dpu catalog structure * @revalidate: force revalidation of all the plane properties @@ -101,29 +99,14 @@ struct dpu_plane { struct mutex lock; enum dpu_sspp pipe; - uint32_t features; /* capabilities from catalog */ struct dpu_hw_pipe *pipe_hw; - struct dpu_hw_pipe_cfg pipe_cfg; - struct dpu_hw_pipe_qos_cfg pipe_qos_cfg; uint32_t color_fill; bool is_error; bool is_rt_pipe; bool is_virtual; struct list_head mplane_list; struct dpu_mdss_cfg *catalog; - - struct dpu_csc_cfg *csc_ptr; - - const struct dpu_sspp_sub_blks *pipe_sblk; - char pipe_name[DPU_NAME_SIZE]; - - /* debugfs related stuff */ - struct dentry *debugfs_root; - struct dpu_debugfs_regset32 debugfs_src; - struct dpu_debugfs_regset32 debugfs_scaler; - struct dpu_debugfs_regset32 debugfs_csc; - bool debugfs_default_scale; }; static const uint64_t supported_format_modifiers[] = { @@ -145,14 +128,15 @@ static struct dpu_kms *_dpu_plane_get_kms(struct drm_plane *plane) * _dpu_plane_calc_bw - calculate bandwidth required for a plane * @plane: Pointer to drm plane. * @fb: Pointer to framebuffer associated with the given plane + * @pipe_cfg: Pointer to pipe configuration * Result: Updates calculated bandwidth in the plane state. * BW Equation: src_w * src_h * bpp * fps * (v_total / v_dest) * Prefill BW Equation: line src bytes * line_time */ static void _dpu_plane_calc_bw(struct drm_plane *plane, - struct drm_framebuffer *fb) + struct drm_framebuffer *fb, + struct dpu_hw_pipe_cfg *pipe_cfg) { - struct dpu_plane *pdpu = to_dpu_plane(plane); struct dpu_plane_state *pstate; struct drm_display_mode *mode; const struct dpu_format *fmt = NULL; @@ -169,9 +153,9 @@ static void _dpu_plane_calc_bw(struct drm_plane *plane, fmt = dpu_get_dpu_format_ext(fb->format->format, fb->modifier); - src_width = drm_rect_width(&pdpu->pipe_cfg.src_rect); - src_height = drm_rect_height(&pdpu->pipe_cfg.src_rect); - dst_height = drm_rect_height(&pdpu->pipe_cfg.dst_rect); + src_width = drm_rect_width(&pipe_cfg->src_rect); + src_height = drm_rect_height(&pipe_cfg->src_rect); + dst_height = drm_rect_height(&pipe_cfg->dst_rect); fps = drm_mode_vrefresh(mode); vbp = mode->vtotal - mode->vsync_end; vpw = mode->vsync_end - mode->vsync_start; @@ -202,12 +186,12 @@ static void _dpu_plane_calc_bw(struct drm_plane *plane, /** * _dpu_plane_calc_clk - calculate clock required for a plane * @plane: Pointer to drm plane. + * @pipe_cfg: Pointer to pipe configuration * Result: Updates calculated clock in the plane state. * Clock equation: dst_w * v_total * fps * (src_h / dst_h) */ -static void _dpu_plane_calc_clk(struct drm_plane *plane) +static void _dpu_plane_calc_clk(struct drm_plane *plane, struct dpu_hw_pipe_cfg *pipe_cfg) { - struct dpu_plane *pdpu = to_dpu_plane(plane); struct dpu_plane_state *pstate; struct drm_display_mode *mode; int dst_width, src_height, dst_height, fps; @@ -215,9 +199,9 @@ static void _dpu_plane_calc_clk(struct drm_plane *plane) pstate = to_dpu_plane_state(plane->state); mode = &plane->state->crtc->mode; - src_height = drm_rect_height(&pdpu->pipe_cfg.src_rect); - dst_width = drm_rect_width(&pdpu->pipe_cfg.dst_rect); - dst_height = drm_rect_height(&pdpu->pipe_cfg.dst_rect); + src_height = drm_rect_height(&pipe_cfg->src_rect); + dst_width = drm_rect_width(&pipe_cfg->dst_rect); + dst_height = drm_rect_height(&pipe_cfg->dst_rect); fps = drm_mode_vrefresh(mode); pstate->plane_clk = @@ -254,14 +238,17 @@ static int _dpu_plane_calc_fill_level(struct drm_plane *plane, fixed_buff_size = pdpu->catalog->caps->pixel_ram_size; list_for_each_entry(tmp, &pdpu->mplane_list, mplane_list) { + u32 tmp_width; + if (!tmp->base.state->visible) continue; + tmp_width = drm_rect_width(&tmp->base.state->src) >> 16; DPU_DEBUG("plane%d/%d src_width:%d/%d\n", pdpu->base.base.id, tmp->base.base.id, src_width, - drm_rect_width(&tmp->pipe_cfg.src_rect)); + tmp_width); src_width = max_t(u32, src_width, - drm_rect_width(&tmp->pipe_cfg.src_rect)); + tmp_width); } if (fmt->fetch_planes == DPU_PLANE_PSEUDO_PLANAR) { @@ -321,9 +308,10 @@ static u64 _dpu_plane_get_qos_lut(const struct dpu_qos_lut_tbl *tbl, * _dpu_plane_set_qos_lut - set QoS LUT of the given plane * @plane: Pointer to drm plane * @fb: Pointer to framebuffer associated with the given plane + * @pipe_cfg: Pointer to pipe configuration */ static void _dpu_plane_set_qos_lut(struct drm_plane *plane, - struct drm_framebuffer *fb) + struct drm_framebuffer *fb, struct dpu_hw_pipe_cfg *pipe_cfg) { struct dpu_plane *pdpu = to_dpu_plane(plane); const struct dpu_format *fmt = NULL; @@ -337,7 +325,7 @@ static void _dpu_plane_set_qos_lut(struct drm_plane *plane, fb->format->format, fb->modifier); total_fl = _dpu_plane_calc_fill_level(plane, fmt, - drm_rect_width(&pdpu->pipe_cfg.src_rect)); + drm_rect_width(&pipe_cfg->src_rect)); if (fmt && DPU_FORMAT_IS_LINEAR(fmt)) lut_usage = DPU_QOS_LUT_USAGE_LINEAR; @@ -348,8 +336,6 @@ static void _dpu_plane_set_qos_lut(struct drm_plane *plane, qos_lut = _dpu_plane_get_qos_lut( &pdpu->catalog->perf.qos_lut_tbl[lut_usage], total_fl); - pdpu->pipe_qos_cfg.creq_lut = qos_lut; - trace_dpu_perf_set_qos_luts(pdpu->pipe - SSPP_VIG0, (fmt) ? fmt->base.pixel_format : 0, pdpu->is_rt_pipe, total_fl, qos_lut, lut_usage); @@ -359,7 +345,7 @@ static void _dpu_plane_set_qos_lut(struct drm_plane *plane, fmt ? (char *)&fmt->base.pixel_format : NULL, pdpu->is_rt_pipe, total_fl, qos_lut); - pdpu->pipe_hw->ops.setup_creq_lut(pdpu->pipe_hw, &pdpu->pipe_qos_cfg); + pdpu->pipe_hw->ops.setup_creq_lut(pdpu->pipe_hw, qos_lut); } /** @@ -397,24 +383,21 @@ static void _dpu_plane_set_danger_lut(struct drm_plane *plane, } } - pdpu->pipe_qos_cfg.danger_lut = danger_lut; - pdpu->pipe_qos_cfg.safe_lut = safe_lut; - trace_dpu_perf_set_danger_luts(pdpu->pipe - SSPP_VIG0, (fmt) ? fmt->base.pixel_format : 0, (fmt) ? fmt->fetch_mode : 0, - pdpu->pipe_qos_cfg.danger_lut, - pdpu->pipe_qos_cfg.safe_lut); + danger_lut, + safe_lut); DPU_DEBUG_PLANE(pdpu, "pnum:%d fmt: %4.4s mode:%d luts[0x%x, 0x%x]\n", pdpu->pipe - SSPP_VIG0, fmt ? (char *)&fmt->base.pixel_format : NULL, fmt ? fmt->fetch_mode : -1, - pdpu->pipe_qos_cfg.danger_lut, - pdpu->pipe_qos_cfg.safe_lut); + danger_lut, + safe_lut); pdpu->pipe_hw->ops.setup_danger_safe_lut(pdpu->pipe_hw, - &pdpu->pipe_qos_cfg); + danger_lut, safe_lut); } /** @@ -427,47 +410,51 @@ static void _dpu_plane_set_qos_ctrl(struct drm_plane *plane, bool enable, u32 flags) { struct dpu_plane *pdpu = to_dpu_plane(plane); + struct dpu_hw_pipe_qos_cfg pipe_qos_cfg; + + memset(&pipe_qos_cfg, 0, sizeof(pipe_qos_cfg)); if (flags & DPU_PLANE_QOS_VBLANK_CTRL) { - pdpu->pipe_qos_cfg.creq_vblank = pdpu->pipe_sblk->creq_vblank; - pdpu->pipe_qos_cfg.danger_vblank = - pdpu->pipe_sblk->danger_vblank; - pdpu->pipe_qos_cfg.vblank_en = enable; + pipe_qos_cfg.creq_vblank = pdpu->pipe_hw->cap->sblk->creq_vblank; + pipe_qos_cfg.danger_vblank = + pdpu->pipe_hw->cap->sblk->danger_vblank; + pipe_qos_cfg.vblank_en = enable; } if (flags & DPU_PLANE_QOS_VBLANK_AMORTIZE) { /* this feature overrules previous VBLANK_CTRL */ - pdpu->pipe_qos_cfg.vblank_en = false; - pdpu->pipe_qos_cfg.creq_vblank = 0; /* clear vblank bits */ + pipe_qos_cfg.vblank_en = false; + pipe_qos_cfg.creq_vblank = 0; /* clear vblank bits */ } if (flags & DPU_PLANE_QOS_PANIC_CTRL) - pdpu->pipe_qos_cfg.danger_safe_en = enable; + pipe_qos_cfg.danger_safe_en = enable; if (!pdpu->is_rt_pipe) { - pdpu->pipe_qos_cfg.vblank_en = false; - pdpu->pipe_qos_cfg.danger_safe_en = false; + pipe_qos_cfg.vblank_en = false; + pipe_qos_cfg.danger_safe_en = false; } DPU_DEBUG_PLANE(pdpu, "pnum:%d ds:%d vb:%d pri[0x%x, 0x%x] is_rt:%d\n", pdpu->pipe - SSPP_VIG0, - pdpu->pipe_qos_cfg.danger_safe_en, - pdpu->pipe_qos_cfg.vblank_en, - pdpu->pipe_qos_cfg.creq_vblank, - pdpu->pipe_qos_cfg.danger_vblank, + pipe_qos_cfg.danger_safe_en, + pipe_qos_cfg.vblank_en, + pipe_qos_cfg.creq_vblank, + pipe_qos_cfg.danger_vblank, pdpu->is_rt_pipe); pdpu->pipe_hw->ops.setup_qos_ctrl(pdpu->pipe_hw, - &pdpu->pipe_qos_cfg); + &pipe_qos_cfg); } /** * _dpu_plane_set_ot_limit - set OT limit for the given plane * @plane: Pointer to drm plane * @crtc: Pointer to drm crtc + * @pipe_cfg: Pointer to pipe configuration */ static void _dpu_plane_set_ot_limit(struct drm_plane *plane, - struct drm_crtc *crtc) + struct drm_crtc *crtc, struct dpu_hw_pipe_cfg *pipe_cfg) { struct dpu_plane *pdpu = to_dpu_plane(plane); struct dpu_vbif_set_ot_params ot_params; @@ -476,8 +463,8 @@ static void _dpu_plane_set_ot_limit(struct drm_plane *plane, memset(&ot_params, 0, sizeof(ot_params)); ot_params.xin_id = pdpu->pipe_hw->cap->xin_id; ot_params.num = pdpu->pipe_hw->idx - SSPP_NONE; - ot_params.width = drm_rect_width(&pdpu->pipe_cfg.src_rect); - ot_params.height = drm_rect_height(&pdpu->pipe_cfg.src_rect); + ot_params.width = drm_rect_width(&pipe_cfg->src_rect); + ot_params.height = drm_rect_height(&pipe_cfg->src_rect); ot_params.is_wfd = !pdpu->is_rt_pipe; ot_params.frame_rate = drm_mode_vrefresh(&crtc->mode); ot_params.vbif_idx = VBIF_RT; @@ -541,14 +528,12 @@ static void _dpu_plane_setup_scaler3(struct dpu_plane *pdpu, struct dpu_plane_state *pstate, uint32_t src_w, uint32_t src_h, uint32_t dst_w, uint32_t dst_h, struct dpu_hw_scaler3_cfg *scale_cfg, + struct dpu_hw_pixel_ext *pixel_ext, const struct dpu_format *fmt, uint32_t chroma_subsmpl_h, uint32_t chroma_subsmpl_v) { uint32_t i; - memset(scale_cfg, 0, sizeof(*scale_cfg)); - memset(&pstate->pixel_ext, 0, sizeof(struct dpu_hw_pixel_ext)); - scale_cfg->phase_step_x[DPU_SSPP_COMP_0] = mult_frac((1 << PHASE_STEP_SHIFT), src_w, dst_w); scale_cfg->phase_step_y[DPU_SSPP_COMP_0] = @@ -587,9 +572,9 @@ static void _dpu_plane_setup_scaler3(struct dpu_plane *pdpu, scale_cfg->preload_y[i] = DPU_QSEED3_DEFAULT_PRELOAD_V; } - pstate->pixel_ext.num_ext_pxls_top[i] = + pixel_ext->num_ext_pxls_top[i] = scale_cfg->src_height[i]; - pstate->pixel_ext.num_ext_pxls_left[i] = + pixel_ext->num_ext_pxls_left[i] = scale_cfg->src_width[i]; } if (!(DPU_FORMAT_IS_YUV(fmt)) && (src_h == dst_h) @@ -606,68 +591,97 @@ static void _dpu_plane_setup_scaler3(struct dpu_plane *pdpu, scale_cfg->enable = 1; } -static void _dpu_plane_setup_csc(struct dpu_plane *pdpu) -{ - static const struct dpu_csc_cfg dpu_csc_YUV2RGB_601L = { - { - /* S15.16 format */ - 0x00012A00, 0x00000000, 0x00019880, - 0x00012A00, 0xFFFF9B80, 0xFFFF3000, - 0x00012A00, 0x00020480, 0x00000000, +static const struct dpu_csc_cfg dpu_csc_YUV2RGB_601L = { + { + /* S15.16 format */ + 0x00012A00, 0x00000000, 0x00019880, + 0x00012A00, 0xFFFF9B80, 0xFFFF3000, + 0x00012A00, 0x00020480, 0x00000000, + }, + /* signed bias */ + { 0xfff0, 0xff80, 0xff80,}, + { 0x0, 0x0, 0x0,}, + /* unsigned clamp */ + { 0x10, 0xeb, 0x10, 0xf0, 0x10, 0xf0,}, + { 0x00, 0xff, 0x00, 0xff, 0x00, 0xff,}, +}; + +static const struct dpu_csc_cfg dpu_csc10_YUV2RGB_601L = { + { + /* S15.16 format */ + 0x00012A00, 0x00000000, 0x00019880, + 0x00012A00, 0xFFFF9B80, 0xFFFF3000, + 0x00012A00, 0x00020480, 0x00000000, }, - /* signed bias */ - { 0xfff0, 0xff80, 0xff80,}, - { 0x0, 0x0, 0x0,}, - /* unsigned clamp */ - { 0x10, 0xeb, 0x10, 0xf0, 0x10, 0xf0,}, - { 0x00, 0xff, 0x00, 0xff, 0x00, 0xff,}, - }; - static const struct dpu_csc_cfg dpu_csc10_YUV2RGB_601L = { - { - /* S15.16 format */ - 0x00012A00, 0x00000000, 0x00019880, - 0x00012A00, 0xFFFF9B80, 0xFFFF3000, - 0x00012A00, 0x00020480, 0x00000000, - }, - /* signed bias */ - { 0xffc0, 0xfe00, 0xfe00,}, - { 0x0, 0x0, 0x0,}, - /* unsigned clamp */ - { 0x40, 0x3ac, 0x40, 0x3c0, 0x40, 0x3c0,}, - { 0x00, 0x3ff, 0x00, 0x3ff, 0x00, 0x3ff,}, - }; + /* signed bias */ + { 0xffc0, 0xfe00, 0xfe00,}, + { 0x0, 0x0, 0x0,}, + /* unsigned clamp */ + { 0x40, 0x3ac, 0x40, 0x3c0, 0x40, 0x3c0,}, + { 0x00, 0x3ff, 0x00, 0x3ff, 0x00, 0x3ff,}, +}; + +static const struct dpu_csc_cfg *_dpu_plane_get_csc(struct dpu_plane *pdpu, const struct dpu_format *fmt) +{ + const struct dpu_csc_cfg *csc_ptr; if (!pdpu) { DPU_ERROR("invalid plane\n"); - return; + return NULL; } - if (BIT(DPU_SSPP_CSC_10BIT) & pdpu->features) - pdpu->csc_ptr = (struct dpu_csc_cfg *)&dpu_csc10_YUV2RGB_601L; + if (!DPU_FORMAT_IS_YUV(fmt)) + return NULL; + + if (BIT(DPU_SSPP_CSC_10BIT) & pdpu->pipe_hw->cap->features) + csc_ptr = &dpu_csc10_YUV2RGB_601L; else - pdpu->csc_ptr = (struct dpu_csc_cfg *)&dpu_csc_YUV2RGB_601L; + csc_ptr = &dpu_csc_YUV2RGB_601L; DPU_DEBUG_PLANE(pdpu, "using 0x%X 0x%X 0x%X...\n", - pdpu->csc_ptr->csc_mv[0], - pdpu->csc_ptr->csc_mv[1], - pdpu->csc_ptr->csc_mv[2]); + csc_ptr->csc_mv[0], + csc_ptr->csc_mv[1], + csc_ptr->csc_mv[2]); + + return csc_ptr; } static void _dpu_plane_setup_scaler(struct dpu_plane *pdpu, struct dpu_plane_state *pstate, - const struct dpu_format *fmt, bool color_fill) + const struct dpu_format *fmt, bool color_fill, + struct dpu_hw_pipe_cfg *pipe_cfg) { const struct drm_format_info *info = drm_format_info(fmt->base.pixel_format); + struct dpu_hw_scaler3_cfg scaler3_cfg; + struct dpu_hw_pixel_ext pixel_ext; + + memset(&scaler3_cfg, 0, sizeof(scaler3_cfg)); + memset(&pixel_ext, 0, sizeof(pixel_ext)); /* don't chroma subsample if decimating */ /* update scaler. calculate default config for QSEED3 */ _dpu_plane_setup_scaler3(pdpu, pstate, - drm_rect_width(&pdpu->pipe_cfg.src_rect), - drm_rect_height(&pdpu->pipe_cfg.src_rect), - drm_rect_width(&pdpu->pipe_cfg.dst_rect), - drm_rect_height(&pdpu->pipe_cfg.dst_rect), - &pstate->scaler3_cfg, fmt, + drm_rect_width(&pipe_cfg->src_rect), + drm_rect_height(&pipe_cfg->src_rect), + drm_rect_width(&pipe_cfg->dst_rect), + drm_rect_height(&pipe_cfg->dst_rect), + &scaler3_cfg, &pixel_ext, fmt, info->hsub, info->vsub); + + if (pdpu->pipe_hw->ops.setup_pe) + pdpu->pipe_hw->ops.setup_pe(pdpu->pipe_hw, + &pixel_ext); + + /** + * when programmed in multirect mode, scalar block will be + * bypassed. Still we need to update alpha and bitwidth + * ONLY for RECT0 + */ + if (pdpu->pipe_hw->ops.setup_scaler && + pstate->multirect_index != DPU_SSPP_RECT_1) + pdpu->pipe_hw->ops.setup_scaler(pdpu->pipe_hw, + pipe_cfg, + &scaler3_cfg); } /** @@ -683,6 +697,7 @@ static int _dpu_plane_color_fill(struct dpu_plane *pdpu, const struct dpu_format *fmt; const struct drm_plane *plane = &pdpu->base; struct dpu_plane_state *pstate = to_dpu_plane_state(plane->state); + struct dpu_hw_pipe_cfg pipe_cfg; DPU_DEBUG_PLANE(pdpu, "\n"); @@ -699,13 +714,14 @@ static int _dpu_plane_color_fill(struct dpu_plane *pdpu, pstate->multirect_index); /* override scaler/decimation if solid fill */ - pdpu->pipe_cfg.src_rect.x1 = 0; - pdpu->pipe_cfg.src_rect.y1 = 0; - pdpu->pipe_cfg.src_rect.x2 = - drm_rect_width(&pdpu->pipe_cfg.dst_rect); - pdpu->pipe_cfg.src_rect.y2 = - drm_rect_height(&pdpu->pipe_cfg.dst_rect); - _dpu_plane_setup_scaler(pdpu, pstate, fmt, true); + pipe_cfg.dst_rect = pstate->base.dst; + + pipe_cfg.src_rect.x1 = 0; + pipe_cfg.src_rect.y1 = 0; + pipe_cfg.src_rect.x2 = + drm_rect_width(&pipe_cfg.dst_rect); + pipe_cfg.src_rect.y2 = + drm_rect_height(&pipe_cfg.dst_rect); if (pdpu->pipe_hw->ops.setup_format) pdpu->pipe_hw->ops.setup_format(pdpu->pipe_hw, @@ -714,18 +730,10 @@ static int _dpu_plane_color_fill(struct dpu_plane *pdpu, if (pdpu->pipe_hw->ops.setup_rects) pdpu->pipe_hw->ops.setup_rects(pdpu->pipe_hw, - &pdpu->pipe_cfg, + &pipe_cfg, pstate->multirect_index); - if (pdpu->pipe_hw->ops.setup_pe) - pdpu->pipe_hw->ops.setup_pe(pdpu->pipe_hw, - &pstate->pixel_ext); - - if (pdpu->pipe_hw->ops.setup_scaler && - pstate->multirect_index != DPU_SSPP_RECT_1) - pdpu->pipe_hw->ops.setup_scaler(pdpu->pipe_hw, - &pdpu->pipe_cfg, &pstate->pixel_ext, - &pstate->scaler3_cfg); + _dpu_plane_setup_scaler(pdpu, pstate, fmt, true, &pipe_cfg); } return 0; @@ -964,10 +972,10 @@ static int dpu_plane_atomic_check(struct drm_plane *plane, crtc_state = drm_atomic_get_new_crtc_state(state, new_plane_state->crtc); - min_scale = FRAC_16_16(1, pdpu->pipe_sblk->maxupscale); + min_scale = FRAC_16_16(1, pdpu->pipe_hw->cap->sblk->maxupscale); ret = drm_atomic_helper_check_plane_state(new_plane_state, crtc_state, min_scale, - pdpu->pipe_sblk->maxdwnscale << 16, + pdpu->pipe_hw->cap->sblk->maxdwnscale << 16, true, true); if (ret) { DPU_DEBUG_PLANE(pdpu, "Check plane state failed (%d)\n", ret); @@ -993,9 +1001,8 @@ static int dpu_plane_atomic_check(struct drm_plane *plane, min_src_size = DPU_FORMAT_IS_YUV(fmt) ? 2 : 1; if (DPU_FORMAT_IS_YUV(fmt) && - (!(pdpu->features & DPU_SSPP_SCALER) || - !(pdpu->features & (BIT(DPU_SSPP_CSC) - | BIT(DPU_SSPP_CSC_10BIT))))) { + (!(pdpu->pipe_hw->cap->features & DPU_SSPP_SCALER) || + !(pdpu->pipe_hw->cap->features & DPU_SSPP_CSC_ANY))) { DPU_DEBUG_PLANE(pdpu, "plane doesn't have scaler/csc for yuv\n"); return -EINVAL; @@ -1056,8 +1063,13 @@ void dpu_plane_flush(struct drm_plane *plane) else if (pdpu->color_fill & DPU_PLANE_COLOR_FILL_FLAG) /* force 100% alpha */ _dpu_plane_color_fill(pdpu, pdpu->color_fill, 0xFF); - else if (pdpu->pipe_hw && pdpu->csc_ptr && pdpu->pipe_hw->ops.setup_csc) - pdpu->pipe_hw->ops.setup_csc(pdpu->pipe_hw, pdpu->csc_ptr); + else if (pdpu->pipe_hw && pdpu->pipe_hw->ops.setup_csc) { + const struct dpu_format *fmt = to_dpu_format(msm_framebuffer_format(plane->state->fb)); + const struct dpu_csc_cfg *csc_ptr = _dpu_plane_get_csc(pdpu, fmt); + + if (csc_ptr) + pdpu->pipe_hw->ops.setup_csc(pdpu->pipe_hw, csc_ptr); + } /* flag h/w flush complete */ if (plane->state) @@ -1091,10 +1103,11 @@ static void dpu_plane_sspp_atomic_update(struct drm_plane *plane) bool is_rt_pipe, update_qos_remap; const struct dpu_format *fmt = to_dpu_format(msm_framebuffer_format(fb)); + struct dpu_hw_pipe_cfg pipe_cfg; - memset(&(pdpu->pipe_cfg), 0, sizeof(struct dpu_hw_pipe_cfg)); + memset(&pipe_cfg, 0, sizeof(struct dpu_hw_pipe_cfg)); - _dpu_plane_set_scanout(plane, pstate, &pdpu->pipe_cfg, fb); + _dpu_plane_set_scanout(plane, pstate, &pipe_cfg, fb); pstate->pending = true; @@ -1106,17 +1119,15 @@ static void dpu_plane_sspp_atomic_update(struct drm_plane *plane) crtc->base.id, DRM_RECT_ARG(&state->dst), (char *)&fmt->base.pixel_format, DPU_FORMAT_IS_UBWC(fmt)); - pdpu->pipe_cfg.src_rect = state->src; + pipe_cfg.src_rect = state->src; /* state->src is 16.16, src_rect is not */ - pdpu->pipe_cfg.src_rect.x1 >>= 16; - pdpu->pipe_cfg.src_rect.x2 >>= 16; - pdpu->pipe_cfg.src_rect.y1 >>= 16; - pdpu->pipe_cfg.src_rect.y2 >>= 16; - - pdpu->pipe_cfg.dst_rect = state->dst; + pipe_cfg.src_rect.x1 >>= 16; + pipe_cfg.src_rect.x2 >>= 16; + pipe_cfg.src_rect.y1 >>= 16; + pipe_cfg.src_rect.y2 >>= 16; - _dpu_plane_setup_scaler(pdpu, pstate, fmt, false); + pipe_cfg.dst_rect = state->dst; /* override for color fill */ if (pdpu->color_fill & DPU_PLANE_COLOR_FILL_FLAG) { @@ -1126,25 +1137,11 @@ static void dpu_plane_sspp_atomic_update(struct drm_plane *plane) if (pdpu->pipe_hw->ops.setup_rects) { pdpu->pipe_hw->ops.setup_rects(pdpu->pipe_hw, - &pdpu->pipe_cfg, + &pipe_cfg, pstate->multirect_index); } - if (pdpu->pipe_hw->ops.setup_pe && - (pstate->multirect_index != DPU_SSPP_RECT_1)) - pdpu->pipe_hw->ops.setup_pe(pdpu->pipe_hw, - &pstate->pixel_ext); - - /** - * when programmed in multirect mode, scalar block will be - * bypassed. Still we need to update alpha and bitwidth - * ONLY for RECT0 - */ - if (pdpu->pipe_hw->ops.setup_scaler && - pstate->multirect_index != DPU_SSPP_RECT_1) - pdpu->pipe_hw->ops.setup_scaler(pdpu->pipe_hw, - &pdpu->pipe_cfg, &pstate->pixel_ext, - &pstate->scaler3_cfg); + _dpu_plane_setup_scaler(pdpu, pstate, fmt, false, &pipe_cfg); if (pdpu->pipe_hw->ops.setup_multirect) pdpu->pipe_hw->ops.setup_multirect( @@ -1173,35 +1170,29 @@ static void dpu_plane_sspp_atomic_update(struct drm_plane *plane) pstate->multirect_index); if (pdpu->pipe_hw->ops.setup_cdp) { - struct dpu_hw_pipe_cdp_cfg *cdp_cfg = &pstate->cdp_cfg; + struct dpu_hw_pipe_cdp_cfg cdp_cfg; - memset(cdp_cfg, 0, sizeof(struct dpu_hw_pipe_cdp_cfg)); + memset(&cdp_cfg, 0, sizeof(struct dpu_hw_pipe_cdp_cfg)); - cdp_cfg->enable = pdpu->catalog->perf.cdp_cfg + cdp_cfg.enable = pdpu->catalog->perf.cdp_cfg [DPU_PERF_CDP_USAGE_RT].rd_enable; - cdp_cfg->ubwc_meta_enable = + cdp_cfg.ubwc_meta_enable = DPU_FORMAT_IS_UBWC(fmt); - cdp_cfg->tile_amortize_enable = + cdp_cfg.tile_amortize_enable = DPU_FORMAT_IS_UBWC(fmt) || DPU_FORMAT_IS_TILE(fmt); - cdp_cfg->preload_ahead = DPU_SSPP_CDP_PRELOAD_AHEAD_64; + cdp_cfg.preload_ahead = DPU_SSPP_CDP_PRELOAD_AHEAD_64; - pdpu->pipe_hw->ops.setup_cdp(pdpu->pipe_hw, cdp_cfg); + pdpu->pipe_hw->ops.setup_cdp(pdpu->pipe_hw, &cdp_cfg, pstate->multirect_index); } - - /* update csc */ - if (DPU_FORMAT_IS_YUV(fmt)) - _dpu_plane_setup_csc(pdpu); - else - pdpu->csc_ptr = NULL; } - _dpu_plane_set_qos_lut(plane, fb); + _dpu_plane_set_qos_lut(plane, fb, &pipe_cfg); _dpu_plane_set_danger_lut(plane, fb); if (plane->type != DRM_PLANE_TYPE_CURSOR) { _dpu_plane_set_qos_ctrl(plane, true, DPU_PLANE_QOS_PANIC_CTRL); - _dpu_plane_set_ot_limit(plane, crtc); + _dpu_plane_set_ot_limit(plane, crtc, &pipe_cfg); } update_qos_remap = (is_rt_pipe != pdpu->is_rt_pipe) || @@ -1215,9 +1206,9 @@ static void dpu_plane_sspp_atomic_update(struct drm_plane *plane) _dpu_plane_set_qos_remap(plane); } - _dpu_plane_calc_bw(plane, fb); + _dpu_plane_calc_bw(plane, fb, &pipe_cfg); - _dpu_plane_calc_clk(plane); + _dpu_plane_calc_clk(plane, &pipe_cfg); } static void _dpu_plane_atomic_disable(struct drm_plane *plane) @@ -1314,6 +1305,46 @@ dpu_plane_duplicate_state(struct drm_plane *plane) return &pstate->base; } +static const char * const multirect_mode_name[] = { + [DPU_SSPP_MULTIRECT_NONE] = "none", + [DPU_SSPP_MULTIRECT_PARALLEL] = "parallel", + [DPU_SSPP_MULTIRECT_TIME_MX] = "time_mx", +}; + +static const char * const multirect_index_name[] = { + [DPU_SSPP_RECT_SOLO] = "solo", + [DPU_SSPP_RECT_0] = "rect_0", + [DPU_SSPP_RECT_1] = "rect_1", +}; + +static const char *dpu_get_multirect_mode(enum dpu_sspp_multirect_mode mode) +{ + if (WARN_ON(mode >= ARRAY_SIZE(multirect_mode_name))) + return "unknown"; + + return multirect_mode_name[mode]; +} + +static const char *dpu_get_multirect_index(enum dpu_sspp_multirect_index index) +{ + if (WARN_ON(index >= ARRAY_SIZE(multirect_index_name))) + return "unknown"; + + return multirect_index_name[index]; +} + +static void dpu_plane_atomic_print_state(struct drm_printer *p, + const struct drm_plane_state *state) +{ + const struct dpu_plane_state *pstate = to_dpu_plane_state(state); + const struct dpu_plane *pdpu = to_dpu_plane(state->plane); + + drm_printf(p, "\tstage=%d\n", pstate->stage); + drm_printf(p, "\tsspp=%s\n", pdpu->pipe_hw->cap->name); + drm_printf(p, "\tmultirect_mode=%s\n", dpu_get_multirect_mode(pstate->multirect_mode)); + drm_printf(p, "\tmultirect_index=%s\n", dpu_get_multirect_index(pstate->multirect_index)); +} + static void dpu_plane_reset(struct drm_plane *plane) { struct dpu_plane *pdpu; @@ -1343,7 +1374,7 @@ static void dpu_plane_reset(struct drm_plane *plane) } #ifdef CONFIG_DEBUG_FS -static void dpu_plane_danger_signal_ctrl(struct drm_plane *plane, bool enable) +void dpu_plane_danger_signal_ctrl(struct drm_plane *plane, bool enable) { struct dpu_plane *pdpu = to_dpu_plane(plane); struct dpu_kms *dpu_kms = _dpu_plane_get_kms(plane); @@ -1356,167 +1387,23 @@ static void dpu_plane_danger_signal_ctrl(struct drm_plane *plane, bool enable) pm_runtime_put_sync(&dpu_kms->pdev->dev); } -static ssize_t _dpu_plane_danger_read(struct file *file, - char __user *buff, size_t count, loff_t *ppos) -{ - struct dpu_kms *kms = file->private_data; - int len; - char buf[40]; - - len = scnprintf(buf, sizeof(buf), "%d\n", !kms->has_danger_ctrl); - - return simple_read_from_buffer(buff, count, ppos, buf, len); -} - -static void _dpu_plane_set_danger_state(struct dpu_kms *kms, bool enable) +/* SSPP live inside dpu_plane private data only. Enumerate them here. */ +void dpu_debugfs_sspp_init(struct dpu_kms *dpu_kms, struct dentry *debugfs_root) { struct drm_plane *plane; + struct dentry *entry = debugfs_create_dir("sspp", debugfs_root); - drm_for_each_plane(plane, kms->dev) { - if (plane->fb && plane->state) { - dpu_plane_danger_signal_ctrl(plane, enable); - DPU_DEBUG("plane:%d img:%dx%d ", - plane->base.id, plane->fb->width, - plane->fb->height); - DPU_DEBUG("src[%d,%d,%d,%d] dst[%d,%d,%d,%d]\n", - plane->state->src_x >> 16, - plane->state->src_y >> 16, - plane->state->src_w >> 16, - plane->state->src_h >> 16, - plane->state->crtc_x, plane->state->crtc_y, - plane->state->crtc_w, plane->state->crtc_h); - } else { - DPU_DEBUG("Inactive plane:%d\n", plane->base.id); - } - } -} - -static ssize_t _dpu_plane_danger_write(struct file *file, - const char __user *user_buf, size_t count, loff_t *ppos) -{ - struct dpu_kms *kms = file->private_data; - int disable_panic; - int ret; - - ret = kstrtouint_from_user(user_buf, count, 0, &disable_panic); - if (ret) - return ret; - - if (disable_panic) { - /* Disable panic signal for all active pipes */ - DPU_DEBUG("Disabling danger:\n"); - _dpu_plane_set_danger_state(kms, false); - kms->has_danger_ctrl = false; - } else { - /* Enable panic signal for all active pipes */ - DPU_DEBUG("Enabling danger:\n"); - kms->has_danger_ctrl = true; - _dpu_plane_set_danger_state(kms, true); - } - - return count; -} + if (IS_ERR(entry)) + return; -static const struct file_operations dpu_plane_danger_enable = { - .open = simple_open, - .read = _dpu_plane_danger_read, - .write = _dpu_plane_danger_write, -}; + drm_for_each_plane(plane, dpu_kms->dev) { + struct dpu_plane *pdpu = to_dpu_plane(plane); -static int _dpu_plane_init_debugfs(struct drm_plane *plane) -{ - struct dpu_plane *pdpu = to_dpu_plane(plane); - struct dpu_kms *kms = _dpu_plane_get_kms(plane); - const struct dpu_sspp_cfg *cfg = pdpu->pipe_hw->cap; - const struct dpu_sspp_sub_blks *sblk = cfg->sblk; - - /* create overall sub-directory for the pipe */ - pdpu->debugfs_root = - debugfs_create_dir(pdpu->pipe_name, - plane->dev->primary->debugfs_root); - - /* don't error check these */ - debugfs_create_x32("features", 0600, - pdpu->debugfs_root, &pdpu->features); - - /* add register dump support */ - dpu_debugfs_setup_regset32(&pdpu->debugfs_src, - sblk->src_blk.base + cfg->base, - sblk->src_blk.len, - kms); - dpu_debugfs_create_regset32("src_blk", 0400, - pdpu->debugfs_root, &pdpu->debugfs_src); - - if (cfg->features & BIT(DPU_SSPP_SCALER_QSEED3) || - cfg->features & BIT(DPU_SSPP_SCALER_QSEED3LITE) || - cfg->features & BIT(DPU_SSPP_SCALER_QSEED2) || - cfg->features & BIT(DPU_SSPP_SCALER_QSEED4)) { - dpu_debugfs_setup_regset32(&pdpu->debugfs_scaler, - sblk->scaler_blk.base + cfg->base, - sblk->scaler_blk.len, - kms); - dpu_debugfs_create_regset32("scaler_blk", 0400, - pdpu->debugfs_root, - &pdpu->debugfs_scaler); - debugfs_create_bool("default_scaling", - 0600, - pdpu->debugfs_root, - &pdpu->debugfs_default_scale); - } - - if (cfg->features & BIT(DPU_SSPP_CSC) || - cfg->features & BIT(DPU_SSPP_CSC_10BIT)) { - dpu_debugfs_setup_regset32(&pdpu->debugfs_csc, - sblk->csc_blk.base + cfg->base, - sblk->csc_blk.len, - kms); - dpu_debugfs_create_regset32("csc_blk", 0400, - pdpu->debugfs_root, &pdpu->debugfs_csc); + _dpu_hw_sspp_init_debugfs(pdpu->pipe_hw, dpu_kms, entry); } - - debugfs_create_u32("xin_id", - 0400, - pdpu->debugfs_root, - (u32 *) &cfg->xin_id); - debugfs_create_u32("clk_ctrl", - 0400, - pdpu->debugfs_root, - (u32 *) &cfg->clk_ctrl); - debugfs_create_x32("creq_vblank", - 0600, - pdpu->debugfs_root, - (u32 *) &sblk->creq_vblank); - debugfs_create_x32("danger_vblank", - 0600, - pdpu->debugfs_root, - (u32 *) &sblk->danger_vblank); - - debugfs_create_file("disable_danger", - 0600, - pdpu->debugfs_root, - kms, &dpu_plane_danger_enable); - - return 0; -} -#else -static int _dpu_plane_init_debugfs(struct drm_plane *plane) -{ - return 0; } #endif -static int dpu_plane_late_register(struct drm_plane *plane) -{ - return _dpu_plane_init_debugfs(plane); -} - -static void dpu_plane_early_unregister(struct drm_plane *plane) -{ - struct dpu_plane *pdpu = to_dpu_plane(plane); - - debugfs_remove_recursive(pdpu->debugfs_root); -} - static bool dpu_plane_format_mod_supported(struct drm_plane *plane, uint32_t format, uint64_t modifier) { @@ -1541,8 +1428,7 @@ static const struct drm_plane_funcs dpu_plane_funcs = { .reset = dpu_plane_reset, .atomic_duplicate_state = dpu_plane_duplicate_state, .atomic_destroy_state = dpu_plane_destroy_state, - .late_register = dpu_plane_late_register, - .early_unregister = dpu_plane_early_unregister, + .atomic_print_state = dpu_plane_atomic_print_state, .format_mod_supported = dpu_plane_format_mod_supported, }; @@ -1609,21 +1495,13 @@ struct drm_plane *dpu_plane_init(struct drm_device *dev, goto clean_sspp; } - /* cache features mask for later */ - pdpu->features = pdpu->pipe_hw->cap->features; - pdpu->pipe_sblk = pdpu->pipe_hw->cap->sblk; - if (!pdpu->pipe_sblk) { - DPU_ERROR("[%u]invalid sblk\n", pipe); - goto clean_sspp; - } - if (pdpu->is_virtual) { - format_list = pdpu->pipe_sblk->virt_format_list; - num_formats = pdpu->pipe_sblk->virt_num_formats; + format_list = pdpu->pipe_hw->cap->sblk->virt_format_list; + num_formats = pdpu->pipe_hw->cap->sblk->virt_num_formats; } else { - format_list = pdpu->pipe_sblk->format_list; - num_formats = pdpu->pipe_sblk->num_formats; + format_list = pdpu->pipe_hw->cap->sblk->format_list; + num_formats = pdpu->pipe_hw->cap->sblk->num_formats; } ret = drm_universal_plane_init(dev, plane, 0xff, &dpu_plane_funcs, @@ -1663,12 +1541,9 @@ struct drm_plane *dpu_plane_init(struct drm_device *dev, /* success! finalize initialization */ drm_plane_helper_add(plane, &dpu_plane_helper_funcs); - /* save user friendly pipe name for later */ - snprintf(pdpu->pipe_name, DPU_NAME_SIZE, "plane%u", plane->base.id); - mutex_init(&pdpu->lock); - DPU_DEBUG("%s created for pipe:%u id:%u virtual:%u\n", pdpu->pipe_name, + DPU_DEBUG("%s created for pipe:%u id:%u virtual:%u\n", plane->name, pipe, plane->base.id, master_plane_id); return plane; @@ -1676,6 +1551,7 @@ clean_sspp: if (pdpu && pdpu->pipe_hw) dpu_hw_sspp_destroy(pdpu->pipe_hw); clean_plane: + list_del(&pdpu->mplane_list); kfree(pdpu); return ERR_PTR(ret); } diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.h index 34e03ac05f4a..9d51dad5c6a5 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.h @@ -23,9 +23,6 @@ * @multirect_index: index of the rectangle of SSPP * @multirect_mode: parallel or time multiplex multirect mode * @pending: whether the current update is still pending - * @scaler3_cfg: configuration data for scaler3 - * @pixel_ext: configuration data for pixel extensions - * @cdp_cfg: CDP configuration * @plane_fetch_bw: calculated BW per plane * @plane_clk: calculated clk per plane */ @@ -38,11 +35,6 @@ struct dpu_plane_state { uint32_t multirect_mode; bool pending; - /* scaler configuration */ - struct dpu_hw_scaler3_cfg scaler3_cfg; - struct dpu_hw_pixel_ext pixel_ext; - - struct dpu_hw_pipe_cdp_cfg cdp_cfg; u64 plane_fetch_bw; u64 plane_clk; }; @@ -134,4 +126,10 @@ void dpu_plane_clear_multirect(const struct drm_plane_state *drm_state); int dpu_plane_color_fill(struct drm_plane *plane, uint32_t color, uint32_t alpha); +#ifdef CONFIG_DEBUG_FS +void dpu_plane_danger_signal_ctrl(struct drm_plane *plane, bool enable); +#else +static inline void dpu_plane_danger_signal_ctrl(struct drm_plane *plane, bool enable) {} +#endif + #endif /* _DPU_PLANE_H_ */ diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_trace.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_trace.h index 37bba57675a8..54d74341e690 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_trace.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_trace.h @@ -266,10 +266,6 @@ DEFINE_EVENT(dpu_drm_obj_template, dpu_crtc_complete_commit, TP_PROTO(uint32_t drm_id), TP_ARGS(drm_id) ); -DEFINE_EVENT(dpu_drm_obj_template, dpu_kms_enc_enable, - TP_PROTO(uint32_t drm_id), - TP_ARGS(drm_id) -); DEFINE_EVENT(dpu_drm_obj_template, dpu_kms_commit, TP_PROTO(uint32_t drm_id), TP_ARGS(drm_id) |