diff options
-rw-r--r-- | drivers/gpu/drm/msm/msm_drv.h | 1 | ||||
-rw-r--r-- | drivers/gpu/drm/msm/sde/sde_connector.c | 78 | ||||
-rw-r--r-- | drivers/gpu/drm/msm/sde/sde_connector.h | 2 | ||||
-rw-r--r-- | include/uapi/drm/msm_drm.h | 21 |
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 |