[Freedreno] [DPU PATCH v3 2/2] drm/msm: remove partial update support
Sean Paul
seanpaul at chromium.org
Fri Mar 2 17:05:06 UTC 2018
On Thu, Mar 01, 2018 at 04:52:35PM -0800, Jeykumar Sankaran wrote:
> Implementation of partial update in DPU DRM is heavily
> dependent on custom properties and dsi hooks. Removing the
> support for now. We may need to revisit the support in the
> future.
>
> changes since v1:
> - get away with unwanted parameter validation
> - code style fixes
> - remove header file definitions for partial update
>
> changes since v2:
> - remove compilation flag for DPU_AD4.
>
> Signed-off-by: Jeykumar Sankaran <jsanka at codeaurora.org>
Thanks for the revised patches. I've applied them to both for-next and
mtp-testing staging branches. I had some trouble applying this patch cleanly, I
resolved the conflicts for this one, but probably a good idea to update your
local branch.
Sean
> ---
> drivers/gpu/drm/msm/disp/dpu1/dpu_connector.c | 139 +------
> drivers/gpu/drm/msm/disp/dpu1/dpu_connector.h | 7 +-
> drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c | 544 +-------------------------
> drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.h | 18 -
> drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 277 ++++---------
> drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h | 8 -
> drivers/gpu/drm/msm/disp/dpu1/dpu_kms_utils.c | 42 --
> drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c | 13 -
> drivers/gpu/drm/msm/msm_drv.h | 56 ---
> 9 files changed, 87 insertions(+), 1017 deletions(-)
>
> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_connector.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_connector.c
> index 57b8627..c5e6c53 100644
> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_connector.c
> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_connector.c
> @@ -424,8 +424,7 @@ int dpu_connector_pre_kickoff(struct drm_connector *connector)
> {
> struct dpu_connector *c_conn;
> struct dpu_connector_state *c_state;
> - struct msm_display_kickoff_params params;
> - int idx, rc;
> + int idx, rc = 0;
>
> if (!connector) {
> DPU_ERROR("invalid argument\n");
> @@ -462,15 +461,8 @@ int dpu_connector_pre_kickoff(struct drm_connector *connector)
> }
> }
>
> - if (!c_conn->ops.pre_kickoff)
> - return 0;
> -
> - params.rois = &c_state->rois;
> -
> DPU_EVT32_VERBOSE(connector->base.id);
>
> - rc = c_conn->ops.pre_kickoff(connector, c_conn->display, ¶ms);
> -
> return rc;
> }
>
> @@ -645,122 +637,6 @@ static void dpu_connector_atomic_reset(struct drm_connector *connector)
> return &c_state->base;
> }
>
> -static int _dpu_connector_roi_v1_check_roi(
> - struct dpu_connector *c_conn,
> - struct drm_clip_rect *roi_conn,
> - const struct msm_roi_caps *caps)
> -{
> - const struct msm_roi_alignment *align = &caps->align;
> - int w = roi_conn->x2 - roi_conn->x1;
> - int h = roi_conn->y2 - roi_conn->y1;
> -
> - if (w <= 0 || h <= 0) {
> - DPU_ERROR_CONN(c_conn, "invalid conn roi w %d h %d\n", w, h);
> - return -EINVAL;
> - }
> -
> - if (w < align->min_width || w % align->width_pix_align) {
> - DPU_ERROR_CONN(c_conn,
> - "invalid conn roi width %d min %d align %d\n",
> - w, align->min_width, align->width_pix_align);
> - return -EINVAL;
> - }
> -
> - if (h < align->min_height || h % align->height_pix_align) {
> - DPU_ERROR_CONN(c_conn,
> - "invalid conn roi height %d min %d align %d\n",
> - h, align->min_height, align->height_pix_align);
> - return -EINVAL;
> - }
> -
> - if (roi_conn->x1 % align->xstart_pix_align) {
> - DPU_ERROR_CONN(c_conn, "invalid conn roi x1 %d align %d\n",
> - roi_conn->x1, align->xstart_pix_align);
> - return -EINVAL;
> - }
> -
> - if (roi_conn->y1 % align->ystart_pix_align) {
> - DPU_ERROR_CONN(c_conn, "invalid conn roi y1 %d align %d\n",
> - roi_conn->y1, align->ystart_pix_align);
> - return -EINVAL;
> - }
> -
> - return 0;
> -}
> -
> -static int _dpu_connector_set_roi_v1(
> - struct dpu_connector *c_conn,
> - struct dpu_connector_state *c_state,
> - void *usr_ptr)
> -{
> - struct dpu_drm_roi_v1 roi_v1;
> - struct msm_display_info display_info;
> - struct msm_roi_caps *caps;
> - int i, rc;
> -
> - if (!c_conn || !c_state) {
> - DPU_ERROR("invalid args\n");
> - return -EINVAL;
> - }
> -
> - rc = dpu_connector_get_info(&c_conn->base, &display_info);
> - if (rc) {
> - DPU_ERROR_CONN(c_conn, "display get info error: %d\n", rc);
> - return rc;
> - }
> -
> - caps = &display_info.roi_caps;
> - if (!caps->enabled) {
> - DPU_ERROR_CONN(c_conn, "display roi capability is disabled\n");
> - return -ENOTSUPP;
> - }
> -
> - memset(&c_state->rois, 0, sizeof(c_state->rois));
> -
> - if (!usr_ptr) {
> - DPU_DEBUG_CONN(c_conn, "rois cleared\n");
> - return 0;
> - }
> -
> - if (copy_from_user(&roi_v1, usr_ptr, sizeof(roi_v1))) {
> - DPU_ERROR_CONN(c_conn, "failed to copy roi_v1 data\n");
> - return -EINVAL;
> - }
> -
> - DPU_DEBUG_CONN(c_conn, "num_rects %d\n", roi_v1.num_rects);
> -
> - if (roi_v1.num_rects == 0) {
> - DPU_DEBUG_CONN(c_conn, "rois cleared\n");
> - return 0;
> - }
> -
> - if (roi_v1.num_rects > DPU_MAX_ROI_V1 ||
> - roi_v1.num_rects > caps->num_roi) {
> - DPU_ERROR_CONN(c_conn, "too many rects specified: %d\n",
> - roi_v1.num_rects);
> - return -EINVAL;
> - }
> -
> - c_state->rois.num_rects = roi_v1.num_rects;
> - for (i = 0; i < roi_v1.num_rects; ++i) {
> - int rc;
> -
> - rc = _dpu_connector_roi_v1_check_roi(c_conn, &roi_v1.roi[i],
> - caps);
> - if (rc)
> - return rc;
> -
> - c_state->rois.roi[i] = roi_v1.roi[i];
> - DPU_DEBUG_CONN(c_conn, "roi%d: roi (%d,%d) (%d,%d)\n", i,
> - c_state->rois.roi[i].x1,
> - c_state->rois.roi[i].y1,
> - c_state->rois.roi[i].x2,
> - c_state->rois.roi[i].y2);
> - }
> -
> - return 0;
> -}
> -
> static int _dpu_connector_update_bl_scale(struct dpu_connector *c_conn,
> int idx,
> uint64_t value)
> @@ -852,12 +728,6 @@ static int dpu_connector_atomic_set_property(struct drm_connector *connector,
> break;
> }
>
> - if (idx == CONNECTOR_PROP_ROI_V1) {
> - rc = _dpu_connector_set_roi_v1(c_conn, c_state, (void *)val);
> - if (rc)
> - DPU_ERROR_CONN(c_conn, "invalid roi_v1, rc: %d\n", rc);
> - }
> -
> /* check for custom property handling */
> if (!rc && c_conn->ops.set_property) {
> rc = c_conn->ops.set_property(connector,
> @@ -1304,13 +1174,6 @@ struct drm_connector *dpu_connector_init(struct drm_device *dev,
> CONNECTOR_PROP_AD_BL_SCALE);
> #endif
>
> - rc = dpu_connector_get_info(&c_conn->base, &display_info);
> - if (!rc && display_info.roi_caps.enabled) {
> - msm_property_install_volatile_range(
> - &c_conn->property_info, "dpu_drm_roi_v1", 0x0,
> - 0, ~0, 0, CONNECTOR_PROP_ROI_V1);
> - }
> -
> msm_property_install_range(&c_conn->property_info, "RETIRE_FENCE",
> 0x0, 0, INR_OPEN_MAX, 0, CONNECTOR_PROP_RETIRE_FENCE);
>
> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_connector.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_connector.h
> index 573a0c8..981f459 100644
> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_connector.h
> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_connector.h
> @@ -163,13 +163,10 @@ struct dpu_connector_ops {
> * pre_kickoff - trigger display to program kickoff-time features
> * @connector: Pointer to drm connector structure
> * @display: Pointer to private display structure
> - * @params: Parameter bundle of connector-stored information for
> - * kickoff-time programming into the display
> * Returns: Zero on success
> */
> int (*pre_kickoff)(struct drm_connector *connector,
> - void *display,
> - struct msm_display_kickoff_params *params);
> + void *display);
>
> /**
> * clk_ctrl - perform clk enable/disable on the connector
> @@ -340,7 +337,6 @@ struct dpu_connector {
> * @out_fb: Pointer to output frame buffer, if applicable
> * @property_state: Local storage for msm_prop properties
> * @property_values: Local cache of current connector property values
> - * @rois: Regions of interest structure for mapping CRTC to Connector output
> * @property_blobs: blob properties
> */
> struct dpu_connector_state {
> @@ -349,7 +345,6 @@ struct dpu_connector_state {
> struct msm_property_state property_state;
> struct msm_property_value property_values[CONNECTOR_PROP_COUNT];
>
> - struct msm_roi_list rois;
> struct drm_property_blob *property_blobs[CONNECTOR_PROP_BLOBCOUNT];
> };
>
> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
> index 3cdf1e3..ab36578 100644
> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
> @@ -782,465 +782,24 @@ static void _dpu_crtc_setup_dim_layer_cfg(struct drm_crtc *crtc,
> }
> }
>
> -void dpu_crtc_get_crtc_roi(struct drm_crtc_state *state,
> - const struct dpu_rect **crtc_roi)
> -{
> - struct dpu_crtc_state *crtc_state;
> -
> - if (!state || !crtc_roi)
> - return;
> -
> - crtc_state = to_dpu_crtc_state(state);
> - *crtc_roi = &crtc_state->crtc_roi;
> -}
> -
> -static int _dpu_crtc_set_roi_v1(struct drm_crtc_state *state,
> - void __user *usr_ptr)
> -{
> - struct drm_crtc *crtc;
> - struct dpu_crtc_state *cstate;
> - struct dpu_drm_roi_v1 roi_v1;
> - int i;
> -
> - if (!state) {
> - DPU_ERROR("invalid args\n");
> - return -EINVAL;
> - }
> -
> - cstate = to_dpu_crtc_state(state);
> - crtc = cstate->base.crtc;
> -
> - memset(&cstate->user_roi_list, 0, sizeof(cstate->user_roi_list));
> -
> - if (!usr_ptr) {
> - DPU_DEBUG("crtc%d: rois cleared\n", DRMID(crtc));
> - return 0;
> - }
> -
> - if (copy_from_user(&roi_v1, usr_ptr, sizeof(roi_v1))) {
> - DPU_ERROR("crtc%d: failed to copy roi_v1 data\n", DRMID(crtc));
> - return -EINVAL;
> - }
> -
> - DPU_DEBUG("crtc%d: num_rects %d\n", DRMID(crtc), roi_v1.num_rects);
> -
> - if (roi_v1.num_rects == 0) {
> - DPU_DEBUG("crtc%d: rois cleared\n", DRMID(crtc));
> - return 0;
> - }
> -
> - if (roi_v1.num_rects > DPU_MAX_ROI_V1) {
> - DPU_ERROR("crtc%d: too many rects specified: %d\n", DRMID(crtc),
> - roi_v1.num_rects);
> - return -EINVAL;
> - }
> -
> - cstate->user_roi_list.num_rects = roi_v1.num_rects;
> - for (i = 0; i < roi_v1.num_rects; ++i) {
> - cstate->user_roi_list.roi[i] = roi_v1.roi[i];
> - DPU_DEBUG("crtc%d: roi%d: roi (%d,%d) (%d,%d)\n",
> - DRMID(crtc), i,
> - cstate->user_roi_list.roi[i].x1,
> - cstate->user_roi_list.roi[i].y1,
> - cstate->user_roi_list.roi[i].x2,
> - cstate->user_roi_list.roi[i].y2);
> - }
> -
> - return 0;
> -}
> -
> -static bool _dpu_crtc_setup_is_3dmux_dsc(struct drm_crtc_state *state)
> -{
> - int i;
> - struct dpu_crtc_state *cstate;
> - bool is_3dmux_dsc = false;
> -
> - cstate = to_dpu_crtc_state(state);
> -
> - for (i = 0; i < cstate->num_connectors; i++) {
> - struct drm_connector *conn = cstate->connectors[i];
> -
> - if (dpu_connector_get_topology_name(conn) ==
> - DPU_RM_TOPOLOGY_DUALPIPE_3DMERGE_DSC)
> - is_3dmux_dsc = true;
> - }
> -
> - return is_3dmux_dsc;
> -}
> -
> -static int _dpu_crtc_set_crtc_roi(struct drm_crtc *crtc,
> - struct drm_crtc_state *state)
> -{
> - struct drm_connector *conn;
> - struct drm_connector_state *conn_state;
> - struct dpu_crtc *dpu_crtc;
> - struct dpu_crtc_state *crtc_state;
> - struct dpu_rect *crtc_roi;
> - int i, num_attached_conns = 0;
> -
> - if (!crtc || !state)
> - return -EINVAL;
> -
> - dpu_crtc = to_dpu_crtc(crtc);
> - crtc_state = to_dpu_crtc_state(state);
> - crtc_roi = &crtc_state->crtc_roi;
> -
> - for_each_old_connector_in_state(state->state, conn, conn_state, i) {
> - struct dpu_connector_state *dpu_conn_state;
> -
> - if (!conn_state || conn_state->crtc != crtc)
> - continue;
> -
> - if (num_attached_conns) {
> - DPU_ERROR(
> - "crtc%d: unsupported: roi on crtc w/ >1 connectors\n",
> - DRMID(crtc));
> - return -EINVAL;
> - }
> - ++num_attached_conns;
> -
> - dpu_conn_state = to_dpu_connector_state(conn_state);
> -
> - /*
> - * current driver only supports same connector and crtc size,
> - * but if support for different sizes is added, driver needs
> - * to check the connector roi here to make sure is full screen
> - * for dsc 3d-mux topology that doesn't support partial update.
> - */
> - if (memcmp(&dpu_conn_state->rois, &crtc_state->user_roi_list,
> - sizeof(crtc_state->user_roi_list))) {
> - DPU_ERROR("%s: crtc -> conn roi scaling unsupported\n",
> - dpu_crtc->name);
> - return -EINVAL;
> - }
> - }
> -
> - dpu_kms_rect_merge_rectangles(&crtc_state->user_roi_list, crtc_roi);
> -
> - DPU_DEBUG("%s: crtc roi (%d,%d,%d,%d)\n", dpu_crtc->name,
> - crtc_roi->x, crtc_roi->y, crtc_roi->w, crtc_roi->h);
> -
> - return 0;
> -}
> -
> -static int _dpu_crtc_check_autorefresh(struct drm_crtc *crtc,
> - struct drm_crtc_state *state)
> -{
> - struct dpu_crtc *dpu_crtc;
> - struct dpu_crtc_state *crtc_state;
> - struct drm_connector *conn;
> - struct drm_connector_state *conn_state;
> - int i;
> -
> - if (!crtc || !state)
> - return -EINVAL;
> -
> - dpu_crtc = to_dpu_crtc(crtc);
> - crtc_state = to_dpu_crtc_state(state);
> -
> - if (dpu_kms_rect_is_null(&crtc_state->crtc_roi))
> - return 0;
> -
> - /* partial update active, check if autorefresh is also requested */
> - for_each_old_connector_in_state(state->state, conn, conn_state, i) {
> - uint64_t autorefresh;
> -
> - if (!conn_state || conn_state->crtc != crtc)
> - continue;
> -
> - autorefresh = dpu_connector_get_property(conn_state,
> - CONNECTOR_PROP_AUTOREFRESH);
> - if (autorefresh) {
> - DPU_ERROR(
> - "%s: autorefresh & partial crtc roi incompatible %llu\n",
> - dpu_crtc->name, autorefresh);
> - return -EINVAL;
> - }
> - }
> -
> - return 0;
> -}
> -
> -static int _dpu_crtc_set_lm_roi(struct drm_crtc *crtc,
> - struct drm_crtc_state *state, int lm_idx)
> -{
> - struct dpu_crtc *dpu_crtc;
> - struct dpu_crtc_state *crtc_state;
> - const struct dpu_rect *crtc_roi;
> - const struct dpu_rect *lm_bounds;
> - struct dpu_rect *lm_roi;
> -
> - if (!crtc || !state || lm_idx >= ARRAY_SIZE(crtc_state->lm_bounds))
> - return -EINVAL;
> -
> - dpu_crtc = to_dpu_crtc(crtc);
> - crtc_state = to_dpu_crtc_state(state);
> - crtc_roi = &crtc_state->crtc_roi;
> - lm_bounds = &crtc_state->lm_bounds[lm_idx];
> - lm_roi = &crtc_state->lm_roi[lm_idx];
> -
> - if (dpu_kms_rect_is_null(crtc_roi))
> - memcpy(lm_roi, lm_bounds, sizeof(*lm_roi));
> - else
> - dpu_kms_rect_intersect(crtc_roi, lm_bounds, lm_roi);
> -
> - DPU_DEBUG("%s: lm%d roi (%d,%d,%d,%d)\n", dpu_crtc->name, lm_idx,
> - lm_roi->x, lm_roi->y, lm_roi->w, lm_roi->h);
> -
> - /*
> - * partial update is not supported with 3dmux dsc or dest scaler.
> - * hence, crtc roi must match the mixer dimensions.
> - */
> - if (crtc_state->num_ds_enabled ||
> - _dpu_crtc_setup_is_3dmux_dsc(state)) {
> - if (memcmp(lm_roi, lm_bounds, sizeof(struct dpu_rect))) {
> - DPU_ERROR("Unsupported: Dest scaler/3d mux DSC + PU\n");
> - return -EINVAL;
> - }
> - }
> -
> - /* if any dimension is zero, clear all dimensions for clarity */
> - if (dpu_kms_rect_is_null(lm_roi))
> - memset(lm_roi, 0, sizeof(*lm_roi));
> -
> - return 0;
> -}
> -
> -static u32 _dpu_crtc_get_displays_affected(struct drm_crtc *crtc,
> - struct drm_crtc_state *state)
> -{
> - struct dpu_crtc *dpu_crtc;
> - struct dpu_crtc_state *crtc_state;
> - u32 disp_bitmask = 0;
> - int i;
> -
> - dpu_crtc = to_dpu_crtc(crtc);
> - crtc_state = to_dpu_crtc_state(state);
> -
> - /* pingpong split: one ROI, one LM, two physical displays */
> - if (crtc_state->is_ppsplit) {
> - u32 lm_split_width = crtc_state->lm_bounds[0].w / 2;
> - struct dpu_rect *roi = &crtc_state->lm_roi[0];
> -
> - if (dpu_kms_rect_is_null(roi))
> - disp_bitmask = 0;
> - else if ((u32)roi->x + (u32)roi->w <= lm_split_width)
> - disp_bitmask = BIT(0); /* left only */
> - else if (roi->x >= lm_split_width)
> - disp_bitmask = BIT(1); /* right only */
> - else
> - disp_bitmask = BIT(0) | BIT(1); /* left and right */
> - } else {
> - for (i = 0; i < dpu_crtc->num_mixers; i++) {
> - if (!dpu_kms_rect_is_null(&crtc_state->lm_roi[i]))
> - disp_bitmask |= BIT(i);
> - }
> - }
> -
> - DPU_DEBUG("affected displays 0x%x\n", disp_bitmask);
> -
> - return disp_bitmask;
> -}
> -
> -static int _dpu_crtc_check_rois_centered_and_symmetric(struct drm_crtc *crtc,
> - struct drm_crtc_state *state)
> -{
> - struct dpu_crtc *dpu_crtc;
> - struct dpu_crtc_state *crtc_state;
> - const struct dpu_rect *roi[CRTC_DUAL_MIXERS];
> -
> - if (!crtc || !state)
> - return -EINVAL;
> -
> - dpu_crtc = to_dpu_crtc(crtc);
> - crtc_state = to_dpu_crtc_state(state);
> -
> - if (dpu_crtc->num_mixers > CRTC_DUAL_MIXERS) {
> - DPU_ERROR("%s: unsupported number of mixers: %d\n",
> - dpu_crtc->name, dpu_crtc->num_mixers);
> - return -EINVAL;
> - }
> -
> - /*
> - * If using pingpong split: one ROI, one LM, two physical displays
> - * then the ROI must be centered on the panel split boundary and
> - * be of equal width across the split.
> - */
> - if (crtc_state->is_ppsplit) {
> - u16 panel_split_width;
> - u32 display_mask;
> -
> - roi[0] = &crtc_state->lm_roi[0];
> -
> - if (dpu_kms_rect_is_null(roi[0]))
> - return 0;
> -
> - display_mask = _dpu_crtc_get_displays_affected(crtc, state);
> - if (display_mask != (BIT(0) | BIT(1)))
> - return 0;
> -
> - panel_split_width = crtc_state->lm_bounds[0].w / 2;
> - if (roi[0]->x + roi[0]->w / 2 != panel_split_width) {
> - DPU_ERROR("%s: roi x %d w %d split %d\n",
> - dpu_crtc->name, roi[0]->x, roi[0]->w,
> - panel_split_width);
> - return -EINVAL;
> - }
> -
> - return 0;
> - }
> -
> - /*
> - * On certain HW, if using 2 LM, ROIs must be split evenly between the
> - * LMs and be of equal width.
> - */
> - if (dpu_crtc->num_mixers < 2)
> - return 0;
> -
> - roi[0] = &crtc_state->lm_roi[0];
> - roi[1] = &crtc_state->lm_roi[1];
> -
> - /* if one of the roi is null it's a left/right-only update */
> - if (dpu_kms_rect_is_null(roi[0]) || dpu_kms_rect_is_null(roi[1]))
> - return 0;
> -
> - /* check lm rois are equal width & first roi ends at 2nd roi */
> - if (roi[0]->x + roi[0]->w != roi[1]->x || roi[0]->w != roi[1]->w) {
> - DPU_ERROR(
> - "%s: rois not centered and symmetric: roi0 x %d w %d roi1 x %d w %d\n",
> - dpu_crtc->name, roi[0]->x, roi[0]->w,
> - roi[1]->x, roi[1]->w);
> - return -EINVAL;
> - }
> -
> - return 0;
> -}
> -
> -static int _dpu_crtc_check_planes_within_crtc_roi(struct drm_crtc *crtc,
> - struct drm_crtc_state *state)
> -{
> - struct dpu_crtc *dpu_crtc;
> - struct dpu_crtc_state *crtc_state;
> - const struct dpu_rect *crtc_roi;
> - struct drm_plane_state *pstate;
> - struct drm_plane *plane;
> -
> - if (!crtc || !state)
> - return -EINVAL;
> -
> - /*
> - * Reject commit if a Plane CRTC destination coordinates fall outside
> - * the partial CRTC ROI. LM output is determined via connector ROIs,
> - * if they are specified, not Plane CRTC ROIs.
> - */
> -
> - dpu_crtc = to_dpu_crtc(crtc);
> - crtc_state = to_dpu_crtc_state(state);
> - crtc_roi = &crtc_state->crtc_roi;
> -
> - if (dpu_kms_rect_is_null(crtc_roi))
> - return 0;
> -
> - drm_atomic_crtc_state_for_each_plane(plane, state) {
> - struct dpu_rect plane_roi, intersection;
> -
> - pstate = drm_atomic_get_plane_state(state->state, plane);
> - if (IS_ERR_OR_NULL(pstate)) {
> - int rc = PTR_ERR(pstate);
> -
> - DPU_ERROR("%s: failed to get plane%d state, %d\n",
> - dpu_crtc->name, plane->base.id, rc);
> - return rc;
> - }
> -
> - plane_roi.x = pstate->crtc_x;
> - plane_roi.y = pstate->crtc_y;
> - plane_roi.w = pstate->crtc_w;
> - plane_roi.h = pstate->crtc_h;
> - dpu_kms_rect_intersect(crtc_roi, &plane_roi, &intersection);
> - if (!dpu_kms_rect_is_equal(&plane_roi, &intersection)) {
> - DPU_ERROR(
> - "%s: plane%d crtc roi (%d,%d,%d,%d) outside crtc roi (%d,%d,%d,%d)\n",
> - dpu_crtc->name, plane->base.id,
> - plane_roi.x, plane_roi.y,
> - plane_roi.w, plane_roi.h,
> - crtc_roi->x, crtc_roi->y,
> - crtc_roi->w, crtc_roi->h);
> - return -E2BIG;
> - }
> - }
> -
> - return 0;
> -}
> -
> -static int _dpu_crtc_check_rois(struct drm_crtc *crtc,
> - struct drm_crtc_state *state)
> -{
> - struct dpu_crtc *dpu_crtc;
> - int lm_idx;
> - int rc;
> -
> - if (!crtc || !state)
> - return -EINVAL;
> -
> - dpu_crtc = to_dpu_crtc(crtc);
> -
> - rc = _dpu_crtc_set_crtc_roi(crtc, state);
> - if (rc)
> - return rc;
> -
> - rc = _dpu_crtc_check_autorefresh(crtc, state);
> - if (rc)
> - return rc;
> -
> - for (lm_idx = 0; lm_idx < dpu_crtc->num_mixers; lm_idx++) {
> - rc = _dpu_crtc_set_lm_roi(crtc, state, lm_idx);
> - if (rc)
> - return rc;
> - }
> -
> - rc = _dpu_crtc_check_rois_centered_and_symmetric(crtc, state);
> - if (rc)
> - return rc;
> -
> - rc = _dpu_crtc_check_planes_within_crtc_roi(crtc, state);
> - if (rc)
> - return rc;
> -
> - return 0;
> -}
> -
> static void _dpu_crtc_program_lm_output_roi(struct drm_crtc *crtc)
> {
> struct dpu_crtc *dpu_crtc;
> struct dpu_crtc_state *crtc_state;
> - const struct dpu_rect *lm_roi;
> - struct dpu_hw_mixer *hw_lm;
> int lm_idx, lm_horiz_position;
>
> - if (!crtc)
> - return;
> -
> dpu_crtc = to_dpu_crtc(crtc);
> crtc_state = to_dpu_crtc_state(crtc->state);
>
> lm_horiz_position = 0;
> for (lm_idx = 0; lm_idx < dpu_crtc->num_mixers; lm_idx++) {
> + const struct dpu_rect *lm_roi = &crtc_state->lm_bounds[lm_idx];
> + struct dpu_hw_mixer *hw_lm = dpu_crtc->mixers[lm_idx].hw_lm;
> struct dpu_hw_mixer_cfg cfg;
>
> - lm_roi = &crtc_state->lm_roi[lm_idx];
> - hw_lm = dpu_crtc->mixers[lm_idx].hw_lm;
> -
> - DPU_EVT32(DRMID(crtc_state->base.crtc), lm_idx,
> - lm_roi->x, lm_roi->y, lm_roi->w, lm_roi->h);
> -
> if (dpu_kms_rect_is_null(lm_roi))
> continue;
>
> - hw_lm->cfg.out_width = lm_roi->w;
> - hw_lm->cfg.out_height = lm_roi->h;
> - hw_lm->cfg.right_mixer = lm_horiz_position;
> -
> cfg.out_width = lm_roi->w;
> cfg.out_height = lm_roi->h;
> cfg.right_mixer = lm_horiz_position++;
> @@ -1361,70 +920,7 @@ static void _dpu_crtc_blend_setup_mixer(struct drm_crtc *crtc,
> mixer, &cstate->dim_layer[i]);
> }
>
> - _dpu_crtc_program_lm_output_roi(crtc);
> -}
> -
> -static void _dpu_crtc_swap_mixers_for_right_partial_update(
> - struct drm_crtc *crtc)
> -{
> - struct dpu_crtc *dpu_crtc;
> - struct dpu_crtc_state *cstate;
> - struct drm_encoder *drm_enc;
> - bool is_right_only;
> - bool encoder_in_dsc_merge = false;
> -
> - if (!crtc || !crtc->state)
> - return;
> -
> - dpu_crtc = to_dpu_crtc(crtc);
> - cstate = to_dpu_crtc_state(crtc->state);
> -
> - if (dpu_crtc->num_mixers != CRTC_DUAL_MIXERS)
> - return;
> -
> - drm_for_each_encoder(drm_enc, crtc->dev) {
> - if (drm_enc->crtc == crtc &&
> - dpu_encoder_is_dsc_merge(drm_enc)) {
> - encoder_in_dsc_merge = true;
> - break;
> - }
> - }
> -
> - /**
> - * For right-only partial update with DSC merge, we swap LM0 & LM1.
> - * This is due to two reasons:
> - * - On 8996, there is a DSC HW requirement that in DSC Merge Mode,
> - * the left DSC must be used, right DSC cannot be used alone.
> - * For right-only partial update, this means swap layer mixers to map
> - * Left LM to Right INTF. On later HW this was relaxed.
> - * - In DSC Merge mode, the physical encoder has already registered
> - * PP0 as the master, to switch to right-only we would have to
> - * reprogram to be driven by PP1 instead.
> - * To support both cases, we prefer to support the mixer swap solution.
> - */
> - if (!encoder_in_dsc_merge)
> - return;
> -
> - is_right_only = dpu_kms_rect_is_null(&cstate->lm_roi[0]) &&
> - !dpu_kms_rect_is_null(&cstate->lm_roi[1]);
> -
> - if (is_right_only && !dpu_crtc->mixers_swapped) {
> - /* right-only update swap mixers */
> - swap(dpu_crtc->mixers[0], dpu_crtc->mixers[1]);
> - dpu_crtc->mixers_swapped = true;
> - } else if (!is_right_only && dpu_crtc->mixers_swapped) {
> - /* left-only or full update, swap back */
> - swap(dpu_crtc->mixers[0], dpu_crtc->mixers[1]);
> - dpu_crtc->mixers_swapped = false;
> - }
> -
> - DPU_DEBUG("%s: right_only %d swapped %d, mix0->lm%d, mix1->lm%d\n",
> - dpu_crtc->name, is_right_only, dpu_crtc->mixers_swapped,
> - dpu_crtc->mixers[0].hw_lm->idx - LM_0,
> - dpu_crtc->mixers[1].hw_lm->idx - LM_0);
> - DPU_EVT32(DRMID(crtc), is_right_only, dpu_crtc->mixers_swapped,
> - dpu_crtc->mixers[0].hw_lm->idx - LM_0,
> - dpu_crtc->mixers[1].hw_lm->idx - LM_0);
> + _dpu_crtc_program_lm_output_roi(crtc);
> }
>
> /**
> @@ -1472,27 +968,15 @@ static void _dpu_crtc_blend_setup(struct drm_crtc *crtc)
> lm->ops.clear_dim_layer(lm);
> }
>
> - _dpu_crtc_swap_mixers_for_right_partial_update(crtc);
> -
> /* initialize stage cfg */
> memset(&dpu_crtc->stage_cfg, 0, sizeof(struct dpu_hw_stage_cfg));
>
> _dpu_crtc_blend_setup_mixer(crtc, dpu_crtc, mixer);
>
> for (i = 0; i < dpu_crtc->num_mixers; i++) {
> - const struct dpu_rect *lm_roi = &dpu_crtc_state->lm_roi[i];
> -
> ctl = mixer[i].hw_ctl;
> lm = mixer[i].hw_lm;
>
> - if (dpu_kms_rect_is_null(lm_roi)) {
> - DPU_DEBUG(
> - "%s: lm%d leave ctl%d mask 0 since null roi\n",
> - dpu_crtc->name, lm->idx - LM_0,
> - ctl->idx - CTL_0);
> - continue;
> - }
> -
> lm->ops.setup_alpha_out(lm, mixer[i].mixer_op_mode);
>
> mixer[i].flush_mask |= ctl->ops.get_bitmask_mixer(ctl,
> @@ -1510,8 +994,6 @@ static void _dpu_crtc_blend_setup(struct drm_crtc *crtc)
> ctl->ops.setup_blendstage(ctl, mixer[i].hw_lm->idx,
> &dpu_crtc->stage_cfg);
> }
> -
> - _dpu_crtc_program_lm_output_roi(crtc);
> }
>
> /**
> @@ -2664,14 +2146,9 @@ static void _dpu_crtc_setup_lm_bounds(struct drm_crtc *crtc,
> cstate->lm_bounds[i].w = crtc_split_width;
> cstate->lm_bounds[i].h =
> dpu_crtc_get_mixer_height(dpu_crtc, cstate, adj_mode);
> - memcpy(&cstate->lm_roi[i], &cstate->lm_bounds[i],
> - sizeof(cstate->lm_roi[i]));
> DPU_EVT32_VERBOSE(DRMID(crtc), i,
> cstate->lm_bounds[i].x, cstate->lm_bounds[i].y,
> cstate->lm_bounds[i].w, cstate->lm_bounds[i].h);
> - DPU_DEBUG("%s: lm%d bnd&roi (%d,%d,%d,%d)\n", dpu_crtc->name, i,
> - cstate->lm_roi[i].x, cstate->lm_roi[i].y,
> - cstate->lm_roi[i].w, cstate->lm_roi[i].h);
> }
>
> drm_mode_debug_printmodeline(adj_mode);
> @@ -3019,8 +2496,6 @@ void dpu_crtc_commit_kickoff(struct drm_crtc *crtc)
> * If so, it may delay and flush at an irq event (e.g. ppdone)
> */
> params.inline_rotate_prefill = cstate->sbuf_prefill_line;
> - params.affected_displays = _dpu_crtc_get_displays_affected(crtc,
> - crtc->state);
> dpu_encoder_prepare_for_kickoff(encoder, ¶ms);
>
> /*
> @@ -3931,12 +3406,6 @@ static int dpu_crtc_atomic_check(struct drm_crtc *crtc,
> }
> }
>
> - rc = _dpu_crtc_check_rois(crtc, state);
> - if (rc) {
> - DPU_ERROR("crtc%d failed roi check %d\n", crtc->base.id, rc);
> - goto end;
> - }
> -
> end:
> _dpu_crtc_rp_free_unused(&cstate->rp);
> return rc;
> @@ -4066,9 +3535,6 @@ static void dpu_crtc_install_properties(struct drm_crtc *crtc,
> msm_property_install_blob(&dpu_crtc->property_info, "capabilities",
> DRM_MODE_PROP_IMMUTABLE, CRTC_PROP_INFO);
>
> - msm_property_install_volatile_range(&dpu_crtc->property_info,
> - "dpu_drm_roi_v1", 0x0, 0, ~0, 0, CRTC_PROP_ROI_V1);
> -
> dpu_kms_info_reset(info);
>
> if (catalog->has_dim_layer) {
> @@ -4217,10 +3683,6 @@ static int dpu_crtc_atomic_set_property(struct drm_crtc *crtc,
> _dpu_crtc_set_dim_layer_v1(cstate,
> (void __user *)val);
> break;
> - case CRTC_PROP_ROI_V1:
> - ret = _dpu_crtc_set_roi_v1(state,
> - (void __user *)val);
> - break;
> case CRTC_PROP_DEST_SCALER:
> ret = _dpu_crtc_set_dest_scaler(dpu_crtc,
> cstate, (void __user *)val);
> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.h
> index b63df24..15e3eb6 100644
> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.h
> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.h
> @@ -345,13 +345,8 @@ struct dpu_crtc_respool {
> * @is_ppsplit : Whether current topology requires PPSplit special handling
> * @bw_control : true if bw/clk controlled by core bw/clk properties
> * @bw_split_vote : true if bw controlled by llcc/dram bw properties
> - * @crtc_roi : Current CRTC ROI. Possibly sub-rectangle of mode.
> - * Origin top left of CRTC.
> * @lm_bounds : LM boundaries based on current mode full resolution, no ROI.
> * Origin top left of CRTC.
> - * @lm_roi : Current LM ROI, possibly sub-rectangle of mode.
> - * Origin top left of CRTC.
> - * @user_roi_list : List of user's requested ROIs as from set property
> * @property_state: Local storage for msm_prop properties
> * @property_values: Current crtc property values
> * @input_fence_timeout_ns : Cached input fence timeout, in ns
> @@ -376,10 +371,7 @@ struct dpu_crtc_state {
> bool bw_split_vote;
>
> bool is_ppsplit;
> - struct dpu_rect crtc_roi;
> struct dpu_rect lm_bounds[CRTC_DUAL_MIXERS];
> - struct dpu_rect lm_roi[CRTC_DUAL_MIXERS];
> - struct msm_roi_list user_roi_list;
>
> struct msm_property_state property_state;
> struct msm_property_value property_values[CRTC_PROP_COUNT];
> @@ -605,14 +597,4 @@ int dpu_crtc_res_add(struct drm_crtc_state *state, u32 type, u64 tag,
> */
> void dpu_crtc_res_put(struct drm_crtc_state *state, u32 type, u64 tag);
>
> -/**
> - * dpu_crtc_get_crtc_roi - retrieve the crtc_roi from the given state object
> - * used to allow the planes to adjust their final lm out_xy value in the
> - * case of partial update
> - * @crtc_state: Pointer to crtc state
> - * @crtc_roi: Output pointer to crtc roi in the given state
> - */
> -void dpu_crtc_get_crtc_roi(struct drm_crtc_state *state,
> - const struct dpu_rect **crtc_roi);
> -
> #endif /* _DPU_CRTC_H_ */
> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
> index 3d168fa0..91b9e07 100644
> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
> @@ -195,8 +195,6 @@ enum dpu_enc_rc_states {
> * @topology: topology of the display
> * @mode_set_complete: flag to indicate modeset completion
> * @rsc_config: rsc configuration for display vtotal, fps, etc.
> - * @cur_conn_roi: current connector roi
> - * @prv_conn_roi: previous connector roi to optimize if unchanged
> * @idle_timeout: idle timeout duration in milliseconds
> */
> struct dpu_encoder_virt {
> @@ -243,8 +241,6 @@ struct dpu_encoder_virt {
> bool mode_set_complete;
>
> struct dpu_rsc_cmd_config rsc_config;
> - struct dpu_rect cur_conn_roi;
> - struct dpu_rect prv_conn_roi;
>
> u32 idle_timeout;
> };
> @@ -868,14 +864,8 @@ static bool _dpu_encoder_dsc_ich_reset_override_needed(bool pu_en,
>
> static void _dpu_encoder_dsc_pipe_cfg(struct dpu_hw_dsc *hw_dsc,
> struct dpu_hw_pingpong *hw_pp, struct msm_display_dsc_info *dsc,
> - u32 common_mode, bool ich_reset, bool enable)
> + u32 common_mode, bool ich_reset)
> {
> - if (!enable) {
> - if (hw_pp->ops.disable_dsc)
> - hw_pp->ops.disable_dsc(hw_pp);
> - return;
> - }
> -
> if (hw_dsc->ops.dsc_config)
> hw_dsc->ops.dsc_config(hw_dsc, dsc, common_mode, ich_reset);
>
> @@ -889,46 +879,27 @@ static void _dpu_encoder_dsc_pipe_cfg(struct dpu_hw_dsc *hw_dsc,
> hw_pp->ops.enable_dsc(hw_pp);
> }
>
> -static void _dpu_encoder_get_connector_roi(
> - struct dpu_encoder_virt *dpu_enc,
> - struct dpu_rect *merged_conn_roi)
> -{
> - struct drm_connector *drm_conn;
> - struct dpu_connector_state *c_state;
> -
> - if (!dpu_enc || !merged_conn_roi)
> - return;
> -
> - drm_conn = dpu_enc->phys_encs[0]->connector;
> -
> - if (!drm_conn || !drm_conn->state)
> - return;
> -
> - c_state = to_dpu_connector_state(drm_conn->state);
> - dpu_kms_rect_merge_rectangles(&c_state->rois, merged_conn_roi);
> -}
> -
> static int _dpu_encoder_dsc_n_lm_1_enc_1_intf(struct dpu_encoder_virt *dpu_enc)
> {
> int this_frame_slices;
> int intf_ip_w, enc_ip_w;
> int ich_res, dsc_common_mode = 0;
> + int rc = 0;
>
> struct dpu_hw_pingpong *hw_pp = dpu_enc->hw_pp[0];
> struct dpu_hw_dsc *hw_dsc = dpu_enc->hw_dsc[0];
> struct dpu_encoder_phys *enc_master = dpu_enc->cur_master;
> - const struct dpu_rect *roi = &dpu_enc->cur_conn_roi;
> struct msm_display_dsc_info *dsc =
> &dpu_enc->mode_info.comp_info.dsc_info;
>
> - if (dsc == NULL || hw_dsc == NULL || hw_pp == NULL || !enc_master) {
> - DPU_ERROR_ENC(dpu_enc, "invalid params for DSC\n");
> - return -EINVAL;
> + rc = _dpu_encoder_dsc_update_pic_dim(dsc, dsc->pic_width,
> + dsc->pic_height);
> + if (rc) {
> + DPU_ERROR_ENC(dpu_enc, "failed to update DSC pic dim\n");
> + return rc;
> }
>
> - _dpu_encoder_dsc_update_pic_dim(dsc, roi->w, roi->h);
> -
> - this_frame_slices = roi->w / dsc->slice_width;
> + this_frame_slices = dsc->pic_width / dsc->slice_width;
> intf_ip_w = this_frame_slices * dsc->slice_width;
> _dpu_encoder_dsc_pclk_param_calc(dsc, intf_ip_w);
>
> @@ -941,205 +912,126 @@ static int _dpu_encoder_dsc_n_lm_1_enc_1_intf(struct dpu_encoder_virt *dpu_enc)
> dsc_common_mode = DSC_MODE_VIDEO;
>
> DPU_DEBUG_ENC(dpu_enc, "pic_w: %d pic_h: %d mode:%d\n",
> - roi->w, roi->h, dsc_common_mode);
> - DPU_EVT32(DRMID(&dpu_enc->base), roi->w, roi->h, dsc_common_mode);
> + dsc->pic_width, dsc->pic_height, dsc_common_mode);
> + DPU_EVT32(DRMID(&dpu_enc->base), dsc->pic_width, dsc->pic_height,
> + dsc_common_mode);
>
> _dpu_encoder_dsc_pipe_cfg(hw_dsc, hw_pp, dsc, dsc_common_mode,
> - ich_res, true);
> + ich_res);
>
> return 0;
> }
> -
> -static int _dpu_encoder_dsc_2_lm_2_enc_2_intf(struct dpu_encoder_virt *dpu_enc,
> - struct dpu_encoder_kickoff_params *params)
> +static int _dpu_encoder_dsc_2_lm_2_enc_2_intf(struct dpu_encoder_virt *dpu_enc)
> {
> int this_frame_slices;
> int intf_ip_w, enc_ip_w;
> int ich_res, dsc_common_mode;
> + int rc = 0;
>
> struct dpu_encoder_phys *enc_master = dpu_enc->cur_master;
> - const struct dpu_rect *roi = &dpu_enc->cur_conn_roi;
> - struct dpu_hw_dsc *hw_dsc[MAX_CHANNELS_PER_ENC];
> - struct dpu_hw_pingpong *hw_pp[MAX_CHANNELS_PER_ENC];
> - struct msm_display_dsc_info dsc[MAX_CHANNELS_PER_ENC];
> - bool half_panel_partial_update;
> - int i;
> -
> - for (i = 0; i < MAX_CHANNELS_PER_ENC; i++) {
> - hw_pp[i] = dpu_enc->hw_pp[i];
> - hw_dsc[i] = dpu_enc->hw_dsc[i];
> + struct dpu_hw_dsc *l_hw_dsc = dpu_enc->hw_dsc[0];
> + struct dpu_hw_dsc *r_hw_dsc = dpu_enc->hw_dsc[1];
> + struct dpu_hw_pingpong *l_hw_pp = dpu_enc->hw_pp[0];
> + struct dpu_hw_pingpong *r_hw_pp = dpu_enc->hw_pp[1];
> + struct msm_display_dsc_info *dsc =
> + &dpu_enc->mode_info.comp_info.dsc_info;
>
> - if (!hw_pp[i] || !hw_dsc[i]) {
> - DPU_ERROR_ENC(dpu_enc, "invalid params for DSC\n");
> - return -EINVAL;
> - }
> + rc = _dpu_encoder_dsc_update_pic_dim(dsc,
> + dsc->pic_width * dpu_enc->display_num_of_h_tiles,
> + dsc->pic_height);
> + if (rc) {
> + DPU_ERROR_ENC(dpu_enc, "failed to update DSC pic dim\n");
> + return rc;
> }
>
> - half_panel_partial_update =
> - hweight_long(params->affected_displays) == 1;
> -
> - dsc_common_mode = 0;
> - if (!half_panel_partial_update)
> - dsc_common_mode |= DSC_MODE_SPLIT_PANEL;
> - if (enc_master->intf_mode == INTF_MODE_VIDEO)
> - dsc_common_mode |= DSC_MODE_VIDEO;
> -
> - memcpy(&dsc[0], &dpu_enc->mode_info.comp_info.dsc_info, sizeof(dsc[0]));
> - memcpy(&dsc[1], &dpu_enc->mode_info.comp_info.dsc_info, sizeof(dsc[1]));
>
> - /*
> - * Since both DSC use same pic dimension, set same pic dimension
> - * to both DSC structures.
> - */
> - _dpu_encoder_dsc_update_pic_dim(&dsc[0], roi->w, roi->h);
> - _dpu_encoder_dsc_update_pic_dim(&dsc[1], roi->w, roi->h);
> -
> - this_frame_slices = roi->w / dsc[0].slice_width;
> - intf_ip_w = this_frame_slices * dsc[0].slice_width;
> -
> - if (!half_panel_partial_update)
> - intf_ip_w /= 2;
> + this_frame_slices = dsc->pic_width / dsc->slice_width;
> + intf_ip_w = this_frame_slices * dsc->slice_width;
>
> - /*
> - * In this topology when both interfaces are active, they have same
> - * load so intf_ip_w will be same.
> - */
> - _dpu_encoder_dsc_pclk_param_calc(&dsc[0], intf_ip_w);
> - _dpu_encoder_dsc_pclk_param_calc(&dsc[1], intf_ip_w);
> + intf_ip_w /= 2;
> + _dpu_encoder_dsc_pclk_param_calc(dsc, intf_ip_w);
>
> - /*
> - * In this topology, since there is no dsc_merge, uncompressed input
> - * to encoder and interface is same.
> - */
> enc_ip_w = intf_ip_w;
> - _dpu_encoder_dsc_initial_line_calc(&dsc[0], enc_ip_w);
> - _dpu_encoder_dsc_initial_line_calc(&dsc[1], enc_ip_w);
> + _dpu_encoder_dsc_initial_line_calc(dsc, enc_ip_w);
>
> - /*
> - * __is_ich_reset_override_needed should be called only after
> - * updating pic dimension, mdss_panel_dsc_update_pic_dim.
> - */
> - ich_res = _dpu_encoder_dsc_ich_reset_override_needed(
> - half_panel_partial_update, &dsc[0]);
> + ich_res = _dpu_encoder_dsc_ich_reset_override_needed(false, dsc);
>
> - DPU_DEBUG_ENC(dpu_enc, "pic_w: %d pic_h: %d mode:%d\n",
> - roi->w, roi->h, dsc_common_mode);
> + dsc_common_mode = DSC_MODE_SPLIT_PANEL;
> + if (enc_master->intf_mode == INTF_MODE_VIDEO)
> + dsc_common_mode |= DSC_MODE_VIDEO;
>
> - for (i = 0; i < dpu_enc->num_phys_encs; i++) {
> - bool active = !!((1 << i) & params->affected_displays);
> + DPU_DEBUG_ENC(dpu_enc, "pic_w: %d pic_h: %d mode:%d\n",
> + dsc->pic_width, dsc->pic_height, dsc_common_mode);
> + DPU_EVT32(DRMID(&dpu_enc->base), dsc->pic_width, dsc->pic_height,
> + dsc_common_mode);
>
> - DPU_EVT32(DRMID(&dpu_enc->base), roi->w, roi->h,
> - dsc_common_mode, i, active);
> - _dpu_encoder_dsc_pipe_cfg(hw_dsc[i], hw_pp[i], &dsc[i],
> - dsc_common_mode, ich_res, active);
> - }
> + _dpu_encoder_dsc_pipe_cfg(l_hw_dsc, l_hw_pp, dsc, dsc_common_mode,
> + ich_res);
> + _dpu_encoder_dsc_pipe_cfg(r_hw_dsc, r_hw_pp, dsc, dsc_common_mode,
> + ich_res);
>
> return 0;
> }
>
> -static int _dpu_encoder_dsc_2_lm_2_enc_1_intf(struct dpu_encoder_virt *dpu_enc,
> - struct dpu_encoder_kickoff_params *params)
> +static int _dpu_encoder_dsc_2_lm_2_enc_1_intf(struct dpu_encoder_virt *dpu_enc)
> {
> int this_frame_slices;
> int intf_ip_w, enc_ip_w;
> int ich_res, dsc_common_mode;
> + int rc = 0;
>
> struct dpu_encoder_phys *enc_master = dpu_enc->cur_master;
> - const struct dpu_rect *roi = &dpu_enc->cur_conn_roi;
> - struct dpu_hw_dsc *hw_dsc[MAX_CHANNELS_PER_ENC];
> - struct dpu_hw_pingpong *hw_pp[MAX_CHANNELS_PER_ENC];
> + struct dpu_hw_dsc *l_hw_dsc = dpu_enc->hw_dsc[0];
> + struct dpu_hw_dsc *r_hw_dsc = dpu_enc->hw_dsc[1];
> + struct dpu_hw_pingpong *l_hw_pp = dpu_enc->hw_pp[0];
> + struct dpu_hw_pingpong *r_hw_pp = dpu_enc->hw_pp[1];
> struct msm_display_dsc_info *dsc =
> &dpu_enc->mode_info.comp_info.dsc_info;
> - bool half_panel_partial_update;
> - int i;
> -
> - for (i = 0; i < MAX_CHANNELS_PER_ENC; i++) {
> - hw_pp[i] = dpu_enc->hw_pp[i];
> - hw_dsc[i] = dpu_enc->hw_dsc[i];
>
> - if (!hw_pp[i] || !hw_dsc[i]) {
> - DPU_ERROR_ENC(dpu_enc, "invalid params for DSC\n");
> - return -EINVAL;
> - }
> + rc = _dpu_encoder_dsc_update_pic_dim(dsc, dsc->pic_width,
> + dsc->pic_height);
> + if (rc) {
> + DPU_ERROR_ENC(dpu_enc, "failed to update DSC pic dim\n");
> + return rc;
> }
>
> - half_panel_partial_update =
> - hweight_long(params->affected_displays) == 1;
> -
> - dsc_common_mode = 0;
> - if (!half_panel_partial_update)
> - dsc_common_mode |= DSC_MODE_SPLIT_PANEL | DSC_MODE_MULTIPLEX;
> - if (enc_master->intf_mode == INTF_MODE_VIDEO)
> - dsc_common_mode |= DSC_MODE_VIDEO;
> -
> - _dpu_encoder_dsc_update_pic_dim(dsc, roi->w, roi->h);
> -
> - this_frame_slices = roi->w / dsc->slice_width;
> + this_frame_slices = dsc->pic_width / dsc->slice_width;
> intf_ip_w = this_frame_slices * dsc->slice_width;
> _dpu_encoder_dsc_pclk_param_calc(dsc, intf_ip_w);
>
> /*
> - * dsc merge case: when using 2 encoders for the same stream,
> - * no. of slices need to be same on both the encoders.
> + * when using 2 encoders for the same stream, no. of slices
> + * need to be same on both the encoders.
> */
> enc_ip_w = intf_ip_w / 2;
> _dpu_encoder_dsc_initial_line_calc(dsc, enc_ip_w);
>
> - ich_res = _dpu_encoder_dsc_ich_reset_override_needed(
> - half_panel_partial_update, dsc);
> -
> - DPU_DEBUG_ENC(dpu_enc, "pic_w: %d pic_h: %d mode:%d\n",
> - roi->w, roi->h, dsc_common_mode);
> - DPU_EVT32(DRMID(&dpu_enc->base), roi->w, roi->h,
> - dsc_common_mode, i, params->affected_displays);
> -
> - _dpu_encoder_dsc_pipe_cfg(hw_dsc[0], hw_pp[0], dsc, dsc_common_mode,
> - ich_res, true);
> - _dpu_encoder_dsc_pipe_cfg(hw_dsc[1], hw_pp[1], dsc, dsc_common_mode,
> - ich_res, !half_panel_partial_update);
> -
> - return 0;
> -}
> -
> -static int _dpu_encoder_update_roi(struct drm_encoder *drm_enc)
> -{
> - struct dpu_encoder_virt *dpu_enc;
> - struct drm_connector *drm_conn;
> - struct drm_display_mode *adj_mode;
> - struct dpu_rect roi;
> -
> - if (!drm_enc || !drm_enc->crtc || !drm_enc->crtc->state)
> - return -EINVAL;
> - dpu_enc = to_dpu_encoder_virt(drm_enc);
> -
> - if (!dpu_enc->cur_master)
> - return -EINVAL;
> + ich_res = _dpu_encoder_dsc_ich_reset_override_needed(false, dsc);
>
> - adj_mode = &dpu_enc->base.crtc->state->adjusted_mode;
> - drm_conn = dpu_enc->cur_master->connector;
> + dsc_common_mode = DSC_MODE_MULTIPLEX | DSC_MODE_SPLIT_PANEL;
> + if (enc_master->intf_mode == INTF_MODE_VIDEO)
> + dsc_common_mode |= DSC_MODE_VIDEO;
>
> - _dpu_encoder_get_connector_roi(dpu_enc, &roi);
> - if (dpu_kms_rect_is_null(&roi)) {
> - roi.w = adj_mode->hdisplay;
> - roi.h = adj_mode->vdisplay;
> - }
> + DPU_DEBUG_ENC(dpu_enc, "pic_w: %d pic_h: %d mode:%d\n",
> + dsc->pic_width, dsc->pic_height, dsc_common_mode);
> + DPU_EVT32(DRMID(&dpu_enc->base), dsc->pic_width, dsc->pic_height,
> + dsc_common_mode);
>
> - memcpy(&dpu_enc->prv_conn_roi, &dpu_enc->cur_conn_roi,
> - sizeof(dpu_enc->prv_conn_roi));
> - memcpy(&dpu_enc->cur_conn_roi, &roi, sizeof(dpu_enc->cur_conn_roi));
> + _dpu_encoder_dsc_pipe_cfg(l_hw_dsc, l_hw_pp, dsc, dsc_common_mode,
> + ich_res);
> + _dpu_encoder_dsc_pipe_cfg(r_hw_dsc, r_hw_pp, dsc, dsc_common_mode,
> + ich_res);
>
> return 0;
> }
>
> -static int _dpu_encoder_dsc_setup(struct dpu_encoder_virt *dpu_enc,
> - struct dpu_encoder_kickoff_params *params)
> +static int _dpu_encoder_dsc_setup(struct dpu_encoder_virt *dpu_enc)
> {
> enum dpu_rm_topology_name topology;
> struct drm_connector *drm_conn;
> int ret = 0;
>
> - if (!dpu_enc || !params || !dpu_enc->phys_encs[0] ||
> - !dpu_enc->phys_encs[0]->connector)
> + if (!dpu_enc)
> return -EINVAL;
>
> drm_conn = dpu_enc->phys_encs[0]->connector;
> @@ -1153,20 +1045,16 @@ static int _dpu_encoder_dsc_setup(struct dpu_encoder_virt *dpu_enc,
> DPU_DEBUG_ENC(dpu_enc, "topology:%d\n", topology);
> DPU_EVT32(DRMID(&dpu_enc->base));
>
> - if (dpu_kms_rect_is_equal(&dpu_enc->cur_conn_roi,
> - &dpu_enc->prv_conn_roi))
> - return ret;
> -
> switch (topology) {
> case DPU_RM_TOPOLOGY_SINGLEPIPE_DSC:
> case DPU_RM_TOPOLOGY_DUALPIPE_3DMERGE_DSC:
> ret = _dpu_encoder_dsc_n_lm_1_enc_1_intf(dpu_enc);
> break;
> case DPU_RM_TOPOLOGY_DUALPIPE_DSCMERGE:
> - ret = _dpu_encoder_dsc_2_lm_2_enc_1_intf(dpu_enc, params);
> + ret = _dpu_encoder_dsc_2_lm_2_enc_1_intf(dpu_enc);
> break;
> case DPU_RM_TOPOLOGY_DUALPIPE_DSC:
> - ret = _dpu_encoder_dsc_2_lm_2_enc_2_intf(dpu_enc, params);
> + ret = _dpu_encoder_dsc_2_lm_2_enc_2_intf(dpu_enc);
> break;
> default:
> DPU_ERROR_ENC(dpu_enc, "No DSC support for topology %d",
> @@ -1429,7 +1317,8 @@ static int _dpu_encoder_update_rsc_client(
> }
>
> if (crtc->base.id != wait_vblank_crtc_id) {
> - primary_crtc = drm_crtc_find(drm_enc->dev, NULL, wait_vblank_crtc_id);
> + primary_crtc = drm_crtc_find(drm_enc->dev, NULL,
> + wait_vblank_crtc_id);
> if (!primary_crtc) {
> DPU_ERROR_ENC(dpu_enc,
> "failed to find primary crtc id %d\n",
> @@ -2073,9 +1962,6 @@ static void _dpu_encoder_virt_enable_helper(struct drm_encoder *drm_enc)
> dpu_kms->catalog);
>
> _dpu_encoder_update_vsync_source(dpu_enc, &dpu_enc->disp_info, false);
> -
> - memset(&dpu_enc->prv_conn_roi, 0, sizeof(dpu_enc->prv_conn_roi));
> - memset(&dpu_enc->cur_conn_roi, 0, sizeof(dpu_enc->cur_conn_roi));
> }
>
> void dpu_encoder_virt_restore(struct drm_encoder *drm_enc)
> @@ -2945,7 +2831,8 @@ static int _dpu_encoder_wakeup_time(struct drm_encoder *drm_enc,
>
> static void dpu_encoder_vsync_event_handler(struct timer_list *t)
> {
> - struct dpu_encoder_virt *dpu_enc = from_timer(dpu_enc, t, vsync_event_timer);
> + struct dpu_encoder_virt *dpu_enc = from_timer(dpu_enc, t,
> + vsync_event_timer);
> struct drm_encoder *drm_enc = &dpu_enc->base;
> struct msm_drm_private *priv;
> struct msm_drm_thread *event_thread;
> @@ -3053,8 +2940,6 @@ void dpu_encoder_prepare_for_kickoff(struct drm_encoder *drm_enc,
>
> _dpu_encoder_update_master(drm_enc, params);
>
> - _dpu_encoder_update_roi(drm_enc);
> -
> if (dpu_enc->cur_master && dpu_enc->cur_master->connector) {
> rc = dpu_connector_pre_kickoff(dpu_enc->cur_master->connector);
> if (rc)
> @@ -3064,7 +2949,7 @@ void dpu_encoder_prepare_for_kickoff(struct drm_encoder *drm_enc,
> }
>
> if (dpu_encoder_is_dsc_enabled(drm_enc)) {
> - rc = _dpu_encoder_dsc_setup(dpu_enc, params);
> + rc = _dpu_encoder_dsc_setup(dpu_enc);
> if (rc)
> DPU_ERROR_ENC(dpu_enc, "failed to setup DSC: %d\n", rc);
> }
> @@ -3654,7 +3539,8 @@ static int dpu_encoder_setup_display(struct dpu_encoder_virt *dpu_enc,
>
> static void dpu_encoder_frame_done_timeout(struct timer_list *t)
> {
> - struct dpu_encoder_virt *dpu_enc = from_timer(dpu_enc, t, frame_done_timer);
> + struct dpu_encoder_virt *dpu_enc = from_timer(dpu_enc, t,
> + frame_done_timer);
> struct drm_encoder *drm_enc = &dpu_enc->base;
> struct msm_drm_private *priv;
> u32 event;
> @@ -3726,7 +3612,8 @@ struct drm_encoder *dpu_encoder_init(
> drm_encoder_helper_add(drm_enc, &dpu_encoder_helper_funcs);
>
> atomic_set(&dpu_enc->frame_done_timeout, 0);
> - timer_setup(&dpu_enc->frame_done_timer, dpu_encoder_frame_done_timeout, 0);
> + timer_setup(&dpu_enc->frame_done_timer,
> + dpu_encoder_frame_done_timeout, 0);
>
> if ((disp_info->intf_type == DRM_MODE_CONNECTOR_DSI) &&
> disp_info->is_primary)
> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h
> index 62e7c5c..d11fb1d 100644
> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h
> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h
> @@ -454,14 +454,6 @@ void dpu_kms_rect_intersect(const struct dpu_rect *r1,
> struct dpu_rect *result);
>
> /**
> - * dpu_kms_rect_merge_rectangles - merge a rectangle list into one rect
> - * @rois: pointer to the list of rois
> - * @result: output rectangle, all 0 on error
> - */
> -void dpu_kms_rect_merge_rectangles(const struct msm_roi_list *rois,
> - struct dpu_rect *result);
> -
> -/**
> * dpu_kms_rect_is_equal - compares two rects
> * @r1: rect value to compare
> * @r2: rect value to compare
> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms_utils.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms_utils.c
> index 006d7ad..40e0162 100644
> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms_utils.c
> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms_utils.c
> @@ -176,45 +176,3 @@ void dpu_kms_rect_intersect(const struct dpu_rect *r1,
> }
> }
>
> -void dpu_kms_rect_merge_rectangles(const struct msm_roi_list *rois,
> - struct dpu_rect *result)
> -{
> - struct drm_clip_rect clip;
> - const struct drm_clip_rect *roi_rect;
> - int i;
> -
> - if (!rois || !result)
> - return;
> -
> - memset(result, 0, sizeof(*result));
> -
> - /* init to invalid range maxes */
> - clip.x1 = ~0;
> - clip.y1 = ~0;
> - clip.x2 = 0;
> - clip.y2 = 0;
> -
> - /* aggregate all clipping rectangles together for overall roi */
> - for (i = 0; i < rois->num_rects; i++) {
> - roi_rect = &rois->roi[i];
> -
> - clip.x1 = min(clip.x1, roi_rect->x1);
> - clip.y1 = min(clip.y1, roi_rect->y1);
> - clip.x2 = max(clip.x2, roi_rect->x2);
> - clip.y2 = max(clip.y2, roi_rect->y2);
> -
> - DPU_DEBUG("roi%d (%d,%d),(%d,%d) -> crtc (%d,%d),(%d,%d)\n", i,
> - roi_rect->x1, roi_rect->y1,
> - roi_rect->x2, roi_rect->y2,
> - clip.x1, clip.y1,
> - clip.x2, clip.y2);
> - }
> -
> - if (clip.x2 && clip.y2) {
> - result->x = clip.x1;
> - result->y = clip.y1;
> - result->w = clip.x2 - clip.x1;
> - result->h = clip.y2 - clip.y1;
> - }
> -}
> -
> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
> index 834dcc0..9e9c9d2 100644
> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
> @@ -3243,7 +3243,6 @@ static int dpu_plane_sspp_atomic_update(struct drm_plane *plane,
> struct drm_crtc *crtc;
> struct drm_framebuffer *fb;
> struct dpu_rect src, dst;
> - const struct dpu_rect *crtc_roi;
> bool q16_data = true;
> int idx;
>
> @@ -3357,11 +3356,6 @@ static int dpu_plane_sspp_atomic_update(struct drm_plane *plane,
> _dpu_plane_sspp_atomic_check_mode_changed(pdpu, state,
> old_state);
>
> - /* re-program the output rects always in the case of partial update */
> - dpu_crtc_get_crtc_roi(crtc->state, &crtc_roi);
> - if (!dpu_kms_rect_is_null(crtc_roi))
> - pstate->dirty |= DPU_PLANE_DIRTY_RECTS;
> -
> if (pstate->dirty & DPU_PLANE_DIRTY_RECTS)
> memset(&(pdpu->pipe_cfg), 0, sizeof(struct dpu_hw_pipe_cfg));
>
> @@ -3399,13 +3393,6 @@ static int dpu_plane_sspp_atomic_update(struct drm_plane *plane,
> src.y &= ~0x1;
> }
>
> - /*
> - * adjust layer mixer position of the sspp in the presence
> - * of a partial update to the active lm origin
> - */
> - dst.x -= crtc_roi->x;
> - dst.y -= crtc_roi->y;
> -
> pdpu->pipe_cfg.src_rect = src;
> pdpu->pipe_cfg.dst_rect = dst;
>
> diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h
> index d8e090f..8574f30 100644
> --- a/drivers/gpu/drm/msm/msm_drv.h
> +++ b/drivers/gpu/drm/msm/msm_drv.h
> @@ -144,7 +144,6 @@ enum msm_mdp_crtc_property {
> CRTC_PROP_DRAM_IB,
> CRTC_PROP_ROT_PREFILL_BW,
> CRTC_PROP_ROT_CLK,
> - CRTC_PROP_ROI_V1,
> CRTC_PROP_IDLE_TIMEOUT,
> CRTC_PROP_DEST_SCALER,
>
> @@ -168,7 +167,6 @@ enum msm_mdp_conn_property {
> CONNECTOR_PROP_DST_Y,
> CONNECTOR_PROP_DST_W,
> CONNECTOR_PROP_DST_H,
> - CONNECTOR_PROP_ROI_V1,
> CONNECTOR_PROP_BL_SCALE,
> CONNECTOR_PROP_AD_BL_SCALE,
>
> @@ -228,38 +226,6 @@ enum msm_event_wait {
> };
>
> /**
> - * struct msm_roi_alignment - region of interest alignment restrictions
> - * @xstart_pix_align: left x offset alignment restriction
> - * @width_pix_align: width alignment restriction
> - * @ystart_pix_align: top y offset alignment restriction
> - * @height_pix_align: height alignment restriction
> - * @min_width: minimum width restriction
> - * @min_height: minimum height restriction
> - */
> -struct msm_roi_alignment {
> - uint32_t xstart_pix_align;
> - uint32_t width_pix_align;
> - uint32_t ystart_pix_align;
> - uint32_t height_pix_align;
> - uint32_t min_width;
> - uint32_t min_height;
> -};
> -
> -/**
> - * struct msm_roi_caps - display's region of interest capabilities
> - * @enabled: true if some region of interest is supported
> - * @merge_rois: merge rois before sending to display
> - * @num_roi: maximum number of rois supported
> - * @align: roi alignment restrictions
> - */
> -struct msm_roi_caps {
> - bool enabled;
> - bool merge_rois;
> - uint32_t num_roi;
> - struct msm_roi_alignment align;
> -};
> -
> -/**
> * struct msm_display_dsc_info - defines dsc configuration
> * @version: DSC version.
> * @scr_rev: DSC revision.
> @@ -427,7 +393,6 @@ struct msm_mode_info {
> * @is_primary: Set to true if display is primary display
> * @is_te_using_watchdog_timer: Boolean to indicate watchdog TE is
> * used instead of panel TE in cmd mode panels
> - * @roi_caps: Region of interest capability info
> */
> struct msm_display_info {
> int intf_type;
> @@ -446,27 +411,6 @@ struct msm_display_info {
>
> bool is_primary;
> bool is_te_using_watchdog_timer;
> - struct msm_roi_caps roi_caps;
> -};
> -
> -#define MSM_MAX_ROI 4
> -
> -/**
> - * struct msm_roi_list - list of regions of interest for a drm object
> - * @num_rects: number of valid rectangles in the roi array
> - * @roi: list of roi rectangles
> - */
> -struct msm_roi_list {
> - uint32_t num_rects;
> - struct drm_clip_rect roi[MSM_MAX_ROI];
> -};
> -
> -/**
> - * struct - msm_display_kickoff_params - info for display features at kickoff
> - * @rois: Regions of interest structure for mapping CRTC to Connector output
> - */
> -struct msm_display_kickoff_params {
> - struct msm_roi_list *rois;
> };
>
> /**
> --
> The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
> a Linux Foundation Collaborative Project
>
--
Sean Paul, Software Engineer, Google / Chromium OS
More information about the Freedreno
mailing list