disp: msm: sde: add support for split VBIF clock access
From Kalama onwards, the VBIF CLK_CTRL register has been moved from TOP block to individual hardware block memory range. This change is adding a backward compatible solution to support per block VBIF CLK_CTRL access by allowing each HW block to register set of callback ops. Additionally, it adds DMA and IPCC/MSI VBIF CLK_CTRL block type. Change-Id: Ia82ced34cfa1636b57cd1c03b327faf923be482a Signed-off-by: Amine Najahi <anajahi@codeaurora.org>
Este cometimento está contido em:
@@ -1,6 +1,6 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (c) 2015-2020, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2015-2021, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#define pr_fmt(fmt) "[drm:%s:%d] " fmt, __func__, __LINE__
|
||||
@@ -14,6 +14,121 @@
|
||||
|
||||
#define MAX_XIN_CLIENT 16
|
||||
|
||||
#define VBIF_CLK_CLIENT(x) sde_kms->vbif_clk_clients[x]
|
||||
#define VBIF_CLK_CLIENT_NAME(x) sde_clk_ctrl_type_s[x]
|
||||
|
||||
int sde_vbif_clk_register(struct sde_kms *sde_kms, struct sde_vbif_clk_client *client)
|
||||
{
|
||||
enum sde_clk_ctrl_type clk_ctrl;
|
||||
|
||||
if (!sde_kms || !client)
|
||||
return -EINVAL;
|
||||
|
||||
clk_ctrl = client->clk_ctrl;
|
||||
if (!SDE_CLK_CTRL_VALID(clk_ctrl))
|
||||
return -EINVAL;
|
||||
|
||||
VBIF_CLK_CLIENT(clk_ctrl).hw = client->hw;
|
||||
VBIF_CLK_CLIENT(clk_ctrl).clk_ctrl = clk_ctrl;
|
||||
memcpy(&VBIF_CLK_CLIENT(clk_ctrl).ops, &client->ops, sizeof(struct sde_vbif_clk_ops));
|
||||
|
||||
SDE_DEBUG("registering hw:%pK clk_ctrl:%s\n", client->hw, VBIF_CLK_CLIENT_NAME(clk_ctrl));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* _sde_vbif_setup_clk_supported - check if VBIF setup_clk_force_ctrl API is supported
|
||||
* @sde_kms: Pointer to sde_kms object
|
||||
* @clk_ctrl: clock to be controlled
|
||||
* @return: true if client is supported, otherwise false
|
||||
*/
|
||||
static bool _sde_vbif_setup_clk_supported(struct sde_kms *sde_kms, enum sde_clk_ctrl_type clk_ctrl)
|
||||
{
|
||||
bool supported = false;
|
||||
bool has_split_vbif = test_bit(SDE_FEATURE_VBIF_CLK_SPLIT, sde_kms->catalog->features);
|
||||
|
||||
if ((has_split_vbif && VBIF_CLK_CLIENT(clk_ctrl).ops.setup_clk_force_ctrl) ||
|
||||
(!has_split_vbif && sde_kms->hw_mdp->ops.setup_clk_force_ctrl))
|
||||
supported = true;
|
||||
|
||||
SDE_DEBUG("split_vbif:%d type:%s supported:%d\n", has_split_vbif,
|
||||
VBIF_CLK_CLIENT_NAME(clk_ctrl), supported);
|
||||
|
||||
return supported;
|
||||
}
|
||||
|
||||
/**
|
||||
* _sde_vbif_get_clk_supported - check if VBIF get_clk_ctrl_status API is supported
|
||||
* @sde_kms: Pointer to sde_kms object
|
||||
* @clk_ctrl: clock to be controlled
|
||||
* @return: true if client is supported, otherwise false
|
||||
*/
|
||||
static bool _sde_vbif_get_clk_supported(struct sde_kms *sde_kms, enum sde_clk_ctrl_type clk_ctrl)
|
||||
{
|
||||
bool supported = false;
|
||||
bool has_split_vbif = test_bit(SDE_FEATURE_VBIF_CLK_SPLIT, sde_kms->catalog->features);
|
||||
|
||||
if ((has_split_vbif && VBIF_CLK_CLIENT(clk_ctrl).ops.get_clk_ctrl_status) ||
|
||||
(!has_split_vbif && sde_kms->hw_mdp->ops.get_clk_ctrl_status))
|
||||
supported = true;
|
||||
|
||||
SDE_DEBUG("split_vbif:%d type:%s supported:%d\n", has_split_vbif,
|
||||
VBIF_CLK_CLIENT_NAME(clk_ctrl), supported);
|
||||
|
||||
return supported;
|
||||
}
|
||||
|
||||
/**
|
||||
* _sde_vbif_setup_clk_force_ctrl - set clock force control
|
||||
* @sde_kms: Pointer to sde_kms object
|
||||
* @clk_ctrl: clock to be controlled
|
||||
* @enable: force on enable
|
||||
* @return: if the clock is forced-on by this function
|
||||
*/
|
||||
static int _sde_vbif_setup_clk_force_ctrl(struct sde_kms *sde_kms, enum sde_clk_ctrl_type clk_ctrl,
|
||||
bool enable)
|
||||
{
|
||||
int rc = 0;
|
||||
struct sde_hw_blk_reg_map *hw = VBIF_CLK_CLIENT(clk_ctrl).hw;
|
||||
bool has_split_vbif = test_bit(SDE_FEATURE_VBIF_CLK_SPLIT, sde_kms->catalog->features);
|
||||
|
||||
if (has_split_vbif)
|
||||
rc = VBIF_CLK_CLIENT(clk_ctrl).ops.setup_clk_force_ctrl(hw, clk_ctrl, enable);
|
||||
else
|
||||
rc = sde_kms->hw_mdp->ops.setup_clk_force_ctrl(sde_kms->hw_mdp, clk_ctrl, enable);
|
||||
|
||||
SDE_DEBUG("split_vbif:%d type:%s en:%d rc:%d\n", has_split_vbif,
|
||||
VBIF_CLK_CLIENT_NAME(clk_ctrl), enable, rc);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
* _sde_vbif_get_clk_ctrl_status - get clock control status
|
||||
* @sde_kms: Pointer to sde_kms object
|
||||
* @clk_ctrl: clock to be controlled
|
||||
* @status: returns true if clock is on
|
||||
* @return: 0 if success, otherwise return error code
|
||||
*/
|
||||
static int _sde_vbif_get_clk_ctrl_status(struct sde_kms *sde_kms, enum sde_clk_ctrl_type clk_ctrl,
|
||||
bool *status)
|
||||
{
|
||||
int rc = 0;
|
||||
struct sde_hw_blk_reg_map *hw = VBIF_CLK_CLIENT(clk_ctrl).hw;
|
||||
bool has_split_vbif = test_bit(SDE_FEATURE_VBIF_CLK_SPLIT, sde_kms->catalog->features);
|
||||
|
||||
if (has_split_vbif)
|
||||
rc = VBIF_CLK_CLIENT(clk_ctrl).ops.get_clk_ctrl_status(hw, clk_ctrl, status);
|
||||
else
|
||||
rc = sde_kms->hw_mdp->ops.get_clk_ctrl_status(sde_kms->hw_mdp, clk_ctrl, status);
|
||||
|
||||
SDE_DEBUG("split_vbif:%d type:%s status:%d rc:%d\n", has_split_vbif,
|
||||
VBIF_CLK_CLIENT_NAME(clk_ctrl), *status, rc);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
* _sde_vbif_wait_for_xin_halt - wait for the xin to halt
|
||||
* @vbif: Pointer to hardware vbif driver
|
||||
@@ -98,7 +213,7 @@ int sde_vbif_halt_plane_xin(struct sde_kms *sde_kms, u32 xin_id, u32 clk_ctrl)
|
||||
mdp = sde_kms->hw_mdp;
|
||||
if (!vbif || !mdp || !vbif->ops.get_xin_halt_status ||
|
||||
!vbif->ops.set_xin_halt ||
|
||||
!mdp->ops.setup_clk_force_ctrl) {
|
||||
!_sde_vbif_setup_clk_supported(sde_kms, clk_ctrl)) {
|
||||
SDE_ERROR("invalid vbif or mdp arguments\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
@@ -118,7 +233,7 @@ int sde_vbif_halt_plane_xin(struct sde_kms *sde_kms, u32 xin_id, u32 clk_ctrl)
|
||||
return 0;
|
||||
}
|
||||
|
||||
forced_on = mdp->ops.setup_clk_force_ctrl(mdp, clk_ctrl, true);
|
||||
forced_on = _sde_vbif_setup_clk_force_ctrl(sde_kms, clk_ctrl, true);
|
||||
|
||||
/* send halt request for unused plane's xin client */
|
||||
vbif->ops.set_xin_halt(vbif, xin_id, true);
|
||||
@@ -134,7 +249,7 @@ int sde_vbif_halt_plane_xin(struct sde_kms *sde_kms, u32 xin_id, u32 clk_ctrl)
|
||||
/* open xin client to enable transactions */
|
||||
vbif->ops.set_xin_halt(vbif, xin_id, false);
|
||||
if (forced_on)
|
||||
mdp->ops.setup_clk_force_ctrl(mdp, clk_ctrl, false);
|
||||
_sde_vbif_setup_clk_force_ctrl(sde_kms, clk_ctrl, false);
|
||||
|
||||
mutex_unlock(&vbif->mutex);
|
||||
|
||||
@@ -268,7 +383,7 @@ void sde_vbif_set_ot_limit(struct sde_kms *sde_kms,
|
||||
return;
|
||||
}
|
||||
|
||||
if (!mdp->ops.setup_clk_force_ctrl ||
|
||||
if (!_sde_vbif_setup_clk_supported(sde_kms, params->clk_ctrl) ||
|
||||
!vbif->ops.set_limit_conf ||
|
||||
!vbif->ops.set_xin_halt)
|
||||
return;
|
||||
@@ -289,7 +404,7 @@ void sde_vbif_set_ot_limit(struct sde_kms *sde_kms,
|
||||
trace_sde_perf_set_ot(params->num, params->xin_id, ot_lim,
|
||||
params->vbif_idx);
|
||||
|
||||
forced_on = mdp->ops.setup_clk_force_ctrl(mdp, params->clk_ctrl, true);
|
||||
forced_on = _sde_vbif_setup_clk_force_ctrl(sde_kms, params->clk_ctrl, true);
|
||||
|
||||
vbif->ops.set_limit_conf(vbif, params->xin_id, params->rd, ot_lim);
|
||||
|
||||
@@ -302,7 +417,8 @@ void sde_vbif_set_ot_limit(struct sde_kms *sde_kms,
|
||||
vbif->ops.set_xin_halt(vbif, params->xin_id, false);
|
||||
|
||||
if (forced_on)
|
||||
mdp->ops.setup_clk_force_ctrl(mdp, params->clk_ctrl, false);
|
||||
_sde_vbif_setup_clk_force_ctrl(sde_kms, params->clk_ctrl, false);
|
||||
|
||||
exit:
|
||||
mutex_unlock(&vbif->mutex);
|
||||
}
|
||||
@@ -376,7 +492,7 @@ bool sde_vbif_set_xin_halt(struct sde_kms *sde_kms,
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!mdp->ops.setup_clk_force_ctrl ||
|
||||
if (!_sde_vbif_setup_clk_supported(sde_kms, params->clk_ctrl) ||
|
||||
!vbif->ops.set_xin_halt)
|
||||
return false;
|
||||
|
||||
@@ -385,8 +501,7 @@ bool sde_vbif_set_xin_halt(struct sde_kms *sde_kms,
|
||||
SDE_EVT32_VERBOSE(vbif->idx, params->xin_id);
|
||||
|
||||
if (params->enable) {
|
||||
forced_on = mdp->ops.setup_clk_force_ctrl(mdp,
|
||||
params->clk_ctrl, true);
|
||||
forced_on = _sde_vbif_setup_clk_force_ctrl(sde_kms, params->clk_ctrl, true);
|
||||
|
||||
vbif->ops.set_xin_halt(vbif, params->xin_id, true);
|
||||
|
||||
@@ -397,8 +512,7 @@ bool sde_vbif_set_xin_halt(struct sde_kms *sde_kms,
|
||||
vbif->ops.set_xin_halt(vbif, params->xin_id, false);
|
||||
|
||||
if (params->forced_on)
|
||||
mdp->ops.setup_clk_force_ctrl(mdp,
|
||||
params->clk_ctrl, false);
|
||||
_sde_vbif_setup_clk_force_ctrl(sde_kms, params->clk_ctrl, false);
|
||||
}
|
||||
|
||||
mutex_unlock(&vbif->mutex);
|
||||
@@ -440,7 +554,7 @@ bool sde_vbif_get_xin_status(struct sde_kms *sde_kms,
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!mdp->ops.get_clk_ctrl_status ||
|
||||
if (!_sde_vbif_get_clk_supported(sde_kms, params->clk_ctrl) ||
|
||||
!vbif->ops.get_xin_halt_status)
|
||||
return false;
|
||||
|
||||
@@ -448,8 +562,7 @@ bool sde_vbif_get_xin_status(struct sde_kms *sde_kms,
|
||||
SDE_EVT32_VERBOSE(vbif->idx, params->xin_id);
|
||||
status = vbif->ops.get_xin_halt_status(vbif, params->xin_id);
|
||||
if (status) {
|
||||
rc = !mdp->ops.get_clk_ctrl_status(mdp, params->clk_ctrl,
|
||||
&status);
|
||||
rc = _sde_vbif_get_clk_ctrl_status(sde_kms, params->clk_ctrl, &status);
|
||||
if (rc)
|
||||
status = false;
|
||||
}
|
||||
@@ -492,7 +605,7 @@ void sde_vbif_set_qos_remap(struct sde_kms *sde_kms,
|
||||
return;
|
||||
}
|
||||
|
||||
if (!vbif->ops.set_qos_remap || !mdp->ops.setup_clk_force_ctrl) {
|
||||
if (!vbif->ops.set_qos_remap || !_sde_vbif_setup_clk_supported(sde_kms, params->clk_ctrl)) {
|
||||
SDE_DEBUG("qos remap not supported\n");
|
||||
return;
|
||||
}
|
||||
@@ -510,7 +623,7 @@ void sde_vbif_set_qos_remap(struct sde_kms *sde_kms,
|
||||
|
||||
mutex_lock(&vbif->mutex);
|
||||
|
||||
forced_on = mdp->ops.setup_clk_force_ctrl(mdp, params->clk_ctrl, true);
|
||||
forced_on = _sde_vbif_setup_clk_force_ctrl(sde_kms, params->clk_ctrl, true);
|
||||
|
||||
for (i = 0; i < qos_tbl->npriority_lvl; i++) {
|
||||
SDE_DEBUG("vbif:%d xin:%d lvl:%d/%d\n",
|
||||
@@ -521,7 +634,7 @@ void sde_vbif_set_qos_remap(struct sde_kms *sde_kms,
|
||||
}
|
||||
|
||||
if (forced_on)
|
||||
mdp->ops.setup_clk_force_ctrl(mdp, params->clk_ctrl, false);
|
||||
_sde_vbif_setup_clk_force_ctrl(sde_kms, params->clk_ctrl, false);
|
||||
|
||||
mutex_unlock(&vbif->mutex);
|
||||
}
|
||||
|
Criar uma nova questão referindo esta
Bloquear um utilizador