Merge "drm: msm: improve early splash mechanism"
This commit is contained in:
commit
d718058109
9 changed files with 519 additions and 172 deletions
|
@ -572,8 +572,6 @@ void sde_connector_complete_commit(struct drm_connector *connector)
|
|||
{
|
||||
struct drm_device *dev;
|
||||
struct msm_drm_private *priv;
|
||||
struct sde_connector *c_conn;
|
||||
struct sde_kms *sde_kms;
|
||||
|
||||
if (!connector) {
|
||||
SDE_ERROR("invalid connector\n");
|
||||
|
@ -582,7 +580,6 @@ void sde_connector_complete_commit(struct drm_connector *connector)
|
|||
|
||||
dev = connector->dev;
|
||||
priv = dev->dev_private;
|
||||
sde_kms = to_sde_kms(priv->kms);
|
||||
|
||||
/* signal connector's retire fence */
|
||||
sde_fence_signal(&to_sde_connector(connector)->retire_fence, 0);
|
||||
|
@ -590,14 +587,8 @@ void sde_connector_complete_commit(struct drm_connector *connector)
|
|||
/* after first vsync comes,
|
||||
* early splash resource should start to be released.
|
||||
*/
|
||||
if (sde_splash_get_lk_complete_status(&sde_kms->splash_info)) {
|
||||
c_conn = to_sde_connector(connector);
|
||||
|
||||
sde_splash_clean_up_free_resource(priv->kms,
|
||||
&priv->phandle,
|
||||
c_conn->connector_type,
|
||||
c_conn->display);
|
||||
}
|
||||
if (sde_splash_get_lk_complete_status(priv->kms))
|
||||
sde_splash_free_resource(priv->kms, &priv->phandle);
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -304,6 +304,8 @@ static void _sde_crtc_blend_setup(struct drm_crtc *crtc)
|
|||
struct sde_crtc_mixer *mixer = sde_crtc->mixers;
|
||||
struct sde_hw_ctl *ctl;
|
||||
struct sde_hw_mixer *lm;
|
||||
struct sde_splash_info *sinfo;
|
||||
struct sde_kms *sde_kms = _sde_crtc_get_kms(crtc);
|
||||
|
||||
int i;
|
||||
|
||||
|
@ -314,6 +316,17 @@ static void _sde_crtc_blend_setup(struct drm_crtc *crtc)
|
|||
return;
|
||||
}
|
||||
|
||||
if (!sde_kms) {
|
||||
SDE_ERROR("invalid sde_kms\n");
|
||||
return;
|
||||
}
|
||||
|
||||
sinfo = &sde_kms->splash_info;
|
||||
if (!sinfo) {
|
||||
SDE_ERROR("invalid splash info\n");
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < sde_crtc->num_mixers; i++) {
|
||||
if (!mixer[i].hw_lm || !mixer[i].hw_ctl) {
|
||||
SDE_ERROR("invalid lm or ctl assigned to mixer\n");
|
||||
|
@ -323,7 +336,10 @@ static void _sde_crtc_blend_setup(struct drm_crtc *crtc)
|
|||
mixer[i].flush_mask = 0;
|
||||
if (mixer[i].hw_ctl->ops.clear_all_blendstages)
|
||||
mixer[i].hw_ctl->ops.clear_all_blendstages(
|
||||
mixer[i].hw_ctl);
|
||||
mixer[i].hw_ctl,
|
||||
sinfo->handoff,
|
||||
sinfo->reserved_pipe_info,
|
||||
MAX_BLOCKS);
|
||||
}
|
||||
|
||||
/* initialize stage cfg */
|
||||
|
@ -350,7 +366,8 @@ static void _sde_crtc_blend_setup(struct drm_crtc *crtc)
|
|||
mixer[i].flush_mask);
|
||||
|
||||
ctl->ops.setup_blendstage(ctl, mixer[i].hw_lm->idx,
|
||||
&sde_crtc->stage_cfg, i);
|
||||
&sde_crtc->stage_cfg, i,
|
||||
sinfo->handoff, sinfo->reserved_pipe_info, MAX_BLOCKS);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
|
||||
/* Copyright (c) 2015-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
|
||||
|
@ -258,6 +258,35 @@ static inline int sde_hw_ctl_get_bitmask_cdm(struct sde_hw_ctl *ctx,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static inline int sde_hw_ctl_get_splash_mixercfg(const u32 *resv_pipes,
|
||||
u32 length)
|
||||
{
|
||||
int i = 0;
|
||||
u32 mixercfg = 0;
|
||||
|
||||
for (i = 0; i < length; i++) {
|
||||
/* LK's splash VIG layer always stays on top */
|
||||
switch (resv_pipes[i]) {
|
||||
case SSPP_VIG0:
|
||||
mixercfg |= 0x7 << 0;
|
||||
break;
|
||||
case SSPP_VIG1:
|
||||
mixercfg |= 0x7 << 3;
|
||||
break;
|
||||
case SSPP_VIG2:
|
||||
mixercfg |= 0x7 << 6;
|
||||
break;
|
||||
case SSPP_VIG3:
|
||||
mixercfg |= 0x7 << 26;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return mixercfg;
|
||||
}
|
||||
|
||||
static u32 sde_hw_ctl_poll_reset_status(struct sde_hw_ctl *ctx, u32 count)
|
||||
{
|
||||
struct sde_hw_blk_reg_map *c = &ctx->hw;
|
||||
|
@ -312,15 +341,29 @@ static int sde_hw_ctl_wait_reset_status(struct sde_hw_ctl *ctx)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void sde_hw_ctl_clear_all_blendstages(struct sde_hw_ctl *ctx)
|
||||
static void sde_hw_ctl_clear_all_blendstages(struct sde_hw_ctl *ctx,
|
||||
bool handoff, const u32 *resv_pipes, u32 resv_pipes_length)
|
||||
{
|
||||
struct sde_hw_blk_reg_map *c = &ctx->hw;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ctx->mixer_count; i++) {
|
||||
int mixer_id = ctx->mixer_hw_caps[i].id;
|
||||
u32 mixercfg = 0;
|
||||
|
||||
SDE_REG_WRITE(c, CTL_LAYER(mixer_id), 0);
|
||||
/*
|
||||
* if bootloaer still has early RVC running, mixer status
|
||||
* can't be direcly cleared.
|
||||
*/
|
||||
if (handoff) {
|
||||
mixercfg =
|
||||
sde_hw_ctl_get_splash_mixercfg(resv_pipes,
|
||||
resv_pipes_length);
|
||||
|
||||
mixercfg &= SDE_REG_READ(c, CTL_LAYER(mixer_id));
|
||||
}
|
||||
|
||||
SDE_REG_WRITE(c, CTL_LAYER(mixer_id), mixercfg);
|
||||
SDE_REG_WRITE(c, CTL_LAYER_EXT(mixer_id), 0);
|
||||
SDE_REG_WRITE(c, CTL_LAYER_EXT2(mixer_id), 0);
|
||||
SDE_REG_WRITE(c, CTL_LAYER_EXT3(mixer_id), 0);
|
||||
|
@ -328,7 +371,8 @@ static void sde_hw_ctl_clear_all_blendstages(struct sde_hw_ctl *ctx)
|
|||
}
|
||||
|
||||
static void sde_hw_ctl_setup_blendstage(struct sde_hw_ctl *ctx,
|
||||
enum sde_lm lm, struct sde_hw_stage_cfg *stage_cfg, u32 index)
|
||||
enum sde_lm lm, struct sde_hw_stage_cfg *stage_cfg, u32 index,
|
||||
bool handoff, const u32 *resv_pipes, u32 resv_pipes_length)
|
||||
{
|
||||
struct sde_hw_blk_reg_map *c = &ctx->hw;
|
||||
u32 mixercfg, mixercfg_ext, mix, ext, mixercfg_ext2;
|
||||
|
@ -353,6 +397,20 @@ static void sde_hw_ctl_setup_blendstage(struct sde_hw_ctl *ctx,
|
|||
mixercfg_ext = 0;
|
||||
mixercfg_ext2 = 0;
|
||||
|
||||
/*
|
||||
* if bootloader still have RVC running, its mixer stauts
|
||||
* should be updated to kernel's mixer setup.
|
||||
*/
|
||||
if (handoff) {
|
||||
mixercfg =
|
||||
sde_hw_ctl_get_splash_mixercfg(resv_pipes,
|
||||
resv_pipes_length);
|
||||
|
||||
mixercfg &= SDE_REG_READ(c, CTL_LAYER(lm));
|
||||
mixercfg |= BIT(24);
|
||||
stages--;
|
||||
}
|
||||
|
||||
for (i = 0; i <= stages; i++) {
|
||||
/* overflow to ext register if 'i + 1 > 7' */
|
||||
mix = (i + 1) & 0x7;
|
||||
|
@ -458,6 +516,38 @@ static void sde_hw_ctl_intf_cfg(struct sde_hw_ctl *ctx,
|
|||
SDE_REG_WRITE(c, CTL_TOP, intf_cfg);
|
||||
}
|
||||
|
||||
static inline u32 sde_hw_ctl_read_ctl_top_for_splash(struct sde_hw_ctl *ctx)
|
||||
{
|
||||
struct sde_hw_blk_reg_map *c;
|
||||
u32 ctl_top;
|
||||
|
||||
if (!ctx) {
|
||||
pr_err("Invalid ctx\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
c = &ctx->hw;
|
||||
ctl_top = SDE_REG_READ(c, CTL_TOP);
|
||||
return ctl_top;
|
||||
}
|
||||
|
||||
static inline u32 sde_hw_ctl_read_ctl_layers_for_splash(struct sde_hw_ctl *ctx,
|
||||
int index)
|
||||
{
|
||||
struct sde_hw_blk_reg_map *c;
|
||||
u32 ctl_top;
|
||||
|
||||
if (!ctx) {
|
||||
pr_err("Invalid ctx\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
c = &ctx->hw;
|
||||
ctl_top = SDE_REG_READ(c, CTL_LAYER(index));
|
||||
|
||||
return ctl_top;
|
||||
}
|
||||
|
||||
static void _setup_ctl_ops(struct sde_hw_ctl_ops *ops,
|
||||
unsigned long cap)
|
||||
{
|
||||
|
@ -478,6 +568,8 @@ static void _setup_ctl_ops(struct sde_hw_ctl_ops *ops,
|
|||
ops->get_bitmask_intf = sde_hw_ctl_get_bitmask_intf;
|
||||
ops->get_bitmask_cdm = sde_hw_ctl_get_bitmask_cdm;
|
||||
ops->get_bitmask_wb = sde_hw_ctl_get_bitmask_wb;
|
||||
ops->read_ctl_top_for_splash = sde_hw_ctl_read_ctl_top_for_splash;
|
||||
ops->read_ctl_layers_for_splash = sde_hw_ctl_read_ctl_layers_for_splash;
|
||||
};
|
||||
|
||||
struct sde_hw_ctl *sde_hw_ctl_init(enum sde_ctl idx,
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
|
||||
/* Copyright (c) 2015-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
|
||||
|
@ -146,17 +146,40 @@ struct sde_hw_ctl_ops {
|
|||
/**
|
||||
* Set all blend stages to disabled
|
||||
* @ctx : ctl path ctx pointer
|
||||
* @handoff : handoff flag
|
||||
* @resv_pipes : reserved pipes in DT
|
||||
* @resv_pipes_length: array size of array reserved_pipes
|
||||
*/
|
||||
void (*clear_all_blendstages)(struct sde_hw_ctl *ctx);
|
||||
void (*clear_all_blendstages)(struct sde_hw_ctl *ctx,
|
||||
bool handoff, const u32 *resv_pipes, u32 resv_pipes_length);
|
||||
|
||||
/**
|
||||
* Configure layer mixer to pipe configuration
|
||||
* @ctx : ctl path ctx pointer
|
||||
* @lm : layer mixer enumeration
|
||||
* @cfg : blend stage configuration
|
||||
* @handoff : handoff flag
|
||||
* @resv_pipes : reserved pipes in DT
|
||||
* @resv_pipes_length: array size of array reserved_pipes
|
||||
*/
|
||||
void (*setup_blendstage)(struct sde_hw_ctl *ctx,
|
||||
enum sde_lm lm, struct sde_hw_stage_cfg *cfg, u32 index);
|
||||
enum sde_lm lm, struct sde_hw_stage_cfg *cfg, u32 index,
|
||||
bool handoff, const u32 *resv_pipes, u32 resv_pipes_length);
|
||||
|
||||
/**
|
||||
* read CTL_TOP register value for splash case
|
||||
* @ctx : ctl path ctx pointer
|
||||
* @Return : CTL top register value
|
||||
*/
|
||||
u32 (*read_ctl_top_for_splash)(struct sde_hw_ctl *ctx);
|
||||
|
||||
/**
|
||||
* read CTL layers register value for splash case
|
||||
* @ctx : ctl path ctx pointer
|
||||
* @index : layer index for this ctl path
|
||||
* @Return : CTL layers register value
|
||||
*/
|
||||
u32 (*read_ctl_layers_for_splash)(struct sde_hw_ctl *ctx, int index);
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -343,8 +343,9 @@ static void sde_kms_prepare_commit(struct msm_kms *kms,
|
|||
struct drm_device *dev = sde_kms->dev;
|
||||
struct msm_drm_private *priv = dev->dev_private;
|
||||
|
||||
if (sde_kms->splash_info.handoff)
|
||||
sde_splash_clean_up_exit_lk(kms);
|
||||
if (sde_kms->splash_info.handoff &&
|
||||
sde_kms->splash_info.display_splash_enabled)
|
||||
sde_splash_lk_stop_splash(kms);
|
||||
else
|
||||
sde_power_resource_enable(&priv->phandle,
|
||||
sde_kms->core_client, true);
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
|
||||
* 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
|
||||
|
@ -24,6 +24,7 @@
|
|||
#include "sde_encoder.h"
|
||||
#include "sde_connector.h"
|
||||
#include "sde_hw_sspp.h"
|
||||
#include "sde_splash.h"
|
||||
|
||||
#define RESERVED_BY_OTHER(h, r) \
|
||||
((h)->rsvp && ((h)->rsvp->enc_id != (r)->enc_id))
|
||||
|
@ -417,6 +418,8 @@ int sde_rm_init(struct sde_rm *rm,
|
|||
|
||||
mutex_init(&rm->rm_lock);
|
||||
|
||||
rm->dev = dev;
|
||||
|
||||
INIT_LIST_HEAD(&rm->rsvps);
|
||||
for (type = 0; type < SDE_HW_BLK_MAX; type++)
|
||||
INIT_LIST_HEAD(&rm->hw_blks[type]);
|
||||
|
@ -652,7 +655,8 @@ static bool _sde_rm_check_lm_and_get_connected_blks(
|
|||
static int _sde_rm_reserve_lms(
|
||||
struct sde_rm *rm,
|
||||
struct sde_rm_rsvp *rsvp,
|
||||
struct sde_rm_requirements *reqs)
|
||||
struct sde_rm_requirements *reqs,
|
||||
uint32_t prefer_lm_id)
|
||||
|
||||
{
|
||||
struct sde_rm_hw_blk *lm[MAX_BLOCKS];
|
||||
|
@ -678,6 +682,10 @@ static int _sde_rm_reserve_lms(
|
|||
lm_count = 0;
|
||||
lm[lm_count] = iter_i.blk;
|
||||
|
||||
/* find the matched lm id */
|
||||
if ((prefer_lm_id > 0) && (iter_i.blk->id != prefer_lm_id))
|
||||
continue;
|
||||
|
||||
if (!_sde_rm_check_lm_and_get_connected_blks(rm, rsvp, reqs,
|
||||
lm[lm_count], &dspp[lm_count], &pp[lm_count],
|
||||
NULL))
|
||||
|
@ -699,6 +707,7 @@ static int _sde_rm_reserve_lms(
|
|||
continue;
|
||||
|
||||
lm[lm_count] = iter_j.blk;
|
||||
|
||||
++lm_count;
|
||||
}
|
||||
}
|
||||
|
@ -747,7 +756,8 @@ static int _sde_rm_reserve_lms(
|
|||
static int _sde_rm_reserve_ctls(
|
||||
struct sde_rm *rm,
|
||||
struct sde_rm_rsvp *rsvp,
|
||||
struct sde_rm_requirements *reqs)
|
||||
struct sde_rm_requirements *reqs,
|
||||
uint32_t prefer_ctl_id)
|
||||
{
|
||||
struct sde_rm_hw_blk *ctls[MAX_BLOCKS];
|
||||
struct sde_rm_hw_iter iter;
|
||||
|
@ -769,6 +779,14 @@ static int _sde_rm_reserve_ctls(
|
|||
|
||||
SDE_DEBUG("ctl %d caps 0x%lX\n", iter.blk->id, caps);
|
||||
|
||||
/* early return when finding the matched ctl id */
|
||||
if ((prefer_ctl_id > 0) && (iter.blk->id == prefer_ctl_id)) {
|
||||
ctls[i] = iter.blk;
|
||||
|
||||
if (++i == reqs->num_ctl)
|
||||
break;
|
||||
}
|
||||
|
||||
if (reqs->needs_split_display != has_split_display)
|
||||
continue;
|
||||
|
||||
|
@ -928,10 +946,10 @@ static int _sde_rm_make_next_rsvp(
|
|||
* - Check mixers without DSPPs
|
||||
* - Only then allow to grab from mixers with DSPP capability
|
||||
*/
|
||||
ret = _sde_rm_reserve_lms(rm, rsvp, reqs);
|
||||
ret = _sde_rm_reserve_lms(rm, rsvp, reqs, 0);
|
||||
if (ret && !RM_RQ_DSPP(reqs)) {
|
||||
reqs->top_ctrl |= BIT(SDE_RM_TOPCTL_DSPP);
|
||||
ret = _sde_rm_reserve_lms(rm, rsvp, reqs);
|
||||
ret = _sde_rm_reserve_lms(rm, rsvp, reqs, 0);
|
||||
}
|
||||
|
||||
if (ret) {
|
||||
|
@ -944,10 +962,10 @@ static int _sde_rm_make_next_rsvp(
|
|||
* - Check mixers without Split Display
|
||||
* - Only then allow to grab from CTLs with split display capability
|
||||
*/
|
||||
_sde_rm_reserve_ctls(rm, rsvp, reqs);
|
||||
_sde_rm_reserve_ctls(rm, rsvp, reqs, 0);
|
||||
if (ret && !reqs->needs_split_display) {
|
||||
reqs->needs_split_display = true;
|
||||
_sde_rm_reserve_ctls(rm, rsvp, reqs);
|
||||
_sde_rm_reserve_ctls(rm, rsvp, reqs, 0);
|
||||
}
|
||||
if (ret) {
|
||||
SDE_ERROR("unable to find appropriate CTL\n");
|
||||
|
@ -962,6 +980,109 @@ static int _sde_rm_make_next_rsvp(
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int _sde_rm_make_next_rsvp_for_splash(
|
||||
struct sde_rm *rm,
|
||||
struct drm_encoder *enc,
|
||||
struct drm_crtc_state *crtc_state,
|
||||
struct drm_connector_state *conn_state,
|
||||
struct sde_rm_rsvp *rsvp,
|
||||
struct sde_rm_requirements *reqs)
|
||||
{
|
||||
int ret;
|
||||
struct msm_drm_private *priv;
|
||||
struct sde_kms *sde_kms;
|
||||
struct sde_splash_info *sinfo;
|
||||
int i;
|
||||
int intf_id = INTF_0;
|
||||
u32 prefer_lm_id = 0;
|
||||
u32 prefer_ctl_id = 0;
|
||||
|
||||
if (!enc->dev || !enc->dev->dev_private) {
|
||||
SDE_ERROR("drm device invalid\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
priv = enc->dev->dev_private;
|
||||
if (!priv->kms) {
|
||||
SDE_ERROR("invalid kms\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
sde_kms = to_sde_kms(priv->kms);
|
||||
sinfo = &sde_kms->splash_info;
|
||||
|
||||
/* Get the intf id first, and reserve the same lk and ctl
|
||||
* in bootloader for kernel resource manager
|
||||
*/
|
||||
for (i = 0; i < ARRAY_SIZE(reqs->hw_res.intfs); i++) {
|
||||
if (reqs->hw_res.intfs[i] == INTF_MODE_NONE)
|
||||
continue;
|
||||
intf_id = i + INTF_0;
|
||||
break;
|
||||
}
|
||||
|
||||
/* get preferred lm id and ctl id */
|
||||
for (i = 0; i < CTL_MAX - 1; i++) {
|
||||
if (sinfo->res.top[i].intf_sel != intf_id)
|
||||
continue;
|
||||
|
||||
prefer_lm_id = sinfo->res.top[i].lm[0].lm_id;
|
||||
prefer_ctl_id = sinfo->res.top[i].lm[0].ctl_id;
|
||||
break;
|
||||
}
|
||||
|
||||
SDE_DEBUG("intf_id %d, prefer lm_id %d, ctl_id %d\n",
|
||||
intf_id, prefer_lm_id, prefer_ctl_id);
|
||||
|
||||
/* Create reservation info, tag reserved blocks with it as we go */
|
||||
rsvp->seq = ++rm->rsvp_next_seq;
|
||||
rsvp->enc_id = enc->base.id;
|
||||
rsvp->topology = reqs->top_name;
|
||||
list_add_tail(&rsvp->list, &rm->rsvps);
|
||||
|
||||
/*
|
||||
* Assign LMs and blocks whose usage is tied to them: DSPP & Pingpong.
|
||||
* Do assignment preferring to give away low-resource mixers first:
|
||||
* - Check mixers without DSPPs
|
||||
* - Only then allow to grab from mixers with DSPP capability
|
||||
*/
|
||||
ret = _sde_rm_reserve_lms(rm, rsvp, reqs, prefer_lm_id);
|
||||
if (ret && !RM_RQ_DSPP(reqs)) {
|
||||
reqs->top_ctrl |= BIT(SDE_RM_TOPCTL_DSPP);
|
||||
ret = _sde_rm_reserve_lms(rm, rsvp, reqs, prefer_lm_id);
|
||||
}
|
||||
|
||||
if (ret) {
|
||||
SDE_ERROR("unable to find appropriate mixers\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Do assignment preferring to give away low-resource CTLs first:
|
||||
* - Check mixers without Split Display
|
||||
* - Only then allow to grab from CTLs with split display capability
|
||||
*/
|
||||
for (i = 0; i < sinfo->res.ctl_top_cnt; i++)
|
||||
SDE_DEBUG("splash_info ctl_ids[%d] = %d\n",
|
||||
i, sinfo->res.ctl_ids[i]);
|
||||
|
||||
ret = _sde_rm_reserve_ctls(rm, rsvp, reqs, prefer_ctl_id);
|
||||
if (ret && !reqs->needs_split_display) {
|
||||
reqs->needs_split_display = true;
|
||||
_sde_rm_reserve_ctls(rm, rsvp, reqs, prefer_ctl_id);
|
||||
}
|
||||
|
||||
if (ret) {
|
||||
SDE_ERROR("unable to find appropriate CTL\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Assign INTFs, WBs, and blks whose usage is tied to them: CTL & CDM */
|
||||
ret = _sde_rm_reserve_intf_related_hw(rm, rsvp, &reqs->hw_res);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int _sde_rm_populate_requirements(
|
||||
struct sde_rm *rm,
|
||||
struct drm_encoder *enc,
|
||||
|
@ -1253,6 +1374,8 @@ int sde_rm_reserve(
|
|||
{
|
||||
struct sde_rm_rsvp *rsvp_cur, *rsvp_nxt;
|
||||
struct sde_rm_requirements reqs;
|
||||
struct msm_drm_private *priv;
|
||||
struct sde_kms *sde_kms;
|
||||
int ret;
|
||||
|
||||
if (!rm || !enc || !crtc_state || !conn_state) {
|
||||
|
@ -1260,6 +1383,19 @@ int sde_rm_reserve(
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (!enc->dev || !enc->dev->dev_private) {
|
||||
SDE_ERROR("invalid drm device\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
priv = enc->dev->dev_private;
|
||||
if (!priv->kms) {
|
||||
SDE_ERROR("invald kms\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
sde_kms = to_sde_kms(priv->kms);
|
||||
|
||||
/* Check if this is just a page-flip */
|
||||
if (!drm_atomic_crtc_needs_modeset(crtc_state))
|
||||
return 0;
|
||||
|
@ -1318,6 +1454,11 @@ int sde_rm_reserve(
|
|||
}
|
||||
|
||||
/* Check the proposed reservation, store it in hw's "next" field */
|
||||
if (sde_kms->splash_info.handoff) {
|
||||
SDE_DEBUG("Reserve resource for splash\n");
|
||||
ret = _sde_rm_make_next_rsvp_for_splash
|
||||
(rm, enc, crtc_state, conn_state, rsvp_nxt, &reqs);
|
||||
} else
|
||||
ret = _sde_rm_make_next_rsvp(rm, enc, crtc_state, conn_state,
|
||||
rsvp_nxt, &reqs);
|
||||
|
||||
|
@ -1352,3 +1493,92 @@ end:
|
|||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int _sde_rm_get_ctl_lm_for_splash(struct sde_hw_ctl *ctl,
|
||||
int max_lm_cnt, u8 lm_cnt, u8 *lm_ids,
|
||||
struct splash_ctl_top *top, int index)
|
||||
{
|
||||
int j;
|
||||
struct splash_lm_hw *lm;
|
||||
|
||||
if (!ctl || !top) {
|
||||
SDE_ERROR("invalid parameters\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
lm = top->lm;
|
||||
for (j = 0; j < max_lm_cnt; j++) {
|
||||
lm[top->ctl_lm_cnt].lm_reg_value =
|
||||
ctl->ops.read_ctl_layers_for_splash(ctl, j + LM_0);
|
||||
|
||||
if (lm[top->ctl_lm_cnt].lm_reg_value) {
|
||||
lm[top->ctl_lm_cnt].ctl_id = index + CTL_0;
|
||||
lm_ids[lm_cnt++] = j + LM_0;
|
||||
lm[top->ctl_lm_cnt].lm_id = j + LM_0;
|
||||
top->ctl_lm_cnt++;
|
||||
}
|
||||
}
|
||||
|
||||
return top->ctl_lm_cnt;
|
||||
}
|
||||
|
||||
static void _sde_rm_get_ctl_top_for_splash(struct sde_hw_ctl *ctl,
|
||||
struct splash_ctl_top *top)
|
||||
{
|
||||
if (!ctl || !top) {
|
||||
SDE_ERROR("invalid ctl or top\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!ctl->ops.read_ctl_top_for_splash) {
|
||||
SDE_ERROR("read_ctl_top not initialized\n");
|
||||
return;
|
||||
}
|
||||
|
||||
top->value = ctl->ops.read_ctl_top_for_splash(ctl);
|
||||
top->intf_sel = (top->value >> 4) & 0xf;
|
||||
}
|
||||
|
||||
int sde_rm_read_resource_for_splash(struct sde_rm *rm,
|
||||
void *splash_info,
|
||||
struct sde_mdss_cfg *cat)
|
||||
{
|
||||
struct sde_rm_hw_iter ctl_iter;
|
||||
int index = 0;
|
||||
struct sde_splash_info *sinfo;
|
||||
struct sde_hw_ctl *ctl;
|
||||
|
||||
if (!rm || !splash_info || !cat)
|
||||
return -EINVAL;
|
||||
|
||||
sinfo = (struct sde_splash_info *)splash_info;
|
||||
|
||||
sde_rm_init_hw_iter(&ctl_iter, 0, SDE_HW_BLK_CTL);
|
||||
|
||||
while (_sde_rm_get_hw_locked(rm, &ctl_iter)) {
|
||||
ctl = (struct sde_hw_ctl *)ctl_iter.hw;
|
||||
|
||||
_sde_rm_get_ctl_top_for_splash(ctl,
|
||||
&sinfo->res.top[index]);
|
||||
|
||||
if (sinfo->res.top[index].intf_sel) {
|
||||
sinfo->res.lm_cnt +=
|
||||
_sde_rm_get_ctl_lm_for_splash(ctl,
|
||||
cat->mixer_count,
|
||||
sinfo->res.lm_cnt,
|
||||
sinfo->res.lm_ids,
|
||||
&sinfo->res.top[index], index);
|
||||
|
||||
sinfo->res.ctl_ids[sinfo->res.ctl_top_cnt] =
|
||||
index + CTL_0;
|
||||
|
||||
sinfo->res.ctl_top_cnt++;
|
||||
}
|
||||
index++;
|
||||
}
|
||||
|
||||
SDE_DEBUG("%s: ctl_top_cnt=%d, lm_cnt=%d\n", __func__,
|
||||
sinfo->res.ctl_top_cnt, sinfo->res.lm_cnt);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
|
||||
* 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
|
||||
|
@ -212,4 +212,14 @@ int sde_rm_check_property_topctl(uint64_t val);
|
|||
*/
|
||||
int sde_rm_check_property_topctl(uint64_t val);
|
||||
|
||||
/**
|
||||
* sde_rm_read_resource_for_splash - read splash resource used in bootloader
|
||||
* @rm: SDE Resource Manager handle
|
||||
* @sinfo: handle for splash info
|
||||
* @cat: Pointer to hardware catalog
|
||||
*/
|
||||
int sde_rm_read_resource_for_splash(struct sde_rm *rm,
|
||||
void *sinfo,
|
||||
struct sde_mdss_cfg *cat);
|
||||
|
||||
#endif /* __SDE_RM_H__ */
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
#include "sde_hw_util.h"
|
||||
#include "sde_hw_intf.h"
|
||||
#include "sde_hw_catalog.h"
|
||||
#include "sde_rm.h"
|
||||
#include "dsi_display.h"
|
||||
#include "sde_hdmi.h"
|
||||
|
||||
|
@ -35,11 +36,9 @@
|
|||
#define SCRATCH_REGISTER_2 0x01C
|
||||
|
||||
#define SDE_LK_RUNNING_VALUE 0xC001CAFE
|
||||
#define SDE_LK_SHUT_DOWN_VALUE 0xDEADDEAD
|
||||
#define SDE_LK_STOP_SPLASH_VALUE 0xDEADDEAD
|
||||
#define SDE_LK_EXIT_VALUE 0xDEADBEEF
|
||||
|
||||
#define SDE_LK_EXIT_MAX_LOOP 20
|
||||
|
||||
#define INTF_HDMI_SEL (BIT(25) | BIT(24))
|
||||
#define INTF_DSI0_SEL BIT(8)
|
||||
#define INTF_DSI1_SEL BIT(16)
|
||||
|
@ -189,26 +188,14 @@ static bool _sde_splash_lk_check(struct sde_hw_intr *intr)
|
|||
}
|
||||
|
||||
/**
|
||||
* _sde_splash_notify_lk_to_exit.
|
||||
* _sde_splash_notify_lk_stop_splash.
|
||||
*
|
||||
* Function to monitor LK's status and tell it to exit.
|
||||
* Function to stop early splash in LK.
|
||||
*/
|
||||
static void _sde_splash_notify_lk_exit(struct sde_hw_intr *intr)
|
||||
static inline void _sde_splash_notify_lk_stop_splash(struct sde_hw_intr *intr)
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
/* first is to write exit signal to scratch register*/
|
||||
SDE_REG_WRITE(&intr->hw, SCRATCH_REGISTER_1, SDE_LK_SHUT_DOWN_VALUE);
|
||||
|
||||
while ((SDE_LK_EXIT_VALUE !=
|
||||
SDE_REG_READ(&intr->hw, SCRATCH_REGISTER_1)) &&
|
||||
(++i < SDE_LK_EXIT_MAX_LOOP)) {
|
||||
DRM_INFO("wait for LK's exit");
|
||||
msleep(20);
|
||||
}
|
||||
|
||||
if (i == SDE_LK_EXIT_MAX_LOOP)
|
||||
SDE_ERROR("Loop LK's exit failed\n");
|
||||
/* write splash stop signal to scratch register*/
|
||||
SDE_REG_WRITE(&intr->hw, SCRATCH_REGISTER_1, SDE_LK_STOP_SPLASH_VALUE);
|
||||
}
|
||||
|
||||
static int _sde_splash_gem_new(struct drm_device *dev,
|
||||
|
@ -326,31 +313,28 @@ static void _sde_splash_sent_pipe_update_uevent(struct sde_kms *sde_kms)
|
|||
kfree(event_string);
|
||||
}
|
||||
|
||||
static void _sde_splash_get_connector_ref_cnt(struct sde_splash_info *sinfo,
|
||||
u32 *hdmi_cnt, u32 *dsi_cnt)
|
||||
static int _sde_splash_free_module_resource(struct msm_mmu *mmu,
|
||||
struct sde_splash_info *sinfo)
|
||||
{
|
||||
mutex_lock(&sde_splash_lock);
|
||||
*hdmi_cnt = sinfo->hdmi_connector_cnt;
|
||||
*dsi_cnt = sinfo->dsi_connector_cnt;
|
||||
mutex_unlock(&sde_splash_lock);
|
||||
}
|
||||
int i = 0;
|
||||
struct msm_gem_object *msm_obj;
|
||||
|
||||
static int _sde_splash_free_resource(struct msm_mmu *mmu,
|
||||
struct sde_splash_info *sinfo, enum splash_connector_type conn)
|
||||
{
|
||||
struct msm_gem_object *msm_obj = to_msm_bo(sinfo->obj[conn]);
|
||||
for (i = 0; i < sinfo->splash_mem_num; i++) {
|
||||
msm_obj = to_msm_bo(sinfo->obj[i]);
|
||||
|
||||
if (!msm_obj)
|
||||
return -EINVAL;
|
||||
|
||||
if (mmu->funcs && mmu->funcs->unmap)
|
||||
mmu->funcs->early_splash_unmap(mmu,
|
||||
sinfo->splash_mem_paddr[conn], msm_obj->sgt);
|
||||
sinfo->splash_mem_paddr[i], msm_obj->sgt);
|
||||
|
||||
_sde_splash_free_bootup_memory_to_system(sinfo->splash_mem_paddr[conn],
|
||||
sinfo->splash_mem_size[conn]);
|
||||
_sde_splash_free_bootup_memory_to_system(
|
||||
sinfo->splash_mem_paddr[i],
|
||||
sinfo->splash_mem_size[i]);
|
||||
|
||||
_sde_splash_destroy_gem_object(msm_obj);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -359,6 +343,7 @@ __ref int sde_splash_init(struct sde_power_handle *phandle, struct msm_kms *kms)
|
|||
{
|
||||
struct sde_kms *sde_kms;
|
||||
struct sde_splash_info *sinfo;
|
||||
int ret = 0;
|
||||
int i = 0;
|
||||
|
||||
if (!phandle || !kms) {
|
||||
|
@ -372,22 +357,27 @@ __ref int sde_splash_init(struct sde_power_handle *phandle, struct msm_kms *kms)
|
|||
sinfo->dsi_connector_cnt = 0;
|
||||
sinfo->hdmi_connector_cnt = 0;
|
||||
|
||||
/* Vote data bus after splash is enabled in bootloader */
|
||||
sde_power_data_bus_bandwidth_ctrl(phandle,
|
||||
sde_kms->core_client, true);
|
||||
|
||||
for (i = 0; i < sinfo->splash_mem_num; i++) {
|
||||
if (!memblock_is_reserved(sinfo->splash_mem_paddr[i])) {
|
||||
SDE_ERROR("failed to reserve memory\n");
|
||||
SDE_ERROR("LK's splash memory is not reserved\n");
|
||||
|
||||
/* withdraw the vote when failed. */
|
||||
sde_power_data_bus_bandwidth_ctrl(phandle,
|
||||
sde_kms->core_client, false);
|
||||
|
||||
return -EINVAL;
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
ret = sde_rm_read_resource_for_splash(&sde_kms->rm,
|
||||
(void *)sinfo, sde_kms->catalog);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void sde_splash_destroy(struct sde_splash_info *sinfo,
|
||||
|
@ -572,12 +562,12 @@ int sde_splash_get_handoff_status(struct msm_kms *kms)
|
|||
|
||||
if (num_of_display_on) {
|
||||
sinfo->handoff = true;
|
||||
sinfo->program_scratch_regs = true;
|
||||
sinfo->display_splash_enabled = true;
|
||||
sinfo->lk_is_exited = false;
|
||||
sinfo->intf_sel_status = intf_sel;
|
||||
} else {
|
||||
sinfo->handoff = false;
|
||||
sinfo->program_scratch_regs = false;
|
||||
sinfo->display_splash_enabled = false;
|
||||
sinfo->lk_is_exited = true;
|
||||
}
|
||||
|
||||
|
@ -703,29 +693,34 @@ void sde_splash_setup_connector_count(struct sde_splash_info *sinfo,
|
|||
}
|
||||
}
|
||||
|
||||
bool sde_splash_get_lk_complete_status(struct sde_splash_info *sinfo)
|
||||
bool sde_splash_get_lk_complete_status(struct msm_kms *kms)
|
||||
{
|
||||
bool ret = 0;
|
||||
struct sde_kms *sde_kms = to_sde_kms(kms);
|
||||
struct sde_hw_intr *intr;
|
||||
|
||||
mutex_lock(&sde_splash_lock);
|
||||
ret = !sinfo->handoff && !sinfo->lk_is_exited;
|
||||
mutex_unlock(&sde_splash_lock);
|
||||
|
||||
return ret;
|
||||
if (!sde_kms || !sde_kms->hw_intr) {
|
||||
SDE_ERROR("invalid kms\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
int sde_splash_clean_up_free_resource(struct msm_kms *kms,
|
||||
struct sde_power_handle *phandle,
|
||||
int connector_type, void *display)
|
||||
intr = sde_kms->hw_intr;
|
||||
|
||||
if (sde_kms->splash_info.handoff &&
|
||||
SDE_LK_EXIT_VALUE == SDE_REG_READ(&intr->hw,
|
||||
SCRATCH_REGISTER_1)) {
|
||||
SDE_DEBUG("LK totoally exits\n");
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
int sde_splash_free_resource(struct msm_kms *kms,
|
||||
struct sde_power_handle *phandle)
|
||||
{
|
||||
struct sde_kms *sde_kms;
|
||||
struct sde_splash_info *sinfo;
|
||||
struct msm_mmu *mmu;
|
||||
struct dsi_display *dsi_display = display;
|
||||
int ret = 0;
|
||||
int hdmi_conn_count = 0;
|
||||
int dsi_conn_count = 0;
|
||||
static const char *last_commit_display_type = "unknown";
|
||||
|
||||
if (!phandle || !kms) {
|
||||
SDE_ERROR("invalid phandle/kms.\n");
|
||||
|
@ -739,88 +734,49 @@ int sde_splash_clean_up_free_resource(struct msm_kms *kms,
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
_sde_splash_get_connector_ref_cnt(sinfo, &hdmi_conn_count,
|
||||
&dsi_conn_count);
|
||||
|
||||
mutex_lock(&sde_splash_lock);
|
||||
if (hdmi_conn_count == 0 && dsi_conn_count == 0 &&
|
||||
!sinfo->lk_is_exited) {
|
||||
/* When both hdmi's and dsi's handoff are finished,
|
||||
* 1. Destroy splash node objects.
|
||||
* 2. Release the memory which LK's stack is running on.
|
||||
* 3. Withdraw AHB data bus bandwidth voting.
|
||||
*/
|
||||
DRM_INFO("HDMI and DSI resource handoff is completed\n");
|
||||
|
||||
sinfo->lk_is_exited = true;
|
||||
|
||||
_sde_splash_destroy_splash_node(sinfo);
|
||||
|
||||
_sde_splash_free_bootup_memory_to_system(sinfo->lk_pool_paddr,
|
||||
sinfo->lk_pool_size);
|
||||
|
||||
sde_power_data_bus_bandwidth_ctrl(phandle,
|
||||
sde_kms->core_client, false);
|
||||
|
||||
_sde_splash_sent_pipe_update_uevent(sde_kms);
|
||||
|
||||
if (!sinfo->handoff) {
|
||||
mutex_unlock(&sde_splash_lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
mmu = sde_kms->aspace[0]->mmu;
|
||||
|
||||
switch (connector_type) {
|
||||
case DRM_MODE_CONNECTOR_HDMIA:
|
||||
if (sinfo->hdmi_connector_cnt == 1) {
|
||||
sinfo->hdmi_connector_cnt--;
|
||||
|
||||
ret = _sde_splash_free_resource(mmu,
|
||||
sinfo, SPLASH_HDMI);
|
||||
}
|
||||
break;
|
||||
case DRM_MODE_CONNECTOR_DSI:
|
||||
/*
|
||||
* Basically, we have commits coming on two DSI connectors.
|
||||
* So when releasing DSI resource, it's ensured that the
|
||||
* coming commits should happen on different DSIs, to promise
|
||||
* the handoff has finished on the two DSIs, then it's safe
|
||||
* to release DSI resource, otherwise, problem happens when
|
||||
* freeing memory, while DSI0 or DSI1 is still visiting
|
||||
* the memory.
|
||||
*/
|
||||
if (strcmp(dsi_display->display_type, "unknown") &&
|
||||
strcmp(last_commit_display_type,
|
||||
dsi_display->display_type)) {
|
||||
if (sinfo->dsi_connector_cnt > 1)
|
||||
sinfo->dsi_connector_cnt--;
|
||||
else if (sinfo->dsi_connector_cnt == 1) {
|
||||
ret = _sde_splash_free_resource(mmu,
|
||||
sinfo, SPLASH_DSI);
|
||||
|
||||
sinfo->dsi_connector_cnt--;
|
||||
if (!mmu) {
|
||||
mutex_unlock(&sde_splash_lock);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
last_commit_display_type = dsi_display->display_type;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
ret = -EINVAL;
|
||||
SDE_ERROR("%s: invalid connector_type %d\n",
|
||||
__func__, connector_type);
|
||||
}
|
||||
/* free HDMI's, DSI's and early camera's reserved memory */
|
||||
_sde_splash_free_module_resource(mmu, sinfo);
|
||||
|
||||
_sde_splash_destroy_splash_node(sinfo);
|
||||
|
||||
/* free lk_pool heap memory */
|
||||
_sde_splash_free_bootup_memory_to_system(sinfo->lk_pool_paddr,
|
||||
sinfo->lk_pool_size);
|
||||
|
||||
/* withdraw data bus vote */
|
||||
sde_power_data_bus_bandwidth_ctrl(phandle,
|
||||
sde_kms->core_client, false);
|
||||
|
||||
/* send uevent to notify user to recycle resource */
|
||||
_sde_splash_sent_pipe_update_uevent(sde_kms);
|
||||
|
||||
/* Finally mark handoff flag to false to say handoff is complete */
|
||||
sinfo->handoff = false;
|
||||
|
||||
DRM_INFO("HDMI and DSI resource handoff is completed\n");
|
||||
|
||||
mutex_unlock(&sde_splash_lock);
|
||||
|
||||
return ret;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* In below function, it will
|
||||
* 1. Notify LK to exit and wait for exiting is done.
|
||||
* 1. Notify LK to stop display splash.
|
||||
* 2. Set DOMAIN_ATTR_EARLY_MAP to 1 to enable stage 1 translation in iommu.
|
||||
*/
|
||||
int sde_splash_clean_up_exit_lk(struct msm_kms *kms)
|
||||
int sde_splash_lk_stop_splash(struct msm_kms *kms)
|
||||
{
|
||||
struct sde_splash_info *sinfo;
|
||||
struct msm_mmu *mmu;
|
||||
|
@ -836,12 +792,11 @@ int sde_splash_clean_up_exit_lk(struct msm_kms *kms)
|
|||
|
||||
/* Monitor LK's status and tell it to exit. */
|
||||
mutex_lock(&sde_splash_lock);
|
||||
if (sinfo->program_scratch_regs) {
|
||||
if (sinfo->display_splash_enabled) {
|
||||
if (_sde_splash_lk_check(sde_kms->hw_intr))
|
||||
_sde_splash_notify_lk_exit(sde_kms->hw_intr);
|
||||
_sde_splash_notify_lk_stop_splash(sde_kms->hw_intr);
|
||||
|
||||
sinfo->handoff = false;
|
||||
sinfo->program_scratch_regs = false;
|
||||
sinfo->display_splash_enabled = false;
|
||||
}
|
||||
mutex_unlock(&sde_splash_lock);
|
||||
|
||||
|
@ -858,7 +813,8 @@ int sde_splash_clean_up_exit_lk(struct msm_kms *kms)
|
|||
*/
|
||||
if (mmu->funcs && mmu->funcs->set_property) {
|
||||
ret = mmu->funcs->set_property(mmu,
|
||||
DOMAIN_ATTR_EARLY_MAP, &sinfo->handoff);
|
||||
DOMAIN_ATTR_EARLY_MAP,
|
||||
&sinfo->display_splash_enabled);
|
||||
|
||||
if (ret)
|
||||
SDE_ERROR("set_property failed\n");
|
||||
|
|
|
@ -15,18 +15,46 @@
|
|||
|
||||
#include "msm_kms.h"
|
||||
#include "msm_mmu.h"
|
||||
#include "sde_hw_mdss.h"
|
||||
|
||||
#define SPLASH_CTL_MAX 5
|
||||
#define SPLASH_LM_MAX 7
|
||||
|
||||
enum splash_connector_type {
|
||||
SPLASH_DSI = 0,
|
||||
SPLASH_HDMI,
|
||||
};
|
||||
|
||||
struct splash_lm_hw {
|
||||
u8 lm_id;
|
||||
u8 ctl_id;
|
||||
u32 lm_reg_value;
|
||||
};
|
||||
|
||||
struct splash_ctl_top {
|
||||
u32 value;
|
||||
u8 intf_sel;
|
||||
u8 ctl_lm_cnt;
|
||||
struct splash_lm_hw lm[SPLASH_LM_MAX];
|
||||
};
|
||||
|
||||
struct sde_res_data {
|
||||
struct splash_ctl_top top[SPLASH_CTL_MAX];
|
||||
u8 ctl_ids[SPLASH_CTL_MAX];
|
||||
u8 lm_ids[SPLASH_LM_MAX];
|
||||
u8 ctl_top_cnt;
|
||||
u8 lm_cnt;
|
||||
};
|
||||
|
||||
struct sde_splash_info {
|
||||
/* handoff flag */
|
||||
bool handoff;
|
||||
|
||||
/* flag of display scratch registers */
|
||||
bool program_scratch_regs;
|
||||
/* current hw configuration */
|
||||
struct sde_res_data res;
|
||||
|
||||
/* flag of display splash status */
|
||||
bool display_splash_enabled;
|
||||
|
||||
/* to indicate LK is totally exited */
|
||||
bool lk_is_exited;
|
||||
|
@ -91,21 +119,20 @@ void sde_splash_setup_connector_count(struct sde_splash_info *sinfo,
|
|||
int connector_type);
|
||||
|
||||
/**
|
||||
* sde_splash_clean_up_exit_lk.
|
||||
* sde_splash_lk_stop_splash.
|
||||
*
|
||||
* Tell LK to exit, and clean up the resource.
|
||||
* Tell LK to stop display splash.
|
||||
*/
|
||||
int sde_splash_clean_up_exit_lk(struct msm_kms *kms);
|
||||
int sde_splash_lk_stop_splash(struct msm_kms *kms);
|
||||
|
||||
/**
|
||||
* sde_splash_clean_up_free_resource.
|
||||
* sde_splash_free_resource.
|
||||
*
|
||||
* According to input connector_type, free
|
||||
* HDMI's and DSI's resource respectively.
|
||||
*/
|
||||
int sde_splash_clean_up_free_resource(struct msm_kms *kms,
|
||||
struct sde_power_handle *phandle,
|
||||
int connector_type, void *display);
|
||||
int sde_splash_free_resource(struct msm_kms *kms,
|
||||
struct sde_power_handle *phandle);
|
||||
|
||||
/**
|
||||
* sde_splash_parse_memory_dt.
|
||||
|
@ -152,7 +179,7 @@ void sde_splash_destroy(struct sde_splash_info *sinfo,
|
|||
*
|
||||
* Get LK's status to check if it has been stopped.
|
||||
*/
|
||||
bool sde_splash_get_lk_complete_status(struct sde_splash_info *sinfo);
|
||||
bool sde_splash_get_lk_complete_status(struct msm_kms *kms);
|
||||
|
||||
/**
|
||||
* sde_splash_setup_display_resource
|
||||
|
|
Loading…
Add table
Reference in a new issue