summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLinux Build Service Account <lnxbuild@localhost>2018-02-13 12:17:06 -0800
committerGerrit - the friendly Code Review server <code-review@localhost>2018-02-13 12:17:06 -0800
commit0100d380ab895d2326b7a34dc3337302ec378f5a (patch)
treede30ff8ffe465ebb2326785992a4c1b8f65ab6a5
parent76ee1b8d18ace50c9cdab13f6386d6dee45b11a0 (diff)
parent1921a9ede6382767da9728815ebc498980ece7e4 (diff)
Merge "SDE: HDMI: Disable HPD if non-pluggable flag is set"
-rw-r--r--drivers/gpu/drm/msm/hdmi-staging/sde_hdmi.c81
-rw-r--r--drivers/gpu/drm/msm/hdmi-staging/sde_hdmi.h16
-rw-r--r--drivers/gpu/drm/msm/hdmi-staging/sde_hdmi_bridge.c34
3 files changed, 125 insertions, 6 deletions
diff --git a/drivers/gpu/drm/msm/hdmi-staging/sde_hdmi.c b/drivers/gpu/drm/msm/hdmi-staging/sde_hdmi.c
index 35ba396e1cd1..3c149f191871 100644
--- a/drivers/gpu/drm/msm/hdmi-staging/sde_hdmi.c
+++ b/drivers/gpu/drm/msm/hdmi-staging/sde_hdmi.c
@@ -1342,15 +1342,73 @@ fail:
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)
{
struct hdmi *hdmi = sde_hdmi->ctrl.ctrl;
const struct hdmi_platform_config *config = hdmi->config;
struct device *dev = &hdmi->pdev->dev;
int i, ret = 0;
+ unsigned long flags;
+ spin_lock_irqsave(&hdmi->reg_lock, flags);
/* 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_STATUS, 0);
+ spin_unlock_irqrestore(&hdmi->reg_lock, flags);
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)
{
struct edid *edid = display->edid_ctrl->edid;
@@ -2388,10 +2452,17 @@ int sde_hdmi_connector_post_init(struct drm_connector *connector,
hdmi->connector = connector;
INIT_WORK(&sde_hdmi->hpd_work, _sde_hdmi_hotplug_work);
- /* Enable HPD detection */
- rc = _sde_hdmi_hpd_enable(sde_hdmi);
- if (rc)
- SDE_ERROR("failed to enable HPD: %d\n", rc);
+ if (sde_hdmi->non_pluggable) {
+ /* 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_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);
@@ -3147,6 +3218,8 @@ int sde_hdmi_drm_init(struct sde_hdmi *display, struct drm_encoder *enc)
if (sde_kms->splash_info.handoff) {
sde_hdmi_bridge_power_on(hdmi->bridge);
hdmi->power_on = true;
+ } else {
+ hdmi->power_on = false;
}
mutex_unlock(&display->display_lock);
diff --git a/drivers/gpu/drm/msm/hdmi-staging/sde_hdmi.h b/drivers/gpu/drm/msm/hdmi-staging/sde_hdmi.h
index 865998c6a126..471472ea23cf 100644
--- a/drivers/gpu/drm/msm/hdmi-staging/sde_hdmi.h
+++ b/drivers/gpu/drm/msm/hdmi-staging/sde_hdmi.h
@@ -302,6 +302,22 @@ sde_hdmi_connector_detect(struct drm_connector *connector,
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
* @display: Pointer to private display handle
diff --git a/drivers/gpu/drm/msm/hdmi-staging/sde_hdmi_bridge.c b/drivers/gpu/drm/msm/hdmi-staging/sde_hdmi_bridge.c
index 5fbe4767ad3a..5a4c4b02c340 100644
--- a/drivers/gpu/drm/msm/hdmi-staging/sde_hdmi_bridge.c
+++ b/drivers/gpu/drm/msm/hdmi-staging/sde_hdmi_bridge.c
@@ -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 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 = NULL;
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++) {
ret = regulator_enable(hdmi->pwr_regs[i]);
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 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 +193,10 @@ 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,
@@ -611,8 +631,10 @@ static void _sde_hdmi_bridge_post_disable(struct drm_bridge *bridge)
hdmi->power_on = false;
}
- /* Powering-on the controller for HPD */
- sde_hdmi_ctrl_cfg(hdmi, 1);
+ if (!display->non_pluggable) {
+ /* Powering-on the controller for HPD */
+ sde_hdmi_ctrl_cfg(hdmi, 1);
+ }
}
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;
+ 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 &
(MSM_MODE_FLAG_RGB444_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_bridge_setup_scrambler(hdmi, mode);
_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,