aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c')
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c163
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;