From patchwork Thu Feb 14 01:52:20 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jeykumar Sankaran X-Patchwork-Id: 10811587 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 2A1F01575 for ; Thu, 14 Feb 2019 01:52:39 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 106A02DF4A for ; Thu, 14 Feb 2019 01:52:39 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 046FE2DF4F; Thu, 14 Feb 2019 01:52:39 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.7 required=2.0 tests=BAYES_00,DKIM_INVALID, DKIM_SIGNED,MAILING_LIST_MULTI,RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id A81952DF4A for ; Thu, 14 Feb 2019 01:52:37 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2391716AbfBNBwh (ORCPT ); Wed, 13 Feb 2019 20:52:37 -0500 Received: from smtp.codeaurora.org ([198.145.29.96]:34880 "EHLO smtp.codeaurora.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2391675AbfBNBwg (ORCPT ); Wed, 13 Feb 2019 20:52:36 -0500 Received: by smtp.codeaurora.org (Postfix, from userid 1000) id A509260929; Thu, 14 Feb 2019 01:52:34 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=codeaurora.org; s=default; t=1550109154; bh=HoXTcAwyKKaxefd7dmvunJo6DT0a8lcjkOHed5cLrIs=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=MTSLF7b+M7aeRH09s4alBJm2BHfLvxyh+Yx/wW1RRSVG4fwXYzfWPLbrpoF3TmbjG DxeDAAODu+BPzvZRJEN3+6A09K4uL5wDqMIPJMN7zAYwQv52HmXWjlgvU0pEY2Dg8J Yf5tQvZU2v94RT/RWxcgf2fsJX3SlVAdSE+EPnF8= Received: from jeykumar-linux.qualcomm.com (i-global254.qualcomm.com [199.106.103.254]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-SHA256 (128/128 bits)) (No client certificate requested) (Authenticated sender: jsanka@smtp.codeaurora.org) by smtp.codeaurora.org (Postfix) with ESMTPSA id 18018608D2; Thu, 14 Feb 2019 01:52:31 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=codeaurora.org; s=default; t=1550109151; bh=HoXTcAwyKKaxefd7dmvunJo6DT0a8lcjkOHed5cLrIs=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=B5aAiDpz5XLWDAAMOy+8XL7co5r37UKKDa11V7iQUdbE46aSVF3DKFHHx40VU9GRD 35t4ZsQOWe+voFLS+WUbPJkF1OYkoihD7SrZbcX99YhVs0siNaOjFRoLhuxNrV7xMS FfHUoYT6TLXx8lOeA5RC+3iRboW8lem2w8+m9tE8= DMARC-Filter: OpenDMARC Filter v1.3.2 smtp.codeaurora.org 18018608D2 Authentication-Results: pdx-caf-mail.web.codeaurora.org; dmarc=none (p=none dis=none) header.from=codeaurora.org Authentication-Results: pdx-caf-mail.web.codeaurora.org; spf=none smtp.mailfrom=jsanka@codeaurora.org From: Jeykumar Sankaran To: dri-devel@lists.freedesktop.org, freedreno@lists.freedesktop.org, linux-arm-msm@vger.kernel.org Cc: Jeykumar Sankaran , seanpaul@chromium.org, robdclark@gmail.com, hoegsberg@google.com Subject: [PATCH v2 2/4] drm/msm/dpu: track HW resources using private object state Date: Wed, 13 Feb 2019 17:52:20 -0800 Message-Id: <1550109142-28303-3-git-send-email-jsanka@codeaurora.org> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1550109142-28303-1-git-send-email-jsanka@codeaurora.org> References: <1550109142-28303-1-git-send-email-jsanka@codeaurora.org> Sender: linux-arm-msm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-arm-msm@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP DPU maintained reservation lists to cache assigned HW blocks for the display and a retrieval mechanism for the individual DRM components to query their respective HW blocks. This patch uses the sub-classed private object state to store and track HW blocks assigned for different components of the display pipeline. It helps the driver: - to get rid of unwanted store and retrieval RM API's - to preserve HW resources assigned in atomic_check through atomic swap/duplicate. Resources are reserved only when drm_atomic_crtc_needs_modeset is set to TRUE and are released in atomic disable path. With TEST_ONLY atomic commit path, reserved resources are released back to RM pool in private_obj_destroy_state call. changes in v2 (comments from Sean Paul): - Track resources in private object state instead of crtc state. - Avoid duplicate tracking of hw_ctls in crtc - No explicit count for hw_ctl as they match with hw_intf count Signed-off-by: Jeykumar Sankaran --- drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.h | 7 +- drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 157 ++++++++++++---------------- drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c | 9 ++ drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h | 17 +++ drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c | 131 +++++++++++++++-------- drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h | 8 +- 6 files changed, 185 insertions(+), 144 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.h index be07554..cec0674 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.h @@ -202,8 +202,6 @@ struct dpu_crtc { * @new_perf: new performance state being requested * @num_mixers : Number of mixers in use * @mixers : List of active mixers - * @num_ctls : Number of ctl paths in use - * @hw_ctls : List of active ctl paths */ struct dpu_crtc_state { struct drm_crtc_state base; @@ -217,11 +215,8 @@ struct dpu_crtc_state { struct dpu_core_perf_params new_perf; /* HW Resources reserved for the crtc */ - u32 num_mixers; + int num_mixers; struct dpu_crtc_mixer mixers[CRTC_DUAL_MIXERS]; - - u32 num_ctls; - struct dpu_hw_ctl *hw_ctls[CRTC_DUAL_MIXERS]; }; #define to_dpu_crtc_state(x) \ diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c index 98ea478..bd646c5 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c @@ -559,7 +559,6 @@ static int dpu_encoder_virt_atomic_check( struct dpu_kms *dpu_kms; const struct drm_display_mode *mode; struct drm_display_mode *adj_mode; - struct msm_display_topology topology; int i = 0; int ret = 0; @@ -605,20 +604,24 @@ static int dpu_encoder_virt_atomic_check( } } - topology = dpu_encoder_get_topology(dpu_enc, dpu_kms, adj_mode); + /* + * Reserve dynamic resources now. Indicating AtomicTest phase + * + * Avoid reserving resources when mode set is pending. Topology + * info may not be available to complete reservation. + */ + if (!ret && drm_atomic_crtc_needs_modeset(crtc_state) + && dpu_enc->mode_set_complete) { + struct msm_display_topology topology; + struct dpu_private_state *dpu_priv_state; - /* Reserve dynamic resources now. Indicating AtomicTest phase */ - if (!ret) { - /* - * Avoid reserving resources when mode set is pending. Topology - * info may not be available to complete reservation. - */ - if (drm_atomic_crtc_needs_modeset(crtc_state) - && dpu_enc->mode_set_complete) { - ret = dpu_rm_reserve(&dpu_kms->rm, drm_enc, crtc_state, - topology, true); - dpu_enc->mode_set_complete = false; - } + topology = dpu_encoder_get_topology(dpu_enc, dpu_kms, adj_mode); + dpu_priv_state = dpu_get_private_state(crtc_state->state, + to_dpu_crtc(crtc_state->crtc)); + + ret = dpu_rm_reserve(&dpu_kms->rm, drm_enc, + &dpu_priv_state->base, topology, true); + dpu_enc->mode_set_complete = false; } if (!ret) @@ -962,12 +965,10 @@ static void dpu_encoder_virt_mode_set(struct drm_encoder *drm_enc, struct list_head *connector_list; struct drm_connector *conn = NULL, *conn_iter; struct drm_crtc *drm_crtc; - struct dpu_crtc_state *cstate; - struct dpu_rm_hw_iter hw_iter; + struct dpu_crtc_state *dpu_cstate; struct msm_display_topology topology; - struct dpu_hw_ctl *hw_ctl[MAX_CHANNELS_PER_ENC] = { NULL }; - struct dpu_hw_mixer *hw_lm[MAX_CHANNELS_PER_ENC] = { NULL }; - int num_lm = 0, num_ctl = 0; + struct dpu_crtc *dpu_crtc; + struct dpu_private_state *dpu_private_state; int i, j, ret; if (!drm_enc) { @@ -1001,100 +1002,59 @@ static void dpu_encoder_virt_mode_set(struct drm_encoder *drm_enc, break; topology = dpu_encoder_get_topology(dpu_enc, dpu_kms, adj_mode); + dpu_crtc = to_dpu_crtc(drm_crtc); /* Reserve dynamic resources now. Indicating non-AtomicTest phase */ - ret = dpu_rm_reserve(&dpu_kms->rm, drm_enc, drm_crtc->state, + ret = dpu_rm_reserve(&dpu_kms->rm, drm_enc, dpu_crtc->priv_obj.state, topology, false); if (ret) { DPU_ERROR_ENC(dpu_enc, - "failed to reserve hw resources, %d\n", ret); + "failed to reserve hw resources, %d\n", ret); return; } - dpu_rm_init_hw_iter(&hw_iter, drm_enc->base.id, DPU_HW_BLK_PINGPONG); - for (i = 0; i < MAX_CHANNELS_PER_ENC; i++) { - dpu_enc->hw_pp[i] = NULL; - if (!dpu_rm_get_hw(&dpu_kms->rm, &hw_iter)) - break; - dpu_enc->hw_pp[i] = (struct dpu_hw_pingpong *) hw_iter.hw; - } - - dpu_rm_init_hw_iter(&hw_iter, drm_enc->base.id, DPU_HW_BLK_CTL); - for (i = 0; i < MAX_CHANNELS_PER_ENC; i++) { - if (!dpu_rm_get_hw(&dpu_kms->rm, &hw_iter)) - break; - hw_ctl[i] = (struct dpu_hw_ctl *)hw_iter.hw; - num_ctl++; - } - - dpu_rm_init_hw_iter(&hw_iter, drm_enc->base.id, DPU_HW_BLK_LM); - for (i = 0; i < MAX_CHANNELS_PER_ENC; i++) { - if (!dpu_rm_get_hw(&dpu_kms->rm, &hw_iter)) - break; - hw_lm[i] = (struct dpu_hw_mixer *)hw_iter.hw; - num_lm++; - } + dpu_cstate = to_dpu_crtc_state(drm_crtc->state); + dpu_private_state = container_of(dpu_crtc->priv_obj.state, + struct dpu_private_state, base); - cstate = to_dpu_crtc_state(drm_crtc->state); + for (i = 0; i < dpu_private_state->num_mixers; i++) { + int ctl_idx; - for (i = 0; i < num_lm; i++) { - int ctl_idx = (i < num_ctl) ? i : (num_ctl-1); + dpu_cstate->mixers[i].hw_lm = dpu_private_state->hw_lms[i]; - cstate->mixers[i].hw_lm = hw_lm[i]; - cstate->mixers[i].lm_ctl = hw_ctl[ctl_idx]; + /* + * hw_ctl count may be <= hw_lm count, if less, multiple LMs are + * controlled by 1 CTL + */ + ctl_idx = min(i, dpu_private_state->num_intfs - 1); + dpu_cstate->mixers[i].lm_ctl = + dpu_private_state->hw_ctls[ctl_idx]; } - - cstate->num_mixers = num_lm; + dpu_cstate->num_mixers = dpu_private_state->num_mixers; for (i = 0; i < dpu_enc->num_phys_encs; i++) { struct dpu_encoder_phys *phys = dpu_enc->phys_encs[i]; - if (phys) { - if (!dpu_enc->hw_pp[i]) { - DPU_ERROR_ENC(dpu_enc, "no pp block assigned" - "at idx: %d\n", i); - goto error; - } - - if (!hw_ctl[i]) { - DPU_ERROR_ENC(dpu_enc, "no ctl block assigned" - "at idx: %d\n", i); - goto error; - } - - phys->hw_pp = dpu_enc->hw_pp[i]; - phys->hw_ctl = hw_ctl[i]; - - dpu_rm_init_hw_iter(&hw_iter, drm_enc->base.id, - DPU_HW_BLK_INTF); - for (j = 0; j < MAX_CHANNELS_PER_ENC; j++) { - struct dpu_hw_intf *hw_intf; + phys->hw_pp = dpu_private_state->hw_pps[i]; + dpu_enc->hw_pp[i] = dpu_private_state->hw_pps[i]; - if (!dpu_rm_get_hw(&dpu_kms->rm, &hw_iter)) - break; + phys->hw_ctl = dpu_cstate->mixers[i].lm_ctl; - hw_intf = (struct dpu_hw_intf *)hw_iter.hw; - if (hw_intf->idx == phys->intf_idx) - phys->hw_intf = hw_intf; + for (j = 0; j < dpu_private_state->num_intfs; j++) { + struct dpu_hw_intf *hw_intf = + dpu_private_state->hw_intfs[j]; + if (hw_intf->idx == phys->intf_idx) { + phys->hw_intf = hw_intf; + break; } - - if (!phys->hw_intf) { - DPU_ERROR_ENC(dpu_enc, - "no intf block assigned at idx: %d\n", - i); - goto error; - } - - phys->connector = conn->state->connector; - if (phys->ops.mode_set) - phys->ops.mode_set(phys, mode, adj_mode); } + + phys->connector = conn->state->connector; + if (phys->ops.mode_set) + phys->ops.mode_set(phys, mode, adj_mode); } dpu_enc->mode_set_complete = true; - -error: - dpu_rm_release(&dpu_kms->rm, drm_enc); } static void _dpu_encoder_virt_enable_helper(struct drm_encoder *drm_enc) @@ -1196,6 +1156,9 @@ static void dpu_encoder_virt_disable(struct drm_encoder *drm_enc) struct msm_drm_private *priv; struct dpu_kms *dpu_kms; struct drm_display_mode *mode; + struct drm_crtc *drm_crtc; + struct dpu_crtc *dpu_crtc; + unsigned long lock_flags; int i = 0; if (!drm_enc) { @@ -1212,10 +1175,20 @@ static void dpu_encoder_virt_disable(struct drm_encoder *drm_enc) dpu_enc = to_dpu_encoder_virt(drm_enc); DPU_DEBUG_ENC(dpu_enc, "\n"); + /* + * client may have reset the crtc encoder_mask before encoder->disable. + * Rely on the dpu_enc->crtc which will be reset only on crtc->disable. + */ + spin_lock_irqsave(&dpu_enc->enc_spinlock, lock_flags); + drm_crtc = dpu_enc->crtc; + spin_unlock_irqrestore(&dpu_enc->enc_spinlock, lock_flags); + + dpu_crtc = to_dpu_crtc(drm_crtc); + mutex_lock(&dpu_enc->enc_lock); dpu_enc->enabled = false; - mode = &drm_enc->crtc->state->adjusted_mode; + mode = &drm_crtc->state->adjusted_mode; priv = drm_enc->dev->dev_private; dpu_kms = to_dpu_kms(priv->kms); @@ -1249,7 +1222,7 @@ static void dpu_encoder_virt_disable(struct drm_encoder *drm_enc) DPU_DEBUG_ENC(dpu_enc, "encoder disabled\n"); - dpu_rm_release(&dpu_kms->rm, drm_enc); + dpu_rm_release(&dpu_kms->rm, dpu_crtc->priv_obj.state); mutex_unlock(&dpu_enc->enc_lock); } diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c index 1677862..43e3211 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c @@ -490,10 +490,19 @@ struct dpu_private_state *dpu_get_private_state(struct drm_atomic_state *state, static void dpu_private_obj_destroy_state(struct drm_private_obj *obj, struct drm_private_state *state) { + struct msm_drm_private *priv = state->state->dev->dev_private; + struct dpu_kms *dpu_kms = to_dpu_kms(priv->kms); struct dpu_private_state *dpu_priv_state = container_of(state, struct dpu_private_state, base); + /* + * Destroy state will be triggering RM release only when resources + * are allocated during TEST_ONLY commits where resources need + * to be freed back to the RM pool + */ + dpu_rm_release(&dpu_kms->rm, state); + kfree(dpu_priv_state); } diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h index 3deedfb..790c4d7 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h @@ -26,6 +26,7 @@ #include "dpu_hw_catalog.h" #include "dpu_hw_ctl.h" #include "dpu_hw_lm.h" +#include "dpu_hw_intf.h" #include "dpu_hw_interrupts.h" #include "dpu_hw_top.h" #include "dpu_io_util.h" @@ -140,6 +141,22 @@ struct dpu_kms { struct dpu_private_state { struct drm_private_state base; + + /* + * layer mixers and ping pong blocks + * are hard chained + */ + int num_mixers; + struct dpu_hw_mixer *hw_lms[CRTC_DUAL_MIXERS]; + struct dpu_hw_pingpong *hw_pps[CRTC_DUAL_MIXERS]; + + /* + * until SDM845 each interface is controlled + * by its own hw_ctl + */ + int num_intfs; + struct dpu_hw_ctl *hw_ctls[CRTC_DUAL_MIXERS]; + struct dpu_hw_intf *hw_intfs[CRTC_DUAL_MIXERS]; }; struct vsync_info { diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c index 037d9f4..4884683 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c @@ -368,6 +368,7 @@ static bool _dpu_rm_check_lm_and_get_connected_blks( } static int _dpu_rm_reserve_lms(struct dpu_rm *rm, uint32_t enc_id, + struct dpu_private_state *dpu_priv_state, struct dpu_rm_requirements *reqs) { @@ -429,8 +430,13 @@ static int _dpu_rm_reserve_lms(struct dpu_rm *rm, uint32_t enc_id, lm[i]->enc_id = enc_id; pp[i]->enc_id = enc_id; + dpu_priv_state->hw_lms[i] = to_dpu_hw_mixer(lm[i]->hw); + dpu_priv_state->hw_pps[i] = container_of(pp[i]->hw, + struct dpu_hw_pingpong, + base); trace_dpu_rm_reserve_lms(lm[i]->id, enc_id, pp[i]->id); } + dpu_priv_state->num_mixers = lm_count; return rc; } @@ -438,6 +444,7 @@ static int _dpu_rm_reserve_lms(struct dpu_rm *rm, uint32_t enc_id, static int _dpu_rm_reserve_ctls( struct dpu_rm *rm, uint32_t enc_id, + struct dpu_private_state *dpu_priv_state, const struct msm_display_topology *top) { struct dpu_rm_hw_blk *ctls[MAX_BLOCKS]; @@ -480,20 +487,20 @@ static int _dpu_rm_reserve_ctls( for (i = 0; i < ARRAY_SIZE(ctls) && i < num_ctls; i++) { ctls[i]->enc_id = enc_id; + dpu_priv_state->hw_ctls[i] = to_dpu_hw_ctl(ctls[i]->hw); trace_dpu_rm_reserve_ctls(ctls[i]->id, enc_id); } return 0; } -static int _dpu_rm_reserve_intf( +static struct dpu_rm_hw_blk *_dpu_rm_reserve_intf( struct dpu_rm *rm, uint32_t enc_id, uint32_t id, enum dpu_hw_blk_type type) { struct dpu_rm_hw_iter iter; - int ret = 0; /* Find the block entry in the rm, and note the reservation */ dpu_rm_init_hw_iter(&iter, 0, type); @@ -503,7 +510,7 @@ static int _dpu_rm_reserve_intf( if (RESERVED_BY_OTHER(iter.blk, enc_id)) { DPU_ERROR("type %d id %d already reserved\n", type, id); - return -ENAVAIL; + return NULL; } iter.blk->enc_id = enc_id; @@ -512,56 +519,63 @@ static int _dpu_rm_reserve_intf( } /* Shouldn't happen since intfs are fixed at probe */ - if (!iter.hw) { + if (!iter.blk) { DPU_ERROR("couldn't find type %d id %d\n", type, id); - return -EINVAL; + return NULL; } - return ret; + return iter.blk; } static int _dpu_rm_reserve_intf_related_hw( struct dpu_rm *rm, uint32_t enc_id, + struct dpu_private_state *dpu_priv_state, struct dpu_encoder_hw_resources *hw_res) { - int i, ret = 0; - u32 id; + struct dpu_rm_hw_blk *blk; + int i, num_intfs = 0; for (i = 0; i < ARRAY_SIZE(hw_res->intfs); i++) { if (hw_res->intfs[i] == INTF_MODE_NONE) continue; - id = i + INTF_0; - ret = _dpu_rm_reserve_intf(rm, enc_id, id, + + blk = _dpu_rm_reserve_intf(rm, enc_id, i + INTF_0, DPU_HW_BLK_INTF); - if (ret) - return ret; + if (!blk) + return -ENAVAIL; + + dpu_priv_state->hw_intfs[num_intfs++] = + container_of(blk->hw, struct dpu_hw_intf, base); } + dpu_priv_state->num_intfs = num_intfs; - return ret; + return 0; } static int _dpu_rm_make_reservation( struct dpu_rm *rm, struct drm_encoder *enc, - struct drm_crtc_state *crtc_state, + struct dpu_private_state *dpu_priv_state, struct dpu_rm_requirements *reqs) { int ret; - ret = _dpu_rm_reserve_lms(rm, enc->base.id, reqs); + ret = _dpu_rm_reserve_lms(rm, enc->base.id, dpu_priv_state, reqs); if (ret) { DPU_ERROR("unable to find appropriate mixers\n"); return ret; } - ret = _dpu_rm_reserve_ctls(rm, enc->base.id, &reqs->topology); + ret = _dpu_rm_reserve_ctls(rm, enc->base.id, dpu_priv_state, + &reqs->topology); if (ret) { DPU_ERROR("unable to find appropriate CTL\n"); return ret; } - ret = _dpu_rm_reserve_intf_related_hw(rm, enc->base.id, &reqs->hw_res); + ret = _dpu_rm_reserve_intf_related_hw(rm, enc->base.id, dpu_priv_state, + &reqs->hw_res); if (ret) return ret; @@ -571,7 +585,6 @@ static int _dpu_rm_make_reservation( static int _dpu_rm_populate_requirements( struct dpu_rm *rm, struct drm_encoder *enc, - struct drm_crtc_state *crtc_state, struct dpu_rm_requirements *reqs, struct msm_display_topology req_topology) { @@ -586,27 +599,64 @@ static int _dpu_rm_populate_requirements( return 0; } -static void _dpu_rm_release_reservation(struct dpu_rm *rm, uint32_t enc_id) +static int _dpu_rm_release_hw(struct dpu_rm *rm, enum dpu_hw_blk_type type, + int id) { struct dpu_rm_hw_blk *blk; - enum dpu_hw_blk_type type; - - for (type = 0; type < DPU_HW_BLK_MAX; type++) { - list_for_each_entry(blk, &rm->hw_blks[type], list) { - if (blk->enc_id == enc_id) { - blk->enc_id = 0; - DPU_DEBUG("rel enc %d %d %d\n", enc_id, - type, blk->id); - } + list_for_each_entry(blk, &rm->hw_blks[type], list) { + if (blk->hw->id == id) { + blk->enc_id = 0; + return 0; } } + + DRM_DEBUG_KMS("failed to find hw id(%d) of type(%d) for releasing\n", + id, type); + + return -EINVAL; +} + +static void _dpu_rm_release_reservation(struct dpu_rm *rm, + struct drm_private_state *priv_state) +{ + struct dpu_private_state *dpu_priv_state = + container_of(priv_state, struct dpu_private_state, base); + int i; + + for (i = 0; i < dpu_priv_state->num_mixers; i++) { + if (!dpu_priv_state->hw_lms[i]) + continue; + + if (!_dpu_rm_release_hw(rm, DPU_HW_BLK_LM, + dpu_priv_state->hw_lms[i]->base.id)) + dpu_priv_state->hw_lms[i] = NULL; + + if (!_dpu_rm_release_hw(rm, DPU_HW_BLK_PINGPONG, + dpu_priv_state->hw_pps[i]->base.id)) + dpu_priv_state->hw_pps[i] = NULL; + } + dpu_priv_state->num_mixers = 0; + + for (i = 0; i < dpu_priv_state->num_intfs; i++) { + if (!dpu_priv_state->hw_ctls[i]) + continue; + + if (!_dpu_rm_release_hw(rm, DPU_HW_BLK_CTL, + dpu_priv_state->hw_ctls[i]->base.id)) + dpu_priv_state->hw_ctls[i] = NULL; + + if (!_dpu_rm_release_hw(rm, DPU_HW_BLK_INTF, + dpu_priv_state->hw_intfs[i]->base.id)) + dpu_priv_state->hw_intfs[i] = NULL; + } + dpu_priv_state->num_intfs = 0; } -void dpu_rm_release(struct dpu_rm *rm, struct drm_encoder *enc) +void dpu_rm_release(struct dpu_rm *rm, struct drm_private_state *priv_state) { mutex_lock(&rm->rm_lock); - _dpu_rm_release_reservation(rm, enc->base.id); + _dpu_rm_release_reservation(rm, priv_state); mutex_unlock(&rm->rm_lock); } @@ -614,38 +664,35 @@ void dpu_rm_release(struct dpu_rm *rm, struct drm_encoder *enc) int dpu_rm_reserve( struct dpu_rm *rm, struct drm_encoder *enc, - struct drm_crtc_state *crtc_state, + struct drm_private_state *priv_state, struct msm_display_topology topology, bool test_only) { struct dpu_rm_requirements reqs; + struct dpu_private_state *dpu_priv_state = + container_of(priv_state, struct dpu_private_state, base); int ret; - /* Check if this is just a page-flip */ - if (!drm_atomic_crtc_needs_modeset(crtc_state)) - return 0; - - DRM_DEBUG_KMS("reserving hw for enc %d crtc %d test_only %d\n", - enc->base.id, crtc_state->crtc->base.id, test_only); + DRM_DEBUG_KMS("reserving hw for enc %d test_only %d\n", + enc->base.id, test_only); mutex_lock(&rm->rm_lock); - ret = _dpu_rm_populate_requirements(rm, enc, crtc_state, &reqs, - topology); + ret = _dpu_rm_populate_requirements(rm, enc, &reqs, topology); if (ret) { DPU_ERROR("failed to populate hw requirements\n"); goto end; } - ret = _dpu_rm_make_reservation(rm, enc, crtc_state, &reqs); + ret = _dpu_rm_make_reservation(rm, enc, dpu_priv_state, &reqs); if (ret) { DPU_ERROR("failed to reserve hw resources: %d\n", ret); - _dpu_rm_release_reservation(rm, enc->base.id); + _dpu_rm_release_reservation(rm, priv_state); } else if (test_only) { /* test_only: test the reservation and then undo */ DPU_DEBUG("test_only: discard test [enc: %d]\n", enc->base.id); - _dpu_rm_release_reservation(rm, enc->base.id); + _dpu_rm_release_reservation(rm, priv_state); } end: diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h index 381611f..252e173 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h @@ -81,14 +81,14 @@ int dpu_rm_init(struct dpu_rm *rm, * HW Reservations should be released via dpu_rm_release_hw. * @rm: DPU Resource Manager handle * @drm_enc: DRM Encoder handle - * @crtc_state: Proposed Atomic DRM CRTC State handle + * @priv_state: Pointer to drm private obj state * @topology: Pointer to topology info for the display * @test_only: Atomic-Test phase, discard results (unless property overrides) * @Return: 0 on Success otherwise -ERROR */ int dpu_rm_reserve(struct dpu_rm *rm, struct drm_encoder *drm_enc, - struct drm_crtc_state *crtc_state, + struct drm_private_state *priv_state, struct msm_display_topology topology, bool test_only); @@ -96,10 +96,10 @@ int dpu_rm_reserve(struct dpu_rm *rm, * dpu_rm_reserve - Given the encoder for the display chain, release any * HW blocks previously reserved for that use case. * @rm: DPU Resource Manager handle - * @enc: DRM Encoder handle + * @priv_state: Pointer to drm private obj state * @Return: 0 on Success otherwise -ERROR */ -void dpu_rm_release(struct dpu_rm *rm, struct drm_encoder *enc); +void dpu_rm_release(struct dpu_rm *rm, struct drm_private_state *priv_state); /** * dpu_rm_init_hw_iter - setup given iterator for new iteration over hw list