DRM: SDE: Update the hdmi bridge to handle HPD clock

For non-pluggable display, it should not enable HPD.  Instead, the
bridge should handle all the clocks for HDMI.  Also the scrambler
should be activated after the HDMI has power on the clock.

Change-Id: I9162a49b8f314de4d30b0d82c7867a639ddf05a6
Signed-off-by: Camus Wong <camusw@codeaurora.org>
This commit is contained in:
Camus Wong 2017-11-23 18:03:21 -05:00 committed by Gerrit - the friendly Code Review server
parent fd7545d7d2
commit b31584ba68
3 changed files with 103 additions and 6 deletions

View file

@ -1342,7 +1342,56 @@ fail:
return ret;
}
static void _sde_hdmi_hdp_disable(struct sde_hdmi *sde_hdmi)
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);
}
}
return ret;
}
static void _sde_hdmi_hpd_disable(struct sde_hdmi *sde_hdmi)
{
struct hdmi *hdmi = sde_hdmi->ctrl.ctrl;
const struct hdmi_platform_config *config = hdmi->config;
@ -1373,6 +1422,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_hpd_disable(sde_hdmi);
}
static void _sde_hdmi_cec_update_phys_addr(struct sde_hdmi *display)
{
struct edid *edid = display->edid_ctrl->edid;
@ -2217,7 +2272,8 @@ int sde_hdmi_connector_pre_deinit(struct drm_connector *connector,
return -EINVAL;
}
_sde_hdmi_hdp_disable(sde_hdmi);
if (!sde_hdmi->non_pluggable)
_sde_hdmi_hpd_disable(sde_hdmi);
return 0;
}
@ -2389,9 +2445,14 @@ int sde_hdmi_connector_post_init(struct drm_connector *connector,
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);
if (rc)
SDE_ERROR("failed to enable HPD: %d\n", rc);
} else {
/* Disable HPD interrupt */
hdmi_write(hdmi, REG_HDMI_HPD_INT_CTRL, 0);
}
_sde_hdmi_get_tx_version(sde_hdmi);

View file

@ -301,6 +301,22 @@ sde_hdmi_connector_detect(struct drm_connector *connector,
bool force,
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()
* @connector: Pointer to drm connector structure

View file

@ -106,6 +106,8 @@ struct sde_hdmi_bridge {
#define HDMI_AVI_IFRAME_LINE_NUMBER 1
#define HDMI_VENDOR_IFRAME_LINE_NUMBER 3
static int _sde_hdmi_bridge_setup_scrambler(struct hdmi *hdmi,
struct drm_display_mode *mode);
void _sde_hdmi_bridge_destroy(struct drm_bridge *bridge)
{
}
@ -129,6 +131,8 @@ static void _sde_hdmi_bridge_power_on(struct drm_bridge *bridge)
struct sde_hdmi_bridge *sde_hdmi_bridge = to_hdmi_bridge(bridge);
struct hdmi *hdmi = sde_hdmi_bridge->hdmi;
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;
for (i = 0; i < config->pwr_reg_cnt; i++) {
@ -155,6 +159,13 @@ static void _sde_hdmi_bridge_power_on(struct drm_bridge *bridge)
config->pwr_clk_names[i], ret);
}
}
if (display->non_pluggable) {
ret = sde_hdmi_core_enable(display);
if (ret)
SDE_ERROR("failed to enable hpd clks: %d\n", ret);
}
_sde_hdmi_bridge_setup_scrambler(hdmi, &display->mode);
}
static void _sde_hdmi_bridge_power_off(struct drm_bridge *bridge)
@ -162,6 +173,8 @@ static void _sde_hdmi_bridge_power_off(struct drm_bridge *bridge)
struct sde_hdmi_bridge *sde_hdmi_bridge = to_hdmi_bridge(bridge);
struct hdmi *hdmi = sde_hdmi_bridge->hdmi;
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;
/* Wait for vsync */
@ -177,6 +190,9 @@ static void _sde_hdmi_bridge_power_off(struct drm_bridge *bridge)
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,
@ -488,6 +504,9 @@ static void _sde_hdmi_bridge_pre_enable(struct drm_bridge *bridge)
if (hdmi->hdcp_ctrl && hdmi->is_hdcp_supported)
hdmi_hdcp_ctrl_on(hdmi->hdcp_ctrl);
/* turn on scrambler, scrambler was skipped if HDMI is off */
_sde_hdmi_bridge_setup_scrambler(hdmi, &display->mode);
mutex_lock(&display->display_lock);
if (display->codec_ready)
sde_hdmi_notify_clients(display, display->connected);
@ -896,6 +915,7 @@ static void _sde_hdmi_bridge_mode_set(struct drm_bridge *bridge,
}
_sde_hdmi_save_mode(hdmi, mode);
if (hdmi->power_on)
_sde_hdmi_bridge_setup_scrambler(hdmi, mode);
_sde_hdmi_bridge_setup_deep_color(hdmi);
}