SDE: HDMI: Disable HPD if non-pluggable flag is set
For non-pluggable display, HPD hardware should be disabled. HPD related clocks should also shutdown during suspend. Change-Id: I59475b07b44c2a7f1784d160263a6bca7701a702 Signed-off-by: Camus Wong <camusw@codeaurora.org>
This commit is contained in:
parent
631acc8fdd
commit
1921a9ede6
3 changed files with 125 additions and 6 deletions
|
@ -1342,15 +1342,73 @@ fail:
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int sde_hdmi_core_enable(struct sde_hdmi *sde_hdmi)
|
||||||
|
{
|
||||||
|
struct hdmi *hdmi = sde_hdmi->ctrl.ctrl;
|
||||||
|
const struct hdmi_platform_config *config = hdmi->config;
|
||||||
|
struct device *dev = &hdmi->pdev->dev;
|
||||||
|
int i, ret;
|
||||||
|
struct drm_connector *connector;
|
||||||
|
struct msm_drm_private *priv;
|
||||||
|
struct sde_kms *sde_kms;
|
||||||
|
|
||||||
|
connector = hdmi->connector;
|
||||||
|
priv = connector->dev->dev_private;
|
||||||
|
sde_kms = to_sde_kms(priv->kms);
|
||||||
|
|
||||||
|
for (i = 0; i < config->hpd_reg_cnt; i++) {
|
||||||
|
ret = regulator_enable(hdmi->hpd_regs[i]);
|
||||||
|
if (ret) {
|
||||||
|
SDE_ERROR("failed to enable hpd regulator: %s (%d)\n",
|
||||||
|
config->hpd_reg_names[i], ret);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = pinctrl_pm_select_default_state(dev);
|
||||||
|
if (ret)
|
||||||
|
SDE_ERROR("pinctrl state chg failed: %d\n", ret);
|
||||||
|
|
||||||
|
ret = _sde_hdmi_gpio_config(hdmi, true);
|
||||||
|
if (ret)
|
||||||
|
SDE_ERROR("failed to configure GPIOs: %d\n", ret);
|
||||||
|
|
||||||
|
for (i = 0; i < config->hpd_clk_cnt; i++) {
|
||||||
|
if (config->hpd_freq && config->hpd_freq[i]) {
|
||||||
|
ret = clk_set_rate(hdmi->hpd_clks[i],
|
||||||
|
config->hpd_freq[i]);
|
||||||
|
if (ret)
|
||||||
|
pr_warn("failed to set clk %s (%d)\n",
|
||||||
|
config->hpd_clk_names[i], ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = clk_prepare_enable(hdmi->hpd_clks[i]);
|
||||||
|
if (ret) {
|
||||||
|
SDE_ERROR("failed to enable hpd clk: %s (%d)\n",
|
||||||
|
config->hpd_clk_names[i], ret);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sde_hdmi_set_mode(hdmi, true);
|
||||||
|
|
||||||
|
/* Wait for vsync */
|
||||||
|
msleep(20);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
static void _sde_hdmi_hdp_disable(struct sde_hdmi *sde_hdmi)
|
static void _sde_hdmi_hdp_disable(struct sde_hdmi *sde_hdmi)
|
||||||
{
|
{
|
||||||
struct hdmi *hdmi = sde_hdmi->ctrl.ctrl;
|
struct hdmi *hdmi = sde_hdmi->ctrl.ctrl;
|
||||||
const struct hdmi_platform_config *config = hdmi->config;
|
const struct hdmi_platform_config *config = hdmi->config;
|
||||||
struct device *dev = &hdmi->pdev->dev;
|
struct device *dev = &hdmi->pdev->dev;
|
||||||
int i, ret = 0;
|
int i, ret = 0;
|
||||||
|
unsigned long flags;
|
||||||
|
|
||||||
|
spin_lock_irqsave(&hdmi->reg_lock, flags);
|
||||||
/* Disable HPD interrupt */
|
/* Disable HPD interrupt */
|
||||||
|
hdmi_write(hdmi, REG_HDMI_HPD_CTRL, 0);
|
||||||
hdmi_write(hdmi, REG_HDMI_HPD_INT_CTRL, 0);
|
hdmi_write(hdmi, REG_HDMI_HPD_INT_CTRL, 0);
|
||||||
|
hdmi_write(hdmi, REG_HDMI_HPD_INT_STATUS, 0);
|
||||||
|
spin_unlock_irqrestore(&hdmi->reg_lock, flags);
|
||||||
|
|
||||||
sde_hdmi_set_mode(hdmi, false);
|
sde_hdmi_set_mode(hdmi, false);
|
||||||
|
|
||||||
|
@ -1373,6 +1431,12 @@ static void _sde_hdmi_hdp_disable(struct sde_hdmi *sde_hdmi)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void sde_hdmi_core_disable(struct sde_hdmi *sde_hdmi)
|
||||||
|
{
|
||||||
|
/* HPD contains all the core clock and pwr */
|
||||||
|
_sde_hdmi_hdp_disable(sde_hdmi);
|
||||||
|
}
|
||||||
|
|
||||||
static void _sde_hdmi_cec_update_phys_addr(struct sde_hdmi *display)
|
static void _sde_hdmi_cec_update_phys_addr(struct sde_hdmi *display)
|
||||||
{
|
{
|
||||||
struct edid *edid = display->edid_ctrl->edid;
|
struct edid *edid = display->edid_ctrl->edid;
|
||||||
|
@ -2388,10 +2452,17 @@ int sde_hdmi_connector_post_init(struct drm_connector *connector,
|
||||||
hdmi->connector = connector;
|
hdmi->connector = connector;
|
||||||
INIT_WORK(&sde_hdmi->hpd_work, _sde_hdmi_hotplug_work);
|
INIT_WORK(&sde_hdmi->hpd_work, _sde_hdmi_hotplug_work);
|
||||||
|
|
||||||
/* Enable HPD detection */
|
if (sde_hdmi->non_pluggable) {
|
||||||
rc = _sde_hdmi_hpd_enable(sde_hdmi);
|
/* Disable HPD interrupt */
|
||||||
if (rc)
|
hdmi_write(hdmi, REG_HDMI_HPD_CTRL, 0);
|
||||||
SDE_ERROR("failed to enable HPD: %d\n", rc);
|
hdmi_write(hdmi, REG_HDMI_HPD_INT_CTRL, 0);
|
||||||
|
hdmi_write(hdmi, REG_HDMI_HPD_INT_STATUS, 0);
|
||||||
|
} else {
|
||||||
|
/* Enable HPD detection if non_pluggable flag is not defined */
|
||||||
|
rc = _sde_hdmi_hpd_enable(sde_hdmi);
|
||||||
|
if (rc)
|
||||||
|
SDE_ERROR("failed to enable HPD: %d\n", rc);
|
||||||
|
}
|
||||||
|
|
||||||
_sde_hdmi_get_tx_version(sde_hdmi);
|
_sde_hdmi_get_tx_version(sde_hdmi);
|
||||||
|
|
||||||
|
@ -3147,6 +3218,8 @@ int sde_hdmi_drm_init(struct sde_hdmi *display, struct drm_encoder *enc)
|
||||||
if (sde_kms->splash_info.handoff) {
|
if (sde_kms->splash_info.handoff) {
|
||||||
sde_hdmi_bridge_power_on(hdmi->bridge);
|
sde_hdmi_bridge_power_on(hdmi->bridge);
|
||||||
hdmi->power_on = true;
|
hdmi->power_on = true;
|
||||||
|
} else {
|
||||||
|
hdmi->power_on = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
mutex_unlock(&display->display_lock);
|
mutex_unlock(&display->display_lock);
|
||||||
|
|
|
@ -301,6 +301,22 @@ sde_hdmi_connector_detect(struct drm_connector *connector,
|
||||||
bool force,
|
bool force,
|
||||||
void *display);
|
void *display);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* sde_hdmi_core_enable()- turn on clk and pwr for hdmi core
|
||||||
|
* @sde_hdmi: Pointer to sde_hdmi structure
|
||||||
|
*
|
||||||
|
* Return: error code
|
||||||
|
*/
|
||||||
|
int sde_hdmi_core_enable(struct sde_hdmi *sde_hdmi);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* sde_hdmi_core_disable()- turn off clk and pwr for hdmi core
|
||||||
|
* @sde_hdmi: Pointer to sde_hdmi structure
|
||||||
|
*
|
||||||
|
* Return: none
|
||||||
|
*/
|
||||||
|
void sde_hdmi_core_disable(struct sde_hdmi *sde_hdmi);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* sde_hdmi_connector_get_modes - add drm modes via drm_mode_probed_add()
|
* sde_hdmi_connector_get_modes - add drm modes via drm_mode_probed_add()
|
||||||
* @connector: Pointer to drm connector structure
|
* @connector: Pointer to drm connector structure
|
||||||
|
|
|
@ -129,8 +129,22 @@ static void _sde_hdmi_bridge_power_on(struct drm_bridge *bridge)
|
||||||
struct sde_hdmi_bridge *sde_hdmi_bridge = to_hdmi_bridge(bridge);
|
struct sde_hdmi_bridge *sde_hdmi_bridge = to_hdmi_bridge(bridge);
|
||||||
struct hdmi *hdmi = sde_hdmi_bridge->hdmi;
|
struct hdmi *hdmi = sde_hdmi_bridge->hdmi;
|
||||||
const struct hdmi_platform_config *config = hdmi->config;
|
const struct hdmi_platform_config *config = hdmi->config;
|
||||||
|
struct sde_connector *c_conn = to_sde_connector(hdmi->connector);
|
||||||
|
struct sde_hdmi *display = NULL;
|
||||||
int i, ret;
|
int i, ret;
|
||||||
|
|
||||||
|
if (c_conn)
|
||||||
|
display = (struct sde_hdmi *)c_conn->display;
|
||||||
|
|
||||||
|
if (display) {
|
||||||
|
if (display->non_pluggable) {
|
||||||
|
ret = sde_hdmi_core_enable(display);
|
||||||
|
if (ret)
|
||||||
|
SDE_ERROR("failed to enable HDMI core (%d)\n",
|
||||||
|
ret);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (i = 0; i < config->pwr_reg_cnt; i++) {
|
for (i = 0; i < config->pwr_reg_cnt; i++) {
|
||||||
ret = regulator_enable(hdmi->pwr_regs[i]);
|
ret = regulator_enable(hdmi->pwr_regs[i]);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
|
@ -162,6 +176,8 @@ static void _sde_hdmi_bridge_power_off(struct drm_bridge *bridge)
|
||||||
struct sde_hdmi_bridge *sde_hdmi_bridge = to_hdmi_bridge(bridge);
|
struct sde_hdmi_bridge *sde_hdmi_bridge = to_hdmi_bridge(bridge);
|
||||||
struct hdmi *hdmi = sde_hdmi_bridge->hdmi;
|
struct hdmi *hdmi = sde_hdmi_bridge->hdmi;
|
||||||
const struct hdmi_platform_config *config = hdmi->config;
|
const struct hdmi_platform_config *config = hdmi->config;
|
||||||
|
struct sde_connector *c_conn = to_sde_connector(hdmi->connector);
|
||||||
|
struct sde_hdmi *display = (struct sde_hdmi *)c_conn->display;
|
||||||
int i, ret;
|
int i, ret;
|
||||||
|
|
||||||
/* Wait for vsync */
|
/* Wait for vsync */
|
||||||
|
@ -177,6 +193,10 @@ static void _sde_hdmi_bridge_power_off(struct drm_bridge *bridge)
|
||||||
config->pwr_reg_names[i], ret);
|
config->pwr_reg_names[i], ret);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (display->non_pluggable) {
|
||||||
|
sde_hdmi_core_disable(display);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int _sde_hdmi_bridge_ddc_clear_irq(struct hdmi *hdmi,
|
static int _sde_hdmi_bridge_ddc_clear_irq(struct hdmi *hdmi,
|
||||||
|
@ -611,8 +631,10 @@ static void _sde_hdmi_bridge_post_disable(struct drm_bridge *bridge)
|
||||||
hdmi->power_on = false;
|
hdmi->power_on = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Powering-on the controller for HPD */
|
if (!display->non_pluggable) {
|
||||||
sde_hdmi_ctrl_cfg(hdmi, 1);
|
/* Powering-on the controller for HPD */
|
||||||
|
sde_hdmi_ctrl_cfg(hdmi, 1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _sde_hdmi_bridge_set_avi_infoframe(struct hdmi *hdmi,
|
static void _sde_hdmi_bridge_set_avi_infoframe(struct hdmi *hdmi,
|
||||||
|
@ -822,6 +844,11 @@ static void _sde_hdmi_bridge_mode_set(struct drm_bridge *bridge,
|
||||||
|
|
||||||
mode = adjusted_mode;
|
mode = adjusted_mode;
|
||||||
|
|
||||||
|
if (display->non_pluggable && !hdmi->power_on) {
|
||||||
|
if (sde_hdmi_core_enable(display))
|
||||||
|
pr_err("mode set enable core failured\n");
|
||||||
|
}
|
||||||
|
|
||||||
display->dc_enable = mode->private_flags &
|
display->dc_enable = mode->private_flags &
|
||||||
(MSM_MODE_FLAG_RGB444_DC_ENABLE |
|
(MSM_MODE_FLAG_RGB444_DC_ENABLE |
|
||||||
MSM_MODE_FLAG_YUV420_DC_ENABLE);
|
MSM_MODE_FLAG_YUV420_DC_ENABLE);
|
||||||
|
@ -898,6 +925,9 @@ static void _sde_hdmi_bridge_mode_set(struct drm_bridge *bridge,
|
||||||
_sde_hdmi_save_mode(hdmi, mode);
|
_sde_hdmi_save_mode(hdmi, mode);
|
||||||
_sde_hdmi_bridge_setup_scrambler(hdmi, mode);
|
_sde_hdmi_bridge_setup_scrambler(hdmi, mode);
|
||||||
_sde_hdmi_bridge_setup_deep_color(hdmi);
|
_sde_hdmi_bridge_setup_deep_color(hdmi);
|
||||||
|
if (display->non_pluggable && !hdmi->power_on) {
|
||||||
|
sde_hdmi_core_disable(display);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool _sde_hdmi_bridge_mode_fixup(struct drm_bridge *bridge,
|
static bool _sde_hdmi_bridge_mode_fixup(struct drm_bridge *bridge,
|
||||||
|
|
Loading…
Add table
Reference in a new issue