drm/msm: add HPD notification and acknowledge support

In HPD case the HDMI driver communicate with external display
module by specific notification and acknowledge interfaces.
Add this support to enable the communication.

CRs-Fixed: 2010135
Change-Id: I24ac1e0f0cb1e3946e2a53e4bf72bafbd84e4395
Signed-off-by: Ray Zhang <rayz@codeaurora.org>
This commit is contained in:
Ray Zhang 2017-02-17 17:46:34 +08:00
parent 1c4ce7aa2c
commit 9b0940a54c
3 changed files with 90 additions and 0 deletions

View file

@ -25,6 +25,7 @@
#include <linux/of_platform.h>
#include "sde_kms.h"
#include "sde_connector.h"
#include "msm_drv.h"
#include "sde_hdmi.h"
@ -404,6 +405,8 @@ static void _sde_hdmi_hotplug_work(struct work_struct *work)
connector = sde_hdmi->ctrl.ctrl->connector;
drm_helper_hpd_irq_event(connector->dev);
sde_hdmi_notify_clients(connector, connector->status);
}
static void _sde_hdmi_connector_irq(struct sde_hdmi *sde_hdmi)
@ -569,6 +572,41 @@ static int _sde_hdmi_ext_disp_init(struct sde_hdmi *display)
return rc;
}
void sde_hdmi_notify_clients(struct drm_connector *connector,
enum drm_connector_status status)
{
struct sde_connector *c_conn = to_sde_connector(connector);
struct sde_hdmi *display = (struct sde_hdmi *)c_conn->display;
int state = (status == connector_status_connected) ?
EXT_DISPLAY_CABLE_CONNECT : EXT_DISPLAY_CABLE_DISCONNECT;
if (display && display->ext_audio_data.intf_ops.hpd) {
struct hdmi *hdmi = display->ctrl.ctrl;
u32 flags = MSM_EXT_DISP_HPD_VIDEO;
if (hdmi->hdmi_mode)
flags |= MSM_EXT_DISP_HPD_AUDIO;
display->ext_audio_data.intf_ops.hpd(display->ext_pdev,
display->ext_audio_data.type, state, flags);
}
}
void sde_hdmi_ack_state(struct drm_connector *connector,
enum drm_connector_status status)
{
struct sde_connector *c_conn = to_sde_connector(connector);
struct sde_hdmi *display = (struct sde_hdmi *)c_conn->display;
if (display) {
struct hdmi *hdmi = display->ctrl.ctrl;
if (hdmi->hdmi_mode && display->ext_audio_data.intf_ops.notify)
display->ext_audio_data.intf_ops.notify(
display->ext_pdev, status);
}
}
void sde_hdmi_set_mode(struct hdmi *hdmi, bool power_on)
{
uint32_t ctrl = 0;

View file

@ -271,6 +271,27 @@ void sde_hdmi_audio_off(struct hdmi *hdmi);
* Return: error code.
*/
int sde_hdmi_config_avmute(struct hdmi *hdmi, bool set);
/**
* sde_hdmi_notify_clients() - notify hdmi clients of the connection status.
* @connector: Handle to the drm_connector.
* @status: connection status.
*
* Return: void.
*/
void sde_hdmi_notify_clients(struct drm_connector *connector,
enum drm_connector_status status);
/**
* sde_hdmi_ack_state() - acknowledge the connection status.
* @connector: Handle to the drm_connector.
* @status: connection status.
*
* Return: void.
*/
void sde_hdmi_ack_state(struct drm_connector *connector,
enum drm_connector_status status);
#else /*#ifdef CONFIG_DRM_SDE_HDMI*/
static inline u32 sde_hdmi_get_num_of_displays(void)

View file

@ -18,6 +18,7 @@
#include "drm_edid.h"
#include "sde_kms.h"
#include "sde_connector.h"
#include "sde_hdmi.h"
#include "hdmi.h"
@ -120,14 +121,42 @@ 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);
sde_hdmi_ack_state(hdmi->connector, EXT_DISPLAY_CABLE_CONNECT);
}
static void sde_hdmi_force_update_audio(struct drm_connector *connector,
enum drm_connector_status status)
{
struct sde_connector *c_conn = to_sde_connector(connector);
struct sde_hdmi *display = (struct sde_hdmi *)c_conn->display;
if (display && display->non_pluggable) {
display->ext_audio_data.intf_ops.hpd(display->ext_pdev,
display->ext_audio_data.type,
status,
MSM_EXT_DISP_HPD_AUDIO);
}
}
static void _sde_hdmi_bridge_enable(struct drm_bridge *bridge)
{
struct sde_hdmi_bridge *sde_hdmi_bridge = to_hdmi_bridge(bridge);
struct hdmi *hdmi = sde_hdmi_bridge->hdmi;
/* force update audio ops when there's no HPD event */
sde_hdmi_force_update_audio(hdmi->connector,
EXT_DISPLAY_CABLE_CONNECT);
}
static void _sde_hdmi_bridge_disable(struct drm_bridge *bridge)
{
struct sde_hdmi_bridge *sde_hdmi_bridge = to_hdmi_bridge(bridge);
struct hdmi *hdmi = sde_hdmi_bridge->hdmi;
/* force update audio ops when there's no HPD event */
sde_hdmi_force_update_audio(hdmi->connector,
EXT_DISPLAY_CABLE_DISCONNECT);
}
static void _sde_hdmi_bridge_post_disable(struct drm_bridge *bridge)
@ -151,6 +180,8 @@ static void _sde_hdmi_bridge_post_disable(struct drm_bridge *bridge)
_sde_hdmi_bridge_power_off(bridge);
hdmi->power_on = false;
}
sde_hdmi_ack_state(hdmi->connector, EXT_DISPLAY_CABLE_DISCONNECT);
}
static void _sde_hdmi_bridge_set_avi_infoframe(struct hdmi *hdmi,