summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLinux Build Service Account <lnxbuild@quicinc.com>2017-07-21 11:08:21 -0700
committerGerrit - the friendly Code Review server <code-review@localhost>2017-07-21 11:08:21 -0700
commit5d3a6dd49d546e2dbaf4acb6303055e02bd40efb (patch)
treeb2d59b1ea5ef1fd25499c27d063270c0d9833a33
parent7aa065cbc4f86125895f6c7c6a5ac1fdda231505 (diff)
parent033b9198d03f2dba7cb89efe34a2d9f2dbc415ad (diff)
Merge "drm/msm: add support for HDR playback control sequence"
-rw-r--r--drivers/gpu/drm/msm/hdmi-staging/sde_hdmi.c43
-rw-r--r--drivers/gpu/drm/msm/hdmi-staging/sde_hdmi.h3
-rw-r--r--drivers/gpu/drm/msm/hdmi-staging/sde_hdmi_bridge.c5
-rw-r--r--drivers/gpu/drm/msm/hdmi-staging/sde_hdmi_util.c56
-rw-r--r--drivers/gpu/drm/msm/hdmi-staging/sde_hdmi_util.h13
-rw-r--r--drivers/gpu/drm/msm/msm_drv.h6
-rw-r--r--drivers/gpu/drm/msm/sde/sde_connector.c26
-rw-r--r--drivers/gpu/drm/msm/sde/sde_connector.h4
-rw-r--r--include/uapi/drm/msm_drm.h15
9 files changed, 153 insertions, 18 deletions
diff --git a/drivers/gpu/drm/msm/hdmi-staging/sde_hdmi.c b/drivers/gpu/drm/msm/hdmi-staging/sde_hdmi.c
index 1b295949122b..e8b3e85603e4 100644
--- a/drivers/gpu/drm/msm/hdmi-staging/sde_hdmi.c
+++ b/drivers/gpu/drm/msm/hdmi-staging/sde_hdmi.c
@@ -1961,6 +1961,30 @@ enable_packet_control:
hdmi_write(hdmi, HDMI_GEN_PKT_CTRL, packet_control);
}
+static void sde_hdmi_clear_hdr_infoframe(struct sde_hdmi *display)
+{
+ struct hdmi *hdmi;
+ struct drm_connector *connector;
+ u32 packet_control = 0;
+
+ if (!display) {
+ SDE_ERROR("invalid input\n");
+ return;
+ }
+
+ hdmi = display->ctrl.ctrl;
+ connector = display->ctrl.ctrl->connector;
+
+ if (!hdmi || !connector) {
+ SDE_ERROR("invalid input\n");
+ return;
+ }
+
+ packet_control = hdmi_read(hdmi, HDMI_GEN_PKT_CTRL);
+ packet_control &= ~HDMI_GEN_PKT_CTRL_CLR_MASK;
+ hdmi_write(hdmi, HDMI_GEN_PKT_CTRL, packet_control);
+}
+
int sde_hdmi_set_property(struct drm_connector *connector,
struct drm_connector_state *state,
int property_index,
@@ -2305,15 +2329,28 @@ int sde_hdmi_pre_kickoff(struct drm_connector *connector,
void *display,
struct msm_display_kickoff_params *params)
{
+ struct sde_hdmi *hdmi_display = (struct sde_hdmi *)display;
+ struct drm_msm_ext_panel_hdr_ctrl *hdr_ctrl;
+ u8 hdr_op;
if (!connector || !display || !params) {
pr_err("Invalid params\n");
return -EINVAL;
}
- if (connector->hdr_supported)
- sde_hdmi_panel_set_hdr_infoframe(display,
- params->hdr_metadata);
+ hdr_ctrl = params->hdr_ctrl;
+
+ hdr_op = sde_hdmi_hdr_get_ops(hdmi_display->curr_hdr_state,
+ hdr_ctrl->hdr_state);
+
+ if (hdr_op == HDR_SEND_INFO) {
+ if (connector->hdr_supported)
+ sde_hdmi_panel_set_hdr_infoframe(display,
+ &hdr_ctrl->hdr_meta);
+ } else if (hdr_op == HDR_CLEAR_INFO)
+ sde_hdmi_clear_hdr_infoframe(display);
+
+ hdmi_display->curr_hdr_state = hdr_ctrl->hdr_state;
return 0;
}
diff --git a/drivers/gpu/drm/msm/hdmi-staging/sde_hdmi.h b/drivers/gpu/drm/msm/hdmi-staging/sde_hdmi.h
index 743d34d05e57..bafb2b949a6b 100644
--- a/drivers/gpu/drm/msm/hdmi-staging/sde_hdmi.h
+++ b/drivers/gpu/drm/msm/hdmi-staging/sde_hdmi.h
@@ -147,6 +147,7 @@ struct sde_hdmi {
u32 hdcp22_present;
u8 hdcp_status;
u32 enc_lvl;
+ u8 curr_hdr_state;
bool auth_state;
bool sink_hdcp22_support;
bool src_hdcp22_support;
@@ -198,6 +199,8 @@ enum hdmi_tx_scdc_access_type {
#define HDMI_YUV420_24BPP_PCLK_TMDS_CH_RATE_RATIO 2
#define HDMI_RGB_24BPP_PCLK_TMDS_CH_RATE_RATIO 1
+#define HDMI_GEN_PKT_CTRL_CLR_MASK 0x7
+
/* Maximum pixel clock rates for hdmi tx */
#define HDMI_DEFAULT_MAX_PCLK_RATE 148500
#define HDMI_TX_3_MAX_PCLK_RATE 297000
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 a4c3c2e7ce46..62dd3aaf7078 100644
--- a/drivers/gpu/drm/msm/hdmi-staging/sde_hdmi_bridge.c
+++ b/drivers/gpu/drm/msm/hdmi-staging/sde_hdmi_bridge.c
@@ -518,12 +518,17 @@ 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;
+ struct sde_connector *c_conn = to_sde_connector(hdmi->connector);
+ struct sde_hdmi *display = (struct sde_hdmi *)c_conn->display;
/* need to update hdcp info here to ensure right HDCP support*/
sde_hdmi_update_hdcp_info(hdmi->connector);
/* start HDCP authentication */
sde_hdmi_start_hdcp(hdmi->connector);
+
+ /* reset HDR state */
+ display->curr_hdr_state = HDR_DISABLE;
}
static void _sde_hdmi_bridge_disable(struct drm_bridge *bridge)
diff --git a/drivers/gpu/drm/msm/hdmi-staging/sde_hdmi_util.c b/drivers/gpu/drm/msm/hdmi-staging/sde_hdmi_util.c
index ba47b7702efd..a291a1112aeb 100644
--- a/drivers/gpu/drm/msm/hdmi-staging/sde_hdmi_util.c
+++ b/drivers/gpu/drm/msm/hdmi-staging/sde_hdmi_util.c
@@ -68,6 +68,15 @@ static void sde_hdmi_hdcp2p2_ddc_clear_status(struct sde_hdmi *display)
hdmi_write(hdmi, HDMI_HDCP2P2_DDC_STATUS, reg_val);
}
+static const char *sde_hdmi_hdr_sname(enum sde_hdmi_hdr_state hdr_state)
+{
+ switch (hdr_state) {
+ case HDR_DISABLE: return "HDR_DISABLE";
+ case HDR_ENABLE: return "HDR_ENABLE";
+ default: return "HDR_INVALID_STATE";
+ }
+}
+
/**
* sde_hdmi_dump_regs - utility to dump HDMI regs
* @hdmi_display: Pointer to private display handle
@@ -898,3 +907,50 @@ int sde_hdmi_sink_dc_support(struct drm_connector *connector,
return dc_format;
}
+
+u8 sde_hdmi_hdr_get_ops(u8 curr_state,
+ u8 new_state)
+{
+
+ /** There could be 3 valid state transitions:
+ * 1. HDR_DISABLE -> HDR_ENABLE
+ *
+ * In this transition, we shall start sending
+ * HDR metadata with metadata from the HDR clip
+ *
+ * 2. HDR_ENABLE -> HDR_ENABLE
+ *
+ * In this transition, we will keep sending
+ * HDR metadata but with EOTF and metadata as 0
+ *
+ * 3. HDR_ENABLE -> HDR_DISABLE
+ *
+ * In this transition, we will stop sending
+ * metadata to the sink and clear PKT_CTRL register
+ * bits.
+ */
+
+ if ((curr_state == HDR_DISABLE)
+ && (new_state == HDR_ENABLE)) {
+ HDMI_UTIL_DEBUG("State changed %s ---> %s\n",
+ sde_hdmi_hdr_sname(curr_state),
+ sde_hdmi_hdr_sname(new_state));
+ return HDR_SEND_INFO;
+ } else if ((curr_state == HDR_ENABLE)
+ && (new_state == HDR_ENABLE)) {
+ HDMI_UTIL_DEBUG("State changed %s ---> %s\n",
+ sde_hdmi_hdr_sname(curr_state),
+ sde_hdmi_hdr_sname(new_state));
+ return HDR_SEND_INFO;
+ } else if ((curr_state == HDR_ENABLE)
+ && (new_state == HDR_DISABLE)) {
+ HDMI_UTIL_DEBUG("State changed %s ---> %s\n",
+ sde_hdmi_hdr_sname(curr_state),
+ sde_hdmi_hdr_sname(new_state));
+ return HDR_CLEAR_INFO;
+ }
+
+ HDMI_UTIL_DEBUG("Unsupported OR no state change\n");
+ return HDR_UNSUPPORTED_OP;
+}
+
diff --git a/drivers/gpu/drm/msm/hdmi-staging/sde_hdmi_util.h b/drivers/gpu/drm/msm/hdmi-staging/sde_hdmi_util.h
index 10effed54a14..1d89ae222a7b 100644
--- a/drivers/gpu/drm/msm/hdmi-staging/sde_hdmi_util.h
+++ b/drivers/gpu/drm/msm/hdmi-staging/sde_hdmi_util.h
@@ -125,6 +125,17 @@ enum sde_hdmi_tx_hdcp2p2_rxstatus_intr_mask {
RXSTATUS_REAUTH_REQ = BIT(14),
};
+enum sde_hdmi_hdr_state {
+ HDR_DISABLE,
+ HDR_ENABLE
+};
+
+enum sde_hdmi_hdr_op {
+ HDR_UNSUPPORTED_OP,
+ HDR_SEND_INFO,
+ HDR_CLEAR_INFO
+};
+
struct sde_hdmi_tx_hdcp2p2_ddc_data {
enum sde_hdmi_tx_hdcp2p2_rxstatus_intr_mask intr_mask;
u32 timeout_ms;
@@ -170,4 +181,6 @@ bool sde_hdmi_validate_pixclk(struct drm_connector *connector,
unsigned long pclk);
int sde_hdmi_sink_dc_support(struct drm_connector *connector,
struct drm_display_mode *mode);
+u8 sde_hdmi_hdr_get_ops(u8 curr_state,
+ u8 new_state);
#endif /* _SDE_HDMI_UTIL_H_ */
diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h
index ac15f399df7d..08868fce1cb0 100644
--- a/drivers/gpu/drm/msm/msm_drv.h
+++ b/drivers/gpu/drm/msm/msm_drv.h
@@ -144,7 +144,7 @@ enum msm_mdp_conn_property {
/* blob properties, always put these first */
CONNECTOR_PROP_SDE_INFO,
CONNECTOR_PROP_HDR_INFO,
- CONNECTOR_PROP_HDR_METADATA,
+ CONNECTOR_PROP_HDR_CONTROL,
/* # of blob properties */
CONNECTOR_PROP_BLOBCOUNT,
@@ -237,10 +237,10 @@ struct msm_display_info {
/**
* struct - msm_display_kickoff_params - info for display features at kickoff
- * @hdr_metadata: HDR metadata info passed from userspace
+ * @hdr_ctrl: HDR control info passed from userspace
*/
struct msm_display_kickoff_params {
- struct drm_msm_ext_panel_hdr_metadata *hdr_metadata;
+ struct drm_msm_ext_panel_hdr_ctrl *hdr_ctrl;
};
/**
diff --git a/drivers/gpu/drm/msm/sde/sde_connector.c b/drivers/gpu/drm/msm/sde/sde_connector.c
index 76e6e4ef6e7d..875513d2840f 100644
--- a/drivers/gpu/drm/msm/sde/sde_connector.c
+++ b/drivers/gpu/drm/msm/sde/sde_connector.c
@@ -83,7 +83,7 @@ int sde_connector_pre_kickoff(struct drm_connector *connector)
if (!c_conn->ops.pre_kickoff)
return 0;
- params.hdr_metadata = &c_state->hdr_meta;
+ params.hdr_ctrl = &c_state->hdr_ctrl;
rc = c_conn->ops.pre_kickoff(connector, c_conn->display, &params);
@@ -247,6 +247,7 @@ static int _sde_connector_set_hdr_info(
void *usr_ptr)
{
struct drm_connector *connector;
+ struct drm_msm_ext_panel_hdr_ctrl *hdr_ctrl;
struct drm_msm_ext_panel_hdr_metadata *hdr_meta;
int i;
@@ -262,21 +263,26 @@ static int _sde_connector_set_hdr_info(
return -ENOTSUPP;
}
- memset(&c_state->hdr_meta, 0, sizeof(c_state->hdr_meta));
+ memset(&c_state->hdr_ctrl, 0, sizeof(c_state->hdr_ctrl));
if (!usr_ptr) {
- SDE_DEBUG_CONN(c_conn, "hdr metadata cleared\n");
+ SDE_DEBUG_CONN(c_conn, "hdr control cleared\n");
return 0;
}
- if (copy_from_user(&c_state->hdr_meta,
+ if (copy_from_user(&c_state->hdr_ctrl,
(void __user *)usr_ptr,
- sizeof(*hdr_meta))) {
- SDE_ERROR_CONN(c_conn, "failed to copy hdr metadata\n");
+ sizeof(*hdr_ctrl))) {
+ SDE_ERROR_CONN(c_conn, "failed to copy hdr control\n");
return -EFAULT;
}
- hdr_meta = &c_state->hdr_meta;
+ hdr_ctrl = &c_state->hdr_ctrl;
+
+ SDE_DEBUG_CONN(c_conn, "hdr_supported %d\n",
+ hdr_ctrl->hdr_state);
+
+ hdr_meta = &hdr_ctrl->hdr_meta;
SDE_DEBUG_CONN(c_conn, "hdr_supported %d\n",
hdr_meta->hdr_supported);
@@ -362,7 +368,7 @@ static int sde_connector_atomic_set_property(struct drm_connector *connector,
SDE_ERROR("invalid topology_control: 0x%llX\n", val);
}
- if (idx == CONNECTOR_PROP_HDR_METADATA) {
+ if (idx == CONNECTOR_PROP_HDR_CONTROL) {
rc = _sde_connector_set_hdr_info(c_conn, c_state, (void *)val);
if (rc)
SDE_ERROR_CONN(c_conn, "cannot set hdr info %d\n", rc);
@@ -718,8 +724,8 @@ struct drm_connector *sde_connector_init(struct drm_device *dev,
}
msm_property_install_volatile_range(&c_conn->property_info,
- "hdr_metadata", 0x0, 0, ~0, 0,
- CONNECTOR_PROP_HDR_METADATA);
+ "hdr_control", 0x0, 0, ~0, 0,
+ CONNECTOR_PROP_HDR_CONTROL);
msm_property_install_range(&c_conn->property_info, "RETIRE_FENCE",
0x0, 0, INR_OPEN_MAX, 0, CONNECTOR_PROP_RETIRE_FENCE);
diff --git a/drivers/gpu/drm/msm/sde/sde_connector.h b/drivers/gpu/drm/msm/sde/sde_connector.h
index 19e2b8a3e41c..8257f29bd4b8 100644
--- a/drivers/gpu/drm/msm/sde/sde_connector.h
+++ b/drivers/gpu/drm/msm/sde/sde_connector.h
@@ -221,14 +221,14 @@ struct sde_connector {
* @out_fb: Pointer to output frame buffer, if applicable
* @aspace: Address space for accessing frame buffer objects, if applicable
* @property_values: Local cache of current connector property values
- * @hdr_meta: HDR metadata info passed from userspace
+ * @hdr_ctrl: HDR control info passed from userspace
*/
struct sde_connector_state {
struct drm_connector_state base;
struct drm_framebuffer *out_fb;
struct msm_gem_address_space *aspace;
uint64_t property_values[CONNECTOR_PROP_COUNT];
- struct drm_msm_ext_panel_hdr_metadata hdr_meta;
+ struct drm_msm_ext_panel_hdr_ctrl hdr_ctrl;
};
/**
diff --git a/include/uapi/drm/msm_drm.h b/include/uapi/drm/msm_drm.h
index 927c3626edb7..8b51873e7b08 100644
--- a/include/uapi/drm/msm_drm.h
+++ b/include/uapi/drm/msm_drm.h
@@ -84,6 +84,21 @@ struct drm_msm_ext_panel_hdr_metadata {
};
/**
+ * HDR Control
+ * This encapsulates the HDR metadata as well as a state control
+ * for the HDR metadata as required by the HDMI spec to send the
+ * relevant metadata depending on the state of the HDR playback.
+ * hdr_state: Controls HDR state, takes values ENABLE(1)/DISABLE(0)
+ * hdr_meta: Metadata sent by the userspace for the HDR clip
+ */
+
+#define DRM_MSM_EXT_PANEL_HDR_CTRL
+struct drm_msm_ext_panel_hdr_ctrl {
+ __u8 hdr_state; /* HDR state */
+ struct drm_msm_ext_panel_hdr_metadata hdr_meta; /* HDR metadata */
+};
+
+/**
* HDR sink properties
* These are defined as per EDID spec and shall be used by the userspace
* to determine the HDR properties to be set to the sink.