drm: msm: add early splash support on triple displays
This patch is to support early splash on triple displays including DSI-HDMI displays and native HDMI display, for auto products. CRs-Fixed: 2225630 Change-Id: I4de17eabbf2b2caf1354390f327ba7b761dc313f Signed-off-by: Guchun Chen <guchunc@codeaurora.org> Signed-off-by: Camus Wong <camusw@codeaurora.org>
This commit is contained in:
parent
ef00227cce
commit
10d7d4f65a
13 changed files with 294 additions and 49 deletions
|
@ -51,6 +51,7 @@ struct dba_bridge {
|
|||
u32 num_of_input_lanes;
|
||||
bool pluggable;
|
||||
u32 panel_count;
|
||||
bool cont_splash_enabled;
|
||||
};
|
||||
#define to_dba_bridge(x) container_of((x), struct dba_bridge, base)
|
||||
|
||||
|
@ -324,6 +325,7 @@ struct drm_bridge *dba_bridge_init(struct drm_device *dev,
|
|||
bridge->panel_count = data->panel_count;
|
||||
bridge->base.funcs = &_dba_bridge_ops;
|
||||
bridge->base.encoder = encoder;
|
||||
bridge->cont_splash_enabled = data->cont_splash_enabled;
|
||||
|
||||
rc = drm_bridge_attach(dev, &bridge->base);
|
||||
if (rc) {
|
||||
|
@ -339,7 +341,10 @@ struct drm_bridge *dba_bridge_init(struct drm_device *dev,
|
|||
encoder->bridge = &bridge->base;
|
||||
}
|
||||
|
||||
if (!bridge->pluggable) {
|
||||
/* If early splash has enabled bridge chip in bootloader,
|
||||
* below call should be skipped.
|
||||
*/
|
||||
if (!bridge->pluggable && !bridge->cont_splash_enabled) {
|
||||
if (bridge->ops.power_on)
|
||||
bridge->ops.power_on(bridge->dba_ctx, true, 0);
|
||||
if (bridge->ops.check_hpd)
|
||||
|
|
|
@ -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
|
||||
|
@ -44,6 +44,7 @@ struct dba_bridge_init {
|
|||
struct drm_bridge *precede_bridge;
|
||||
bool pluggable;
|
||||
u32 panel_count;
|
||||
bool cont_splash_enabled;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -1598,7 +1598,7 @@ exit:
|
|||
*
|
||||
* Return: error code.
|
||||
*/
|
||||
int dsi_ctrl_host_init(struct dsi_ctrl *dsi_ctrl)
|
||||
int dsi_ctrl_host_init(struct dsi_ctrl *dsi_ctrl, bool cont_splash_enabled)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
|
@ -1615,37 +1615,40 @@ int dsi_ctrl_host_init(struct dsi_ctrl *dsi_ctrl)
|
|||
goto error;
|
||||
}
|
||||
|
||||
dsi_ctrl->hw.ops.setup_lane_map(&dsi_ctrl->hw,
|
||||
if (!cont_splash_enabled) {
|
||||
dsi_ctrl->hw.ops.setup_lane_map(&dsi_ctrl->hw,
|
||||
&dsi_ctrl->host_config.lane_map);
|
||||
|
||||
dsi_ctrl->hw.ops.host_setup(&dsi_ctrl->hw,
|
||||
dsi_ctrl->hw.ops.host_setup(&dsi_ctrl->hw,
|
||||
&dsi_ctrl->host_config.common_config);
|
||||
|
||||
if (dsi_ctrl->host_config.panel_mode == DSI_OP_CMD_MODE) {
|
||||
dsi_ctrl->hw.ops.cmd_engine_setup(&dsi_ctrl->hw,
|
||||
if (dsi_ctrl->host_config.panel_mode == DSI_OP_CMD_MODE) {
|
||||
dsi_ctrl->hw.ops.cmd_engine_setup(&dsi_ctrl->hw,
|
||||
&dsi_ctrl->host_config.common_config,
|
||||
&dsi_ctrl->host_config.u.cmd_engine);
|
||||
|
||||
dsi_ctrl->hw.ops.setup_cmd_stream(&dsi_ctrl->hw,
|
||||
dsi_ctrl->hw.ops.setup_cmd_stream(&dsi_ctrl->hw,
|
||||
dsi_ctrl->host_config.video_timing.h_active,
|
||||
dsi_ctrl->host_config.video_timing.h_active * 3,
|
||||
dsi_ctrl->host_config.video_timing.v_active,
|
||||
0x0);
|
||||
} else {
|
||||
dsi_ctrl->hw.ops.video_engine_setup(&dsi_ctrl->hw,
|
||||
} else {
|
||||
dsi_ctrl->hw.ops.video_engine_setup(&dsi_ctrl->hw,
|
||||
&dsi_ctrl->host_config.common_config,
|
||||
&dsi_ctrl->host_config.u.video_engine);
|
||||
dsi_ctrl->hw.ops.set_video_timing(&dsi_ctrl->hw,
|
||||
dsi_ctrl->hw.ops.set_video_timing(&dsi_ctrl->hw,
|
||||
&dsi_ctrl->host_config.video_timing);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
dsi_ctrl->hw.ops.enable_status_interrupts(&dsi_ctrl->hw, 0x0);
|
||||
dsi_ctrl->hw.ops.enable_error_interrupts(&dsi_ctrl->hw, 0x0);
|
||||
|
||||
/* Perform a soft reset before enabling dsi controller */
|
||||
dsi_ctrl->hw.ops.soft_reset(&dsi_ctrl->hw);
|
||||
/* Perform a soft reset before enabling dsi controller
|
||||
* But skip the reset if dsi is enabled in bootloader.
|
||||
*/
|
||||
if (!cont_splash_enabled)
|
||||
dsi_ctrl->hw.ops.soft_reset(&dsi_ctrl->hw);
|
||||
pr_debug("[DSI_%d]Host initialization complete\n", dsi_ctrl->index);
|
||||
dsi_ctrl_update_state(dsi_ctrl, DSI_CTRL_OP_HOST_INIT, 0x1);
|
||||
error:
|
||||
|
@ -1967,6 +1970,12 @@ error:
|
|||
return rc;
|
||||
}
|
||||
|
||||
void dsi_ctrl_update_power_state(struct dsi_ctrl *dsi_ctrl,
|
||||
enum dsi_power_state state)
|
||||
{
|
||||
dsi_ctrl_update_state(dsi_ctrl, DSI_CTRL_OP_POWER_STATE_CHANGE, state);
|
||||
}
|
||||
|
||||
/**
|
||||
* dsi_ctrl_set_tpg_state() - enable/disable test pattern on the controller
|
||||
* @dsi_ctrl: DSI controller handle.
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2015-2016, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2015-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
|
||||
|
@ -331,6 +331,7 @@ int dsi_ctrl_phy_sw_reset(struct dsi_ctrl *dsi_ctrl);
|
|||
/**
|
||||
* dsi_ctrl_host_init() - Initialize DSI host hardware.
|
||||
* @dsi_ctrl: DSI controller handle.
|
||||
* @cont_splash_enabled: Flag for DSI splash enabled in bootloader.
|
||||
*
|
||||
* Initializes DSI controller hardware with host configuration provided by
|
||||
* dsi_ctrl_update_host_config(). Initialization can be performed only during
|
||||
|
@ -339,7 +340,7 @@ int dsi_ctrl_phy_sw_reset(struct dsi_ctrl *dsi_ctrl);
|
|||
*
|
||||
* Return: error code.
|
||||
*/
|
||||
int dsi_ctrl_host_init(struct dsi_ctrl *dsi_ctrl);
|
||||
int dsi_ctrl_host_init(struct dsi_ctrl *dsi_ctrl, bool cont_splash_enabled);
|
||||
|
||||
/**
|
||||
* dsi_ctrl_host_deinit() - De-Initialize DSI host hardware.
|
||||
|
@ -403,6 +404,16 @@ int dsi_ctrl_cmd_tx_trigger(struct dsi_ctrl *dsi_ctrl, u32 flags);
|
|||
int dsi_ctrl_set_power_state(struct dsi_ctrl *dsi_ctrl,
|
||||
enum dsi_power_state state);
|
||||
|
||||
/**
|
||||
* dsi_ctrl_update_power_state() - update power state for dsi controller
|
||||
* @dsi_ctrl: DSI controller handle.
|
||||
* @state: Power state.
|
||||
*
|
||||
* Update power state for DSI controller.
|
||||
*
|
||||
*/
|
||||
void dsi_ctrl_update_power_state(struct dsi_ctrl *dsi_ctrl,
|
||||
enum dsi_power_state state);
|
||||
/**
|
||||
* dsi_ctrl_set_cmd_engine_state() - set command engine state
|
||||
* @dsi_ctrl: DSI Controller handle.
|
||||
|
|
|
@ -174,6 +174,11 @@ static int dsi_display_ctrl_power_on(struct dsi_display *display)
|
|||
int i;
|
||||
struct dsi_display_ctrl *ctrl;
|
||||
|
||||
if (display->cont_splash_enabled) {
|
||||
pr_debug("skip ctrl power on\n");
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* Sequence does not matter for split dsi usecases */
|
||||
|
||||
for (i = 0; i < display->ctrl_count; i++) {
|
||||
|
@ -460,7 +465,8 @@ static int dsi_display_ctrl_init(struct dsi_display *display)
|
|||
|
||||
for (i = 0 ; i < display->ctrl_count; i++) {
|
||||
ctrl = &display->ctrl[i];
|
||||
rc = dsi_ctrl_host_init(ctrl->ctrl);
|
||||
rc = dsi_ctrl_host_init(ctrl->ctrl,
|
||||
display->cont_splash_enabled);
|
||||
if (rc) {
|
||||
pr_err("[%s] failed to init host_%d, rc=%d\n",
|
||||
display->name, i, rc);
|
||||
|
@ -720,7 +726,7 @@ static int dsi_display_phy_enable(struct dsi_display *display)
|
|||
rc = dsi_phy_enable(m_ctrl->phy,
|
||||
&display->config,
|
||||
m_src,
|
||||
true);
|
||||
true, display->cont_splash_enabled);
|
||||
if (rc) {
|
||||
pr_err("[%s] failed to enable DSI PHY, rc=%d\n",
|
||||
display->name, rc);
|
||||
|
@ -735,7 +741,7 @@ static int dsi_display_phy_enable(struct dsi_display *display)
|
|||
rc = dsi_phy_enable(ctrl->phy,
|
||||
&display->config,
|
||||
DSI_PLL_SOURCE_NON_NATIVE,
|
||||
true);
|
||||
true, display->cont_splash_enabled);
|
||||
if (rc) {
|
||||
pr_err("[%s] failed to enable DSI PHY, rc=%d\n",
|
||||
display->name, rc);
|
||||
|
@ -848,6 +854,11 @@ static int dsi_display_phy_sw_reset(struct dsi_display *display)
|
|||
int i;
|
||||
struct dsi_display_ctrl *m_ctrl, *ctrl;
|
||||
|
||||
if (display->cont_splash_enabled) {
|
||||
pr_debug("skip phy sw reset\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
m_ctrl = &display->ctrl[display->cmd_master_idx];
|
||||
|
||||
rc = dsi_ctrl_phy_sw_reset(m_ctrl->ctrl);
|
||||
|
@ -1748,6 +1759,45 @@ static int _dsi_display_dev_deinit(struct dsi_display *display)
|
|||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
* _dsi_display_config_ctrl_for_splash
|
||||
*
|
||||
* Config ctrl engine for DSI display.
|
||||
* @display: Handle to the display
|
||||
* Returns: Zero on success
|
||||
*/
|
||||
static int _dsi_display_config_ctrl_for_splash(struct dsi_display *display)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
if (!display) {
|
||||
pr_err("Invalid params\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (display->config.panel_mode == DSI_OP_VIDEO_MODE) {
|
||||
rc = dsi_display_vid_engine_enable(display);
|
||||
if (rc) {
|
||||
pr_err("[%s]failed to enable video engine, rc=%d\n",
|
||||
display->name, rc);
|
||||
goto error_out;
|
||||
}
|
||||
} else if (display->config.panel_mode == DSI_OP_CMD_MODE) {
|
||||
rc = dsi_display_cmd_engine_enable(display);
|
||||
if (rc) {
|
||||
pr_err("[%s]failed to enable cmd engine, rc=%d\n",
|
||||
display->name, rc);
|
||||
goto error_out;
|
||||
}
|
||||
} else {
|
||||
pr_err("[%s] Invalid configuration\n", display->name);
|
||||
rc = -EINVAL;
|
||||
}
|
||||
|
||||
error_out:
|
||||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
* dsi_display_bind - bind dsi device with controlling device
|
||||
* @dev: Pointer to base of platform device
|
||||
|
@ -2141,6 +2191,8 @@ int dsi_display_drm_bridge_init(struct dsi_display *display,
|
|||
init_data.num_of_input_lanes = num_of_lanes;
|
||||
init_data.precede_bridge = precede_bridge;
|
||||
init_data.panel_count = display->panel_count;
|
||||
init_data.cont_splash_enabled =
|
||||
display->cont_splash_enabled;
|
||||
dba_bridge = dba_bridge_init(display->drm_dev, enc,
|
||||
&init_data);
|
||||
if (IS_ERR_OR_NULL(dba_bridge)) {
|
||||
|
@ -2451,26 +2503,28 @@ int dsi_display_prepare(struct dsi_display *display)
|
|||
|
||||
mutex_lock(&display->display_lock);
|
||||
|
||||
for (i = 0; i < display->panel_count; i++) {
|
||||
rc = dsi_panel_pre_prepare(display->panel[i]);
|
||||
if (rc) {
|
||||
SDE_ERROR("[%s] panel pre-prepare failed, rc=%d\n",
|
||||
display->name, rc);
|
||||
goto error_panel_post_unprep;
|
||||
if (!display->cont_splash_enabled) {
|
||||
for (i = 0; i < display->panel_count; i++) {
|
||||
rc = dsi_panel_pre_prepare(display->panel[i]);
|
||||
if (rc) {
|
||||
SDE_ERROR("[%s]pre-prepare failed, rc=%d\n",
|
||||
display->name, rc);
|
||||
goto error_panel_post_unprep;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
rc = dsi_display_ctrl_power_on(display);
|
||||
if (rc) {
|
||||
pr_err("[%s] failed to power on dsi controllers, rc=%d\n",
|
||||
display->name, rc);
|
||||
display->name, rc);
|
||||
goto error_panel_post_unprep;
|
||||
}
|
||||
|
||||
rc = dsi_display_phy_power_on(display);
|
||||
if (rc) {
|
||||
pr_err("[%s] failed to power on dsi phy, rc = %d\n",
|
||||
display->name, rc);
|
||||
display->name, rc);
|
||||
goto error_ctrl_pwr_off;
|
||||
}
|
||||
|
||||
|
@ -2497,21 +2551,21 @@ int dsi_display_prepare(struct dsi_display *display)
|
|||
rc = dsi_display_ctrl_init(display);
|
||||
if (rc) {
|
||||
pr_err("[%s] failed to setup DSI controller, rc=%d\n",
|
||||
display->name, rc);
|
||||
display->name, rc);
|
||||
goto error_phy_disable;
|
||||
}
|
||||
|
||||
rc = dsi_display_ctrl_link_clk_on(display);
|
||||
if (rc) {
|
||||
pr_err("[%s] failed to enable DSI link clocks, rc=%d\n",
|
||||
display->name, rc);
|
||||
display->name, rc);
|
||||
goto error_ctrl_deinit;
|
||||
}
|
||||
|
||||
rc = dsi_display_ctrl_host_enable(display);
|
||||
if (rc) {
|
||||
pr_err("[%s] failed to enable DSI host, rc=%d\n",
|
||||
display->name, rc);
|
||||
display->name, rc);
|
||||
goto error_ctrl_link_off;
|
||||
}
|
||||
|
||||
|
@ -2519,11 +2573,10 @@ int dsi_display_prepare(struct dsi_display *display)
|
|||
rc = dsi_panel_prepare(display->panel[j]);
|
||||
if (rc) {
|
||||
SDE_ERROR("[%s] panel prepare failed, rc=%d\n",
|
||||
display->name, rc);
|
||||
display->name, rc);
|
||||
goto error_panel_unprep;
|
||||
}
|
||||
}
|
||||
|
||||
goto error;
|
||||
|
||||
error_panel_unprep:
|
||||
|
@ -2559,6 +2612,12 @@ int dsi_display_enable(struct dsi_display *display)
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (display->cont_splash_enabled) {
|
||||
_dsi_display_config_ctrl_for_splash(display);
|
||||
display->cont_splash_enabled = false;
|
||||
return 0;
|
||||
}
|
||||
|
||||
mutex_lock(&display->display_lock);
|
||||
|
||||
for (i = 0; i < display->panel_count; i++) {
|
||||
|
@ -2755,6 +2814,46 @@ int dsi_display_unprepare(struct dsi_display *display)
|
|||
return rc;
|
||||
}
|
||||
|
||||
int dsi_dsiplay_setup_splash_resource(struct dsi_display *display)
|
||||
{
|
||||
int ret = 0, i = 0;
|
||||
struct dsi_display_ctrl *ctrl;
|
||||
|
||||
if (!display)
|
||||
return -EINVAL;
|
||||
|
||||
for (i = 0; i < display->ctrl_count; i++) {
|
||||
ctrl = &display->ctrl[i];
|
||||
if (!ctrl)
|
||||
return -EINVAL;
|
||||
|
||||
dsi_pwr_enable_regulator(&ctrl->ctrl->pwr_info.host_pwr, true);
|
||||
dsi_pwr_enable_regulator(&ctrl->ctrl->pwr_info.digital, true);
|
||||
dsi_pwr_enable_regulator(&ctrl->phy->pwr_info.phy_pwr, true);
|
||||
|
||||
ret = dsi_clk_enable_core_clks(&ctrl->ctrl->clk_info.core_clks,
|
||||
true);
|
||||
if (ret) {
|
||||
SDE_ERROR("failed to set core clk for dsi, ret = %d\n",
|
||||
ret);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = dsi_clk_enable_link_clks(&ctrl->ctrl->clk_info.link_clks,
|
||||
true);
|
||||
if (ret) {
|
||||
SDE_ERROR("failed to set link clk for dsi, ret = %d\n",
|
||||
ret);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
dsi_ctrl_update_power_state(ctrl->ctrl,
|
||||
DSI_CTRL_POWER_LINK_CLK_ON);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int __init dsi_display_register(void)
|
||||
{
|
||||
dsi_phy_drv_register();
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* 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
|
||||
|
@ -158,6 +158,8 @@ struct dsi_display {
|
|||
|
||||
/* DEBUG FS */
|
||||
struct dentry *root;
|
||||
|
||||
bool cont_splash_enabled;
|
||||
};
|
||||
|
||||
int dsi_display_dev_probe(struct platform_device *pdev);
|
||||
|
@ -338,4 +340,15 @@ int dsi_display_clock_gate(struct dsi_display *display, bool enable);
|
|||
int dsi_dispaly_static_frame(struct dsi_display *display, bool enable);
|
||||
|
||||
int dsi_display_set_backlight(void *display, u32 bl_lvl);
|
||||
|
||||
/**
|
||||
* dsi_dsiplay_setup_splash_resource
|
||||
* @display: Handle to display.
|
||||
*
|
||||
* Setup DSI splash resource to avoid reset and glitch if DSI is enabled
|
||||
* in bootloder.
|
||||
*
|
||||
* Return: error code.
|
||||
*/
|
||||
int dsi_dsiplay_setup_splash_resource(struct dsi_display *display);
|
||||
#endif /* _DSI_DISPLAY_H_ */
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2016, 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
|
||||
|
@ -721,9 +721,10 @@ error:
|
|||
* Return: error code.
|
||||
*/
|
||||
int dsi_phy_enable(struct msm_dsi_phy *phy,
|
||||
struct dsi_host_config *config,
|
||||
enum dsi_phy_pll_source pll_source,
|
||||
bool skip_validation)
|
||||
struct dsi_host_config *config,
|
||||
enum dsi_phy_pll_source pll_source,
|
||||
bool skip_validation,
|
||||
bool cont_splash_enabled)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
|
@ -758,7 +759,8 @@ int dsi_phy_enable(struct msm_dsi_phy *phy,
|
|||
goto error_disable_clks;
|
||||
}
|
||||
|
||||
dsi_phy_enable_hw(phy);
|
||||
if (!cont_splash_enabled)
|
||||
dsi_phy_enable_hw(phy);
|
||||
|
||||
error_disable_clks:
|
||||
rc = dsi_clk_enable_core_clks(&phy->clks.core_clks, false);
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2016, 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
|
||||
|
@ -157,9 +157,10 @@ int dsi_phy_set_power_state(struct msm_dsi_phy *dsi_phy, bool enable);
|
|||
* Return: error code.
|
||||
*/
|
||||
int dsi_phy_enable(struct msm_dsi_phy *dsi_phy,
|
||||
struct dsi_host_config *config,
|
||||
enum dsi_phy_pll_source pll_source,
|
||||
bool skip_validation);
|
||||
struct dsi_host_config *config,
|
||||
enum dsi_phy_pll_source pll_source,
|
||||
bool skip_validation,
|
||||
bool cont_splash_enabled);
|
||||
|
||||
/**
|
||||
* dsi_phy_disable() - disable DSI PHY hardware.
|
||||
|
|
|
@ -1311,7 +1311,7 @@ static int _sde_hdmi_hpd_enable(struct sde_hdmi *sde_hdmi)
|
|||
}
|
||||
}
|
||||
|
||||
if (!sde_kms->splash_info.handoff) {
|
||||
if (!sde_hdmi->cont_splash_enabled) {
|
||||
sde_hdmi_set_mode(hdmi, false);
|
||||
_sde_hdmi_phy_reset(hdmi);
|
||||
sde_hdmi_set_mode(hdmi, true);
|
||||
|
@ -3186,7 +3186,6 @@ int sde_hdmi_drm_init(struct sde_hdmi *display, struct drm_encoder *enc)
|
|||
struct msm_drm_private *priv = NULL;
|
||||
struct hdmi *hdmi;
|
||||
struct platform_device *pdev;
|
||||
struct sde_kms *sde_kms;
|
||||
|
||||
DBG("");
|
||||
if (!display || !display->drm_dev || !enc) {
|
||||
|
@ -3252,8 +3251,7 @@ int sde_hdmi_drm_init(struct sde_hdmi *display, struct drm_encoder *enc)
|
|||
* clocks. This can skip the clock disabling operation in
|
||||
* clock_late_init when finding clk.count == 1.
|
||||
*/
|
||||
sde_kms = to_sde_kms(priv->kms);
|
||||
if (sde_kms->splash_info.handoff) {
|
||||
if (display->cont_splash_enabled) {
|
||||
sde_hdmi_bridge_power_on(hdmi->bridge);
|
||||
hdmi->power_on = true;
|
||||
} else {
|
||||
|
|
|
@ -196,6 +196,8 @@ struct sde_hdmi {
|
|||
struct dss_io_data io[HDMI_TX_MAX_IO];
|
||||
/* DEBUG FS */
|
||||
struct dentry *root;
|
||||
|
||||
bool cont_splash_enabled;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -639,6 +639,15 @@ static int _sde_kms_setup_displays(struct drm_device *dev,
|
|||
continue;
|
||||
}
|
||||
|
||||
rc = sde_splash_setup_display_resource(&sde_kms->splash_info,
|
||||
display, DRM_MODE_CONNECTOR_DSI);
|
||||
if (rc) {
|
||||
SDE_ERROR("dsi %d splash resource setup failed %d\n",
|
||||
i, rc);
|
||||
sde_encoder_destroy(encoder);
|
||||
continue;
|
||||
}
|
||||
|
||||
rc = dsi_display_drm_bridge_init(display, encoder);
|
||||
if (rc) {
|
||||
SDE_ERROR("dsi bridge %d init failed, %d\n", i, rc);
|
||||
|
@ -731,6 +740,15 @@ static int _sde_kms_setup_displays(struct drm_device *dev,
|
|||
continue;
|
||||
}
|
||||
|
||||
rc = sde_splash_setup_display_resource(&sde_kms->splash_info,
|
||||
display, DRM_MODE_CONNECTOR_HDMIA);
|
||||
if (rc) {
|
||||
SDE_ERROR("hdmi %d splash resource setup failed %d\n",
|
||||
i, rc);
|
||||
sde_encoder_destroy(encoder);
|
||||
continue;
|
||||
}
|
||||
|
||||
rc = sde_hdmi_drm_init(display, encoder);
|
||||
if (rc) {
|
||||
SDE_ERROR("hdmi drm %d init failed, %d\n", i, rc);
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
#include "sde_hw_intf.h"
|
||||
#include "sde_hw_catalog.h"
|
||||
#include "dsi_display.h"
|
||||
#include "sde_hdmi.h"
|
||||
|
||||
#define MDP_SSPP_TOP0_OFF 0x1000
|
||||
#define DISP_INTF_SEL 0x004
|
||||
|
@ -39,6 +40,10 @@
|
|||
|
||||
#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)
|
||||
|
||||
static DEFINE_MUTEX(sde_splash_lock);
|
||||
|
||||
/*
|
||||
|
@ -448,14 +453,17 @@ int sde_splash_get_handoff_status(struct msm_kms *kms)
|
|||
* considered as single display. So decrement
|
||||
* 'num_of_display_on' by 1
|
||||
*/
|
||||
if (split_display)
|
||||
if (split_display) {
|
||||
num_of_display_on--;
|
||||
sinfo->split_is_enabled = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (num_of_display_on) {
|
||||
sinfo->handoff = true;
|
||||
sinfo->program_scratch_regs = true;
|
||||
sinfo->lk_is_exited = false;
|
||||
sinfo->intf_sel_status = intf_sel;
|
||||
} else {
|
||||
sinfo->handoff = false;
|
||||
sinfo->program_scratch_regs = false;
|
||||
|
@ -504,6 +512,71 @@ int sde_splash_smmu_map(struct drm_device *dev, struct msm_mmu *mmu,
|
|||
return ret ? 0 : -ENOMEM;
|
||||
}
|
||||
|
||||
static bool _sde_splash_get_panel_intf_status(struct sde_splash_info *sinfo,
|
||||
const char *display_name, int connector_type)
|
||||
{
|
||||
bool ret = false;
|
||||
int intf_status = 0;
|
||||
|
||||
if (sinfo && sinfo->handoff) {
|
||||
if (connector_type == DRM_MODE_CONNECTOR_DSI) {
|
||||
if (!strcmp(display_name, "dsi_adv_7533_1")) {
|
||||
if (sinfo->intf_sel_status & INTF_DSI0_SEL)
|
||||
ret = true;
|
||||
} else if (!strcmp(display_name, "dsi_adv_7533_2")) {
|
||||
if (sinfo->intf_sel_status & INTF_DSI1_SEL)
|
||||
ret = true;
|
||||
} else
|
||||
DRM_INFO("wrong display name %s\n",
|
||||
display_name);
|
||||
} else if (connector_type == DRM_MODE_CONNECTOR_HDMIA) {
|
||||
intf_status = sinfo->intf_sel_status & INTF_HDMI_SEL;
|
||||
ret = (intf_status == INTF_HDMI_SEL);
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int sde_splash_setup_display_resource(struct sde_splash_info *sinfo,
|
||||
void *disp, int connector_type)
|
||||
{
|
||||
if (!sinfo || !disp)
|
||||
return -EINVAL;
|
||||
|
||||
/* early return if splash is not enabled in bootloader */
|
||||
if (!sinfo->handoff)
|
||||
return 0;
|
||||
|
||||
if (connector_type == DRM_MODE_CONNECTOR_DSI) {
|
||||
struct dsi_display *display = (struct dsi_display *)disp;
|
||||
|
||||
display->cont_splash_enabled =
|
||||
_sde_splash_get_panel_intf_status(sinfo,
|
||||
display->name,
|
||||
connector_type);
|
||||
|
||||
DRM_INFO("DSI splash %s\n",
|
||||
display->cont_splash_enabled ? "enabled" : "disabled");
|
||||
|
||||
if (display->cont_splash_enabled) {
|
||||
if (dsi_dsiplay_setup_splash_resource(display))
|
||||
return -EINVAL;
|
||||
}
|
||||
} else if (connector_type == DRM_MODE_CONNECTOR_HDMIA) {
|
||||
struct sde_hdmi *sde_hdmi = (struct sde_hdmi *)disp;
|
||||
|
||||
sde_hdmi->cont_splash_enabled =
|
||||
_sde_splash_get_panel_intf_status(sinfo,
|
||||
NULL, connector_type);
|
||||
|
||||
DRM_INFO("HDMI splash %s\n",
|
||||
sde_hdmi->cont_splash_enabled ? "enabled" : "disabled");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void sde_splash_setup_connector_count(struct sde_splash_info *sinfo,
|
||||
int connector_type)
|
||||
{
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/**
|
||||
* Copyright (c) 2017 The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2017-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
|
||||
|
@ -49,6 +49,12 @@ struct sde_splash_info {
|
|||
/* memory size of lk pool */
|
||||
size_t lk_pool_size;
|
||||
|
||||
/* enabled statue of displays*/
|
||||
uint32_t intf_sel_status;
|
||||
|
||||
/* DSI split enabled flag */
|
||||
bool split_is_enabled;
|
||||
|
||||
/* registered hdmi connector count */
|
||||
uint32_t hdmi_connector_cnt;
|
||||
|
||||
|
@ -129,4 +135,11 @@ void sde_splash_destroy(struct sde_splash_info *sinfo,
|
|||
*/
|
||||
bool sde_splash_get_lk_complete_status(struct sde_splash_info *sinfo);
|
||||
|
||||
/**
|
||||
* sde_splash_setup_display_resource
|
||||
*
|
||||
* Setup display resource based on connector type.
|
||||
*/
|
||||
int sde_splash_setup_display_resource(struct sde_splash_info *sinfo,
|
||||
void *disp, int connector_type);
|
||||
#endif
|
||||
|
|
Loading…
Add table
Reference in a new issue