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:
Navid Bahrani 2018-02-07 19:17:53 -08:00
parent 5b91f0e883
commit 7f85fee1bc
5 changed files with 71 additions and 7 deletions

View file

@ -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;
}

View file

@ -50,6 +50,9 @@ struct hdmi {
const struct hdmi_platform_config *config;
/* hpd state: */
bool hpd_off;
/* audio state: */
struct hdmi_audio audio;

View file

@ -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

View file

@ -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");

View file

@ -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;