drm/msm: HPD_OFF Property for SDE HDMI Connector
Adding a new "HPD_OFF" atomic property for the SDE Connector which enables or disables the hpd related clocks for the hdmi display Change-Id: Ie46c97ae0db9bad231acf7efc660499bac28f45a Signed-off-by: Navid Bahrani <nbahrani@codeaurora.org>
This commit is contained in:
parent
5b91f0e883
commit
7f85fee1bc
5 changed files with 71 additions and 7 deletions
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2016-2018, The Linux Foundation. All rights reserved.
|
||||
* Copyright (C) 2013 Red Hat
|
||||
* Author: Rob Clark <robdclark@gmail.com>
|
||||
*
|
||||
|
@ -1215,6 +1215,9 @@ static int _sde_hdmi_gpio_config(struct hdmi *hdmi, bool on)
|
|||
|
||||
gpio_free(config->hpd_gpio);
|
||||
|
||||
if (config->hpd5v_gpio != -1)
|
||||
gpio_free(config->hpd5v_gpio);
|
||||
|
||||
if (config->mux_en_gpio != -1) {
|
||||
gpio_set_value_cansleep(config->mux_en_gpio, 0);
|
||||
gpio_free(config->mux_en_gpio);
|
||||
|
@ -1336,6 +1339,8 @@ static int _sde_hdmi_hpd_enable(struct sde_hdmi *sde_hdmi)
|
|||
HDMI_HPD_CTRL_ENABLE | hpd_ctrl);
|
||||
spin_unlock_irqrestore(&hdmi->reg_lock, flags);
|
||||
|
||||
hdmi->hpd_off = false;
|
||||
SDE_DEBUG("enabled hdmi hpd\n");
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
|
@ -1395,7 +1400,7 @@ int sde_hdmi_core_enable(struct sde_hdmi *sde_hdmi)
|
|||
return ret;
|
||||
}
|
||||
|
||||
static void _sde_hdmi_hdp_disable(struct sde_hdmi *sde_hdmi)
|
||||
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;
|
||||
|
@ -1403,6 +1408,11 @@ static void _sde_hdmi_hdp_disable(struct sde_hdmi *sde_hdmi)
|
|||
int i, ret = 0;
|
||||
unsigned long flags;
|
||||
|
||||
if (hdmi->hpd_off) {
|
||||
pr_warn("hdmi display hpd was already disabled\n");
|
||||
return;
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&hdmi->reg_lock, flags);
|
||||
/* Disable HPD interrupt */
|
||||
hdmi_write(hdmi, REG_HDMI_HPD_CTRL, 0);
|
||||
|
@ -1429,12 +1439,42 @@ static void _sde_hdmi_hdp_disable(struct sde_hdmi *sde_hdmi)
|
|||
pr_warn("failed to disable hpd regulator: %s (%d)\n",
|
||||
config->hpd_reg_names[i], ret);
|
||||
}
|
||||
hdmi->hpd_off = true;
|
||||
SDE_DEBUG("disabled hdmi hpd\n");
|
||||
}
|
||||
|
||||
/**
|
||||
* _sde_hdmi_update_hpd_state() - Update the HDMI HPD clock state
|
||||
*
|
||||
* @state: non-zero to disbale HPD clock, 0 to enable.
|
||||
* return: 0 on success, non-zero in case of failure.
|
||||
*
|
||||
*/
|
||||
static int
|
||||
_sde_hdmi_update_hpd_state(struct sde_hdmi *hdmi_display, u64 state)
|
||||
{
|
||||
struct hdmi *hdmi = hdmi_display->ctrl.ctrl;
|
||||
int rc = 0;
|
||||
|
||||
if (hdmi_display->non_pluggable)
|
||||
return 0;
|
||||
|
||||
SDE_DEBUG("changing hdmi hpd state to %llu\n", state);
|
||||
|
||||
if (state == SDE_MODE_HPD_ON) {
|
||||
if (!hdmi->hpd_off)
|
||||
pr_warn("hdmi display hpd was already enabled\n");
|
||||
rc = _sde_hdmi_hpd_enable(hdmi_display);
|
||||
} else
|
||||
_sde_hdmi_hpd_disable(hdmi_display);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
void sde_hdmi_core_disable(struct sde_hdmi *sde_hdmi)
|
||||
{
|
||||
/* HPD contains all the core clock and pwr */
|
||||
_sde_hdmi_hdp_disable(sde_hdmi);
|
||||
_sde_hdmi_hpd_disable(sde_hdmi);
|
||||
}
|
||||
|
||||
static void _sde_hdmi_cec_update_phys_addr(struct sde_hdmi *display)
|
||||
|
@ -2204,6 +2244,8 @@ int sde_hdmi_set_property(struct drm_connector *connector,
|
|||
rc = _sde_hdmi_enable_pll_update(display, value);
|
||||
else if (property_index == CONNECTOR_PROP_PLL_DELTA)
|
||||
rc = _sde_hdmi_update_pll_delta(display, value);
|
||||
else if (property_index == CONNECTOR_PROP_HPD_OFF)
|
||||
rc = _sde_hdmi_update_hpd_state(display, value);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
@ -2281,7 +2323,7 @@ int sde_hdmi_connector_pre_deinit(struct drm_connector *connector,
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
_sde_hdmi_hdp_disable(sde_hdmi);
|
||||
_sde_hdmi_hpd_disable(sde_hdmi);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -50,6 +50,9 @@ struct hdmi {
|
|||
|
||||
const struct hdmi_platform_config *config;
|
||||
|
||||
/* hpd state: */
|
||||
bool hpd_off;
|
||||
|
||||
/* audio state: */
|
||||
struct hdmi_audio audio;
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2016-2018, The Linux Foundation. All rights reserved.
|
||||
* Copyright (C) 2013 Red Hat
|
||||
* Author: Rob Clark <robdclark@gmail.com>
|
||||
*
|
||||
|
@ -164,6 +164,7 @@ enum msm_mdp_conn_property {
|
|||
CONNECTOR_PROP_TOPOLOGY_NAME,
|
||||
CONNECTOR_PROP_TOPOLOGY_CONTROL,
|
||||
CONNECTOR_PROP_LP,
|
||||
CONNECTOR_PROP_HPD_OFF,
|
||||
|
||||
/* total # of properties */
|
||||
CONNECTOR_PROP_COUNT
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* 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
|
||||
|
@ -46,6 +46,11 @@ static const struct drm_prop_enum_list e_power_mode[] = {
|
|||
{SDE_MODE_DPMS_OFF, "OFF"},
|
||||
};
|
||||
|
||||
static const struct drm_prop_enum_list hpd_clock_state[] = {
|
||||
{SDE_MODE_HPD_ON, "ON"},
|
||||
{SDE_MODE_HPD_OFF, "OFF"},
|
||||
};
|
||||
|
||||
int sde_connector_get_info(struct drm_connector *connector,
|
||||
struct msm_display_info *info)
|
||||
{
|
||||
|
@ -475,6 +480,9 @@ static int sde_connector_atomic_set_property(struct drm_connector *connector,
|
|||
_sde_connector_update_power_locked(c_conn);
|
||||
mutex_unlock(&c_conn->lock);
|
||||
break;
|
||||
case CONNECTOR_PROP_HPD_OFF:
|
||||
c_conn->hpd_mode = val;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -819,6 +827,7 @@ struct drm_connector *sde_connector_init(struct drm_device *dev,
|
|||
c_conn->display = display;
|
||||
|
||||
c_conn->dpms_mode = DRM_MODE_DPMS_ON;
|
||||
c_conn->hpd_mode = SDE_MODE_HPD_ON;
|
||||
c_conn->lp_mode = 0;
|
||||
c_conn->last_panel_power_mode = SDE_MODE_DPMS_ON;
|
||||
|
||||
|
@ -946,6 +955,11 @@ struct drm_connector *sde_connector_init(struct drm_device *dev,
|
|||
ARRAY_SIZE(e_power_mode),
|
||||
CONNECTOR_PROP_LP, 0);
|
||||
|
||||
msm_property_install_enum(&c_conn->property_info, "HPD_OFF",
|
||||
DRM_MODE_PROP_ATOMIC, 0, hpd_clock_state,
|
||||
ARRAY_SIZE(hpd_clock_state),
|
||||
CONNECTOR_PROP_HPD_OFF, 0);
|
||||
|
||||
rc = msm_property_install_get_status(&c_conn->property_info);
|
||||
if (rc) {
|
||||
SDE_ERROR("failed to create one or more properties\n");
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* 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
|
||||
|
@ -22,6 +22,9 @@
|
|||
#include "sde_kms.h"
|
||||
#include "sde_fence.h"
|
||||
|
||||
#define SDE_MODE_HPD_ON 0
|
||||
#define SDE_MODE_HPD_OFF 1
|
||||
|
||||
#define SDE_CONNECTOR_NAME_SIZE 16
|
||||
|
||||
struct sde_connector;
|
||||
|
@ -207,6 +210,7 @@ struct sde_connector {
|
|||
struct sde_fence retire_fence;
|
||||
struct sde_connector_ops ops;
|
||||
int dpms_mode;
|
||||
u64 hpd_mode;
|
||||
int lp_mode;
|
||||
int last_panel_power_mode;
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue