From patchwork Wed Apr 4 09:06:29 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Rajesh Yadav X-Patchwork-Id: 10322297 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 4DFE560318 for ; Wed, 4 Apr 2018 09:07:01 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 3972728C3B for ; Wed, 4 Apr 2018 09:07:01 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 2D98D28E19; Wed, 4 Apr 2018 09:07:01 +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=-4.1 required=2.0 tests=BAYES_00,DKIM_SIGNED, RCVD_IN_DNSWL_MED,T_DKIM_INVALID autolearn=ham version=3.3.1 Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher DHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id ED72328C3B for ; Wed, 4 Apr 2018 09:06:52 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 3694D6E222; Wed, 4 Apr 2018 09:06:51 +0000 (UTC) X-Original-To: dri-devel@lists.freedesktop.org Delivered-To: dri-devel@lists.freedesktop.org Received: from smtp.codeaurora.org (smtp.codeaurora.org [198.145.29.96]) by gabe.freedesktop.org (Postfix) with ESMTPS id ADF0F6E20E; Wed, 4 Apr 2018 09:06:49 +0000 (UTC) Received: by smtp.codeaurora.org (Postfix, from userid 1000) id 78AF260807; Wed, 4 Apr 2018 09:06:49 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=codeaurora.org; s=default; t=1522832809; bh=W1GfZCF/lpGgpDJsyXOs7D1h6F6riQcAleYNb/p6PVU=; h=From:To:Cc:Subject:Date:From; b=npPEAV1M1tYeoNnFPXm98m+q1BI7bKC1IeGOebjF1Db+/a56SpMlHgW2FWFYdBMbY rT4Bodf+IKGhPYwtQFmJ4Q9hZ5AlphVqLkp9tNHZgABfFYLoR05tuyKrsrO21PmZSX 3QGCKk/06WG07Wf1Oq7+DnGCN07zHl45tJTMwcxA= Received: from ryadav-linux.qualcomm.com (blr-c-bdr-fw-01_globalnat_allzones-outside.qualcomm.com [103.229.19.19]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-SHA256 (128/128 bits)) (No client certificate requested) (Authenticated sender: ryadav@smtp.codeaurora.org) by smtp.codeaurora.org (Postfix) with ESMTPSA id E8AE9607E5; Wed, 4 Apr 2018 09:06:38 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=codeaurora.org; s=default; t=1522832804; bh=W1GfZCF/lpGgpDJsyXOs7D1h6F6riQcAleYNb/p6PVU=; h=From:To:Cc:Subject:Date:From; b=HNBhpuEEwmzSURDBMi041evlWi/r9QYe6un4/+21KJ+Ap05lbmlqTKGOO4vDF58vg acw15D987ZsTyLdx+jfMMtpkRvlVUwK0Kgh5R1m9HJch4of6hn4nYyXGfqU/RYNzOP D/Xm/Q7QIQSwBtOHmBclh7cBUQOa7I+otm7MBW/k= DMARC-Filter: OpenDMARC Filter v1.3.2 smtp.codeaurora.org E8AE9607E5 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=ryadav@codeaurora.org From: Rajesh Yadav To: dri-devel@lists.freedesktop.org, freedreno@lists.freedesktop.org, linux-arm-msm@vger.kernel.org Subject: [DPU PATCH v2 2/2] drm/msm: Remove RSC support from DPU driver Date: Wed, 4 Apr 2018 14:36:29 +0530 Message-Id: <1522832789-24678-1-git-send-email-ryadav@codeaurora.org> X-Mailer: git-send-email 1.9.1 X-BeenThere: dri-devel@lists.freedesktop.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: Direct Rendering Infrastructure - Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Rajesh Yadav , hoegsberg@chromium.org MIME-Version: 1.0 Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" X-Virus-Scanned: ClamAV using ClamSMTP Display controller's power resources and bus bandwidth voting is controlled by dpu driver. Remove DPU RSC driver support. Signed-off-by: Rajesh Yadav --- drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.c | 130 +- drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.h | 6 - drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c | 14 - drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.h | 9 +- drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 242 +--- drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h | 7 - drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h | 1 - drivers/gpu/drm/msm/disp/dpu1/dpu_hw_top.c | 20 +- drivers/gpu/drm/msm/disp/dpu1/dpu_hw_top.h | 3 - drivers/gpu/drm/msm/dpu_dbg.c | 27 - drivers/gpu/drm/msm/dpu_dbg.h | 10 - drivers/gpu/drm/msm/dpu_power_handle.c | 73 +- drivers/gpu/drm/msm/dpu_power_handle.h | 4 - drivers/gpu/drm/msm/dpu_rsc.c | 1367 ---------------------- drivers/gpu/drm/msm/dpu_rsc_hw.c | 818 ------------- drivers/gpu/drm/msm/dpu_rsc_priv.h | 191 --- include/linux/dpu_rsc.h | 302 ----- 17 files changed, 42 insertions(+), 3182 deletions(-) delete mode 100644 drivers/gpu/drm/msm/dpu_rsc.c delete mode 100644 drivers/gpu/drm/msm/dpu_rsc_hw.c delete mode 100644 drivers/gpu/drm/msm/dpu_rsc_priv.h delete mode 100644 include/linux/dpu_rsc.h diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.c index 36a4795..981f77f 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.c @@ -18,7 +18,6 @@ #include #include #include -#include #include "msm_prop.h" @@ -42,23 +41,6 @@ enum dpu_perf_mode { DPU_PERF_MODE_MAX }; -/** - * enum dpu_perf_vote_mode: perf vote mode. - * @APPS_RSC_MODE: It combines the vote for all displays and votes it - * through APPS rsc. This is default mode when display - * rsc is not available. - * @DISP_RSC_MODE: It combines the vote for all displays and votes it - * through display rsc. This is default configuration - * when display rsc is available. - * @DISP_RSC_PRIMARY_MODE: The primary display votes through display rsc - * while all other displays votes through apps rsc. - */ -enum dpu_perf_vote_mode { - APPS_RSC_MODE, - DISP_RSC_MODE, - DISP_RSC_PRIMARY_MODE, -}; - static struct dpu_kms *_dpu_crtc_get_kms(struct drm_crtc *crtc) { struct msm_drm_private *priv; @@ -266,38 +248,12 @@ int dpu_core_perf_crtc_check(struct drm_crtc *crtc, return 0; } -static inline bool _is_crtc_client_type_matches(struct drm_crtc *tmp_crtc, - enum dpu_crtc_client_type curr_client_type, - struct dpu_core_perf *perf) -{ - if (!tmp_crtc) - return false; - else if (perf->bw_vote_mode == DISP_RSC_PRIMARY_MODE && - perf->dpu_rsc_available) - return curr_client_type == dpu_crtc_get_client_type(tmp_crtc); - else - return true; -} - -static inline enum dpu_crtc_client_type _get_dpu_client_type( - enum dpu_crtc_client_type curr_client_type, - struct dpu_core_perf *perf) -{ - if (perf->bw_vote_mode == DISP_RSC_PRIMARY_MODE && - perf->dpu_rsc_available) - return curr_client_type; - else if (perf->bw_vote_mode != APPS_RSC_MODE && perf->dpu_rsc_available) - return RT_RSC_CLIENT; - else - return RT_CLIENT; -} - static void _dpu_core_perf_crtc_update_bus(struct dpu_kms *kms, struct drm_crtc *crtc, u32 bus_id) { u64 bw_sum_of_intfs = 0, bus_ab_quota, bus_ib_quota; struct dpu_core_perf_params perf = { { 0 } }; - enum dpu_crtc_client_type client_vote, curr_client_type + enum dpu_crtc_client_type curr_client_type = dpu_crtc_get_client_type(crtc); struct drm_crtc *tmp_crtc; struct dpu_crtc_state *dpu_cstate; @@ -305,8 +261,8 @@ static void _dpu_core_perf_crtc_update_bus(struct dpu_kms *kms, drm_for_each_crtc(tmp_crtc, crtc->dev) { if (_dpu_core_perf_crtc_is_power_on(tmp_crtc) && - _is_crtc_client_type_matches(tmp_crtc, curr_client_type, - &kms->perf)) { + curr_client_type == + dpu_crtc_get_client_type(tmp_crtc)) { dpu_cstate = to_dpu_crtc_state(tmp_crtc->state); perf.max_per_pipe_ib[bus_id] = @@ -329,8 +285,7 @@ static void _dpu_core_perf_crtc_update_bus(struct dpu_kms *kms, bus_ib_quota = kms->perf.fix_core_ib_vote; } - client_vote = _get_dpu_client_type(curr_client_type, &kms->perf); - switch (client_vote) { + switch (curr_client_type) { case NRT_CLIENT: dpu_power_data_bus_set_quota(&priv->phandle, kms->core_client, DPU_POWER_HANDLE_DATA_BUS_CLIENT_NRT, @@ -347,46 +302,10 @@ static void _dpu_core_perf_crtc_update_bus(struct dpu_kms *kms, bus_id, bus_ab_quota, bus_ib_quota); break; - case RT_RSC_CLIENT: - dpu_cstate = to_dpu_crtc_state(crtc->state); - dpu_rsc_client_vote(dpu_cstate->rsc_client, - bus_id, bus_ab_quota, bus_ib_quota); - DPU_DEBUG("client:%s bus_id=%d ab=%llu ib=%llu\n", "rt_rsc", - bus_id, bus_ab_quota, bus_ib_quota); - break; - default: DPU_ERROR("invalid client type:%d\n", curr_client_type); break; } - - if (kms->perf.bw_vote_mode_updated) { - switch (kms->perf.bw_vote_mode) { - case DISP_RSC_MODE: - dpu_power_data_bus_set_quota(&priv->phandle, - kms->core_client, - DPU_POWER_HANDLE_DATA_BUS_CLIENT_NRT, - bus_id, 0, 0); - dpu_power_data_bus_set_quota(&priv->phandle, - kms->core_client, - DPU_POWER_HANDLE_DATA_BUS_CLIENT_RT, - bus_id, 0, 0); - kms->perf.bw_vote_mode_updated = false; - break; - - case APPS_RSC_MODE: - dpu_cstate = to_dpu_crtc_state(crtc->state); - if (dpu_cstate->rsc_client) { - dpu_rsc_client_vote(dpu_cstate->rsc_client, - bus_id, 0, 0); - kms->perf.bw_vote_mode_updated = false; - } - break; - - default: - break; - } - } } /** @@ -419,9 +338,8 @@ void dpu_core_perf_crtc_release_bw(struct drm_crtc *crtc) dpu_crtc = to_dpu_crtc(crtc); dpu_cstate = to_dpu_crtc_state(crtc->state); - /* only do this for command mode rt client (non-rsc client) */ - if ((dpu_crtc_get_intf_mode(crtc) != INTF_MODE_CMD) && - (dpu_crtc_get_client_type(crtc) != RT_RSC_CLIENT)) + /* only do this for command mode rt client */ + if (dpu_crtc_get_intf_mode(crtc) != INTF_MODE_CMD) return; /* @@ -494,10 +412,6 @@ void dpu_core_perf_crtc_update(struct drm_crtc *crtc, } priv = kms->dev->dev_private; - /* wake vote update is not required with display rsc */ - if (kms->perf.bw_vote_mode == DISP_RSC_MODE && stop_req) - return; - dpu_crtc = to_dpu_crtc(crtc); dpu_cstate = to_dpu_crtc_state(crtc->state); @@ -533,28 +447,6 @@ void dpu_core_perf_crtc_update(struct drm_crtc *crtc, new->max_per_pipe_ib[i]; update_bus |= BIT(i); } - - /* display rsc override during solver mode */ - if (kms->perf.bw_vote_mode == DISP_RSC_MODE && - get_dpu_rsc_current_state(DPU_RSC_INDEX) == - DPU_RSC_CMD_STATE) { - /* update new bandwidth in all cases */ - if (params_changed && ((new->bw_ctl[i] != - old->bw_ctl[i]) || - (new->max_per_pipe_ib[i] != - old->max_per_pipe_ib[i]))) { - old->bw_ctl[i] = new->bw_ctl[i]; - old->max_per_pipe_ib[i] = - new->max_per_pipe_ib[i]; - update_bus |= BIT(i); - /* - * reduce bw vote is not required in solver - * mode - */ - } else if (!params_changed) { - update_bus &= ~BIT(i); - } - } } if ((params_changed && @@ -733,10 +625,6 @@ int dpu_core_perf_debugfs_init(struct dpu_core_perf *perf, (u32 *)&catalog->perf.min_dram_ib); debugfs_create_file("perf_mode", 0600, perf->debugfs_root, (u32 *)perf, &dpu_core_perf_mode_fops); - debugfs_create_u32("bw_vote_mode", 0600, perf->debugfs_root, - &perf->bw_vote_mode); - debugfs_create_bool("bw_vote_mode_updated", 0600, perf->debugfs_root, - &perf->bw_vote_mode_updated); debugfs_create_u64("fix_core_clk_rate", 0600, perf->debugfs_root, &perf->fix_core_clk_rate); debugfs_create_u64("fix_core_ib_vote", 0600, perf->debugfs_root, @@ -791,12 +679,6 @@ int dpu_core_perf_init(struct dpu_core_perf *perf, perf->phandle = phandle; perf->pclient = pclient; perf->clk_name = clk_name; - perf->dpu_rsc_available = is_dpu_rsc_available(DPU_RSC_INDEX); - /* set default mode */ - if (perf->dpu_rsc_available) - perf->bw_vote_mode = DISP_RSC_MODE; - else - perf->bw_vote_mode = APPS_RSC_MODE; perf->core_clk = dpu_power_clk_get_clk(phandle, clk_name); if (!perf->core_clk) { diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.h index 09c01da..1965ff5 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.h @@ -63,9 +63,6 @@ struct dpu_core_perf_tune { * @fix_core_clk_rate: fixed core clock request in Hz used in mode 2 * @fix_core_ib_vote: fixed core ib vote in bps used in mode 2 * @fix_core_ab_vote: fixed core ab vote in bps used in mode 2 - * @bw_vote_mode: apps rsc vs display rsc bandwidth vote mode - * @dpu_rsc_available: is display rsc available - * @bw_vote_mode_updated: bandwidth vote mode update */ struct dpu_core_perf { struct drm_device *dev; @@ -82,9 +79,6 @@ struct dpu_core_perf { u64 fix_core_clk_rate; u64 fix_core_ib_vote; u64 fix_core_ab_vote; - u32 bw_vote_mode; - bool dpu_rsc_available; - bool bw_vote_mode_updated; }; /** diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c index 3308929..001ddae 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c @@ -2048,7 +2048,6 @@ static void dpu_crtc_atomic_begin(struct drm_crtc *crtc, static void dpu_crtc_atomic_flush(struct drm_crtc *crtc, struct drm_crtc_state *old_crtc_state) { - struct drm_encoder *encoder; struct dpu_crtc *dpu_crtc; struct drm_device *dev; struct drm_plane *plane; @@ -2109,17 +2108,6 @@ static void dpu_crtc_atomic_flush(struct drm_crtc *crtc, drm_atomic_crtc_for_each_plane(plane, crtc) dpu_plane_restore(plane); - if (!cstate->rsc_update) { - drm_for_each_encoder(encoder, dev) { - if (encoder->crtc != crtc) - continue; - - cstate->rsc_client = - dpu_encoder_get_rsc_client(encoder); - } - cstate->rsc_update = true; - } - /* update performance setting before crtc kickoff */ dpu_core_perf_crtc_update(crtc, 1, false); @@ -2661,8 +2649,6 @@ static void dpu_crtc_disable(struct drm_crtc *crtc) if (encoder->crtc != crtc) continue; dpu_encoder_register_frame_event_callback(encoder, NULL, NULL); - cstate->rsc_client = NULL; - cstate->rsc_update = false; } if (dpu_crtc->power_event) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.h index df0dce3..8756b2b 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.h @@ -38,12 +38,10 @@ * voting through apps rsc * @NRT_CLIENT: Non-RealTime client like WB display * voting through apps rsc - * @RT_RSC_CLIENT: Realtime display RSC voting client */ enum dpu_crtc_client_type { RT_CLIENT, NRT_CLIENT, - RT_RSC_CLIENT, }; /** @@ -310,7 +308,6 @@ struct dpu_crtc_respool { * @base: Base drm crtc state structure * @connectors : Currently associated drm connectors * @num_connectors: Number of associated drm connectors - * @rsc_client : dpu rsc client when mode is valid * @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 @@ -332,8 +329,6 @@ struct dpu_crtc_state { struct drm_connector *connectors[MAX_CONNECTORS]; int num_connectors; - struct dpu_rsc_client *rsc_client; - bool rsc_update; bool bw_control; bool bw_split_vote; @@ -471,7 +466,7 @@ int dpu_crtc_register_custom_event(struct dpu_kms *kms, enum dpu_intf_mode dpu_crtc_get_intf_mode(struct drm_crtc *crtc); /** - * dpu_crtc_get_client_type - check the crtc type- rt, nrt, rsc, etc. + * dpu_crtc_get_client_type - check the crtc type- rt, nrt etc. * @crtc: Pointer to crtc */ static inline enum dpu_crtc_client_type dpu_crtc_get_client_type( @@ -484,7 +479,7 @@ static inline enum dpu_crtc_client_type dpu_crtc_get_client_type( return NRT_CLIENT; return dpu_crtc_get_intf_mode(crtc) == INTF_MODE_WB_LINE ? NRT_CLIENT : - (cstate->rsc_client ? RT_RSC_CLIENT : RT_CLIENT); + RT_CLIENT; } /** diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c index 7f41822..4f46a06 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c @@ -20,7 +20,6 @@ #include #include #include -#include #include "msm_drv.h" #include "dpu_kms.h" @@ -72,17 +71,13 @@ #define IDLE_SHORT_TIMEOUT 1 -/* Maximum number of VSYNC wait attempts for RSC state transition */ -#define MAX_RSC_WAIT 5 - /** * enum dpu_enc_rc_events - events for resource control state machine * @DPU_ENC_RC_EVENT_KICKOFF: * This event happens at NORMAL priority. * Event that signals the start of the transfer. When this event is - * received, enable MDP/DSI core clocks and request RSC with CMD state. - * Regardless of the previous state, the resource should be in ON state - * at the end of this event. + * received, enable MDP/DSI core clocks. Regardless of the previous + * state, the resource should be in ON state at the end of this event. * @DPU_ENC_RC_EVENT_FRAME_DONE: * This event happens at INTERRUPT level. * Event signals the end of the data transfer after the PP FRAME_DONE @@ -90,9 +85,9 @@ * IDLE_PC state after IDLE_TIMEOUT time. * @DPU_ENC_RC_EVENT_PRE_STOP: * This event happens at NORMAL priority. - * This event, when received during the ON state, set RSC to IDLE, and - * and leave the RC STATE in the PRE_OFF state. - * It should be followed by the STOP event as part of encoder disable. + * This event, when received during the ON state, leave the RC STATE + * in the PRE_OFF state. It should be followed by the STOP event as + * part of encoder disable. * If received during IDLE or OFF states, it will do nothing. * @DPU_ENC_RC_EVENT_STOP: * This event happens at NORMAL priority. @@ -109,13 +104,12 @@ * @DPU_ENC_RC_EVENT_POST_MODESET: * This event happens at NORMAL priority from a work item. * Event signals that seamless mode switch is complete and resources are - * acquired. Clients wants to turn on the irq again and update the rsc - * with new vtotal. + * acquired. Clients wants to turn on the irq again. * @DPU_ENC_RC_EVENT_ENTER_IDLE: * This event happens at NORMAL priority from a work item. * Event signals that there were no frame updates for IDLE_TIMEOUT time. - * This would disable MDP/DSI core clocks and request RSC with IDLE state - * and change the resource state to IDLE. + * This would disable MDP/DSI core clocks and change the resource state + * to IDLE. */ enum dpu_enc_rc_events { DPU_ENC_RC_EVENT_KICKOFF = 1, @@ -179,8 +173,6 @@ enum dpu_enc_rc_states { * @frame_done_timeout: frame done timeout in Hz * @frame_done_timer: watchdog timer for frame done event * @vsync_event_timer: vsync timer - * @rsc_client: rsc client pointer - * @rsc_state_init: boolean to indicate rsc config init * @disp_info: local copy of msm_display_info struct * @mode_info: local copy of msm_mode_info struct * @misr_enable: misr enable/disable status @@ -194,7 +186,6 @@ enum dpu_enc_rc_states { * @vsync_event_work: worker to handle vsync event for autorefresh * @topology: topology of the display * @mode_set_complete: flag to indicate modeset completion - * @rsc_config: rsc configuration for display vtotal, fps, etc. * @idle_timeout: idle timeout duration in milliseconds */ struct dpu_encoder_virt { @@ -225,8 +216,6 @@ struct dpu_encoder_virt { struct timer_list frame_done_timer; struct timer_list vsync_event_timer; - struct dpu_rsc_client *rsc_client; - bool rsc_state_init; struct msm_display_info disp_info; struct msm_mode_info mode_info; bool misr_enable; @@ -240,8 +229,6 @@ struct dpu_encoder_virt { struct msm_display_topology topology; bool mode_set_complete; - struct dpu_rsc_cmd_config rsc_config; - u32 idle_timeout; }; @@ -570,7 +557,6 @@ void dpu_encoder_destroy(struct drm_encoder *drm_enc) DPU_DEBUG_ENC(dpu_enc, "\n"); mutex_lock(&dpu_enc->enc_lock); - dpu_rsc_client_destroy(dpu_enc->rsc_client); for (i = 0; i < dpu_enc->num_phys_encs; i++) { struct dpu_encoder_phys *phys = dpu_enc->phys_encs[i]; @@ -1066,7 +1052,7 @@ static int _dpu_encoder_dsc_setup(struct dpu_encoder_virt *dpu_enc) } static void _dpu_encoder_update_vsync_source(struct dpu_encoder_virt *dpu_enc, - struct msm_display_info *disp_info, bool is_dummy) + struct msm_display_info *disp_info) { struct dpu_vsync_source_cfg vsync_cfg = { 0 }; struct msm_drm_private *priv; @@ -1116,13 +1102,10 @@ static void _dpu_encoder_update_vsync_source(struct dpu_encoder_virt *dpu_enc, vsync_cfg.pp_count = dpu_enc->num_phys_encs; vsync_cfg.frame_rate = mode_info->frame_rate; - if (is_dummy) - vsync_cfg.vsync_source = DPU_VSYNC_SOURCE_WD_TIMER_1; - else if (disp_info->is_te_using_watchdog_timer) + if (disp_info->is_te_using_watchdog_timer) vsync_cfg.vsync_source = DPU_VSYNC_SOURCE_WD_TIMER_0; else vsync_cfg.vsync_source = DPU_VSYNC0_SOURCE_GPIO; - vsync_cfg.is_dummy = is_dummy; hw_mdptop->ops.setup_vsync_source(hw_mdptop, &vsync_cfg); } @@ -1224,136 +1207,6 @@ static int _dpu_encoder_dsc_disable(struct dpu_encoder_virt *dpu_enc) return ret; } -static int _dpu_encoder_update_rsc_client( - struct drm_encoder *drm_enc, bool enable) -{ - struct dpu_encoder_virt *dpu_enc; - struct drm_crtc *crtc; - enum dpu_rsc_state rsc_state; - struct dpu_rsc_cmd_config *rsc_config; - int ret, prefill_lines; - struct msm_display_info *disp_info; - struct msm_mode_info *mode_info; - int wait_vblank_crtc_id = DPU_RSC_INVALID_CRTC_ID; - int wait_count = 0; - struct drm_crtc *primary_crtc; - int pipe = -1; - - if (!drm_enc || !drm_enc->crtc || !drm_enc->dev) { - DPU_ERROR("invalid arguments\n"); - return -EINVAL; - } - - dpu_enc = to_dpu_encoder_virt(drm_enc); - crtc = drm_enc->crtc; - disp_info = &dpu_enc->disp_info; - mode_info = &dpu_enc->mode_info; - rsc_config = &dpu_enc->rsc_config; - - if (!dpu_enc->rsc_client) { - DPU_DEBUG_ENC(dpu_enc, "rsc client not created\n"); - return 0; - } - - /** - * only primary command mode panel can request CMD state. - * all other panels/displays can request for VID state including - * secondary command mode panel. - */ - rsc_state = enable ? - (((disp_info->capabilities & MSM_DISPLAY_CAP_CMD_MODE) && - disp_info->is_primary) ? DPU_RSC_CMD_STATE : - DPU_RSC_VID_STATE) : DPU_RSC_IDLE_STATE; - - /* compare specific items and reconfigure the rsc */ - if ((rsc_config->fps != mode_info->frame_rate) || - (rsc_config->vtotal != mode_info->vtotal) || - (rsc_config->prefill_lines != mode_info->prefill_lines) || - (rsc_config->jitter_numer != mode_info->jitter_numer) || - (rsc_config->jitter_denom != mode_info->jitter_denom)) { - rsc_config->fps = mode_info->frame_rate; - rsc_config->vtotal = mode_info->vtotal; - rsc_config->prefill_lines = prefill_lines; - rsc_config->jitter_numer = mode_info->jitter_numer; - rsc_config->jitter_denom = mode_info->jitter_denom; - dpu_enc->rsc_state_init = false; - } - - if (rsc_state != DPU_RSC_IDLE_STATE && !dpu_enc->rsc_state_init - && disp_info->is_primary) { - /* update it only once */ - dpu_enc->rsc_state_init = true; - - ret = dpu_rsc_client_state_update(dpu_enc->rsc_client, - rsc_state, rsc_config, crtc->base.id, - &wait_vblank_crtc_id); - } else { - ret = dpu_rsc_client_state_update(dpu_enc->rsc_client, - rsc_state, NULL, crtc->base.id, - &wait_vblank_crtc_id); - } - - /** - * if RSC performed a state change that requires a VBLANK wait, it will - * set wait_vblank_crtc_id to the CRTC whose VBLANK we must wait on. - * - * if we are the primary display, we will need to enable and wait - * locally since we hold the commit thread - * - * if we are an external display, we must send a signal to the primary - * to enable its VBLANK and wait one, since the RSC hardware is driven - * by the primary panel's VBLANK signals - */ - DPU_EVT32_VERBOSE(DRMID(drm_enc), wait_vblank_crtc_id); - if (ret) { - DPU_ERROR_ENC(dpu_enc, - "dpu rsc client update failed ret:%d\n", ret); - return ret; - } else if (wait_vblank_crtc_id == DPU_RSC_INVALID_CRTC_ID) { - return ret; - } - - if (crtc->base.id != 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", - wait_vblank_crtc_id); - return -EINVAL; - } - pipe = drm_crtc_index(primary_crtc); - } - - /** - * note: VBLANK is expected to be enabled at this point in - * resource control state machine if on primary CRTC - */ - for (wait_count = 0; wait_count < MAX_RSC_WAIT; wait_count++) { - if (dpu_rsc_client_is_state_update_complete( - dpu_enc->rsc_client)) - break; - - if (crtc->base.id == wait_vblank_crtc_id) - ret = dpu_encoder_wait_for_event(drm_enc, - MSM_ENC_VBLANK); - else - drm_wait_one_vblank(drm_enc->dev, pipe); - - if (ret) { - DPU_ERROR_ENC(dpu_enc, - "wait for vblank failed ret:%d\n", ret); - break; - } - } - - if (wait_count >= MAX_RSC_WAIT) - DPU_EVT32(DRMID(drm_enc), wait_vblank_crtc_id, wait_count, - DPU_EVTLOG_ERROR); - - return ret; -} - static void _dpu_encoder_irq_control(struct drm_encoder *drm_enc, bool enable) { struct dpu_encoder_virt *dpu_enc; @@ -1376,45 +1229,6 @@ static void _dpu_encoder_irq_control(struct drm_encoder *drm_enc, bool enable) } -struct dpu_rsc_client *dpu_encoder_get_rsc_client(struct drm_encoder *drm_enc) -{ - struct dpu_encoder_virt *dpu_enc; - - if (!drm_enc) - return NULL; - dpu_enc = to_dpu_encoder_virt(drm_enc); - return dpu_enc->rsc_client; -} - -static void _dpu_encoder_resource_control_rsc_update( - struct drm_encoder *drm_enc, bool enable) -{ - struct dpu_encoder_virt *dpu_enc = to_dpu_encoder_virt(drm_enc); - int i; - - if (enable) { - _dpu_encoder_update_rsc_client(drm_enc, true); - } else { - _dpu_encoder_update_rsc_client(drm_enc, false); - - /** - * disable the vsync source after updating the rsc state. rsc - * state update might have vsync wait and vsync source must be - * disabled after it. It will avoid generating any vsync from - * this point till mode-2 entry. It is SW workaround for - * HW limitation and should not be removed without checking the - * updated design. - */ - for (i = 0; i < dpu_enc->num_phys_encs; i++) { - struct dpu_encoder_phys *phys = dpu_enc->phys_encs[i]; - - if (phys && phys->ops.prepare_idle_pc) - phys->ops.prepare_idle_pc(phys); - } - - } -} - static void _dpu_encoder_resource_control_helper(struct drm_encoder *drm_enc, bool enable) { @@ -1533,13 +1347,10 @@ static int dpu_encoder_resource_control(struct drm_encoder *drm_enc, return -EINVAL; } - if (is_vid_mode && dpu_enc->rc_state == DPU_ENC_RC_STATE_IDLE) { + if (is_vid_mode && dpu_enc->rc_state == DPU_ENC_RC_STATE_IDLE) _dpu_encoder_irq_control(drm_enc, true); - } else { - /* enable all the clks and resources */ + else _dpu_encoder_resource_control_helper(drm_enc, true); - _dpu_encoder_resource_control_rsc_update(drm_enc, true); - } DPU_EVT32(DRMID(drm_enc), sw_event, dpu_enc->rc_state, DPU_ENC_RC_STATE_ON, DPU_EVTLOG_FUNC_CASE1); @@ -1629,12 +1440,6 @@ static int dpu_encoder_resource_control(struct drm_encoder *drm_enc, return 0; } - /** - * IRQs are still enabled currently, which allows wait for - * VBLANK which RSC may require to correctly transition to OFF - */ - _dpu_encoder_resource_control_rsc_update(drm_enc, false); - DPU_EVT32(DRMID(drm_enc), sw_event, dpu_enc->rc_state, DPU_ENC_RC_STATE_PRE_OFF, DPU_EVTLOG_FUNC_CASE3); @@ -1694,8 +1499,6 @@ static int dpu_encoder_resource_control(struct drm_encoder *drm_enc, /* enable all the clks and resources */ _dpu_encoder_resource_control_helper(drm_enc, true); - _dpu_encoder_resource_control_rsc_update(drm_enc, true); - DPU_EVT32(DRMID(drm_enc), sw_event, dpu_enc->rc_state, DPU_ENC_RC_STATE_ON, DPU_EVTLOG_FUNC_CASE5); dpu_enc->rc_state = DPU_ENC_RC_STATE_ON; @@ -1737,8 +1540,6 @@ static int dpu_encoder_resource_control(struct drm_encoder *drm_enc, _dpu_encoder_irq_control(drm_enc, true); - _dpu_encoder_update_rsc_client(drm_enc, true); - DPU_EVT32(DRMID(drm_enc), sw_event, dpu_enc->rc_state, DPU_ENC_RC_STATE_ON, DPU_EVTLOG_FUNC_CASE6); @@ -1773,14 +1574,10 @@ static int dpu_encoder_resource_control(struct drm_encoder *drm_enc, return 0; } - if (is_vid_mode) { + if (is_vid_mode) _dpu_encoder_irq_control(drm_enc, false); - } else { - /* disable all the clks and resources */ - _dpu_encoder_resource_control_rsc_update(drm_enc, - false); + else _dpu_encoder_resource_control_helper(drm_enc, false); - } DPU_EVT32(DRMID(drm_enc), sw_event, dpu_enc->rc_state, DPU_ENC_RC_STATE_IDLE, DPU_EVTLOG_FUNC_CASE7); @@ -1954,7 +1751,7 @@ static void _dpu_encoder_virt_enable_helper(struct drm_encoder *drm_enc) dpu_enc->cur_master->hw_mdptop, dpu_kms->catalog); - _dpu_encoder_update_vsync_source(dpu_enc, &dpu_enc->disp_info, false); + _dpu_encoder_update_vsync_source(dpu_enc, &dpu_enc->disp_info); } void dpu_encoder_virt_restore(struct drm_encoder *drm_enc) @@ -3589,7 +3386,6 @@ struct drm_encoder *dpu_encoder_init( struct drm_encoder *drm_enc = NULL; struct dpu_encoder_virt *dpu_enc = NULL; int drm_enc_mode = DRM_MODE_ENCODER_NONE; - char name[DPU_NAME_SIZE]; int ret = 0; dpu_enc = kzalloc(sizeof(*dpu_enc), GFP_KERNEL); @@ -3620,14 +3416,6 @@ struct drm_encoder *dpu_encoder_init( dpu_encoder_vsync_event_handler, 0); - snprintf(name, DPU_NAME_SIZE, "rsc_enc%u", drm_enc->base.id); - dpu_enc->rsc_client = dpu_rsc_client_create(DPU_RSC_INDEX, name, - disp_info->is_primary); - if (IS_ERR_OR_NULL(dpu_enc->rsc_client)) { - DPU_DEBUG("dpu rsc client create failed :%ld\n", - PTR_ERR(dpu_enc->rsc_client)); - dpu_enc->rsc_client = NULL; - } mutex_init(&dpu_enc->rc_lock); kthread_init_delayed_work(&dpu_enc->delayed_off_work, diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h index 4c5560b..e85e5a4 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h @@ -88,13 +88,6 @@ void dpu_encoder_register_frame_event_callback(struct drm_encoder *encoder, void (*cb)(void *, u32), void *data); /** - * dpu_encoder_get_rsc_client - gets the rsc client state for primary - * for primary display. - * @encoder: encoder pointer - */ -struct dpu_rsc_client *dpu_encoder_get_rsc_client(struct drm_encoder *encoder); - -/** * dpu_encoder_prepare_for_kickoff - schedule double buffer flip of the ctl * path (i.e. ctl flush and start) at next appropriate time. * Immediately: if no previous commit is outstanding. diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h index e9484fe..9bbf339b 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h @@ -16,7 +16,6 @@ #define __DPU_ENCODER_PHYS_H__ #include -#include #include "dpu_kms.h" #include "dpu_hw_intf.h" diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_top.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_top.c index 0caadcee..68163a1 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_top.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_top.c @@ -270,18 +270,14 @@ static void dpu_hw_setup_vsync_source(struct dpu_hw_mdp *mdp, break; } - if (cfg->is_dummy) { - DPU_REG_WRITE(c, wd_ctl2, 0x0); - } else { - DPU_REG_WRITE(c, wd_load_value, - CALCULATE_WD_LOAD_VALUE(cfg->frame_rate)); - - DPU_REG_WRITE(c, wd_ctl, BIT(0)); /* clear timer */ - reg = DPU_REG_READ(c, wd_ctl2); - reg |= BIT(8); /* enable heartbeat timer */ - reg |= BIT(0); /* enable WD timer */ - DPU_REG_WRITE(c, wd_ctl2, reg); - } + DPU_REG_WRITE(c, wd_load_value, + CALCULATE_WD_LOAD_VALUE(cfg->frame_rate)); + + DPU_REG_WRITE(c, wd_ctl, BIT(0)); /* clear timer */ + reg = DPU_REG_READ(c, wd_ctl2); + reg |= BIT(8); /* enable heartbeat timer */ + reg |= BIT(0); /* enable WD timer */ + DPU_REG_WRITE(c, wd_ctl2, reg); /* make sure that timers are enabled/disabled for vsync state */ wmb(); diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_top.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_top.h index 18e76a1..375cb7c 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_top.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_top.h @@ -84,15 +84,12 @@ struct dpu_danger_safe_status { * @frame_rate: Display frame rate * @ppnumber: ping pong index array * @vsync_source: vsync source selection - * @is_dummy: a dummy source of vsync selection. It must not be selected for - * any case other than dpu rsc idle request. */ struct dpu_vsync_source_cfg { u32 pp_count; u32 frame_rate; u32 ppnumber[PINGPONG_MAX]; u32 vsync_source; - bool is_dummy; }; /** diff --git a/drivers/gpu/drm/msm/dpu_dbg.c b/drivers/gpu/drm/msm/dpu_dbg.c index 8118fb7..341b596 100644 --- a/drivers/gpu/drm/msm/dpu_dbg.c +++ b/drivers/gpu/drm/msm/dpu_dbg.c @@ -67,7 +67,6 @@ /* print debug ranges in groups of 4 u32s */ #define REG_DUMP_ALIGN 16 -#define RSC_DEBUG_MUX_SEL_SDM845 9 /** * struct dpu_dbg_reg_offset - tracking for start and end of region * @start: start offset @@ -238,29 +237,6 @@ static void _dpu_debug_bus_ppb1_dump(void __iomem *mem_base, entry->wr_addr, entry->block_id, entry->test_id, val); } -static void _dpu_debug_bus_axi_dump_sdm845(void __iomem *mem_base, - struct dpu_debug_bus_entry *entry, u32 val) -{ - u32 status, i; - - if (!mem_base || !entry) - return; - - for (i = 0; i <= RSC_DEBUG_MUX_SEL_SDM845; i++) { - //dpu_rsc_debug_dump(i); - - /* make sure that mux_sel updated */ - wmb(); - - /* read status again after rsc routes the debug bus */ - status = readl_relaxed(mem_base + DBGBUS_DSPP_STATUS); - - dev_err(dpu_dbg_base.dev, "rsc mux_sel:%d 0x%x %d %d 0x%x\n", - i, entry->wr_addr, entry->block_id, - entry->test_id, status); - } -} - static struct dpu_debug_bus_entry dbg_bus_dpu_8998[] = { /* Unpack 0 sspp 0*/ @@ -2014,9 +1990,6 @@ static void _dpu_debug_bus_axi_dump_sdm845(void __iomem *mem_base, { DBGBUS_PERIPH, 71, 3}, { DBGBUS_PERIPH, 71, 4}, { DBGBUS_PERIPH, 71, 5}, - - /* axi - should be last entry */ - { DBGBUS_AXI_INTF, 62, 0, _dpu_debug_bus_axi_dump_sdm845}, }; static struct vbif_debug_bus_entry vbif_dbg_bus_msm8998[] = { diff --git a/drivers/gpu/drm/msm/dpu_dbg.h b/drivers/gpu/drm/msm/dpu_dbg.h index 9e3b0eb..710e918 100644 --- a/drivers/gpu/drm/msm/dpu_dbg.h +++ b/drivers/gpu/drm/msm/dpu_dbg.h @@ -316,12 +316,6 @@ int dpu_evtlog_get_filter(struct dpu_dbg_evtlog *evtlog, int index, char *buf, size_t bufsz); /** - * dpu_rsc_debug_dump - dpu rsc debug dump status - * @mux_sel: select mux on rsc debug bus - */ -void dpu_rsc_debug_dump(u32 mux_sel); - -/** * dsi_ctrl_debug_dump - dump dsi debug dump status */ static inline void dsi_ctrl_debug_dump(void) {} @@ -407,10 +401,6 @@ static inline int dpu_evtlog_get_filter(struct dpu_dbg_evtlog *evtlog, return -EINVAL; } -static inline void dpu_rsc_debug_dump(u32 mux_sel) -{ -} - static inline void dsi_ctrl_debug_dump(void) { } diff --git a/drivers/gpu/drm/msm/dpu_power_handle.c b/drivers/gpu/drm/msm/dpu_power_handle.c index a52be86..4e0f371 100644 --- a/drivers/gpu/drm/msm/dpu_power_handle.c +++ b/drivers/gpu/drm/msm/dpu_power_handle.c @@ -27,7 +27,6 @@ #include #endif #include -#include #include "dpu_power_handle.h" #include "dpu_trace.h" @@ -57,32 +56,6 @@ static void dpu_power_event_trigger_locked(struct dpu_power_handle *phandle, } } -static int dpu_power_rsc_update(struct dpu_power_handle *phandle, bool enable) -{ - u32 rsc_state; - int ret = 0; - - /* creates the rsc client on the first enable */ - if (!phandle->rsc_client_init) { - phandle->rsc_client = dpu_rsc_client_create(DPU_RSC_INDEX, - "dpu_power_handle", false); - if (IS_ERR_OR_NULL(phandle->rsc_client)) { - pr_debug("dpu rsc client create failed :%ld\n", - PTR_ERR(phandle->rsc_client)); - phandle->rsc_client = NULL; - } - phandle->rsc_client_init = true; - } - - rsc_state = enable ? DPU_RSC_CLK_STATE : DPU_RSC_IDLE_STATE; - - if (phandle->rsc_client) - ret = dpu_rsc_client_state_update(phandle->rsc_client, - rsc_state, NULL, DPU_RSC_INVALID_CRTC_ID, NULL); - - return ret; -} - struct dpu_power_client *dpu_power_client_create( struct dpu_power_handle *phandle, char *client_name) { @@ -761,9 +734,6 @@ int dpu_power_resource_init(struct platform_device *pdev, INIT_LIST_HEAD(&phandle->power_client_clist); INIT_LIST_HEAD(&phandle->event_list); - phandle->rsc_client = NULL; - phandle->rsc_client_init = false; - mutex_init(&phandle->phandle_lock); return rc; @@ -840,8 +810,6 @@ void dpu_power_resource_deinit(struct platform_device *pdev, mp->num_vreg = 0; mp->num_clk = 0; - if (phandle->rsc_client) - dpu_rsc_client_destroy(phandle->rsc_client); } int dpu_power_resource_enable(struct dpu_power_handle *phandle, @@ -906,21 +874,12 @@ int dpu_power_resource_enable(struct dpu_power_handle *phandle, goto data_bus_hdl_err; } } - /* - * - When the target is RSCC enabled, regulator should - * be enabled by the s/w only for the first time during - * bootup. After that, RSCC hardware takes care of enabling/ - * disabling it. - * - When the target is not RSCC enabled, regulator should - * be totally handled by the software. - */ - if (!phandle->rsc_client) { - rc = msm_dss_enable_vreg(mp->vreg_config, mp->num_vreg, - enable); - if (rc) { - pr_err("failed to enable vregs rc=%d\n", rc); - goto vreg_err; - } + + rc = msm_dss_enable_vreg(mp->vreg_config, mp->num_vreg, + enable); + if (rc) { + pr_err("failed to enable vregs rc=%d\n", rc); + goto vreg_err; } rc = dpu_power_reg_bus_update(phandle->reg_bus_hdl, @@ -930,12 +889,6 @@ int dpu_power_resource_enable(struct dpu_power_handle *phandle, goto reg_bus_hdl_err; } - rc = dpu_power_rsc_update(phandle, true); - if (rc) { - pr_err("failed to update rsc\n"); - goto rsc_err; - } - rc = msm_dss_enable_clk(mp->clk_config, mp->num_clk, enable); if (rc) { pr_err("clock enable failed rc:%d\n", rc); @@ -951,14 +904,11 @@ int dpu_power_resource_enable(struct dpu_power_handle *phandle, msm_dss_enable_clk(mp->clk_config, mp->num_clk, enable); - dpu_power_rsc_update(phandle, false); - dpu_power_reg_bus_update(phandle->reg_bus_hdl, max_usecase_ndx); - if (!phandle->rsc_client) - msm_dss_enable_vreg(mp->vreg_config, mp->num_vreg, - enable); + msm_dss_enable_vreg(mp->vreg_config, mp->num_vreg, + enable); for (i = 0 ; i < DPU_POWER_HANDLE_DBUS_ID_MAX; i++) dpu_power_data_bus_update(&phandle->data_bus_handle[i], enable); @@ -967,13 +917,12 @@ int dpu_power_resource_enable(struct dpu_power_handle *phandle, DPU_POWER_EVENT_POST_DISABLE); } + goto end; + clk_err: - dpu_power_rsc_update(phandle, false); -rsc_err: dpu_power_reg_bus_update(phandle->reg_bus_hdl, prev_usecase_ndx); reg_bus_hdl_err: - if (!phandle->rsc_client) - msm_dss_enable_vreg(mp->vreg_config, mp->num_vreg, 0); + msm_dss_enable_vreg(mp->vreg_config, mp->num_vreg, 0); vreg_err: for (i = 0 ; i < DPU_POWER_HANDLE_DBUS_ID_MAX; i++) dpu_power_data_bus_update(&phandle->data_bus_handle[i], 0); diff --git a/drivers/gpu/drm/msm/dpu_power_handle.h b/drivers/gpu/drm/msm/dpu_power_handle.h index 25a00b1..1edae5c 100644 --- a/drivers/gpu/drm/msm/dpu_power_handle.h +++ b/drivers/gpu/drm/msm/dpu_power_handle.h @@ -155,8 +155,6 @@ struct dpu_power_event { * @reg_bus_hdl: current register bus handle * @data_bus_handle: context structure for data bus control * @event_list: current power handle event list - * @rsc_client: dpu rsc client pointer - * @rsc_client_init: boolean to control rsc client create */ struct dpu_power_handle { struct dss_module_power mp; @@ -168,8 +166,6 @@ struct dpu_power_handle { struct dpu_power_data_bus_handle data_bus_handle [DPU_POWER_HANDLE_DBUS_ID_MAX]; struct list_head event_list; - struct dpu_rsc_client *rsc_client; - bool rsc_client_init; }; /** diff --git a/drivers/gpu/drm/msm/dpu_rsc.c b/drivers/gpu/drm/msm/dpu_rsc.c deleted file mode 100644 index 67bf79d..0000000 --- a/drivers/gpu/drm/msm/dpu_rsc.c +++ /dev/null @@ -1,1367 +0,0 @@ -/* Copyright (c) 2016-2018, The Linux Foundation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 and - * only version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - */ - -#define pr_fmt(fmt) "[dpu_rsc:%s:%d]: " fmt, __func__, __LINE__ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include "dpu_rsc_priv.h" -#include "dpu_dbg.h" - -#define DPU_RSC_DRV_DBG_NAME "dpu_rsc_drv" -#define DPU_RSC_WRAPPER_DBG_NAME "dpu_rsc_wrapper" - -/* worst case time to execute the one tcs vote(sleep/wake) - ~1ms */ -#define SINGLE_TCS_EXECUTION_TIME 1064000 - -/* this time is ~1ms - only wake tcs in any mode */ -#define RSC_BACKOFF_TIME_NS (SINGLE_TCS_EXECUTION_TIME + 100) - -/* this time is ~1ms - only wake TCS in mode-0 */ -#define RSC_MODE_THRESHOLD_TIME_IN_NS (SINGLE_TCS_EXECUTION_TIME + 100) - -/* this time is ~2ms - sleep+ wake TCS in mode-1 */ -#define RSC_TIME_SLOT_0_NS ((SINGLE_TCS_EXECUTION_TIME * 2) + 100) - -#define DEFAULT_PANEL_FPS 60 -#define DEFAULT_PANEL_JITTER_NUMERATOR 2 -#define DEFAULT_PANEL_JITTER_DENOMINATOR 1 -#define DEFAULT_PANEL_PREFILL_LINES 25 -#define DEFAULT_PANEL_VTOTAL (480 + DEFAULT_PANEL_PREFILL_LINES) -#define TICKS_IN_NANO_SECOND 1000000000 - -#define MAX_BUFFER_SIZE 256 - -#define TRY_CMD_MODE_SWITCH 0xFFFF -#define TRY_CLK_MODE_SWITCH 0xFFFE -#define STATE_UPDATE_NOT_ALLOWED 0xFFFD - -/* Primary panel worst case VSYNC expected to be no less than 30fps */ -#define PRIMARY_VBLANK_WORST_CASE_MS 34 - -static struct dpu_rsc_priv *rsc_prv_list[MAX_RSC_COUNT]; - -/** - * dpu_rsc_client_create() - create the client for dpu rsc. - * Different displays like DSI, HDMI, DP, WB, etc should call this - * api to register their vote for rpmh. They still need to vote for - * power handle to get the clocks. - - * @rsc_index: A client will be created on this RSC. As of now only - * DPU_RSC_INDEX is valid rsc index. - * @name: Caller needs to provide some valid string to identify - * the client. "primary", "dp", "hdmi" are suggested name. - * @is_primary: Caller needs to provide information if client is primary - * or not. Primary client votes will be redirected to - * display rsc. - * - * Return: client node pointer. - */ -struct dpu_rsc_client *dpu_rsc_client_create(u32 rsc_index, char *client_name, - bool is_primary_client) -{ - struct dpu_rsc_client *client; - struct dpu_rsc_priv *rsc; - static int id; - - if (!client_name) { - pr_err("client name is null- not supported\n"); - return ERR_PTR(-EINVAL); - } else if (rsc_index >= MAX_RSC_COUNT) { - pr_err("invalid rsc index\n"); - return ERR_PTR(-EINVAL); - } else if (!rsc_prv_list[rsc_index]) { - pr_err("rsc not probed yet or not available\n"); - return NULL; - } - - rsc = rsc_prv_list[rsc_index]; - client = kzalloc(sizeof(struct dpu_rsc_client), GFP_KERNEL); - if (!client) - return ERR_PTR(-ENOMEM); - - mutex_lock(&rsc->client_lock); - strlcpy(client->name, client_name, MAX_RSC_CLIENT_NAME_LEN); - client->current_state = DPU_RSC_IDLE_STATE; - client->rsc_index = rsc_index; - client->id = id; - if (is_primary_client) - rsc->primary_client = client; - pr_debug("client %s rsc index:%d primary:%d\n", client_name, - rsc_index, is_primary_client); - - list_add(&client->list, &rsc->client_list); - id++; - mutex_unlock(&rsc->client_lock); - - return client; -} -EXPORT_SYMBOL(dpu_rsc_client_create); - -/** - * dpu_rsc_client_destroy() - Destroy the dpu rsc client. - * - * @client: Client pointer provided by dpu_rsc_client_create(). - * - * Return: none - */ -void dpu_rsc_client_destroy(struct dpu_rsc_client *client) -{ - struct dpu_rsc_priv *rsc; - enum dpu_rsc_state state; - - if (!client) { - pr_debug("invalid client\n"); - goto end; - } else if (client->rsc_index >= MAX_RSC_COUNT) { - pr_err("invalid rsc index\n"); - goto end; - } - - pr_debug("client %s destroyed\n", client->name); - rsc = rsc_prv_list[client->rsc_index]; - if (!rsc) - goto end; - - mutex_lock(&rsc->client_lock); - state = client->current_state; - mutex_unlock(&rsc->client_lock); - - if (state != DPU_RSC_IDLE_STATE) { - int wait_vblank_crtc_id; - - dpu_rsc_client_state_update(client, DPU_RSC_IDLE_STATE, NULL, - DPU_RSC_INVALID_CRTC_ID, &wait_vblank_crtc_id); - - /* if vblank wait required at shutdown, use a simple sleep */ - if (wait_vblank_crtc_id != DPU_RSC_INVALID_CRTC_ID) { - pr_err("unexpected sleep required on crtc %d at rsc client destroy\n", - wait_vblank_crtc_id); - DPU_EVT32(client->id, state, rsc->current_state, - client->crtc_id, wait_vblank_crtc_id, - DPU_EVTLOG_ERROR); - msleep(PRIMARY_VBLANK_WORST_CASE_MS); - } - } - mutex_lock(&rsc->client_lock); - list_del_init(&client->list); - mutex_unlock(&rsc->client_lock); - - kfree(client); -end: - return; -} -EXPORT_SYMBOL(dpu_rsc_client_destroy); - -struct dpu_rsc_event *dpu_rsc_register_event(int rsc_index, uint32_t event_type, - void (*cb_func)(uint32_t event_type, void *usr), void *usr) -{ - struct dpu_rsc_event *evt; - struct dpu_rsc_priv *rsc; - - if (rsc_index >= MAX_RSC_COUNT) { - pr_err("invalid rsc index:%d\n", rsc_index); - return ERR_PTR(-EINVAL); - } else if (!rsc_prv_list[rsc_index]) { - pr_err("rsc idx:%d not probed yet or not available\n", - rsc_index); - return ERR_PTR(-EINVAL); - } else if (!cb_func || !event_type) { - pr_err("no event or cb func\n"); - return ERR_PTR(-EINVAL); - } - - rsc = rsc_prv_list[rsc_index]; - evt = kzalloc(sizeof(struct dpu_rsc_event), GFP_KERNEL); - if (!evt) - return ERR_PTR(-ENOMEM); - - evt->event_type = event_type; - evt->rsc_index = rsc_index; - evt->usr = usr; - evt->cb_func = cb_func; - pr_debug("event register type:%d rsc index:%d\n", - event_type, rsc_index); - - mutex_lock(&rsc->client_lock); - list_add(&evt->list, &rsc->event_list); - mutex_unlock(&rsc->client_lock); - - return evt; -} -EXPORT_SYMBOL(dpu_rsc_register_event); - -void dpu_rsc_unregister_event(struct dpu_rsc_event *event) -{ - struct dpu_rsc_priv *rsc; - - if (!event) { - pr_debug("invalid event client\n"); - goto end; - } else if (event->rsc_index >= MAX_RSC_COUNT) { - pr_err("invalid rsc index\n"); - goto end; - } - - pr_debug("event client destroyed\n"); - rsc = rsc_prv_list[event->rsc_index]; - if (!rsc) - goto end; - - mutex_lock(&rsc->client_lock); - list_del_init(&event->list); - mutex_unlock(&rsc->client_lock); - - kfree(event); -end: - return; -} -EXPORT_SYMBOL(dpu_rsc_unregister_event); - -bool is_dpu_rsc_available(int rsc_index) -{ - if (rsc_index >= MAX_RSC_COUNT) { - pr_err("invalid rsc index:%d\n", rsc_index); - return false; - } else if (!rsc_prv_list[rsc_index]) { - pr_err("rsc idx:%d not probed yet or not available\n", - rsc_index); - return false; - } - - return true; -} -EXPORT_SYMBOL(is_dpu_rsc_available); - -enum dpu_rsc_state get_dpu_rsc_current_state(int rsc_index) -{ - struct dpu_rsc_priv *rsc; - - if (rsc_index >= MAX_RSC_COUNT) { - pr_err("invalid rsc index:%d\n", rsc_index); - return DPU_RSC_IDLE_STATE; - } else if (!rsc_prv_list[rsc_index]) { - pr_err("rsc idx:%d not probed yet or not available\n", - rsc_index); - return DPU_RSC_IDLE_STATE; - } - - rsc = rsc_prv_list[rsc_index]; - return rsc->current_state; -} -EXPORT_SYMBOL(get_dpu_rsc_current_state); - -static int dpu_rsc_clk_enable(struct dpu_power_handle *phandle, - struct dpu_power_client *pclient, bool enable) -{ - int rc = 0; - struct dss_module_power *mp; - - if (!phandle || !pclient) { - pr_err("invalid input argument\n"); - return -EINVAL; - } - - mp = &phandle->mp; - - if (enable) - pclient->refcount++; - else if (pclient->refcount) - pclient->refcount--; - - if (pclient->refcount) - pclient->usecase_ndx = VOTE_INDEX_LOW; - else - pclient->usecase_ndx = VOTE_INDEX_DISABLE; - - if (phandle->current_usecase_ndx == pclient->usecase_ndx) - goto end; - - if (enable) { - rc = msm_dss_enable_clk(mp->clk_config, mp->num_clk, enable); - if (rc) { - pr_err("clock enable failed rc:%d\n", rc); - goto end; - } - } else { - msm_dss_enable_clk(mp->clk_config, mp->num_clk, enable); - } - - phandle->current_usecase_ndx = pclient->usecase_ndx; - -end: - return rc; -} - -static u32 dpu_rsc_timer_calculate(struct dpu_rsc_priv *rsc, - struct dpu_rsc_cmd_config *cmd_config) -{ - const u32 cxo_period_ns = 52; - u64 rsc_backoff_time_ns = RSC_BACKOFF_TIME_NS; - u64 rsc_mode_threshold_time_ns = RSC_MODE_THRESHOLD_TIME_IN_NS; - u64 rsc_time_slot_0_ns = RSC_TIME_SLOT_0_NS; - u64 rsc_time_slot_1_ns; - const u64 pdc_jitter = 20; /* 20% more */ - - u64 frame_time_ns, frame_jitter; - u64 line_time_ns, prefill_time_ns; - u64 pdc_backoff_time_ns; - s64 total; - int ret = 0; - - if (cmd_config) - memcpy(&rsc->cmd_config, cmd_config, sizeof(*cmd_config)); - - /* calculate for 640x480 60 fps resolution by default */ - if (!rsc->cmd_config.fps) - rsc->cmd_config.fps = DEFAULT_PANEL_FPS; - if (!rsc->cmd_config.jitter_numer) - rsc->cmd_config.jitter_numer = DEFAULT_PANEL_JITTER_NUMERATOR; - if (!rsc->cmd_config.jitter_denom) - rsc->cmd_config.jitter_denom = DEFAULT_PANEL_JITTER_DENOMINATOR; - if (!rsc->cmd_config.vtotal) - rsc->cmd_config.vtotal = DEFAULT_PANEL_VTOTAL; - if (!rsc->cmd_config.prefill_lines) - rsc->cmd_config.prefill_lines = DEFAULT_PANEL_PREFILL_LINES; - pr_debug("frame fps:%d jitter_numer:%d jitter_denom:%d vtotal:%d prefill lines:%d\n", - rsc->cmd_config.fps, rsc->cmd_config.jitter_numer, - rsc->cmd_config.jitter_denom, rsc->cmd_config.vtotal, - rsc->cmd_config.prefill_lines); - - /* 1 nano second */ - frame_time_ns = TICKS_IN_NANO_SECOND; - frame_time_ns = div_u64(frame_time_ns, rsc->cmd_config.fps); - - frame_jitter = frame_time_ns * rsc->cmd_config.jitter_numer; - frame_jitter = div_u64(frame_jitter, rsc->cmd_config.jitter_denom); - /* convert it to percentage */ - frame_jitter = div_u64(frame_jitter, 100); - - line_time_ns = frame_time_ns; - line_time_ns = div_u64(line_time_ns, rsc->cmd_config.vtotal); - prefill_time_ns = line_time_ns * rsc->cmd_config.prefill_lines; - - total = frame_time_ns - frame_jitter - prefill_time_ns; - if (total < 0) { - pr_err("invalid total time period time:%llu jiter_time:%llu blanking time:%llu\n", - frame_time_ns, frame_jitter, prefill_time_ns); - total = 0; - } - - total = div_u64(total, cxo_period_ns); - rsc->timer_config.static_wakeup_time_ns = total; - - pr_debug("frame time:%llu frame jiter_time:%llu\n", - frame_time_ns, frame_jitter); - pr_debug("line time:%llu prefill time ps:%llu\n", - line_time_ns, prefill_time_ns); - pr_debug("static wakeup time:%lld cxo:%u\n", total, cxo_period_ns); - - pdc_backoff_time_ns = rsc_backoff_time_ns; - rsc_backoff_time_ns = div_u64(rsc_backoff_time_ns, cxo_period_ns); - rsc->timer_config.rsc_backoff_time_ns = (u32) rsc_backoff_time_ns; - - pdc_backoff_time_ns *= pdc_jitter; - pdc_backoff_time_ns = div_u64(pdc_backoff_time_ns, 100); - rsc->timer_config.pdc_backoff_time_ns = (u32) pdc_backoff_time_ns; - - rsc_mode_threshold_time_ns = - div_u64(rsc_mode_threshold_time_ns, cxo_period_ns); - rsc->timer_config.rsc_mode_threshold_time_ns - = (u32) rsc_mode_threshold_time_ns; - - /* time_slot_0 for mode0 latency */ - rsc_time_slot_0_ns = div_u64(rsc_time_slot_0_ns, cxo_period_ns); - rsc->timer_config.rsc_time_slot_0_ns = (u32) rsc_time_slot_0_ns; - - /* time_slot_1 for mode1 latency */ - rsc_time_slot_1_ns = frame_time_ns; - rsc_time_slot_1_ns = div_u64(rsc_time_slot_1_ns, cxo_period_ns); - rsc->timer_config.rsc_time_slot_1_ns = (u32) rsc_time_slot_1_ns; - - /* mode 2 is infinite */ - rsc->timer_config.rsc_time_slot_2_ns = 0xFFFFFFFF; - - /* timer update should be called with client call */ - if (cmd_config && rsc->hw_ops.timer_update) { - ret = rsc->hw_ops.timer_update(rsc); - if (ret) - pr_err("dpu rsc: hw timer update failed ret:%d\n", ret); - /* rsc init should be called during rsc probe - one time only */ - } else if (rsc->hw_ops.init) { - ret = rsc->hw_ops.init(rsc); - if (ret) - pr_err("dpu rsc: hw init failed ret:%d\n", ret); - } - - return ret; -} - -static int dpu_rsc_switch_to_idle(struct dpu_rsc_priv *rsc) -{ - struct dpu_rsc_client *client; - int rc = STATE_UPDATE_NOT_ALLOWED; - bool idle_switch = true; - - list_for_each_entry(client, &rsc->client_list, list) - if (client->current_state != DPU_RSC_IDLE_STATE) { - idle_switch = false; - break; - } - - if (!idle_switch) { - /** - * following code needs to run the loop through each - * client because they might be in different order - * sorting is not possible; only preference is available - */ - - /* first check if any vid client active */ - list_for_each_entry(client, &rsc->client_list, list) - if (client->current_state == DPU_RSC_VID_STATE) - return rc; - - /* now try cmd state switch */ - list_for_each_entry(client, &rsc->client_list, list) - if (client->current_state == DPU_RSC_CMD_STATE) - return TRY_CMD_MODE_SWITCH; - - /* now try clk state switch */ - list_for_each_entry(client, &rsc->client_list, list) - if (client->current_state == DPU_RSC_CLK_STATE) - return TRY_CLK_MODE_SWITCH; - - } else if (rsc->hw_ops.state_update) { - rc = rsc->hw_ops.state_update(rsc, DPU_RSC_IDLE_STATE); - if (!rc) - rpmh_mode_solver_set(rsc->disp_rsc, true); - } - - return rc; -} - -static int dpu_rsc_switch_to_cmd(struct dpu_rsc_priv *rsc, - struct dpu_rsc_cmd_config *config, - struct dpu_rsc_client *caller_client, - int *wait_vblank_crtc_id) -{ - struct dpu_rsc_client *client; - int rc = STATE_UPDATE_NOT_ALLOWED; - - if (!rsc->primary_client) { - pr_err("primary client not available for cmd state switch\n"); - rc = -EINVAL; - goto end; - } else if (caller_client != rsc->primary_client) { - pr_err("primary client state:%d not cmd state request\n", - rsc->primary_client->current_state); - rc = -EINVAL; - goto end; - } - - /* update timers - might not be available at next switch */ - if (config) - dpu_rsc_timer_calculate(rsc, config); - - /** - * rsc clients can still send config at any time. If a config is - * received during cmd_state then vsync_wait will execute with the logic - * below. If a config is received when rsc is in AMC mode; A mode - * switch will do the vsync wait. updated checks still support all cases - * for dynamic mode switch and inline rotation. - */ - if (rsc->current_state == DPU_RSC_CMD_STATE) { - rc = 0; - if (config) - goto vsync_wait; - else - goto end; - } - - /* any one client in video state blocks the cmd state switch */ - list_for_each_entry(client, &rsc->client_list, list) - if (client->current_state == DPU_RSC_VID_STATE) - goto end; - - if (rsc->hw_ops.state_update) { - rc = rsc->hw_ops.state_update(rsc, DPU_RSC_CMD_STATE); - if (!rc) - rpmh_mode_solver_set(rsc->disp_rsc, true); - } - -vsync_wait: - /* indicate wait for vsync for vid to cmd state switch & cfg update */ - if (!rc && (rsc->current_state == DPU_RSC_VID_STATE || - rsc->current_state == DPU_RSC_CMD_STATE)) { - /* clear VSYNC timestamp for indication when update completes */ - if (rsc->hw_ops.hw_vsync) - rsc->hw_ops.hw_vsync(rsc, VSYNC_ENABLE, NULL, 0, 0); - if (!wait_vblank_crtc_id) { - pr_err("invalid crtc id wait pointer, client %d\n", - caller_client->id); - DPU_EVT32(caller_client->id, rsc->current_state, - caller_client->crtc_id, - wait_vblank_crtc_id, DPU_EVTLOG_ERROR); - msleep(PRIMARY_VBLANK_WORST_CASE_MS); - } else { - *wait_vblank_crtc_id = rsc->primary_client->crtc_id; - } - } -end: - return rc; -} - -static int dpu_rsc_switch_to_clk(struct dpu_rsc_priv *rsc, - int *wait_vblank_crtc_id) -{ - struct dpu_rsc_client *client; - int rc = STATE_UPDATE_NOT_ALLOWED; - - list_for_each_entry(client, &rsc->client_list, list) - if ((client->current_state == DPU_RSC_VID_STATE) || - (client->current_state == DPU_RSC_CMD_STATE)) - goto end; - - if (rsc->hw_ops.state_update) { - rc = rsc->hw_ops.state_update(rsc, DPU_RSC_CLK_STATE); - if (!rc) - rpmh_mode_solver_set(rsc->disp_rsc, false); - } - - /* indicate wait for vsync for cmd to clk state switch */ - if (!rc && rsc->primary_client && - (rsc->current_state == DPU_RSC_CMD_STATE)) { - /* clear VSYNC timestamp for indication when update completes */ - if (rsc->hw_ops.hw_vsync) - rsc->hw_ops.hw_vsync(rsc, VSYNC_ENABLE, NULL, 0, 0); - if (!wait_vblank_crtc_id) { - pr_err("invalid crtc id wait pointer provided\n"); - msleep(PRIMARY_VBLANK_WORST_CASE_MS); - } else { - *wait_vblank_crtc_id = rsc->primary_client->crtc_id; - } - } -end: - return rc; -} - -static int dpu_rsc_switch_to_vid(struct dpu_rsc_priv *rsc, - struct dpu_rsc_cmd_config *config, - struct dpu_rsc_client *caller_client, - int *wait_vblank_crtc_id) -{ - int rc = 0; - - /* update timers - might not be available at next switch */ - if (config && (caller_client == rsc->primary_client)) - dpu_rsc_timer_calculate(rsc, config); - - /* early exit without vsync wait for vid state */ - if (rsc->current_state == DPU_RSC_VID_STATE) - goto end; - - /* video state switch should be done immediately */ - if (rsc->hw_ops.state_update) { - rc = rsc->hw_ops.state_update(rsc, DPU_RSC_VID_STATE); - if (!rc) - rpmh_mode_solver_set(rsc->disp_rsc, false); - } - - /* indicate wait for vsync for cmd to vid state switch */ - if (!rc && rsc->primary_client && - (rsc->current_state == DPU_RSC_CMD_STATE)) { - /* clear VSYNC timestamp for indication when update completes */ - if (rsc->hw_ops.hw_vsync) - rsc->hw_ops.hw_vsync(rsc, VSYNC_ENABLE, NULL, 0, 0); - if (!wait_vblank_crtc_id) { - pr_err("invalid crtc id wait pointer provided\n"); - msleep(PRIMARY_VBLANK_WORST_CASE_MS); - } else { - *wait_vblank_crtc_id = rsc->primary_client->crtc_id; - } - } - -end: - return rc; -} - -/** - * dpu_rsc_client_is_state_update_complete() - check if state update is complete - * RSC state transition is not complete until HW receives VBLANK signal. This - * function checks RSC HW to determine whether that signal has been received. - * @client: Client pointer provided by dpu_rsc_client_create(). - * - * Return: true if the state update has completed. - */ -bool dpu_rsc_client_is_state_update_complete( - struct dpu_rsc_client *caller_client) -{ - struct dpu_rsc_priv *rsc; - u32 vsync_timestamp0 = 0; - - if (!caller_client) { - pr_err("invalid client for rsc state update\n"); - return false; - } else if (caller_client->rsc_index >= MAX_RSC_COUNT) { - pr_err("invalid rsc index\n"); - return false; - } - - rsc = rsc_prv_list[caller_client->rsc_index]; - if (!rsc) - return false; - - /** - * state updates clear VSYNC timestamp, check if a new one arrived. - * use VSYNC mode 0 (CMD TE) always for this, per HW recommendation. - */ - if (rsc->hw_ops.hw_vsync) - vsync_timestamp0 = rsc->hw_ops.hw_vsync(rsc, VSYNC_READ_VSYNC0, - NULL, 0, 0); - - return vsync_timestamp0 != 0; -} - -/** - * dpu_rsc_client_state_update() - rsc client state update - * Video mode, cmd mode and clk state are suppoed as modes. A client need to - * set this property during panel config time. A switching client can set the - * property to change the state - * - * @client: Client pointer provided by dpu_rsc_client_create(). - * @state: Client state - video/cmd - * @config: fps, vtotal, porches, etc configuration for command mode - * panel - * @crtc_id: current client's crtc id - * @wait_vblank_crtc_id: Output parameter. If set to non-zero, rsc hw - * state update requires a wait for one vblank on - * the primary crtc. In that case, this output - * param will be set to the crtc on which to wait. - * If DPU_RSC_INVALID_CRTC_ID, no wait necessary - * - * Return: error code. - */ -int dpu_rsc_client_state_update(struct dpu_rsc_client *caller_client, - enum dpu_rsc_state state, - struct dpu_rsc_cmd_config *config, int crtc_id, - int *wait_vblank_crtc_id) -{ - int rc = 0; - struct dpu_rsc_priv *rsc; - - if (!caller_client) { - pr_err("invalid client for rsc state update\n"); - return -EINVAL; - } else if (caller_client->rsc_index >= MAX_RSC_COUNT) { - pr_err("invalid rsc index\n"); - return -EINVAL; - } - - rsc = rsc_prv_list[caller_client->rsc_index]; - if (!rsc) - return -EINVAL; - - if (wait_vblank_crtc_id) - *wait_vblank_crtc_id = DPU_RSC_INVALID_CRTC_ID; - - mutex_lock(&rsc->client_lock); - DPU_EVT32_VERBOSE(caller_client->id, caller_client->current_state, - state, rsc->current_state, DPU_EVTLOG_FUNC_ENTRY); - caller_client->crtc_id = crtc_id; - caller_client->current_state = state; - - if (rsc->master_drm == NULL) { - pr_err("invalid master component binding\n"); - rc = -EINVAL; - goto end; - } else if ((rsc->current_state == state) && !config) { - pr_debug("no state change: %d\n", state); - goto end; - } - - pr_debug("%pS: rsc state:%d request client:%s state:%d\n", - __builtin_return_address(0), rsc->current_state, - caller_client->name, state); - - if (rsc->current_state == DPU_RSC_IDLE_STATE) - dpu_rsc_clk_enable(&rsc->phandle, rsc->pclient, true); - - switch (state) { - case DPU_RSC_IDLE_STATE: - rc = dpu_rsc_switch_to_idle(rsc); - - /* video state client might be exiting; try cmd state switch */ - if (rc == TRY_CMD_MODE_SWITCH) { - rc = dpu_rsc_switch_to_cmd(rsc, NULL, - rsc->primary_client, - wait_vblank_crtc_id); - if (!rc) - state = DPU_RSC_CMD_STATE; - - /* cmd state client might be exiting; try clk state switch */ - } else if (rc == TRY_CLK_MODE_SWITCH) { - rc = dpu_rsc_switch_to_clk(rsc, wait_vblank_crtc_id); - if (!rc) - state = DPU_RSC_CLK_STATE; - } - break; - - case DPU_RSC_CMD_STATE: - rc = dpu_rsc_switch_to_cmd(rsc, config, caller_client, - wait_vblank_crtc_id); - break; - - case DPU_RSC_VID_STATE: - rc = dpu_rsc_switch_to_vid(rsc, config, caller_client, - wait_vblank_crtc_id); - break; - - case DPU_RSC_CLK_STATE: - rc = dpu_rsc_switch_to_clk(rsc, wait_vblank_crtc_id); - break; - - default: - pr_err("invalid state handling %d\n", state); - break; - } - - if (rc == STATE_UPDATE_NOT_ALLOWED) { - rc = 0; - DPU_EVT32(caller_client->id, caller_client->current_state, - state, rsc->current_state, rc, DPU_EVTLOG_FUNC_CASE1); - goto clk_disable; - } else if (rc) { - pr_debug("state:%d update failed rc:%d\n", state, rc); - DPU_EVT32(caller_client->id, caller_client->current_state, - state, rsc->current_state, rc, DPU_EVTLOG_FUNC_CASE2); - goto clk_disable; - } - - pr_debug("state switch successfully complete: %d\n", state); - rsc->current_state = state; - DPU_EVT32(caller_client->id, caller_client->current_state, - state, rsc->current_state, DPU_EVTLOG_FUNC_EXIT); - -clk_disable: - if (rsc->current_state == DPU_RSC_IDLE_STATE) - dpu_rsc_clk_enable(&rsc->phandle, rsc->pclient, false); -end: - mutex_unlock(&rsc->client_lock); - return rc; -} -EXPORT_SYMBOL(dpu_rsc_client_state_update); - -/** - * dpu_rsc_client_vote() - ab/ib vote from rsc client - * - * @client: Client pointer provided by dpu_rsc_client_create(). - * @bus_id: data bus for which to be voted - * @ab: aggregated bandwidth vote from client. - * @ib: instant bandwidth vote from client. - * - * Return: error code. - */ -int dpu_rsc_client_vote(struct dpu_rsc_client *caller_client, - u32 bus_id, u64 ab_vote, u64 ib_vote) -{ - int rc = 0; - struct dpu_rsc_priv *rsc; - - if (!caller_client) { - pr_err("invalid client for ab/ib vote\n"); - return -EINVAL; - } else if (caller_client->rsc_index >= MAX_RSC_COUNT) { - pr_err("invalid rsc index\n"); - return -EINVAL; - } - - rsc = rsc_prv_list[caller_client->rsc_index]; - if (!rsc) - return -EINVAL; - - pr_debug("client:%s ab:%llu ib:%llu\n", - caller_client->name, ab_vote, ib_vote); - - mutex_lock(&rsc->client_lock); - rc = dpu_rsc_clk_enable(&rsc->phandle, rsc->pclient, true); - if (rc) - goto clk_enable_fail; - - if (rsc->hw_ops.tcs_wait) { - rc = rsc->hw_ops.tcs_wait(rsc); - if (rc) { - pr_err("tcs is still busy; can't send command\n"); - if (rsc->hw_ops.tcs_use_ok) - rsc->hw_ops.tcs_use_ok(rsc); - goto end; - } - } - - rpmh_invalidate(rsc->disp_rsc); - dpu_power_data_bus_set_quota(&rsc->phandle, rsc->pclient, - DPU_POWER_HANDLE_DATA_BUS_CLIENT_RT, - bus_id, ab_vote, ib_vote); - rpmh_flush(rsc->disp_rsc); - - if (rsc->hw_ops.tcs_use_ok) - rsc->hw_ops.tcs_use_ok(rsc); - -end: - dpu_rsc_clk_enable(&rsc->phandle, rsc->pclient, false); -clk_enable_fail: - mutex_unlock(&rsc->client_lock); - - return rc; -} -EXPORT_SYMBOL(dpu_rsc_client_vote); - -#if defined(CONFIG_DEBUG_FS) -void dpu_rsc_debug_dump(u32 mux_sel) -{ - struct dpu_rsc_priv *rsc; - - rsc = rsc_prv_list[DPU_RSC_INDEX]; - if (!rsc) - return; - - /* this must be called with rsc clocks enabled */ - if (rsc->hw_ops.debug_dump) - rsc->hw_ops.debug_dump(rsc, mux_sel); -} -#endif /* defined(CONFIG_DEBUG_FS) */ - -static int _dpu_debugfs_status_show(struct seq_file *s, void *data) -{ - struct dpu_rsc_priv *rsc; - struct dpu_rsc_client *client; - int ret; - - if (!s || !s->private) - return -EINVAL; - - rsc = s->private; - - mutex_lock(&rsc->client_lock); - ret = dpu_rsc_clk_enable(&rsc->phandle, rsc->pclient, true); - if (ret) - goto end; - - seq_printf(s, "rsc current state:%d\n", rsc->current_state); - seq_printf(s, "wraper backoff time(ns):%d\n", - rsc->timer_config.static_wakeup_time_ns); - seq_printf(s, "rsc backoff time(ns):%d\n", - rsc->timer_config.rsc_backoff_time_ns); - seq_printf(s, "pdc backoff time(ns):%d\n", - rsc->timer_config.pdc_backoff_time_ns); - seq_printf(s, "rsc mode threshold time(ns):%d\n", - rsc->timer_config.rsc_mode_threshold_time_ns); - seq_printf(s, "rsc time slot 0(ns):%d\n", - rsc->timer_config.rsc_time_slot_0_ns); - seq_printf(s, "rsc time slot 1(ns):%d\n", - rsc->timer_config.rsc_time_slot_1_ns); - seq_printf(s, "frame fps:%d jitter_numer:%d jitter_denom:%d vtotal:%d prefill lines:%d\n", - rsc->cmd_config.fps, rsc->cmd_config.jitter_numer, - rsc->cmd_config.jitter_denom, - rsc->cmd_config.vtotal, rsc->cmd_config.prefill_lines); - - seq_puts(s, "\n"); - - list_for_each_entry(client, &rsc->client_list, list) - seq_printf(s, "\t client:%s state:%d\n", - client->name, client->current_state); - - if (rsc->hw_ops.debug_show) { - ret = rsc->hw_ops.debug_show(s, rsc); - if (ret) - pr_err("dpu rsc: hw debug failed ret:%d\n", ret); - } - dpu_rsc_clk_enable(&rsc->phandle, rsc->pclient, false); - -end: - mutex_unlock(&rsc->client_lock); - return 0; -} - -static int _dpu_debugfs_status_open(struct inode *inode, struct file *file) -{ - return single_open(file, _dpu_debugfs_status_show, inode->i_private); -} - -static int _dpu_debugfs_mode_ctrl_open(struct inode *inode, struct file *file) -{ - /* non-seekable */ - file->private_data = inode->i_private; - return nonseekable_open(inode, file); -} - -static ssize_t _dpu_debugfs_mode_ctrl_read(struct file *file, char __user *buf, - size_t count, loff_t *ppos) -{ - struct dpu_rsc_priv *rsc = file->private_data; - char buffer[MAX_BUFFER_SIZE]; - int blen = 0, rc; - - if (*ppos || !rsc || !rsc->hw_ops.mode_ctrl) - return 0; - - mutex_lock(&rsc->client_lock); - rc = dpu_rsc_clk_enable(&rsc->phandle, rsc->pclient, true); - if (rc) - goto end; - - blen = rsc->hw_ops.mode_ctrl(rsc, MODE_READ, buffer, - MAX_BUFFER_SIZE, 0); - - dpu_rsc_clk_enable(&rsc->phandle, rsc->pclient, false); - -end: - mutex_unlock(&rsc->client_lock); - if (blen <= 0) - return 0; - - if (copy_to_user(buf, buffer, blen)) - return -EFAULT; - - *ppos += blen; - return blen; -} - -static ssize_t _dpu_debugfs_mode_ctrl_write(struct file *file, - const char __user *p, size_t count, loff_t *ppos) -{ - struct dpu_rsc_priv *rsc = file->private_data; - char *input; - u32 mode_state = 0; - int rc; - - if (!rsc || !rsc->hw_ops.mode_ctrl || !count || - count > MAX_COUNT_SIZE_SUPPORTED) - return 0; - - input = kmalloc(count + 1, GFP_KERNEL); - if (!input) - return -ENOMEM; - - if (copy_from_user(input, p, count)) { - kfree(input); - return -EFAULT; - } - input[count] = '\0'; - - rc = kstrtoint(input, 0, &mode_state); - if (rc) { - pr_err("mode_state: int conversion failed rc:%d\n", rc); - goto end; - } - - pr_debug("mode_state: %d\n", mode_state); - mode_state &= 0x7; - if (mode_state != ALL_MODES_DISABLED && - mode_state != ALL_MODES_ENABLED && - mode_state != ONLY_MODE_0_ENABLED && - mode_state != ONLY_MODE_0_1_ENABLED) { - pr_err("invalid mode:%d combination\n", mode_state); - goto end; - } - - mutex_lock(&rsc->client_lock); - rc = dpu_rsc_clk_enable(&rsc->phandle, rsc->pclient, true); - if (rc) - goto clk_enable_fail; - - rsc->hw_ops.mode_ctrl(rsc, MODE_UPDATE, NULL, 0, mode_state); - dpu_rsc_clk_enable(&rsc->phandle, rsc->pclient, false); - -clk_enable_fail: - mutex_unlock(&rsc->client_lock); -end: - kfree(input); - return count; -} - -static int _dpu_debugfs_vsync_mode_open(struct inode *inode, struct file *file) -{ - /* non-seekable */ - file->private_data = inode->i_private; - return nonseekable_open(inode, file); -} - -static ssize_t _dpu_debugfs_vsync_mode_read(struct file *file, char __user *buf, - size_t count, loff_t *ppos) -{ - struct dpu_rsc_priv *rsc = file->private_data; - char buffer[MAX_BUFFER_SIZE]; - int blen = 0, rc; - - if (*ppos || !rsc || !rsc->hw_ops.hw_vsync) - return 0; - - mutex_lock(&rsc->client_lock); - rc = dpu_rsc_clk_enable(&rsc->phandle, rsc->pclient, true); - if (rc) - goto end; - - blen = rsc->hw_ops.hw_vsync(rsc, VSYNC_READ, buffer, - MAX_BUFFER_SIZE, 0); - - dpu_rsc_clk_enable(&rsc->phandle, rsc->pclient, false); - -end: - mutex_unlock(&rsc->client_lock); - if (blen <= 0) - return 0; - - if (copy_to_user(buf, buffer, blen)) - return -EFAULT; - - *ppos += blen; - return blen; -} - -static ssize_t _dpu_debugfs_vsync_mode_write(struct file *file, - const char __user *p, size_t count, loff_t *ppos) -{ - struct dpu_rsc_priv *rsc = file->private_data; - char *input; - u32 vsync_state = 0; - int rc; - - if (!rsc || !rsc->hw_ops.hw_vsync || !count || - count > MAX_COUNT_SIZE_SUPPORTED) - return 0; - - input = kmalloc(count + 1, GFP_KERNEL); - if (!input) - return -ENOMEM; - - if (copy_from_user(input, p, count)) { - kfree(input); - return -EFAULT; - } - input[count] = '\0'; - - rc = kstrtoint(input, 0, &vsync_state); - if (rc) { - pr_err("vsync_state: int conversion failed rc:%d\n", rc); - goto end; - } - - pr_debug("vsync_state: %d\n", vsync_state); - vsync_state &= 0x7; - - mutex_lock(&rsc->client_lock); - rc = dpu_rsc_clk_enable(&rsc->phandle, rsc->pclient, true); - if (rc) - goto clk_en_fail; - - if (vsync_state) - rsc->hw_ops.hw_vsync(rsc, VSYNC_ENABLE, NULL, - 0, vsync_state - 1); - else - rsc->hw_ops.hw_vsync(rsc, VSYNC_DISABLE, NULL, 0, 0); - - dpu_rsc_clk_enable(&rsc->phandle, rsc->pclient, false); - -clk_en_fail: - mutex_unlock(&rsc->client_lock); -end: - kfree(input); - return count; -} - -static const struct file_operations debugfs_status_fops = { - .open = _dpu_debugfs_status_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; - -static const struct file_operations mode_control_fops = { - .open = _dpu_debugfs_mode_ctrl_open, - .read = _dpu_debugfs_mode_ctrl_read, - .write = _dpu_debugfs_mode_ctrl_write, -}; - -static const struct file_operations vsync_status_fops = { - .open = _dpu_debugfs_vsync_mode_open, - .read = _dpu_debugfs_vsync_mode_read, - .write = _dpu_debugfs_vsync_mode_write, -}; - -static void _dpu_rsc_init_debugfs(struct dpu_rsc_priv *rsc, char *name) -{ - rsc->debugfs_root = debugfs_create_dir(name, NULL); - if (!rsc->debugfs_root) - return; - - /* don't error check these */ - debugfs_create_file("status", 0400, rsc->debugfs_root, rsc, - &debugfs_status_fops); - debugfs_create_file("mode_control", 0600, rsc->debugfs_root, rsc, - &mode_control_fops); - debugfs_create_file("vsync_mode", 0600, rsc->debugfs_root, rsc, - &vsync_status_fops); - debugfs_create_x32("debug_mode", 0600, rsc->debugfs_root, - &rsc->debug_mode); -} - -static void dpu_rsc_deinit(struct platform_device *pdev, - struct dpu_rsc_priv *rsc) -{ - if (!rsc) - return; - - if (rsc->pclient) - dpu_rsc_clk_enable(&rsc->phandle, rsc->pclient, false); - if (rsc->fs) - devm_regulator_put(rsc->fs); - if (rsc->wrapper_io.base) - msm_dss_iounmap(&rsc->wrapper_io); - if (rsc->drv_io.base) - msm_dss_iounmap(&rsc->drv_io); - if (rsc->disp_rsc) - rpmh_release(rsc->disp_rsc); - if (rsc->pclient) - dpu_power_client_destroy(&rsc->phandle, rsc->pclient); - - dpu_power_resource_deinit(pdev, &rsc->phandle); - debugfs_remove_recursive(rsc->debugfs_root); - kfree(rsc); -} - -/** - * dpu_rsc_bind - bind rsc device with controlling device - * @dev: Pointer to base of platform device - * @master: Pointer to container of drm device - * @data: Pointer to private data - * Returns: Zero on success - */ -static int dpu_rsc_bind(struct device *dev, - struct device *master, - void *data) -{ - struct dpu_rsc_priv *rsc; - struct drm_device *drm; - struct platform_device *pdev = to_platform_device(dev); - - if (!dev || !pdev || !master) { - pr_err("invalid param(s), dev %pK, pdev %pK, master %pK\n", - dev, pdev, master); - return -EINVAL; - } - - drm = dev_get_drvdata(master); - rsc = platform_get_drvdata(pdev); - if (!drm || !rsc) { - pr_err("invalid param(s), drm %pK, rsc %pK\n", - drm, rsc); - return -EINVAL; - } - - mutex_lock(&rsc->client_lock); - rsc->master_drm = drm; - mutex_unlock(&rsc->client_lock); - - dpu_dbg_reg_register_base(DPU_RSC_DRV_DBG_NAME, rsc->drv_io.base, - rsc->drv_io.len); - dpu_dbg_reg_register_base(DPU_RSC_WRAPPER_DBG_NAME, - rsc->wrapper_io.base, rsc->wrapper_io.len); - return 0; -} - -/** - * dpu_rsc_unbind - unbind rsc from controlling device - * @dev: Pointer to base of platform device - * @master: Pointer to container of drm device - * @data: Pointer to private data - */ -static void dpu_rsc_unbind(struct device *dev, - struct device *master, void *data) -{ - struct dpu_rsc_priv *rsc; - struct platform_device *pdev = to_platform_device(dev); - - if (!dev || !pdev) { - pr_err("invalid param(s)\n"); - return; - } - - rsc = platform_get_drvdata(pdev); - if (!rsc) { - pr_err("invalid display rsc\n"); - return; - } - - mutex_lock(&rsc->client_lock); - rsc->master_drm = NULL; - mutex_unlock(&rsc->client_lock); -} - -static const struct component_ops dpu_rsc_comp_ops = { - .bind = dpu_rsc_bind, - .unbind = dpu_rsc_unbind, -}; - -static int dpu_rsc_probe(struct platform_device *pdev) -{ - int ret; - struct dpu_rsc_priv *rsc; - static int counter; - char name[MAX_RSC_CLIENT_NAME_LEN]; - - rsc = kzalloc(sizeof(*rsc), GFP_KERNEL); - if (!rsc) { - ret = -ENOMEM; - goto rsc_alloc_fail; - } - - platform_set_drvdata(pdev, rsc); - of_property_read_u32(pdev->dev.of_node, "qcom,dpu-rsc-version", - &rsc->version); - - ret = dpu_power_resource_init(pdev, &rsc->phandle); - if (ret) { - pr_err("dpu rsc:power resource init failed ret:%d\n", ret); - goto dpu_rsc_fail; - } - - rsc->pclient = dpu_power_client_create(&rsc->phandle, "rsc"); - if (IS_ERR_OR_NULL(rsc->pclient)) { - ret = PTR_ERR(rsc->pclient); - rsc->pclient = NULL; - pr_err("dpu rsc:power client create failed ret:%d\n", ret); - goto dpu_rsc_fail; - } - - /** - * dpu rsc should always vote through enable path, sleep vote is - * set to "0" by default. - */ - dpu_power_data_bus_state_update(&rsc->phandle, true); - - rsc->disp_rsc = rpmh_get_byname(pdev, "disp_rsc"); - if (IS_ERR_OR_NULL(rsc->disp_rsc)) { - ret = PTR_ERR(rsc->disp_rsc); - rsc->disp_rsc = NULL; - pr_err("dpu rsc:get display rsc failed ret:%d\n", ret); - goto dpu_rsc_fail; - } - - ret = msm_dss_ioremap_byname(pdev, &rsc->wrapper_io, "wrapper"); - if (ret) { - pr_err("dpu rsc: wrapper io data mapping failed ret=%d\n", ret); - goto dpu_rsc_fail; - } - - ret = msm_dss_ioremap_byname(pdev, &rsc->drv_io, "drv"); - if (ret) { - pr_err("dpu rsc: drv io data mapping failed ret:%d\n", ret); - goto dpu_rsc_fail; - } - - rsc->fs = devm_regulator_get(&pdev->dev, "vdd"); - if (IS_ERR_OR_NULL(rsc->fs)) { - rsc->fs = NULL; - pr_err("unable to get regulator\n"); - goto dpu_rsc_fail; - } - - ret = dpu_rsc_hw_register(rsc); - if (ret) { - pr_err("dpu rsc: hw register failed ret:%d\n", ret); - goto dpu_rsc_fail; - } - - if (dpu_rsc_clk_enable(&rsc->phandle, rsc->pclient, true)) { - pr_err("failed to enable dpu rsc power resources\n"); - goto dpu_rsc_fail; - } - - if (dpu_rsc_timer_calculate(rsc, NULL)) - goto dpu_rsc_fail; - - dpu_rsc_clk_enable(&rsc->phandle, rsc->pclient, false); - - INIT_LIST_HEAD(&rsc->client_list); - INIT_LIST_HEAD(&rsc->event_list); - mutex_init(&rsc->client_lock); - - pr_info("dpu rsc index:%d probed successfully\n", - DPU_RSC_INDEX + counter); - - rsc_prv_list[DPU_RSC_INDEX + counter] = rsc; - snprintf(name, MAX_RSC_CLIENT_NAME_LEN, "%s%d", "dpu_rsc", counter); - _dpu_rsc_init_debugfs(rsc, name); - counter++; - - ret = component_add(&pdev->dev, &dpu_rsc_comp_ops); - if (ret) - pr_debug("component add failed, ret=%d\n", ret); - ret = 0; - - return ret; - -dpu_rsc_fail: - dpu_rsc_deinit(pdev, rsc); -rsc_alloc_fail: - return ret; -} - -static int dpu_rsc_remove(struct platform_device *pdev) -{ - struct dpu_rsc_priv *rsc = platform_get_drvdata(pdev); - - dpu_rsc_deinit(pdev, rsc); - return 0; -} - -static const struct of_device_id dt_match[] = { - { .compatible = "qcom,dpu-rsc"}, - {} -}; - -MODULE_DEVICE_TABLE(of, dt_match); - -static struct platform_driver dpu_rsc_platform_driver = { - .probe = dpu_rsc_probe, - .remove = dpu_rsc_remove, - .driver = { - .name = "dpu_rsc", - .of_match_table = dt_match, - }, -}; - -static int __init dpu_rsc_register(void) -{ - return platform_driver_register(&dpu_rsc_platform_driver); -} - -static void __exit dpu_rsc_unregister(void) -{ - platform_driver_unregister(&dpu_rsc_platform_driver); -} - -module_init(dpu_rsc_register); -module_exit(dpu_rsc_unregister); diff --git a/drivers/gpu/drm/msm/dpu_rsc_hw.c b/drivers/gpu/drm/msm/dpu_rsc_hw.c deleted file mode 100644 index 1a379de..0000000 --- a/drivers/gpu/drm/msm/dpu_rsc_hw.c +++ /dev/null @@ -1,818 +0,0 @@ -/* Copyright (c) 2016-2018, The Linux Foundation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 and - * only version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - */ - -#define pr_fmt(fmt) "[dpu_rsc_hw:%s:%d]: " fmt, __func__, __LINE__ - -#include -#include -#include - -#include "dpu_rsc_priv.h" -#include "dpu_dbg.h" - -/* display rsc offset */ -#define DPU_RSCC_PDC_SEQ_START_ADDR_REG_OFFSET_DRV0 0x020 -#define DPU_RSCC_PDC_MATCH_VALUE_LO_REG_OFFSET_DRV0 0x024 -#define DPU_RSCC_PDC_MATCH_VALUE_HI_REG_OFFSET_DRV0 0x028 -#define DPU_RSCC_PDC_SLAVE_ID_DRV0 0x02c -#define DPU_RSCC_SEQ_PROGRAM_COUNTER 0x408 -#define DPU_RSCC_SEQ_CFG_BR_ADDR_0_DRV0 0x410 -#define DPU_RSCC_SEQ_CFG_BR_ADDR_1_DRV0 0x414 -#define DPU_RSCC_SEQ_MEM_0_DRV0 0x600 -#define DPU_RSCC_SOLVER_OVERRIDE_CTRL_DRV0 0xc14 -#define DPU_RSCC_ERROR_IRQ_STATUS_DRV0 0x0d0 -#define DPU_RSCC_SEQ_BUSY_DRV0 0x404 -#define DPU_RSCC_SOLVER_STATUS0_DRV0 0xc24 -#define DPU_RSCC_SOLVER_STATUS1_DRV0 0xc28 -#define DPU_RSCC_SOLVER_STATUS2_DRV0 0xc2c -#define DPU_RSCC_AMC_TCS_MODE_IRQ_STATUS_DRV0 0x1c00 - -#define DPU_RSCC_SOFT_WAKEUP_TIME_LO_DRV0 0xc04 -#define DPU_RSCC_SOFT_WAKEUP_TIME_HI_DRV0 0xc08 -#define DPU_RSCC_MAX_IDLE_DURATION_DRV0 0xc0c -#define DPU_RSC_SOLVER_TIME_SLOT_TABLE_0_DRV0 0x1000 -#define DPU_RSC_SOLVER_TIME_SLOT_TABLE_1_DRV0 0x1004 -#define DPU_RSC_SOLVER_TIME_SLOT_TABLE_2_DRV0 0x1008 -#define DPU_RSC_SOLVER_TIME_SLOT_TABLE_3_DRV0 0x100c - -#define DPU_RSC_SOLVER_SOLVER_MODES_ENABLED_DRV0 0xc20 -#define DPU_RSC_SOLVER_MODE_PRI_TABLE_SLOT0_PRI0_DRV0 0x1080 -#define DPU_RSC_SOLVER_MODE_PRI_TABLE_SLOT1_PRI0_DRV0 0x1100 -#define DPU_RSC_SOLVER_MODE_PRI_TABLE_SLOT1_PRI3_DRV0 0x110c -#define DPU_RSC_SOLVER_MODE_PRI_TABLE_SLOT2_PRI0_DRV0 0x1180 -#define DPU_RSC_SOLVER_MODE_PRI_TABLE_SLOT2_PRI3_DRV0 0x118c - -#define DPU_RSC_SOLVER_OVERRIDE_MODE_DRV0 0xc18 -#define DPU_RSC_SOLVER_OVERRIDE_CTRL_DRV0 0xc14 -#define DPU_RSC_TIMERS_CONSIDERED_DRV0 0xc00 -#define DPU_RSC_SOLVER_OVERRIDE_IDLE_TIME_DRV0 0xc1c - -#define DPU_RSC_SOLVER_MODE_PARM0_DRV0_MODE0 0xc30 -#define DPU_RSC_SOLVER_MODE_PARM1_DRV0_MODE0 0xc34 -#define DPU_RSC_SOLVER_MODE_PARM2_DRV0_MODE0 0xc38 -#define DPU_RSC_SOLVER_MODE_PARM3_DRV0_MODE0 0xc40 - -#define DPU_RSC_SOLVER_MODE_PARM0_DRV0_MODE1 0xc4c -#define DPU_RSC_SOLVER_MODE_PARM1_DRV0_MODE1 0xc50 -#define DPU_RSC_SOLVER_MODE_PARM2_DRV0_MODE1 0xc54 -#define DPU_RSC_SOLVER_MODE_PARM3_DRV0_MODE1 0xc5c - -#define DPU_RSC_SOLVER_MODE_PARM0_DRV0_MODE2 0xc68 -#define DPU_RSC_SOLVER_MODE_PARM1_DRV0_MODE2 0xc6c -#define DPU_RSC_SOLVER_MODE_PARM2_DRV0_MODE2 0xc70 -#define DPU_RSC_SOLVER_MODE_PARM3_DRV0_MODE2 0xc78 - -#define DPU_RSCC_TCS_DRV0_CONTROL 0x1c14 - -#define DPU_RSCC_WRAPPER_CTRL 0x000 -#define DPU_RSCC_WRAPPER_OVERRIDE_CTRL 0x004 -#define DPU_RSCC_WRAPPER_STATIC_WAKEUP_0 0x008 -#define DPU_RSCC_WRAPPER_RSCC_MODE_THRESHOLD 0x00c -#define DPU_RSCC_WRAPPER_DEBUG_BUS 0x010 -#define DPU_RSCC_WRAPPER_VSYNC_TIMESTAMP0 0x018 -#define DPU_RSCC_WRAPPER_VSYNC_TIMESTAMP1 0x01c -#define DPU_RSCC_SPARE_PWR_EVENT 0x020 -#define DPU_RSCC_PWR_CTRL 0x024 - -/* qtimer offset */ -#define DPU_RSCC_QTMR_AC_HW_FRAME_SEL_1 0x1FE0 -#define DPU_RSCC_QTMR_AC_HW_FRAME_SEL_2 0x1FF0 -#define DPU_RSCC_QTMR_AC_CNTACR0_FG0 0x1040 -#define DPU_RSCC_QTMR_AC_CNTACR1_FG0 0x1044 -#define DPU_RSCC_F0_QTMR_V1_CNTP_CVAL_LO 0x2020 -#define DPU_RSCC_F0_QTMR_V1_CNTP_CVAL_HI 0x2024 -#define DPU_RSCC_F1_QTMR_V1_CNTP_CVAL_LO 0x3020 -#define DPU_RSCC_F1_QTMR_V1_CNTP_CVAL_HI 0x3024 -#define DPU_RSCC_F0_QTMR_V1_CNTP_CTL 0x202C -#define DPU_RSCC_F1_QTMR_V1_CNTP_CTL 0x302C - -#define MAX_CHECK_LOOPS 500 -#define POWER_CTRL_BIT_12 12 - -static void rsc_event_trigger(struct dpu_rsc_priv *rsc, uint32_t event_type) -{ - struct dpu_rsc_event *event; - - list_for_each_entry(event, &rsc->event_list, list) - if (event->event_type & event_type) - event->cb_func(event_type, event->usr); -} - -static int rsc_hw_qtimer_init(struct dpu_rsc_priv *rsc) -{ - pr_debug("rsc hardware qtimer init\n"); - - dss_reg_w(&rsc->wrapper_io, DPU_RSCC_QTMR_AC_HW_FRAME_SEL_1, - 0xffffffff, rsc->debug_mode); - dss_reg_w(&rsc->wrapper_io, DPU_RSCC_QTMR_AC_HW_FRAME_SEL_2, - 0xffffffff, rsc->debug_mode); - - dss_reg_w(&rsc->wrapper_io, DPU_RSCC_QTMR_AC_CNTACR0_FG0, - 0x1, rsc->debug_mode); - dss_reg_w(&rsc->wrapper_io, DPU_RSCC_QTMR_AC_CNTACR1_FG0, - 0x1, rsc->debug_mode); - - dss_reg_w(&rsc->wrapper_io, DPU_RSCC_F0_QTMR_V1_CNTP_CVAL_LO, - 0xffffffff, rsc->debug_mode); - dss_reg_w(&rsc->wrapper_io, DPU_RSCC_F0_QTMR_V1_CNTP_CVAL_HI, - 0xffffffff, rsc->debug_mode); - dss_reg_w(&rsc->wrapper_io, DPU_RSCC_F1_QTMR_V1_CNTP_CVAL_LO, - 0xffffffff, rsc->debug_mode); - dss_reg_w(&rsc->wrapper_io, DPU_RSCC_F1_QTMR_V1_CNTP_CVAL_HI, - 0xffffffff, rsc->debug_mode); - - dss_reg_w(&rsc->wrapper_io, DPU_RSCC_F0_QTMR_V1_CNTP_CTL, - 0x1, rsc->debug_mode); - dss_reg_w(&rsc->wrapper_io, DPU_RSCC_F1_QTMR_V1_CNTP_CTL, - 0x1, rsc->debug_mode); - - return 0; -} - -static int rsc_hw_pdc_init(struct dpu_rsc_priv *rsc) -{ - pr_debug("rsc hardware pdc init\n"); - - dss_reg_w(&rsc->drv_io, DPU_RSCC_PDC_SEQ_START_ADDR_REG_OFFSET_DRV0, - 0x4520, rsc->debug_mode); - dss_reg_w(&rsc->drv_io, DPU_RSCC_PDC_MATCH_VALUE_LO_REG_OFFSET_DRV0, - 0x4510, rsc->debug_mode); - dss_reg_w(&rsc->drv_io, DPU_RSCC_PDC_MATCH_VALUE_HI_REG_OFFSET_DRV0, - 0x4514, rsc->debug_mode); - dss_reg_w(&rsc->drv_io, DPU_RSCC_PDC_SLAVE_ID_DRV0, - 0x1, rsc->debug_mode); - - return 0; -} - -static int rsc_hw_wrapper_init(struct dpu_rsc_priv *rsc) -{ - pr_debug("rsc hardware wrapper init\n"); - - dss_reg_w(&rsc->wrapper_io, DPU_RSCC_WRAPPER_STATIC_WAKEUP_0, - rsc->timer_config.static_wakeup_time_ns, rsc->debug_mode); - - dss_reg_w(&rsc->wrapper_io, DPU_RSCC_WRAPPER_RSCC_MODE_THRESHOLD, - rsc->timer_config.rsc_mode_threshold_time_ns, rsc->debug_mode); - - dss_reg_w(&rsc->wrapper_io, DPU_RSCC_WRAPPER_OVERRIDE_CTRL, - BIT(8), rsc->debug_mode); - return 0; -} - -static int rsc_hw_seq_memory_init(struct dpu_rsc_priv *rsc) -{ - pr_debug("rsc sequencer memory init\n"); - - /* Mode - 0 sequence */ - dss_reg_w(&rsc->drv_io, DPU_RSCC_SEQ_MEM_0_DRV0 + 0x0, - 0xe0a88bab, rsc->debug_mode); - dss_reg_w(&rsc->drv_io, DPU_RSCC_SEQ_MEM_0_DRV0 + 0x4, - 0x8babec39, rsc->debug_mode); - dss_reg_w(&rsc->drv_io, DPU_RSCC_SEQ_MEM_0_DRV0 + 0x8, - 0x8bab2088, rsc->debug_mode); - - /* Mode - 1 sequence */ - dss_reg_w(&rsc->drv_io, DPU_RSCC_SEQ_MEM_0_DRV0 + 0xc, - 0x39e038a8, rsc->debug_mode); - dss_reg_w(&rsc->drv_io, DPU_RSCC_SEQ_MEM_0_DRV0 + 0x10, - 0x888babec, rsc->debug_mode); - dss_reg_w(&rsc->drv_io, DPU_RSCC_SEQ_MEM_0_DRV0 + 0x14, - 0xa806a020, rsc->debug_mode); - - /* Mode - 2 sequence */ - dss_reg_w(&rsc->drv_io, DPU_RSCC_SEQ_MEM_0_DRV0 + 0x18, - 0xa138ebaa, rsc->debug_mode); - dss_reg_w(&rsc->drv_io, DPU_RSCC_SEQ_MEM_0_DRV0 + 0x1c, - 0xaca581e1, rsc->debug_mode); - dss_reg_w(&rsc->drv_io, DPU_RSCC_SEQ_MEM_0_DRV0 + 0x20, - 0xe2a2ede0, rsc->debug_mode); - dss_reg_w(&rsc->drv_io, DPU_RSCC_SEQ_MEM_0_DRV0 + 0x24, - 0xea8a3982, rsc->debug_mode); - dss_reg_w(&rsc->drv_io, DPU_RSCC_SEQ_MEM_0_DRV0 + 0x28, - 0xa920888c, rsc->debug_mode); - - /* tcs sleep sequence */ - dss_reg_w(&rsc->drv_io, DPU_RSCC_SEQ_MEM_0_DRV0 + 0x2c, - 0x89e6a6e9, rsc->debug_mode); - dss_reg_w(&rsc->drv_io, DPU_RSCC_SEQ_MEM_0_DRV0 + 0x30, - 0xa7e9a920, rsc->debug_mode); - dss_reg_w(&rsc->drv_io, DPU_RSCC_SEQ_MEM_0_DRV0 + 0x34, - 0x002089e7, rsc->debug_mode); - - /* branch address */ - dss_reg_w(&rsc->drv_io, DPU_RSCC_SEQ_CFG_BR_ADDR_0_DRV0, - 0x2b, rsc->debug_mode); - dss_reg_w(&rsc->drv_io, DPU_RSCC_SEQ_CFG_BR_ADDR_1_DRV0, - 0x31, rsc->debug_mode); - - return 0; -} - -static int rsc_hw_solver_init(struct dpu_rsc_priv *rsc) -{ - const u32 mode_0_start_addr = 0x0; - const u32 mode_1_start_addr = 0xa; - const u32 mode_2_start_addr = 0x15; - - pr_debug("rsc solver init\n"); - - dss_reg_w(&rsc->drv_io, DPU_RSCC_SOFT_WAKEUP_TIME_LO_DRV0, - 0xFFFFFFFF, rsc->debug_mode); - dss_reg_w(&rsc->drv_io, DPU_RSCC_SOFT_WAKEUP_TIME_HI_DRV0, - 0xFFFFFFFF, rsc->debug_mode); - dss_reg_w(&rsc->drv_io, DPU_RSCC_MAX_IDLE_DURATION_DRV0, - 0xEFFFFFFF, rsc->debug_mode); - - dss_reg_w(&rsc->drv_io, DPU_RSC_SOLVER_TIME_SLOT_TABLE_0_DRV0, - 0x0, rsc->debug_mode); - dss_reg_w(&rsc->drv_io, DPU_RSC_SOLVER_TIME_SLOT_TABLE_1_DRV0, - rsc->timer_config.rsc_time_slot_0_ns, rsc->debug_mode); - dss_reg_w(&rsc->drv_io, DPU_RSC_SOLVER_TIME_SLOT_TABLE_2_DRV0, - rsc->timer_config.rsc_time_slot_1_ns, rsc->debug_mode); - dss_reg_w(&rsc->drv_io, DPU_RSC_SOLVER_TIME_SLOT_TABLE_3_DRV0, - rsc->timer_config.rsc_time_slot_2_ns, rsc->debug_mode); - - dss_reg_w(&rsc->drv_io, DPU_RSC_SOLVER_SOLVER_MODES_ENABLED_DRV0, - 0x7, rsc->debug_mode); - - dss_reg_w(&rsc->drv_io, DPU_RSC_SOLVER_MODE_PRI_TABLE_SLOT0_PRI0_DRV0, - 0x0, rsc->debug_mode); - dss_reg_w(&rsc->drv_io, DPU_RSC_SOLVER_MODE_PRI_TABLE_SLOT1_PRI0_DRV0, - 0x1, rsc->debug_mode); - dss_reg_w(&rsc->drv_io, DPU_RSC_SOLVER_MODE_PRI_TABLE_SLOT1_PRI3_DRV0, - 0x1, rsc->debug_mode); - dss_reg_w(&rsc->drv_io, DPU_RSC_SOLVER_MODE_PRI_TABLE_SLOT2_PRI0_DRV0, - 0x2, rsc->debug_mode); - dss_reg_w(&rsc->drv_io, DPU_RSC_SOLVER_MODE_PRI_TABLE_SLOT2_PRI3_DRV0, - 0x2, rsc->debug_mode); - - dss_reg_w(&rsc->drv_io, DPU_RSC_SOLVER_OVERRIDE_MODE_DRV0, - 0x0, rsc->debug_mode); - dss_reg_w(&rsc->drv_io, DPU_RSC_SOLVER_OVERRIDE_CTRL_DRV0, - mode_0_start_addr, rsc->debug_mode); - dss_reg_w(&rsc->drv_io, DPU_RSC_TIMERS_CONSIDERED_DRV0, - 0x1, rsc->debug_mode); - dss_reg_w(&rsc->drv_io, DPU_RSC_SOLVER_OVERRIDE_IDLE_TIME_DRV0, - 0x01000010, rsc->debug_mode); - - dss_reg_w(&rsc->drv_io, DPU_RSC_SOLVER_MODE_PARM0_DRV0_MODE0, - mode_0_start_addr, rsc->debug_mode); - dss_reg_w(&rsc->drv_io, DPU_RSC_SOLVER_MODE_PARM1_DRV0_MODE0, - 0x80000000, rsc->debug_mode); - dss_reg_w(&rsc->drv_io, DPU_RSC_SOLVER_MODE_PARM2_DRV0_MODE0, - rsc->timer_config.rsc_backoff_time_ns, rsc->debug_mode); - dss_reg_w(&rsc->drv_io, DPU_RSC_SOLVER_MODE_PARM3_DRV0_MODE0, - rsc->timer_config.pdc_backoff_time_ns, rsc->debug_mode); - - dss_reg_w(&rsc->drv_io, DPU_RSC_SOLVER_MODE_PARM0_DRV0_MODE1, - mode_1_start_addr, rsc->debug_mode); - dss_reg_w(&rsc->drv_io, DPU_RSC_SOLVER_MODE_PARM1_DRV0_MODE1, - 0x80000000, rsc->debug_mode); - dss_reg_w(&rsc->drv_io, DPU_RSC_SOLVER_MODE_PARM2_DRV0_MODE1, - rsc->timer_config.rsc_backoff_time_ns, rsc->debug_mode); - dss_reg_w(&rsc->drv_io, DPU_RSC_SOLVER_MODE_PARM3_DRV0_MODE1, - rsc->timer_config.pdc_backoff_time_ns, rsc->debug_mode); - - dss_reg_w(&rsc->drv_io, DPU_RSC_SOLVER_MODE_PARM0_DRV0_MODE2, - mode_2_start_addr, rsc->debug_mode); - dss_reg_w(&rsc->drv_io, DPU_RSC_SOLVER_MODE_PARM1_DRV0_MODE2, - 0x80000000, rsc->debug_mode); - dss_reg_w(&rsc->drv_io, DPU_RSC_SOLVER_MODE_PARM2_DRV0_MODE2, - 0x0, rsc->debug_mode); - dss_reg_w(&rsc->drv_io, DPU_RSC_SOLVER_MODE_PARM3_DRV0_MODE2, - rsc->timer_config.pdc_backoff_time_ns, rsc->debug_mode); - - return 0; -} - -static int rsc_hw_timer_update(struct dpu_rsc_priv *rsc) -{ - if (!rsc) { - pr_debug("invalid input param\n"); - return -EINVAL; - } - - pr_debug("rsc hw timer update\n"); - - dss_reg_w(&rsc->drv_io, DPU_RSC_SOLVER_TIME_SLOT_TABLE_1_DRV0, - rsc->timer_config.rsc_time_slot_0_ns, rsc->debug_mode); - dss_reg_w(&rsc->drv_io, DPU_RSC_SOLVER_TIME_SLOT_TABLE_2_DRV0, - rsc->timer_config.rsc_time_slot_1_ns, rsc->debug_mode); - dss_reg_w(&rsc->drv_io, DPU_RSC_SOLVER_TIME_SLOT_TABLE_3_DRV0, - rsc->timer_config.rsc_time_slot_2_ns, rsc->debug_mode); - - dss_reg_w(&rsc->drv_io, DPU_RSC_SOLVER_MODE_PARM2_DRV0_MODE0, - rsc->timer_config.rsc_backoff_time_ns, rsc->debug_mode); - dss_reg_w(&rsc->drv_io, DPU_RSC_SOLVER_MODE_PARM3_DRV0_MODE0, - rsc->timer_config.pdc_backoff_time_ns, rsc->debug_mode); - - dss_reg_w(&rsc->drv_io, DPU_RSC_SOLVER_MODE_PARM2_DRV0_MODE1, - rsc->timer_config.rsc_backoff_time_ns, rsc->debug_mode); - dss_reg_w(&rsc->drv_io, DPU_RSC_SOLVER_MODE_PARM3_DRV0_MODE1, - rsc->timer_config.pdc_backoff_time_ns, rsc->debug_mode); - - dss_reg_w(&rsc->drv_io, DPU_RSC_SOLVER_MODE_PARM3_DRV0_MODE2, - rsc->timer_config.pdc_backoff_time_ns, rsc->debug_mode); - - dss_reg_w(&rsc->wrapper_io, DPU_RSCC_WRAPPER_STATIC_WAKEUP_0, - rsc->timer_config.static_wakeup_time_ns, rsc->debug_mode); - - dss_reg_w(&rsc->wrapper_io, DPU_RSCC_WRAPPER_RSCC_MODE_THRESHOLD, - rsc->timer_config.rsc_mode_threshold_time_ns, rsc->debug_mode); - - /* make sure that hw timers are updated */ - wmb(); - - return 0; -} - -static int dpu_rsc_mode2_exit(struct dpu_rsc_priv *rsc, - enum dpu_rsc_state state) -{ - int rc = -EBUSY; - int count, reg; - unsigned long power_status; - - rsc_event_trigger(rsc, DPU_RSC_EVENT_PRE_CORE_RESTORE); - - /** - * force busy and idle during clk & video mode state because it - * is trying to entry in mode-2 without turning on the vysnc. - */ - if ((state == DPU_RSC_VID_STATE) || (state == DPU_RSC_CLK_STATE)) { - reg = dss_reg_r(&rsc->wrapper_io, - DPU_RSCC_WRAPPER_OVERRIDE_CTRL, rsc->debug_mode); - reg &= ~(BIT(8) | BIT(0)); - dss_reg_w(&rsc->wrapper_io, DPU_RSCC_WRAPPER_OVERRIDE_CTRL, - reg, rsc->debug_mode); - } - - // needs review with HPG sequence - dss_reg_w(&rsc->wrapper_io, DPU_RSCC_F1_QTMR_V1_CNTP_CVAL_LO, - 0x0, rsc->debug_mode); - dss_reg_w(&rsc->wrapper_io, DPU_RSCC_F1_QTMR_V1_CNTP_CVAL_HI, - 0x0, rsc->debug_mode); - - reg = dss_reg_r(&rsc->wrapper_io, DPU_RSCC_WRAPPER_CTRL, - rsc->debug_mode); - reg &= ~BIT(3); - dss_reg_w(&rsc->wrapper_io, DPU_RSCC_WRAPPER_CTRL, - reg, rsc->debug_mode); - - reg = dss_reg_r(&rsc->wrapper_io, DPU_RSCC_SPARE_PWR_EVENT, - rsc->debug_mode); - reg |= BIT(13); - dss_reg_w(&rsc->wrapper_io, DPU_RSCC_SPARE_PWR_EVENT, - reg, rsc->debug_mode); - - /* make sure that mode-2 exit before wait*/ - wmb(); - - /* this wait is required to make sure that gdsc is powered on */ - for (count = MAX_CHECK_LOOPS; count > 0; count--) { - power_status = dss_reg_r(&rsc->wrapper_io, - DPU_RSCC_PWR_CTRL, rsc->debug_mode); - if (!test_bit(POWER_CTRL_BIT_12, &power_status)) { - reg = dss_reg_r(&rsc->drv_io, - DPU_RSCC_SEQ_PROGRAM_COUNTER, rsc->debug_mode); - DPU_EVT32_VERBOSE(count, reg, power_status); - rc = 0; - break; - } - usleep_range(10, 100); - } - - reg = dss_reg_r(&rsc->wrapper_io, DPU_RSCC_SPARE_PWR_EVENT, - rsc->debug_mode); - reg &= ~BIT(13); - dss_reg_w(&rsc->wrapper_io, DPU_RSCC_SPARE_PWR_EVENT, - reg, rsc->debug_mode); - if (rc) - pr_err("vdd reg is not enabled yet\n"); - - rsc_event_trigger(rsc, DPU_RSC_EVENT_POST_CORE_RESTORE); - - return rc; -} - -static int dpu_rsc_mode2_entry(struct dpu_rsc_priv *rsc) -{ - int rc; - int count, wrapper_status; - unsigned long reg; - - if (rsc->power_collapse_block) - return -EINVAL; - - rc = regulator_set_mode(rsc->fs, REGULATOR_MODE_FAST); - if (rc) { - pr_err("vdd reg fast mode set failed rc:%d\n", rc); - return rc; - } - - rsc_event_trigger(rsc, DPU_RSC_EVENT_PRE_CORE_PC); - - /* update qtimers to high during clk & video mode state */ - if ((rsc->current_state == DPU_RSC_VID_STATE) || - (rsc->current_state == DPU_RSC_CLK_STATE)) { - dss_reg_w(&rsc->wrapper_io, DPU_RSCC_F0_QTMR_V1_CNTP_CVAL_HI, - 0xffffffff, rsc->debug_mode); - dss_reg_w(&rsc->wrapper_io, DPU_RSCC_F0_QTMR_V1_CNTP_CVAL_LO, - 0xffffffff, rsc->debug_mode); - } - - wrapper_status = dss_reg_r(&rsc->wrapper_io, DPU_RSCC_WRAPPER_CTRL, - rsc->debug_mode); - wrapper_status |= BIT(3); - wrapper_status |= BIT(0); - dss_reg_w(&rsc->wrapper_io, DPU_RSCC_WRAPPER_CTRL, - wrapper_status, rsc->debug_mode); - - /** - * force busy and idle during clk & video mode state because it - * is trying to entry in mode-2 without turning on the vysnc. - */ - if ((rsc->current_state == DPU_RSC_VID_STATE) || - (rsc->current_state == DPU_RSC_CLK_STATE)) { - dss_reg_w(&rsc->wrapper_io, DPU_RSCC_WRAPPER_OVERRIDE_CTRL, - BIT(0) | BIT(1), rsc->debug_mode); - wmb(); /* force busy gurantee */ - dss_reg_w(&rsc->wrapper_io, DPU_RSCC_WRAPPER_OVERRIDE_CTRL, - BIT(0) | BIT(9), rsc->debug_mode); - } - - /* make sure that mode-2 is triggered before wait*/ - wmb(); - - rc = -EBUSY; - /* this wait is required to turn off the rscc clocks */ - for (count = MAX_CHECK_LOOPS; count > 0; count--) { - reg = dss_reg_r(&rsc->wrapper_io, - DPU_RSCC_PWR_CTRL, rsc->debug_mode); - if (test_bit(POWER_CTRL_BIT_12, ®)) { - rc = 0; - break; - } - usleep_range(10, 100); - } - - if (rc) { - pr_err("mdss gdsc power down failed rc:%d\n", rc); - DPU_EVT32(rc, DPU_EVTLOG_ERROR); - goto end; - } - - if ((rsc->current_state == DPU_RSC_VID_STATE) || - (rsc->current_state == DPU_RSC_CLK_STATE)) { - dss_reg_w(&rsc->wrapper_io, DPU_RSCC_WRAPPER_OVERRIDE_CTRL, - BIT(0) | BIT(8), rsc->debug_mode); - wmb(); /* force busy on vsync */ - } - - rsc_event_trigger(rsc, DPU_RSC_EVENT_POST_CORE_PC); - - return 0; - -end: - dpu_rsc_mode2_exit(rsc, rsc->current_state); - - return rc; -} - -static int dpu_rsc_state_update(struct dpu_rsc_priv *rsc, - enum dpu_rsc_state state) -{ - int rc = 0; - int reg; - - if (rsc->power_collapse) { - rc = dpu_rsc_mode2_exit(rsc, state); - if (rc) - pr_err("power collapse: mode2 exit failed\n"); - else - rsc->power_collapse = false; - } - - switch (state) { - case DPU_RSC_CMD_STATE: - pr_debug("command mode handling\n"); - - dss_reg_w(&rsc->wrapper_io, DPU_RSCC_WRAPPER_CTRL, - 0x1, rsc->debug_mode); - dss_reg_w(&rsc->drv_io, DPU_RSCC_SOLVER_OVERRIDE_CTRL_DRV0, - 0x0, rsc->debug_mode); - reg = dss_reg_r(&rsc->wrapper_io, - DPU_RSCC_WRAPPER_OVERRIDE_CTRL, rsc->debug_mode); - reg |= (BIT(0) | BIT(8)); - reg &= ~(BIT(1) | BIT(2) | BIT(3) | BIT(6) | BIT(7) | BIT(9)); - dss_reg_w(&rsc->wrapper_io, DPU_RSCC_WRAPPER_OVERRIDE_CTRL, - reg, rsc->debug_mode); - /* make sure that solver is enabled */ - wmb(); - - rsc_event_trigger(rsc, DPU_RSC_EVENT_SOLVER_ENABLED); - break; - - case DPU_RSC_VID_STATE: - pr_debug("video mode handling\n"); - - dss_reg_w(&rsc->wrapper_io, DPU_RSCC_WRAPPER_CTRL, - 0x1, rsc->debug_mode); - reg = dss_reg_r(&rsc->wrapper_io, - DPU_RSCC_WRAPPER_OVERRIDE_CTRL, rsc->debug_mode); - reg |= BIT(8); - reg &= ~(BIT(1) | BIT(0)); - dss_reg_w(&rsc->wrapper_io, DPU_RSCC_WRAPPER_OVERRIDE_CTRL, - reg, rsc->debug_mode); - /* make sure that solver mode is override */ - wmb(); - - rsc_event_trigger(rsc, DPU_RSC_EVENT_SOLVER_DISABLED); - break; - - case DPU_RSC_CLK_STATE: - pr_debug("clk state handling\n"); - - reg = dss_reg_r(&rsc->wrapper_io, - DPU_RSCC_WRAPPER_OVERRIDE_CTRL, rsc->debug_mode); - reg &= ~(BIT(8) | BIT(0)); - dss_reg_w(&rsc->wrapper_io, DPU_RSCC_WRAPPER_OVERRIDE_CTRL, - reg, rsc->debug_mode); - /* make sure that solver mode is disabled */ - wmb(); - break; - - case DPU_RSC_IDLE_STATE: - rc = dpu_rsc_mode2_entry(rsc); - if (rc) - pr_err("power collapse - mode 2 entry failed\n"); - else - rsc->power_collapse = true; - break; - - default: - pr_err("state:%d handling is not supported\n", state); - break; - } - - return rc; -} - -int rsc_hw_init(struct dpu_rsc_priv *rsc) -{ - int rc = 0; - - rc = rsc_hw_qtimer_init(rsc); - if (rc) { - pr_err("rsc hw qtimer init failed\n"); - goto end; - } - - rc = rsc_hw_wrapper_init(rsc); - if (rc) { - pr_err("rsc hw wrapper init failed\n"); - goto end; - } - - rc = rsc_hw_seq_memory_init(rsc); - if (rc) { - pr_err("rsc sequencer memory init failed\n"); - goto end; - } - - rc = rsc_hw_solver_init(rsc); - if (rc) { - pr_err("rsc solver init failed\n"); - goto end; - } - - rc = rsc_hw_pdc_init(rsc); - if (rc) { - pr_err("rsc hw pdc init failed\n"); - goto end; - } - - /* make sure that hw is initialized */ - wmb(); - - pr_info("dpu rsc init successfully done\n"); -end: - return rc; -} - -int rsc_hw_mode_ctrl(struct dpu_rsc_priv *rsc, enum rsc_mode_req request, - char *buffer, int buffer_size, u32 mode) -{ - u32 blen = 0; - u32 slot_time; - - switch (request) { - case MODE_READ: - if (!buffer || !buffer_size) - return blen; - - blen = snprintf(buffer, buffer_size - blen, - "mode_status:0x%x\n", - dss_reg_r(&rsc->drv_io, DPU_RSCC_SOLVER_STATUS2_DRV0, - rsc->debug_mode)); - break; - - case MODE_UPDATE: - slot_time = mode & BIT(0) ? 0x0 : - rsc->timer_config.rsc_time_slot_2_ns; - dss_reg_w(&rsc->drv_io, DPU_RSC_SOLVER_TIME_SLOT_TABLE_0_DRV0, - slot_time, rsc->debug_mode); - - slot_time = mode & BIT(1) ? - rsc->timer_config.rsc_time_slot_0_ns : - rsc->timer_config.rsc_time_slot_2_ns; - dss_reg_w(&rsc->drv_io, DPU_RSC_SOLVER_TIME_SLOT_TABLE_1_DRV0, - slot_time, rsc->debug_mode); - - rsc->power_collapse_block = !(mode & BIT(2)); - break; - - default: - break; - } - - return blen; -} - -int dpu_rsc_debug_show(struct seq_file *s, struct dpu_rsc_priv *rsc) -{ - seq_printf(s, "override ctrl:0x%x\n", - dss_reg_r(&rsc->wrapper_io, DPU_RSCC_WRAPPER_OVERRIDE_CTRL, - rsc->debug_mode)); - seq_printf(s, "power ctrl:0x%x\n", - dss_reg_r(&rsc->wrapper_io, DPU_RSCC_PWR_CTRL, - rsc->debug_mode)); - seq_printf(s, "vsycn timestamp0:0x%x\n", - dss_reg_r(&rsc->wrapper_io, DPU_RSCC_WRAPPER_VSYNC_TIMESTAMP0, - rsc->debug_mode)); - seq_printf(s, "vsycn timestamp1:0x%x\n", - dss_reg_r(&rsc->wrapper_io, DPU_RSCC_WRAPPER_VSYNC_TIMESTAMP1, - rsc->debug_mode)); - - seq_printf(s, "error irq status:0x%x\n", - dss_reg_r(&rsc->drv_io, DPU_RSCC_ERROR_IRQ_STATUS_DRV0, - rsc->debug_mode)); - - seq_printf(s, "seq busy status:0x%x\n", - dss_reg_r(&rsc->drv_io, DPU_RSCC_SEQ_BUSY_DRV0, - rsc->debug_mode)); - - seq_printf(s, "solver override ctrl status:0x%x\n", - dss_reg_r(&rsc->drv_io, DPU_RSCC_SOLVER_OVERRIDE_CTRL_DRV0, - rsc->debug_mode)); - seq_printf(s, "solver override status:0x%x\n", - dss_reg_r(&rsc->drv_io, DPU_RSCC_SOLVER_STATUS0_DRV0, - rsc->debug_mode)); - seq_printf(s, "solver timeslot status:0x%x\n", - dss_reg_r(&rsc->drv_io, DPU_RSCC_SOLVER_STATUS1_DRV0, - rsc->debug_mode)); - seq_printf(s, "solver mode status:0x%x\n", - dss_reg_r(&rsc->drv_io, DPU_RSCC_SOLVER_STATUS2_DRV0, - rsc->debug_mode)); - - seq_printf(s, "amc status:0x%x\n", - dss_reg_r(&rsc->drv_io, DPU_RSCC_AMC_TCS_MODE_IRQ_STATUS_DRV0, - rsc->debug_mode)); - - return 0; -} - -int rsc_hw_vsync(struct dpu_rsc_priv *rsc, enum rsc_vsync_req request, - char *buffer, int buffer_size, u32 mode) -{ - u32 blen = 0, reg; - - switch (request) { - case VSYNC_READ: - if (!buffer || !buffer_size) - return blen; - - blen = snprintf(buffer, buffer_size - blen, "vsync0:0x%x\n", - dss_reg_r(&rsc->wrapper_io, - DPU_RSCC_WRAPPER_VSYNC_TIMESTAMP0, - rsc->debug_mode)); - if (blen >= buffer_size) - return blen; - - blen += snprintf(buffer + blen, buffer_size - blen, - "vsync1:0x%x\n", - dss_reg_r(&rsc->wrapper_io, - DPU_RSCC_WRAPPER_VSYNC_TIMESTAMP1, - rsc->debug_mode)); - break; - - case VSYNC_READ_VSYNC0: - return dss_reg_r(&rsc->wrapper_io, - DPU_RSCC_WRAPPER_VSYNC_TIMESTAMP0, - rsc->debug_mode); - - case VSYNC_ENABLE: - /* clear the current VSYNC value */ - reg = BIT(9) | ((mode & 0x7) << 10); - dss_reg_w(&rsc->wrapper_io, DPU_RSCC_WRAPPER_DEBUG_BUS, - reg, rsc->debug_mode); - - /* enable the VSYNC logging */ - reg = BIT(8) | ((mode & 0x7) << 10); - dss_reg_w(&rsc->wrapper_io, DPU_RSCC_WRAPPER_DEBUG_BUS, - reg, rsc->debug_mode); - - /* ensure vsync config has been written before waiting on it */ - wmb(); - break; - - case VSYNC_DISABLE: - dss_reg_w(&rsc->wrapper_io, DPU_RSCC_WRAPPER_DEBUG_BUS, - 0x0, rsc->debug_mode); - break; - } - - return blen; -} - -static void rsc_hw_debug_dump(struct dpu_rsc_priv *rsc, u32 mux_sel) -{ - dss_reg_w(&rsc->wrapper_io, DPU_RSCC_WRAPPER_DEBUG_BUS, - ((mux_sel & 0xf) << 1) | BIT(0), rsc->debug_mode); -} - -bool rsc_hw_is_amc_mode(struct dpu_rsc_priv *rsc) -{ - return dss_reg_r(&rsc->drv_io, DPU_RSCC_TCS_DRV0_CONTROL, - rsc->debug_mode) & BIT(16); -} - -int rsc_hw_tcs_wait(struct dpu_rsc_priv *rsc) -{ - int rc = -EBUSY; - int count, seq_status; - - dss_reg_w(&rsc->wrapper_io, DPU_RSCC_WRAPPER_CTRL, - 0x0, rsc->debug_mode); - seq_status = dss_reg_r(&rsc->wrapper_io, DPU_RSCC_WRAPPER_CTRL, - rsc->debug_mode) & BIT(1); - /* if seq busy - set TCS use OK to high and wait for 200us */ - if (seq_status) { - dss_reg_w(&rsc->wrapper_io, DPU_RSCC_WRAPPER_CTRL, - 0x1, rsc->debug_mode); - usleep_range(100, 200); - dss_reg_w(&rsc->wrapper_io, DPU_RSCC_WRAPPER_CTRL, - 0x0, rsc->debug_mode); - } - - /* check for sequence running status before exiting */ - for (count = MAX_CHECK_LOOPS; count > 0; count--) { - seq_status = dss_reg_r(&rsc->wrapper_io, DPU_RSCC_WRAPPER_CTRL, - rsc->debug_mode) & BIT(1); - if (!seq_status) { - rc = 0; - break; - } - usleep_range(1, 2); - } - - return rc; -} - -int rsc_hw_tcs_use_ok(struct dpu_rsc_priv *rsc) -{ - dss_reg_w(&rsc->wrapper_io, DPU_RSCC_WRAPPER_CTRL, - 0x1, rsc->debug_mode); - return 0; -} - -int dpu_rsc_hw_register(struct dpu_rsc_priv *rsc) -{ - pr_debug("rsc hardware register\n"); - - rsc->hw_ops.init = rsc_hw_init; - rsc->hw_ops.timer_update = rsc_hw_timer_update; - - rsc->hw_ops.tcs_wait = rsc_hw_tcs_wait; - rsc->hw_ops.tcs_use_ok = rsc_hw_tcs_use_ok; - rsc->hw_ops.is_amc_mode = rsc_hw_is_amc_mode; - - rsc->hw_ops.hw_vsync = rsc_hw_vsync; - rsc->hw_ops.state_update = dpu_rsc_state_update; - rsc->hw_ops.debug_show = dpu_rsc_debug_show; - rsc->hw_ops.mode_ctrl = rsc_hw_mode_ctrl; - rsc->hw_ops.debug_dump = rsc_hw_debug_dump; - - return 0; -} diff --git a/drivers/gpu/drm/msm/dpu_rsc_priv.h b/drivers/gpu/drm/msm/dpu_rsc_priv.h deleted file mode 100644 index b28a339..0000000 --- a/drivers/gpu/drm/msm/dpu_rsc_priv.h +++ /dev/null @@ -1,191 +0,0 @@ -/* Copyright (c) 2016-2018, The Linux Foundation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 and - * only version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - */ - -#ifndef _DPU_RSC_PRIV_H_ -#define _DPU_RSC_PRIV_H_ - -#include -#include -#include - -#include -#include "dpu_power_handle.h" - -#define DPU_RSC_COMPATIBLE "disp_rscc" - -#define MAX_RSC_COUNT 5 - -#define ALL_MODES_DISABLED 0x0 -#define ONLY_MODE_0_ENABLED 0x1 -#define ONLY_MODE_0_1_ENABLED 0x3 -#define ALL_MODES_ENABLED 0x7 - -#define MAX_COUNT_SIZE_SUPPORTED 128 - -struct dpu_rsc_priv; - -/** - * rsc_mode_req: dpu rsc mode request information - * MODE_READ: read vsync status - * MODE_UPDATE: mode timeslot update - * 0x0: all modes are disabled. - * 0x1: Mode-0 is enabled and other two modes are disabled. - * 0x3: Mode-0 & Mode-1 are enabled and mode-2 is disabled. - * 0x7: all modes are enabled. - */ -enum rsc_mode_req { - MODE_READ, - MODE_UPDATE = 0x1, -}; - -/** - * rsc_vsync_req: dpu rsc vsync request information - * VSYNC_READ: read vsync status - * VSYNC_READ_VSYNC0: read value vsync0 timestamp (cast to int from u32) - * VSYNC_ENABLE: enable rsc wrapper vsync status - * VSYNC_DISABLE: disable rsc wrapper vsync status - */ -enum rsc_vsync_req { - VSYNC_READ, - VSYNC_READ_VSYNC0, - VSYNC_ENABLE, - VSYNC_DISABLE, -}; - -/** - * struct dpu_rsc_hw_ops - dpu resource state coordinator hardware ops - * @init: Initialize the sequencer, solver, qtimer, - etc. hardware blocks on RSC. - * @timer_update: update the static wrapper time and pdc/rsc - backoff time. - * @tcs_wait: Waits for TCS block OK to allow sending a - * TCS command. - * @hw_vsync: Enables the vsync on RSC block. - * @tcs_use_ok: set TCS set to high to allow RSC to use it. - * @is_amc_mode: Check current amc mode status - * @debug_dump: dump debug bus registers or enable debug bus - * @state_update: Enable/override the solver based on rsc state - * status (command/video) - * @mode_show: shows current mode status, mode0/1/2 - * @debug_show: Show current debug status. - */ - -struct dpu_rsc_hw_ops { - int (*init)(struct dpu_rsc_priv *rsc); - int (*timer_update)(struct dpu_rsc_priv *rsc); - int (*tcs_wait)(struct dpu_rsc_priv *rsc); - int (*hw_vsync)(struct dpu_rsc_priv *rsc, enum rsc_vsync_req request, - char *buffer, int buffer_size, u32 mode); - int (*tcs_use_ok)(struct dpu_rsc_priv *rsc); - bool (*is_amc_mode)(struct dpu_rsc_priv *rsc); - void (*debug_dump)(struct dpu_rsc_priv *rsc, u32 mux_sel); - int (*state_update)(struct dpu_rsc_priv *rsc, enum dpu_rsc_state state); - int (*debug_show)(struct seq_file *s, struct dpu_rsc_priv *rsc); - int (*mode_ctrl)(struct dpu_rsc_priv *rsc, enum rsc_mode_req request, - char *buffer, int buffer_size, u32 mode); -}; - -/** - * struct dpu_rsc_timer_config: this is internal configuration between - * rsc and rsc_hw API. - * - * @static_wakeup_time_ns: wrapper backoff time in nano seconds - * @rsc_backoff_time_ns: rsc backoff time in nano seconds - * @pdc_backoff_time_ns: pdc backoff time in nano seconds - * @rsc_mode_threshold_time_ns: rsc mode threshold time in nano seconds - * @rsc_time_slot_0_ns: mode-0 time slot threshold in nano seconds - * @rsc_time_slot_1_ns: mode-1 time slot threshold in nano seconds - * @rsc_time_slot_2_ns: mode-2 time slot threshold in nano seconds - */ -struct dpu_rsc_timer_config { - u32 static_wakeup_time_ns; - - u32 rsc_backoff_time_ns; - u32 pdc_backoff_time_ns; - u32 rsc_mode_threshold_time_ns; - u32 rsc_time_slot_0_ns; - u32 rsc_time_slot_1_ns; - u32 rsc_time_slot_2_ns; -}; - -/** - * struct dpu_rsc_priv: dpu resource state coordinator(rsc) private handle - * @version: rsc sequence version - * @phandle: module power handle for clocks - * @pclient: module power client of phandle - * @fs: "MDSS GDSC" handle - * - * @disp_rsc: display rsc handle - * @drv_io: dpu drv io data mapping - * @wrapper_io: wrapper io data mapping - * - * @client_list: current rsc client list handle - * @event_list: current rsc event list handle - * @client_lock: current rsc client synchronization lock - * - * timer_config: current rsc timer configuration - * cmd_config: current panel config - * current_state: current rsc state (video/command), solver - * override/enabled. - * debug_mode: enables the logging for each register read/write - * debugfs_root: debugfs file system root node - * - * hw_ops: dpu rsc hardware operations - * power_collapse: if all clients are in IDLE state then it enters in - * mode2 state and enable the power collapse state - * power_collapse_block:By default, rsc move to mode-2 if all clients are in - * invalid state. It can be blocked by this boolean entry. - * primary_client: A client which is allowed to make command state request - * and ab/ib vote on display rsc - * master_drm: Primary client waits for vsync on this drm object based - * on crtc id - */ -struct dpu_rsc_priv { - u32 version; - struct dpu_power_handle phandle; - struct dpu_power_client *pclient; - struct regulator *fs; - - struct rpmh_client *disp_rsc; - struct dss_io_data drv_io; - struct dss_io_data wrapper_io; - - struct list_head client_list; - struct list_head event_list; - struct mutex client_lock; - - struct dpu_rsc_timer_config timer_config; - struct dpu_rsc_cmd_config cmd_config; - u32 current_state; - - u32 debug_mode; - struct dentry *debugfs_root; - - struct dpu_rsc_hw_ops hw_ops; - bool power_collapse; - bool power_collapse_block; - struct dpu_rsc_client *primary_client; - - struct drm_device *master_drm; -}; - -/** - * dpu_rsc_hw_register() - register hardware API - * - * @client: Client pointer provided by dpu_rsc_client_create(). - * - * Return: error code. - */ -int dpu_rsc_hw_register(struct dpu_rsc_priv *rsc); - -#endif /* _DPU_RSC_PRIV_H_ */ diff --git a/include/linux/dpu_rsc.h b/include/linux/dpu_rsc.h deleted file mode 100644 index 81bea5e..0000000 --- a/include/linux/dpu_rsc.h +++ /dev/null @@ -1,302 +0,0 @@ -/* Copyright (c) 2016-2018, The Linux Foundation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 and - * only version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - */ - -#ifndef _DPU_RSC_H_ -#define _DPU_RSC_H_ - -#include - -/* primary display rsc index */ -#define DPU_RSC_INDEX 0 - -#define MAX_RSC_CLIENT_NAME_LEN 128 - -/* DRM Object IDs are numbered excluding 0, use 0 to indicate invalid CRTC */ -#define DPU_RSC_INVALID_CRTC_ID 0 - -/** - * event will be triggered before sde core power collapse, - * mdss gdsc is still on - */ -#define DPU_RSC_EVENT_PRE_CORE_PC 0x1 -/** - * event will be triggered after sde core collapse complete, - * mdss gdsc is off now - */ -#define DPU_RSC_EVENT_POST_CORE_PC 0x2 -/** - * event will be triggered before restoring the sde core from power collapse, - * mdss gdsc is still off - */ -#define DPU_RSC_EVENT_PRE_CORE_RESTORE 0x4 -/** - * event will be triggered after restoring the sde core from power collapse, - * mdss gdsc is on now - */ -#define DPU_RSC_EVENT_POST_CORE_RESTORE 0x8 -/** - * event attached with solver state enabled - * all clients in clk_state or cmd_state - */ -#define DPU_RSC_EVENT_SOLVER_ENABLED 0x10 -/** - * event attached with solver state disabled - * one of the client requested for vid state - */ -#define DPU_RSC_EVENT_SOLVER_DISABLED 0x20 - -/** - * dpu_rsc_state: sde rsc state information - * DPU_RSC_IDLE_STATE: A client requests for idle state when there is no - * pixel or cmd transfer expected. An idle vote from - * all clients lead to power collapse state. - * DPU_RSC_CLK_STATE: A client requests for clk state when it wants to - * only avoid mode-2 entry/exit. For ex: V4L2 driver, - * sde power handle, etc. - * DPU_RSC_CMD_STATE: A client requests for cmd state when it wants to - * enable the solver mode. - * DPU_RSC_VID_STATE: A client requests for vid state it wants to avoid - * solver enable because client is fetching data from - * continuously. - */ -enum dpu_rsc_state { - DPU_RSC_IDLE_STATE, - DPU_RSC_CLK_STATE, - DPU_RSC_CMD_STATE, - DPU_RSC_VID_STATE, -}; - -/** - * struct dpu_rsc_client: stores the rsc client for sde driver - * @name: name of the client - * @current_state: current client state - * @crtc_id: crtc_id associated with this rsc client. - * @rsc_index: rsc index of a client - only index "0" valid. - * @id: Index of client. It will be assigned during client_create call - * @list: list to attach client master list - */ -struct dpu_rsc_client { - char name[MAX_RSC_CLIENT_NAME_LEN]; - short current_state; - int crtc_id; - u32 rsc_index; - u32 id; - struct list_head list; -}; - -/** - * struct dpu_rsc_event: local event registration entry structure - * @cb_func: Pointer to desired callback function - * @usr: User pointer to pass to callback on event trigger - * @rsc_index: rsc index of a client - only index "0" valid. - * @event_type: refer comments in event_register - * @list: list to attach event master list - */ -struct dpu_rsc_event { - void (*cb_func)(uint32_t event_type, void *usr); - void *usr; - u32 rsc_index; - uint32_t event_type; - struct list_head list; -}; - -/** - * struct dpu_rsc_cmd_config: provides panel configuration to rsc - * when client is command mode. It is not required to set it during - * video mode. - * - * @fps: panel te interval - * @vtotal: current vertical total (height + vbp + vfp) - * @jitter_numer: panel jitter numerator value. This config causes rsc/solver - * early before te. Default is 0.8% jitter. - * @jitter_denom: panel jitter denominator. - * @prefill_lines: max prefill lines based on panel - */ -struct dpu_rsc_cmd_config { - u32 fps; - u32 vtotal; - u32 jitter_numer; - u32 jitter_denom; - u32 prefill_lines; -}; - -#ifdef CONFIG_DRM_DPU_RSC -/** - * dpu_rsc_client_create() - create the client for sde rsc. - * Different displays like DSI, HDMI, DP, WB, etc should call this - * api to register their vote for rpmh. They still need to vote for - * power handle to get the clocks. - - * @rsc_index: A client will be created on this RSC. As of now only - * DPU_RSC_INDEX is valid rsc index. - * @name: Caller needs to provide some valid string to identify - * the client. "primary", "dp", "hdmi" are suggested name. - * @is_primary: Caller needs to provide information if client is primary - * or not. Primary client votes will be redirected to - * display rsc. - * @config: fps, vtotal, porches, etc configuration for command mode - * panel - * - * Return: client node pointer. - */ -struct dpu_rsc_client *dpu_rsc_client_create(u32 rsc_index, char *name, - bool is_primary_display); - -/** - * dpu_rsc_client_destroy() - Destroy the sde rsc client. - * - * @client: Client pointer provided by dpu_rsc_client_create(). - * - * Return: none - */ -void dpu_rsc_client_destroy(struct dpu_rsc_client *client); - -/** - * dpu_rsc_client_state_update() - rsc client state update - * Video mode, cmd mode and clk state are supported as modes. A client need to - * set this property during panel time. A switching client can set the - * property to change the state - * - * @client: Client pointer provided by dpu_rsc_client_create(). - * @state: Client state - video/cmd - * @config: fps, vtotal, porches, etc configuration for command mode - * panel - * @crtc_id: current client's crtc id - * @wait_vblank_crtc_id: Output parameter. If set to non-zero, rsc hw - * state update requires a wait for one vblank on - * the primary crtc. In that case, this output - * param will be set to the crtc on which to wait. - * If DPU_RSC_INVALID_CRTC_ID, no wait necessary - * - * Return: error code. - */ -int dpu_rsc_client_state_update(struct dpu_rsc_client *client, - enum dpu_rsc_state state, - struct dpu_rsc_cmd_config *config, int crtc_id, - int *wait_vblank_crtc_id); - -/** - * dpu_rsc_client_is_state_update_complete() - check if state update is complete - * RSC state transition is not complete until HW receives VBLANK signal. This - * function checks RSC HW to determine whether that signal has been received. - * @client: Client pointer provided by dpu_rsc_client_create(). - * - * Return: true if the state update has completed. - */ -bool dpu_rsc_client_is_state_update_complete( - struct dpu_rsc_client *caller_client); - -/** - * dpu_rsc_client_vote() - ab/ib vote from rsc client - * - * @client: Client pointer provided by dpu_rsc_client_create(). - * @bus_id: data bus identifier - * @ab: aggregated bandwidth vote from client. - * @ib: instant bandwidth vote from client. - * - * Return: error code. - */ -int dpu_rsc_client_vote(struct dpu_rsc_client *caller_client, - u32 bus_id, u64 ab_vote, u64 ib_vote); - -/** - * dpu_rsc_register_event - register a callback function for an event - * @rsc_index: A client will be created on this RSC. As of now only - * DPU_RSC_INDEX is valid rsc index. - * @event_type: event type to register; client sets 0x3 if it wants - * to register for CORE_PC and CORE_RESTORE - both events. - * @cb_func: Pointer to desired callback function - * @usr: User pointer to pass to callback on event trigger - * Returns: dpu_rsc_event pointer on success - */ -struct dpu_rsc_event *dpu_rsc_register_event(int rsc_index, uint32_t event_type, - void (*cb_func)(uint32_t event_type, void *usr), void *usr); - -/** - * dpu_rsc_unregister_event - unregister callback for an event - * @dpu_rsc_event: event returned by dpu_rsc_register_event - */ -void dpu_rsc_unregister_event(struct dpu_rsc_event *event); - -/** - * is_dpu_rsc_available - check if display rsc available. - * @rsc_index: A client will be created on this RSC. As of now only - * DPU_RSC_INDEX is valid rsc index. - * Returns: true if rsc is available; false in all other cases - */ -bool is_dpu_rsc_available(int rsc_index); - -/** - * get_dpu_rsc_current_state - gets the current state of sde rsc. - * @rsc_index: A client will be created on this RSC. As of now only - * DPU_RSC_INDEX is valid rsc index. - * Returns: current state if rsc available; DPU_RSC_IDLE_STATE for - * all other cases - */ -enum dpu_rsc_state get_dpu_rsc_current_state(int rsc_index); - -#else - -static inline struct dpu_rsc_client *dpu_rsc_client_create(u32 rsc_index, - char *name, bool is_primary_display) -{ - return NULL; -} - -static inline void dpu_rsc_client_destroy(struct dpu_rsc_client *client) -{ -} - -static inline int dpu_rsc_client_state_update(struct dpu_rsc_client *client, - enum dpu_rsc_state state, - struct dpu_rsc_cmd_config *config, int crtc_id, - int *wait_vblank_crtc_id) -{ - return 0; -} - -static inline bool dpu_rsc_client_is_state_update_complete( - struct dpu_rsc_client *caller_client) -{ - return false; -} - -static inline int dpu_rsc_client_vote(struct dpu_rsc_client *caller_client, - u32 bus_id, u64 ab_vote, u64 ib_vote) -{ - return 0; -} - -static inline struct dpu_rsc_event *dpu_rsc_register_event(int rsc_index, - uint32_t event_type, - void (*cb_func)(uint32_t event_type, void *usr), void *usr) -{ - return NULL; -} - -static inline void dpu_rsc_unregister_event(struct dpu_rsc_event *event) -{ -} - -static inline bool is_dpu_rsc_available(int rsc_index) -{ - return false; -} - -static inline enum dpu_rsc_state get_dpu_rsc_current_state(int rsc_index) -{ - return DPU_RSC_IDLE_STATE; -} -#endif /* CONFIG_DRM_DPU_RSC */ - -#endif /* _DPU_RSC_H_ */