summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/gpu/drm/msm/msm_drv.h1
-rw-r--r--drivers/gpu/drm/msm/sde/sde_connector.c78
-rw-r--r--drivers/gpu/drm/msm/sde/sde_connector.h2
-rw-r--r--include/uapi/drm/msm_drm.h21
4 files changed, 102 insertions, 0 deletions
diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h
index 8d6451084a1a..209e90628642 100644
--- a/drivers/gpu/drm/msm/msm_drv.h
+++ b/drivers/gpu/drm/msm/msm_drv.h
@@ -144,6 +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,
/* # of blob properties */
CONNECTOR_PROP_BLOBCOUNT,
diff --git a/drivers/gpu/drm/msm/sde/sde_connector.c b/drivers/gpu/drm/msm/sde/sde_connector.c
index 04539ff8a59d..cf84700d7592 100644
--- a/drivers/gpu/drm/msm/sde/sde_connector.c
+++ b/drivers/gpu/drm/msm/sde/sde_connector.c
@@ -17,6 +17,12 @@
#include "sde_connector.h"
#include "sde_backlight.h"
+#define SDE_DEBUG_CONN(c, fmt, ...) SDE_DEBUG("conn%d " fmt,\
+ (c) ? (c)->base.base.id : -1, ##__VA_ARGS__)
+
+#define SDE_ERROR_CONN(c, fmt, ...) SDE_ERROR("conn%d " fmt,\
+ (c) ? (c)->base.base.id : -1, ##__VA_ARGS__)
+
static const struct drm_prop_enum_list e_topology_name[] = {
{SDE_RM_TOPOLOGY_UNKNOWN, "sde_unknown"},
{SDE_RM_TOPOLOGY_SINGLEPIPE, "sde_singlepipe"},
@@ -205,6 +211,68 @@ sde_connector_atomic_duplicate_state(struct drm_connector *connector)
return &c_state->base;
}
+static int _sde_connector_set_hdr_info(
+ struct sde_connector *c_conn,
+ struct sde_connector_state *c_state,
+ void *usr_ptr)
+{
+ struct drm_connector *connector;
+ struct drm_msm_ext_panel_hdr_metadata *hdr_meta;
+ int i;
+
+ if (!c_conn || !c_state) {
+ SDE_ERROR_CONN(c_conn, "invalid args\n");
+ return -EINVAL;
+ }
+
+ connector = &c_conn->base;
+
+ if (!connector->hdr_supported) {
+ SDE_ERROR_CONN(c_conn, "sink doesn't support HDR\n");
+ return -ENOTSUPP;
+ }
+
+ memset(&c_state->hdr_meta, 0, sizeof(c_state->hdr_meta));
+
+ if (!usr_ptr) {
+ SDE_DEBUG_CONN(c_conn, "hdr metadata cleared\n");
+ return 0;
+ }
+
+ if (copy_from_user(&c_state->hdr_meta,
+ (void __user *)usr_ptr,
+ sizeof(*hdr_meta))) {
+ SDE_ERROR_CONN(c_conn, "failed to copy hdr metadata\n");
+ return -EFAULT;
+ }
+
+ hdr_meta = &c_state->hdr_meta;
+
+ SDE_DEBUG_CONN(c_conn, "hdr_supported %d\n",
+ hdr_meta->hdr_supported);
+ SDE_DEBUG_CONN(c_conn, "eotf %d\n",
+ hdr_meta->eotf);
+ SDE_DEBUG_CONN(c_conn, "white_point_x %d\n",
+ hdr_meta->white_point_x);
+ SDE_DEBUG_CONN(c_conn, "white_point_y %d\n",
+ hdr_meta->white_point_y);
+ SDE_DEBUG_CONN(c_conn, "max_luminance %d\n",
+ hdr_meta->max_luminance);
+ SDE_DEBUG_CONN(c_conn, "max_content_light_level %d\n",
+ hdr_meta->max_content_light_level);
+ SDE_DEBUG_CONN(c_conn, "max_average_light_level %d\n",
+ hdr_meta->max_average_light_level);
+
+ for (i = 0; i < HDR_PRIMARIES_COUNT; i++) {
+ SDE_DEBUG_CONN(c_conn, "display_primaries_x [%d]\n",
+ hdr_meta->display_primaries_x[i]);
+ SDE_DEBUG_CONN(c_conn, "display_primaries_y [%d]\n",
+ hdr_meta->display_primaries_y[i]);
+ }
+
+ return 0;
+}
+
static int sde_connector_atomic_set_property(struct drm_connector *connector,
struct drm_connector_state *state,
struct drm_property *property,
@@ -264,6 +332,12 @@ 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) {
+ 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);
+ }
+
/* check for custom property handling */
if (!rc && c_conn->ops.set_property) {
rc = c_conn->ops.set_property(connector,
@@ -613,6 +687,10 @@ struct drm_connector *sde_connector_init(struct drm_device *dev,
CONNECTOR_PROP_HDR_INFO);
}
+ msm_property_install_volatile_range(&c_conn->property_info,
+ "hdr_metadata", 0x0, 0, ~0, 0,
+ CONNECTOR_PROP_HDR_METADATA);
+
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 4b140176b5f6..885f3cf94864 100644
--- a/drivers/gpu/drm/msm/sde/sde_connector.h
+++ b/drivers/gpu/drm/msm/sde/sde_connector.h
@@ -208,12 +208,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
*/
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;
};
/**
diff --git a/include/uapi/drm/msm_drm.h b/include/uapi/drm/msm_drm.h
index b98912f4ae47..a60e84ab905b 100644
--- a/include/uapi/drm/msm_drm.h
+++ b/include/uapi/drm/msm_drm.h
@@ -62,6 +62,27 @@ struct drm_msm_timespec {
__s64 tv_nsec; /* nanoseconds */
};
+/*
+ * HDR Metadata
+ * These are defined as per EDID spec and shall be used by the sink
+ * to set the HDR metadata for playback from userspace.
+ */
+
+#define HDR_PRIMARIES_COUNT 3
+
+struct drm_msm_ext_panel_hdr_metadata {
+ __u32 eotf; /* electro optical transfer function */
+ __u32 hdr_supported; /* HDR supported */
+ __u32 display_primaries_x[HDR_PRIMARIES_COUNT]; /* Primaries x */
+ __u32 display_primaries_y[HDR_PRIMARIES_COUNT]; /* Primaries y */
+ __u32 white_point_x; /* white_point_x */
+ __u32 white_point_y; /* white_point_y */
+ __u32 max_luminance; /* Max luminance */
+ __u32 min_luminance; /* Min Luminance */
+ __u32 max_content_light_level; /* max content light level */
+ __u32 max_average_light_level; /* max average light level */
+};
+
/**
* HDR sink properties
* These are defined as per EDID spec and shall be used by the userspace