diff options
Diffstat (limited to 'drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c')
-rw-r--r-- | drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 163 |
1 files changed, 111 insertions, 52 deletions
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c index a1b8c4592943..c682d4e02d1b 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c @@ -225,6 +225,70 @@ bool dpu_encoder_is_widebus_enabled(const struct drm_encoder *drm_enc) return dpu_enc->wide_bus_en; } +int dpu_encoder_get_crc_values_cnt(const struct drm_encoder *drm_enc) +{ + struct dpu_encoder_virt *dpu_enc; + int i, num_intf = 0; + + dpu_enc = to_dpu_encoder_virt(drm_enc); + + for (i = 0; i < dpu_enc->num_phys_encs; i++) { + struct dpu_encoder_phys *phys = dpu_enc->phys_encs[i]; + + if (phys->hw_intf && phys->hw_intf->ops.setup_misr + && phys->hw_intf->ops.collect_misr) + num_intf++; + } + + return num_intf; +} + +void dpu_encoder_setup_misr(const struct drm_encoder *drm_enc) +{ + struct dpu_encoder_virt *dpu_enc; + + int i; + + dpu_enc = to_dpu_encoder_virt(drm_enc); + + for (i = 0; i < dpu_enc->num_phys_encs; i++) { + struct dpu_encoder_phys *phys = dpu_enc->phys_encs[i]; + + if (!phys->hw_intf || !phys->hw_intf->ops.setup_misr) + continue; + + phys->hw_intf->ops.setup_misr(phys->hw_intf, true, 1); + } +} + +int dpu_encoder_get_crc(const struct drm_encoder *drm_enc, u32 *crcs, int pos) +{ + struct dpu_encoder_virt *dpu_enc; + + int i, rc = 0, entries_added = 0; + + if (!drm_enc->crtc) { + DRM_ERROR("no crtc found for encoder %d\n", drm_enc->index); + return -EINVAL; + } + + dpu_enc = to_dpu_encoder_virt(drm_enc); + + for (i = 0; i < dpu_enc->num_phys_encs; i++) { + struct dpu_encoder_phys *phys = dpu_enc->phys_encs[i]; + + if (!phys->hw_intf || !phys->hw_intf->ops.collect_misr) + continue; + + rc = phys->hw_intf->ops.collect_misr(phys->hw_intf, &crcs[pos + entries_added]); + if (rc) + return rc; + entries_added++; + } + + return entries_added; +} + static void _dpu_encoder_setup_dither(struct dpu_hw_pingpong *hw_pp, unsigned bpc) { struct dpu_hw_dither_cfg dither_cfg = { 0 }; @@ -634,7 +698,7 @@ static void _dpu_encoder_update_vsync_source(struct dpu_encoder_virt *dpu_enc, } if (hw_mdptop->ops.setup_vsync_source && - disp_info->capabilities & MSM_DISPLAY_CAP_CMD_MODE) { + disp_info->is_cmd_mode) { for (i = 0; i < dpu_enc->num_phys_encs; i++) vsync_cfg.ppnumber[i] = dpu_enc->hw_pp[i]->idx; @@ -718,8 +782,7 @@ static int dpu_encoder_resource_control(struct drm_encoder *drm_enc, } dpu_enc = to_dpu_encoder_virt(drm_enc); priv = drm_enc->dev->dev_private; - is_vid_mode = dpu_enc->disp_info.capabilities & - MSM_DISPLAY_CAP_VID_MODE; + is_vid_mode = !dpu_enc->disp_info.is_cmd_mode; /* * when idle_pc is not supported, process only KICKOFF, STOP and MODESET @@ -1048,24 +1111,6 @@ static void dpu_encoder_virt_atomic_mode_set(struct drm_encoder *drm_enc, phys->hw_pp = dpu_enc->hw_pp[i]; phys->hw_ctl = to_dpu_hw_ctl(hw_ctl[i]); - if (phys->intf_idx >= INTF_0 && phys->intf_idx < INTF_MAX) - phys->hw_intf = dpu_rm_get_intf(&dpu_kms->rm, phys->intf_idx); - - if (phys->wb_idx >= WB_0 && phys->wb_idx < WB_MAX) - phys->hw_wb = dpu_rm_get_wb(&dpu_kms->rm, phys->wb_idx); - - if (!phys->hw_intf && !phys->hw_wb) { - DPU_ERROR_ENC(dpu_enc, - "no intf or wb block assigned at idx: %d\n", i); - return; - } - - if (phys->hw_intf && phys->hw_wb) { - DPU_ERROR_ENC(dpu_enc, - "invalid phys both intf and wb block at idx: %d\n", i); - return; - } - phys->cached_mode = crtc_state->adjusted_mode; if (phys->ops.atomic_mode_set) phys->ops.atomic_mode_set(phys, crtc_state, conn_state); @@ -1205,37 +1250,37 @@ static void dpu_encoder_virt_disable(struct drm_encoder *drm_enc) mutex_unlock(&dpu_enc->enc_lock); } -static enum dpu_intf dpu_encoder_get_intf(struct dpu_mdss_cfg *catalog, +static enum dpu_intf dpu_encoder_get_intf(const struct dpu_mdss_cfg *catalog, enum dpu_intf_type type, u32 controller_id) { int i = 0; - if (type != INTF_WB) { - for (i = 0; i < catalog->intf_count; i++) { - if (catalog->intf[i].type == type - && catalog->intf[i].controller_id == controller_id) { - return catalog->intf[i].id; - } + if (type == INTF_WB) + return INTF_MAX; + + for (i = 0; i < catalog->intf_count; i++) { + if (catalog->intf[i].type == type + && catalog->intf[i].controller_id == controller_id) { + return catalog->intf[i].id; } } return INTF_MAX; } -static enum dpu_wb dpu_encoder_get_wb(struct dpu_mdss_cfg *catalog, +static enum dpu_wb dpu_encoder_get_wb(const struct dpu_mdss_cfg *catalog, enum dpu_intf_type type, u32 controller_id) { int i = 0; if (type != INTF_WB) - goto end; + return WB_MAX; for (i = 0; i < catalog->wb_count; i++) { if (catalog->wb[i].id == controller_id) return catalog->wb[i].id; } -end: return WB_MAX; } @@ -1603,7 +1648,7 @@ void dpu_encoder_trigger_kickoff_pending(struct drm_encoder *drm_enc) /* update only for command mode primary ctl */ if ((phys == dpu_enc->cur_master) && - (disp_info->capabilities & MSM_DISPLAY_CAP_CMD_MODE) + disp_info->is_cmd_mode && ctl->ops.trigger_pending) ctl->ops.trigger_pending(ctl); } @@ -2139,39 +2184,36 @@ static int dpu_encoder_virt_add_phys_encs( return -EINVAL; } - if (disp_info->capabilities & MSM_DISPLAY_CAP_VID_MODE) { - enc = dpu_encoder_phys_vid_init(params); - if (IS_ERR_OR_NULL(enc)) { - DPU_ERROR_ENC(dpu_enc, "failed to init vid enc: %ld\n", + if (disp_info->intf_type == DRM_MODE_ENCODER_VIRTUAL) { + enc = dpu_encoder_phys_wb_init(params); + + if (IS_ERR(enc)) { + DPU_ERROR_ENC(dpu_enc, "failed to init wb enc: %ld\n", PTR_ERR(enc)); - return enc == NULL ? -EINVAL : PTR_ERR(enc); + return PTR_ERR(enc); } dpu_enc->phys_encs[dpu_enc->num_phys_encs] = enc; ++dpu_enc->num_phys_encs; - } - - if (disp_info->capabilities & MSM_DISPLAY_CAP_CMD_MODE) { + } else if (disp_info->is_cmd_mode) { enc = dpu_encoder_phys_cmd_init(params); - if (IS_ERR_OR_NULL(enc)) { + if (IS_ERR(enc)) { DPU_ERROR_ENC(dpu_enc, "failed to init cmd enc: %ld\n", PTR_ERR(enc)); - return enc == NULL ? -EINVAL : PTR_ERR(enc); + return PTR_ERR(enc); } dpu_enc->phys_encs[dpu_enc->num_phys_encs] = enc; ++dpu_enc->num_phys_encs; - } - - if (disp_info->intf_type == DRM_MODE_ENCODER_VIRTUAL) { - enc = dpu_encoder_phys_wb_init(params); + } else { + enc = dpu_encoder_phys_vid_init(params); - if (IS_ERR_OR_NULL(enc)) { - DPU_ERROR_ENC(dpu_enc, "failed to init wb enc: %ld\n", - PTR_ERR(enc)); - return enc == NULL ? -EINVAL : PTR_ERR(enc); + if (IS_ERR(enc)) { + DPU_ERROR_ENC(dpu_enc, "failed to init vid enc: %ld\n", + PTR_ERR(enc)); + return PTR_ERR(enc); } dpu_enc->phys_encs[dpu_enc->num_phys_encs] = enc; @@ -2230,8 +2272,7 @@ static int dpu_encoder_setup_display(struct dpu_encoder_virt *dpu_enc, DPU_DEBUG("dsi_info->num_of_h_tiles %d\n", disp_info->num_of_h_tiles); - if ((disp_info->capabilities & MSM_DISPLAY_CAP_CMD_MODE) || - (disp_info->capabilities & MSM_DISPLAY_CAP_VID_MODE)) + if (disp_info->intf_type != DRM_MODE_ENCODER_VIRTUAL) dpu_enc->idle_pc_supported = dpu_kms->catalog->caps->has_idle_pc; @@ -2294,7 +2335,25 @@ static int dpu_encoder_setup_display(struct dpu_encoder_virt *dpu_enc, struct dpu_encoder_phys *phys = dpu_enc->phys_encs[i]; atomic_set(&phys->vsync_cnt, 0); atomic_set(&phys->underrun_cnt, 0); + + if (phys->intf_idx >= INTF_0 && phys->intf_idx < INTF_MAX) + phys->hw_intf = dpu_rm_get_intf(&dpu_kms->rm, phys->intf_idx); + + if (phys->wb_idx >= WB_0 && phys->wb_idx < WB_MAX) + phys->hw_wb = dpu_rm_get_wb(&dpu_kms->rm, phys->wb_idx); + + if (!phys->hw_intf && !phys->hw_wb) { + DPU_ERROR_ENC(dpu_enc, "no intf or wb block assigned at idx: %d\n", i); + ret = -EINVAL; + } + + if (phys->hw_intf && phys->hw_wb) { + DPU_ERROR_ENC(dpu_enc, + "invalid phys both intf and wb block at idx: %d\n", i); + ret = -EINVAL; + } } + mutex_unlock(&dpu_enc->enc_lock); return ret; |