Merge "drm: sde: Check commit's validity when starting splash handoff"
This commit is contained in:
commit
7f1e39e00b
4 changed files with 137 additions and 44 deletions
|
@ -572,6 +572,7 @@ void sde_connector_complete_commit(struct drm_connector *connector)
|
||||||
{
|
{
|
||||||
struct drm_device *dev;
|
struct drm_device *dev;
|
||||||
struct msm_drm_private *priv;
|
struct msm_drm_private *priv;
|
||||||
|
struct sde_connector *c_conn;
|
||||||
|
|
||||||
if (!connector) {
|
if (!connector) {
|
||||||
SDE_ERROR("invalid connector\n");
|
SDE_ERROR("invalid connector\n");
|
||||||
|
@ -584,11 +585,17 @@ void sde_connector_complete_commit(struct drm_connector *connector)
|
||||||
/* signal connector's retire fence */
|
/* signal connector's retire fence */
|
||||||
sde_fence_signal(&to_sde_connector(connector)->retire_fence, 0);
|
sde_fence_signal(&to_sde_connector(connector)->retire_fence, 0);
|
||||||
|
|
||||||
/* after first vsync comes,
|
/*
|
||||||
* early splash resource should start to be released.
|
* After LK totally exits, LK's early splash resource
|
||||||
|
* should be released.
|
||||||
*/
|
*/
|
||||||
if (sde_splash_get_lk_complete_status(priv->kms))
|
if (sde_splash_get_lk_complete_status(priv->kms)) {
|
||||||
sde_splash_free_resource(priv->kms, &priv->phandle);
|
c_conn = to_sde_connector(connector);
|
||||||
|
|
||||||
|
sde_splash_free_resource(priv->kms, &priv->phandle,
|
||||||
|
c_conn->connector_type,
|
||||||
|
c_conn->display);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -345,10 +345,10 @@ static void sde_kms_prepare_commit(struct msm_kms *kms,
|
||||||
|
|
||||||
if (sde_kms->splash_info.handoff &&
|
if (sde_kms->splash_info.handoff &&
|
||||||
sde_kms->splash_info.display_splash_enabled)
|
sde_kms->splash_info.display_splash_enabled)
|
||||||
sde_splash_lk_stop_splash(kms);
|
sde_splash_lk_stop_splash(kms, state);
|
||||||
else
|
|
||||||
sde_power_resource_enable(&priv->phandle,
|
sde_power_resource_enable(&priv->phandle,
|
||||||
sde_kms->core_client, true);
|
sde_kms->core_client, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void sde_kms_commit(struct msm_kms *kms,
|
static void sde_kms_commit(struct msm_kms *kms,
|
||||||
|
|
|
@ -313,6 +313,15 @@ static void _sde_splash_sent_pipe_update_uevent(struct sde_kms *sde_kms)
|
||||||
kfree(event_string);
|
kfree(event_string);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void _sde_splash_get_connector_ref_cnt(struct sde_splash_info *sinfo,
|
||||||
|
u32 *hdmi_cnt, u32 *dsi_cnt)
|
||||||
|
{
|
||||||
|
mutex_lock(&sde_splash_lock);
|
||||||
|
*hdmi_cnt = sinfo->hdmi_connector_cnt;
|
||||||
|
*dsi_cnt = sinfo->dsi_connector_cnt;
|
||||||
|
mutex_unlock(&sde_splash_lock);
|
||||||
|
}
|
||||||
|
|
||||||
static int _sde_splash_free_module_resource(struct msm_mmu *mmu,
|
static int _sde_splash_free_module_resource(struct msm_mmu *mmu,
|
||||||
struct sde_splash_info *sinfo)
|
struct sde_splash_info *sinfo)
|
||||||
{
|
{
|
||||||
|
@ -339,6 +348,29 @@ static int _sde_splash_free_module_resource(struct msm_mmu *mmu,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool _sde_splash_validate_commit(struct sde_kms *sde_kms,
|
||||||
|
struct drm_atomic_state *state)
|
||||||
|
{
|
||||||
|
int i, nplanes;
|
||||||
|
struct drm_plane *plane;
|
||||||
|
struct drm_device *dev = sde_kms->dev;
|
||||||
|
|
||||||
|
nplanes = dev->mode_config.num_total_plane;
|
||||||
|
|
||||||
|
for (i = 0; i < nplanes; i++) {
|
||||||
|
plane = state->planes[i];
|
||||||
|
|
||||||
|
/*
|
||||||
|
* As plane state has been swapped, we need to check
|
||||||
|
* fb in state->planes, not fb in state->plane_state.
|
||||||
|
*/
|
||||||
|
if (plane && plane->fb)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
__ref int sde_splash_init(struct sde_power_handle *phandle, struct msm_kms *kms)
|
__ref int sde_splash_init(struct sde_power_handle *phandle, struct msm_kms *kms)
|
||||||
{
|
{
|
||||||
struct sde_kms *sde_kms;
|
struct sde_kms *sde_kms;
|
||||||
|
@ -369,8 +401,7 @@ __ref int sde_splash_init(struct sde_power_handle *phandle, struct msm_kms *kms)
|
||||||
sde_power_data_bus_bandwidth_ctrl(phandle,
|
sde_power_data_bus_bandwidth_ctrl(phandle,
|
||||||
sde_kms->core_client, false);
|
sde_kms->core_client, false);
|
||||||
|
|
||||||
ret = -EINVAL;
|
return -EINVAL;
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -716,11 +747,17 @@ bool sde_splash_get_lk_complete_status(struct msm_kms *kms)
|
||||||
}
|
}
|
||||||
|
|
||||||
int sde_splash_free_resource(struct msm_kms *kms,
|
int sde_splash_free_resource(struct msm_kms *kms,
|
||||||
struct sde_power_handle *phandle)
|
struct sde_power_handle *phandle,
|
||||||
|
int connector_type, void *display)
|
||||||
{
|
{
|
||||||
struct sde_kms *sde_kms;
|
struct sde_kms *sde_kms;
|
||||||
struct sde_splash_info *sinfo;
|
struct sde_splash_info *sinfo;
|
||||||
struct msm_mmu *mmu;
|
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) {
|
if (!phandle || !kms) {
|
||||||
SDE_ERROR("invalid phandle/kms.\n");
|
SDE_ERROR("invalid phandle/kms.\n");
|
||||||
|
@ -734,41 +771,88 @@ int sde_splash_free_resource(struct msm_kms *kms,
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Get connector number where the early splash in on. */
|
||||||
|
_sde_splash_get_connector_ref_cnt(sinfo, &hdmi_conn_count,
|
||||||
|
&dsi_conn_count);
|
||||||
|
|
||||||
mutex_lock(&sde_splash_lock);
|
mutex_lock(&sde_splash_lock);
|
||||||
if (!sinfo->handoff) {
|
if (!sinfo->handoff) {
|
||||||
mutex_unlock(&sde_splash_lock);
|
mutex_unlock(&sde_splash_lock);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
mmu = sde_kms->aspace[0]->mmu;
|
/*
|
||||||
if (!mmu) {
|
* Start to free all LK's resource till user commit happens
|
||||||
mutex_unlock(&sde_splash_lock);
|
* on each display which early splash is enabled on.
|
||||||
return -EINVAL;
|
*/
|
||||||
}
|
if (hdmi_conn_count == 0 && dsi_conn_count == 0) {
|
||||||
|
mmu = sde_kms->aspace[0]->mmu;
|
||||||
|
if (!mmu) {
|
||||||
|
mutex_unlock(&sde_splash_lock);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
/* free HDMI's, DSI's and early camera's reserved memory */
|
/* free HDMI's, DSI's and early camera's reserved memory */
|
||||||
_sde_splash_free_module_resource(mmu, sinfo);
|
_sde_splash_free_module_resource(mmu, sinfo);
|
||||||
|
|
||||||
_sde_splash_destroy_splash_node(sinfo);
|
_sde_splash_destroy_splash_node(sinfo);
|
||||||
|
|
||||||
/* free lk_pool heap memory */
|
/* free lk_pool heap memory */
|
||||||
_sde_splash_free_bootup_memory_to_system(sinfo->lk_pool_paddr,
|
_sde_splash_free_bootup_memory_to_system(sinfo->lk_pool_paddr,
|
||||||
sinfo->lk_pool_size);
|
sinfo->lk_pool_size);
|
||||||
|
|
||||||
/* withdraw data bus vote */
|
/* withdraw data bus vote */
|
||||||
sde_power_data_bus_bandwidth_ctrl(phandle,
|
sde_power_data_bus_bandwidth_ctrl(phandle,
|
||||||
sde_kms->core_client, false);
|
sde_kms->core_client, false);
|
||||||
|
|
||||||
/* send uevent to notify user to recycle resource */
|
/*
|
||||||
_sde_splash_sent_pipe_update_uevent(sde_kms);
|
* Turn off MDP core power to keep power on/off operations
|
||||||
|
* be matched, as MDP core power is enabled already when
|
||||||
|
* early splash is enabled.
|
||||||
|
*/
|
||||||
|
sde_power_resource_enable(phandle,
|
||||||
|
sde_kms->core_client, false);
|
||||||
|
|
||||||
/* Finally mark handoff flag to false to say handoff is complete */
|
/* send uevent to notify user to recycle resource */
|
||||||
sinfo->handoff = false;
|
_sde_splash_sent_pipe_update_uevent(sde_kms);
|
||||||
|
|
||||||
DRM_INFO("HDMI and DSI resource handoff is completed\n");
|
/* 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 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Ensure user commit happens on different connectors
|
||||||
|
* who has splash.
|
||||||
|
*/
|
||||||
|
switch (connector_type) {
|
||||||
|
case DRM_MODE_CONNECTOR_HDMIA:
|
||||||
|
if (sinfo->hdmi_connector_cnt == 1)
|
||||||
|
sinfo->hdmi_connector_cnt--;
|
||||||
|
break;
|
||||||
|
case DRM_MODE_CONNECTOR_DSI:
|
||||||
|
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--;
|
||||||
|
|
||||||
|
last_commit_display_type = dsi_display->display_type;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
ret = -EINVAL;
|
||||||
|
SDE_ERROR("%s: invalid connector_type %d\n",
|
||||||
|
__func__, connector_type);
|
||||||
|
}
|
||||||
|
|
||||||
mutex_unlock(&sde_splash_lock);
|
mutex_unlock(&sde_splash_lock);
|
||||||
return 0;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -776,7 +860,8 @@ int sde_splash_free_resource(struct msm_kms *kms,
|
||||||
* 1. Notify LK to stop display splash.
|
* 1. Notify LK to stop display splash.
|
||||||
* 2. Set DOMAIN_ATTR_EARLY_MAP to 1 to enable stage 1 translation in iommu.
|
* 2. Set DOMAIN_ATTR_EARLY_MAP to 1 to enable stage 1 translation in iommu.
|
||||||
*/
|
*/
|
||||||
int sde_splash_lk_stop_splash(struct msm_kms *kms)
|
int sde_splash_lk_stop_splash(struct msm_kms *kms,
|
||||||
|
struct drm_atomic_state *state)
|
||||||
{
|
{
|
||||||
struct sde_splash_info *sinfo;
|
struct sde_splash_info *sinfo;
|
||||||
struct msm_mmu *mmu;
|
struct msm_mmu *mmu;
|
||||||
|
@ -792,7 +877,8 @@ int sde_splash_lk_stop_splash(struct msm_kms *kms)
|
||||||
|
|
||||||
/* Monitor LK's status and tell it to exit. */
|
/* Monitor LK's status and tell it to exit. */
|
||||||
mutex_lock(&sde_splash_lock);
|
mutex_lock(&sde_splash_lock);
|
||||||
if (sinfo->display_splash_enabled) {
|
if (_sde_splash_validate_commit(sde_kms, state) &&
|
||||||
|
sinfo->display_splash_enabled) {
|
||||||
if (_sde_splash_lk_check(sde_kms->hw_intr))
|
if (_sde_splash_lk_check(sde_kms->hw_intr))
|
||||||
_sde_splash_notify_lk_stop_splash(sde_kms->hw_intr);
|
_sde_splash_notify_lk_stop_splash(sde_kms->hw_intr);
|
||||||
|
|
||||||
|
|
|
@ -17,9 +17,6 @@
|
||||||
#include "msm_mmu.h"
|
#include "msm_mmu.h"
|
||||||
#include "sde_hw_mdss.h"
|
#include "sde_hw_mdss.h"
|
||||||
|
|
||||||
#define SPLASH_CTL_MAX 5
|
|
||||||
#define SPLASH_LM_MAX 7
|
|
||||||
|
|
||||||
enum splash_connector_type {
|
enum splash_connector_type {
|
||||||
SPLASH_DSI = 0,
|
SPLASH_DSI = 0,
|
||||||
SPLASH_HDMI,
|
SPLASH_HDMI,
|
||||||
|
@ -35,13 +32,13 @@ struct splash_ctl_top {
|
||||||
u32 value;
|
u32 value;
|
||||||
u8 intf_sel;
|
u8 intf_sel;
|
||||||
u8 ctl_lm_cnt;
|
u8 ctl_lm_cnt;
|
||||||
struct splash_lm_hw lm[SPLASH_LM_MAX];
|
struct splash_lm_hw lm[LM_MAX - LM_0];
|
||||||
};
|
};
|
||||||
|
|
||||||
struct sde_res_data {
|
struct sde_res_data {
|
||||||
struct splash_ctl_top top[SPLASH_CTL_MAX];
|
struct splash_ctl_top top[CTL_MAX - CTL_0];
|
||||||
u8 ctl_ids[SPLASH_CTL_MAX];
|
u8 ctl_ids[CTL_MAX - CTL_0];
|
||||||
u8 lm_ids[SPLASH_LM_MAX];
|
u8 lm_ids[LM_MAX - LM_0];
|
||||||
u8 ctl_top_cnt;
|
u8 ctl_top_cnt;
|
||||||
u8 lm_cnt;
|
u8 lm_cnt;
|
||||||
};
|
};
|
||||||
|
@ -121,18 +118,21 @@ void sde_splash_setup_connector_count(struct sde_splash_info *sinfo,
|
||||||
/**
|
/**
|
||||||
* sde_splash_lk_stop_splash.
|
* sde_splash_lk_stop_splash.
|
||||||
*
|
*
|
||||||
* Tell LK to stop display splash.
|
* Tell LK to stop display splash once one valid user commit arrives.
|
||||||
*/
|
*/
|
||||||
int sde_splash_lk_stop_splash(struct msm_kms *kms);
|
int sde_splash_lk_stop_splash(struct msm_kms *kms,
|
||||||
|
struct drm_atomic_state *state);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* sde_splash_free_resource.
|
* sde_splash_free_resource.
|
||||||
*
|
*
|
||||||
* According to input connector_type, free
|
* To free all LK's resource, including free reserved memory to system,
|
||||||
* HDMI's and DSI's resource respectively.
|
* withdraw data bus vote, disable MDP core power, send uevent to user
|
||||||
|
* to recycle pipe etc.
|
||||||
*/
|
*/
|
||||||
int sde_splash_free_resource(struct msm_kms *kms,
|
int sde_splash_free_resource(struct msm_kms *kms,
|
||||||
struct sde_power_handle *phandle);
|
struct sde_power_handle *phandle,
|
||||||
|
int connector_type, void *display);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* sde_splash_parse_memory_dt.
|
* sde_splash_parse_memory_dt.
|
||||||
|
|
Loading…
Add table
Reference in a new issue