aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm')
-rw-r--r--drivers/gpu/drm/drm_edid.c72
1 files changed, 72 insertions, 0 deletions
diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
index a5ef9f45fee0..73560c9437cd 100644
--- a/drivers/gpu/drm/drm_edid.c
+++ b/drivers/gpu/drm/drm_edid.c
@@ -4904,6 +4904,78 @@ static bool is_hdmi2_sink(struct drm_connector *connector)
connector->display_info.color_formats & DRM_COLOR_FORMAT_YCRCB420;
}
+static inline bool is_eotf_supported(u8 output_eotf, u8 sink_eotf)
+{
+ return sink_eotf & BIT(output_eotf);
+}
+
+/**
+ * drm_hdmi_infoframe_set_hdr_metadata() - fill an HDMI DRM infoframe with
+ * HDR metadata from userspace
+ * @frame: HDMI DRM infoframe
+ * @hdr_metadata: hdr_source_metadata info from userspace
+ *
+ * Return: 0 on success or a negative error code on failure.
+ */
+int
+drm_hdmi_infoframe_set_hdr_metadata(struct hdmi_drm_infoframe *frame,
+ const struct drm_connector_state *conn_state)
+{
+ struct drm_connector *connector;
+ struct hdr_output_metadata *hdr_metadata;
+ int err;
+
+ if (!frame || !conn_state)
+ return -EINVAL;
+
+ connector = conn_state->connector;
+
+ if (!conn_state->hdr_output_metadata)
+ return -EINVAL;
+
+ hdr_metadata = conn_state->hdr_output_metadata->data;
+
+ if (!hdr_metadata || !connector)
+ return -EINVAL;
+
+ /* Sink EOTF is Bit map while infoframe is absolute values */
+ if (!is_eotf_supported(hdr_metadata->hdmi_metadata_type1.eotf,
+ connector->hdr_sink_metadata.hdmi_type1.eotf)) {
+ DRM_DEBUG_KMS("EOTF Not Supported\n");
+ return -EINVAL;
+ }
+
+ err = hdmi_drm_infoframe_init(frame);
+ if (err < 0)
+ return err;
+
+ frame->eotf = hdr_metadata->hdmi_metadata_type1.eotf;
+ frame->metadata_type = hdr_metadata->hdmi_metadata_type1.metadata_type;
+
+ BUILD_BUG_ON(sizeof(frame->display_primaries) !=
+ sizeof(hdr_metadata->hdmi_metadata_type1.display_primaries));
+ BUILD_BUG_ON(sizeof(frame->white_point) !=
+ sizeof(hdr_metadata->hdmi_metadata_type1.white_point));
+
+ memcpy(&frame->display_primaries,
+ &hdr_metadata->hdmi_metadata_type1.display_primaries,
+ sizeof(frame->display_primaries));
+
+ memcpy(&frame->white_point,
+ &hdr_metadata->hdmi_metadata_type1.white_point,
+ sizeof(frame->white_point));
+
+ frame->max_display_mastering_luminance =
+ hdr_metadata->hdmi_metadata_type1.max_display_mastering_luminance;
+ frame->min_display_mastering_luminance =
+ hdr_metadata->hdmi_metadata_type1.min_display_mastering_luminance;
+ frame->max_fall = hdr_metadata->hdmi_metadata_type1.max_fall;
+ frame->max_cll = hdr_metadata->hdmi_metadata_type1.max_cll;
+
+ return 0;
+}
+EXPORT_SYMBOL(drm_hdmi_infoframe_set_hdr_metadata);
+
/**
* drm_hdmi_avi_infoframe_from_display_mode() - fill an HDMI AVI infoframe with
* data from a DRM display mode