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
|
* Copyright (C) 2013 Red Hat
|
||||||
* Author: Rob Clark <robdclark@gmail.com>
|
* 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);
|
gpio_free(config->hpd_gpio);
|
||||||
|
|
||||||
|
if (config->hpd5v_gpio != -1)
|
||||||
|
gpio_free(config->hpd5v_gpio);
|
||||||
|
|
||||||
if (config->mux_en_gpio != -1) {
|
if (config->mux_en_gpio != -1) {
|
||||||
gpio_set_value_cansleep(config->mux_en_gpio, 0);
|
gpio_set_value_cansleep(config->mux_en_gpio, 0);
|
||||||
gpio_free(config->mux_en_gpio);
|
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);
|
HDMI_HPD_CTRL_ENABLE | hpd_ctrl);
|
||||||
spin_unlock_irqrestore(&hdmi->reg_lock, flags);
|
spin_unlock_irqrestore(&hdmi->reg_lock, flags);
|
||||||
|
|
||||||
|
hdmi->hpd_off = false;
|
||||||
|
SDE_DEBUG("enabled hdmi hpd\n");
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
fail:
|
fail:
|
||||||
|
@ -1395,7 +1400,7 @@ int sde_hdmi_core_enable(struct sde_hdmi *sde_hdmi)
|
||||||
return ret;
|
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;
|
struct hdmi *hdmi = sde_hdmi->ctrl.ctrl;
|
||||||
const struct hdmi_platform_config *config = hdmi->config;
|
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;
|
int i, ret = 0;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
|
||||||
|
if (hdmi->hpd_off) {
|
||||||
|
pr_warn("hdmi display hpd was already disabled\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
spin_lock_irqsave(&hdmi->reg_lock, 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_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",
|
pr_warn("failed to disable hpd regulator: %s (%d)\n",
|
||||||
config->hpd_reg_names[i], ret);
|
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)
|
void sde_hdmi_core_disable(struct sde_hdmi *sde_hdmi)
|
||||||
{
|
{
|
||||||
/* HPD contains all the core clock and pwr */
|
/* 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)
|
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);
|
rc = _sde_hdmi_enable_pll_update(display, value);
|
||||||
else if (property_index == CONNECTOR_PROP_PLL_DELTA)
|
else if (property_index == CONNECTOR_PROP_PLL_DELTA)
|
||||||
rc = _sde_hdmi_update_pll_delta(display, value);
|
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;
|
return rc;
|
||||||
}
|
}
|
||||||
|
@ -2281,7 +2323,7 @@ int sde_hdmi_connector_pre_deinit(struct drm_connector *connector,
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
_sde_hdmi_hdp_disable(sde_hdmi);
|
_sde_hdmi_hpd_disable(sde_hdmi);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -50,6 +50,9 @@ struct hdmi {
|
||||||
|
|
||||||
const struct hdmi_platform_config *config;
|
const struct hdmi_platform_config *config;
|
||||||
|
|
||||||
|
/* hpd state: */
|
||||||
|
bool hpd_off;
|
||||||
|
|
||||||
/* audio state: */
|
/* audio state: */
|
||||||
struct hdmi_audio audio;
|
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
|
* Copyright (C) 2013 Red Hat
|
||||||
* Author: Rob Clark <robdclark@gmail.com>
|
* Author: Rob Clark <robdclark@gmail.com>
|
||||||
*
|
*
|
||||||
|
@ -164,6 +164,7 @@ enum msm_mdp_conn_property {
|
||||||
CONNECTOR_PROP_TOPOLOGY_NAME,
|
CONNECTOR_PROP_TOPOLOGY_NAME,
|
||||||
CONNECTOR_PROP_TOPOLOGY_CONTROL,
|
CONNECTOR_PROP_TOPOLOGY_CONTROL,
|
||||||
CONNECTOR_PROP_LP,
|
CONNECTOR_PROP_LP,
|
||||||
|
CONNECTOR_PROP_HPD_OFF,
|
||||||
|
|
||||||
/* total # of properties */
|
/* total # of properties */
|
||||||
CONNECTOR_PROP_COUNT
|
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
|
* 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
|
* 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"},
|
{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,
|
int sde_connector_get_info(struct drm_connector *connector,
|
||||||
struct msm_display_info *info)
|
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);
|
_sde_connector_update_power_locked(c_conn);
|
||||||
mutex_unlock(&c_conn->lock);
|
mutex_unlock(&c_conn->lock);
|
||||||
break;
|
break;
|
||||||
|
case CONNECTOR_PROP_HPD_OFF:
|
||||||
|
c_conn->hpd_mode = val;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -819,6 +827,7 @@ struct drm_connector *sde_connector_init(struct drm_device *dev,
|
||||||
c_conn->display = display;
|
c_conn->display = display;
|
||||||
|
|
||||||
c_conn->dpms_mode = DRM_MODE_DPMS_ON;
|
c_conn->dpms_mode = DRM_MODE_DPMS_ON;
|
||||||
|
c_conn->hpd_mode = SDE_MODE_HPD_ON;
|
||||||
c_conn->lp_mode = 0;
|
c_conn->lp_mode = 0;
|
||||||
c_conn->last_panel_power_mode = SDE_MODE_DPMS_ON;
|
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),
|
ARRAY_SIZE(e_power_mode),
|
||||||
CONNECTOR_PROP_LP, 0);
|
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);
|
rc = msm_property_install_get_status(&c_conn->property_info);
|
||||||
if (rc) {
|
if (rc) {
|
||||||
SDE_ERROR("failed to create one or more properties\n");
|
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
|
* 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
|
* it under the terms of the GNU General Public License version 2 and
|
||||||
|
@ -22,6 +22,9 @@
|
||||||
#include "sde_kms.h"
|
#include "sde_kms.h"
|
||||||
#include "sde_fence.h"
|
#include "sde_fence.h"
|
||||||
|
|
||||||
|
#define SDE_MODE_HPD_ON 0
|
||||||
|
#define SDE_MODE_HPD_OFF 1
|
||||||
|
|
||||||
#define SDE_CONNECTOR_NAME_SIZE 16
|
#define SDE_CONNECTOR_NAME_SIZE 16
|
||||||
|
|
||||||
struct sde_connector;
|
struct sde_connector;
|
||||||
|
@ -207,6 +210,7 @@ struct sde_connector {
|
||||||
struct sde_fence retire_fence;
|
struct sde_fence retire_fence;
|
||||||
struct sde_connector_ops ops;
|
struct sde_connector_ops ops;
|
||||||
int dpms_mode;
|
int dpms_mode;
|
||||||
|
u64 hpd_mode;
|
||||||
int lp_mode;
|
int lp_mode;
|
||||||
int last_panel_power_mode;
|
int last_panel_power_mode;
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue