[MMFMWK-7905] kmssink: add hdr10 support

upstream status: imx specific
diff --git a/sys/kms/gstkmssink.c b/sys/kms/gstkmssink.c
index 86fa1ce..a59ea2e 100644
--- a/sys/kms/gstkmssink.c
+++ b/sys/kms/gstkmssink.c
@@ -48,9 +48,8 @@
 #include <gst/allocators/gstdmabufmeta.h>
 #include <gst/allocators/gstphymemmeta.h>
 
-#include <drm.h>
-#include <xf86drm.h>
-#include <xf86drmMode.h>
+#include <stdint.h>
+
 #include <drm_fourcc.h>
 
 #include <string.h>
@@ -1452,6 +1451,7 @@
       GST_DEBUG ("set global alpha %d to primary plane %d property %d",
           alpha, plane->plane_id, prop->prop_id);
       drmModeObjectSetProperty (self->ctrl_fd, plane->plane_id, DRM_MODE_OBJECT_PLANE, prop->prop_id, alpha);
+      self->primary_plane_id = plane->plane_id;
     }
     drmModeFreeProperty (prop);
     prop = NULL;
@@ -1484,6 +1484,7 @@
   switch (transition) {
     case GST_STATE_CHANGE_NULL_TO_READY:
       self->is_kmsproperty_set = FALSE;
+      memset (&self->hdr10meta, 0, sizeof (self->hdr10meta));
       break;
     case GST_STATE_CHANGE_READY_TO_PAUSED:
     {
@@ -1516,6 +1517,17 @@
         if (self->hold_buf[i])
           gst_buffer_unref (self->hold_buf[i]);
       }
+
+      if (self->old_crtc) {
+        gint err;
+        err = drmModeSetCrtc (self->ctrl_fd, self->crtc_id, self->old_crtc->buffer_id, 0, 0,
+            (uint32_t *) & self->conn_id, 1, & self->old_crtc->mode);
+        if (err) {
+          GST_ERROR_OBJECT (self, "set crtc fail");
+        }
+        drmModeFreeCrtc (self->old_crtc);
+      }
+      self->old_crtc = NULL;
       break;
     }
     case GST_STATE_CHANGE_READY_TO_NULL:
@@ -1618,17 +1630,36 @@
 }
 
 void
-dump_hdr10meta (GstKMSSink *self, GstBuffer * buf)
+gst_kms_sink_config_hdr10 (GstKMSSink *self, GstBuffer * buf)
 {
-
+  guint blob_id = 0, prop_id = 0;
+  int err;
+  gint i;
+  guint32 fb_id;
+  drmModeConnector *conn = NULL;
+  drmModeModeInfo *mode = NULL;
+  drmModeObjectPropertiesPtr props = NULL;
+  drmModePropertyPtr prop = NULL;
   GstVideoHdr10Meta *meta = NULL;
+  GstKMSMemory *kmsmem = NULL;
+  GstVideoInfo vinfo;
+
+  if (self->conn_id < 0) {
+    GST_ERROR_OBJECT (self, "no connector");
+    return;
+  }
 
   /* buf could be NULL when resize */
   if (buf)
     meta = gst_buffer_get_video_hdr10_meta (buf);
 
-  if (meta){
-    /* TODO: just dump temporarily, to do configure to drm driver for hdr10 in future */
+  if (meta && self->hdr10meta.eotf == 0) {
+    conn = drmModeGetConnector (self->fd, self->conn_id);
+    if (!conn) {
+      GST_ERROR_OBJECT (self, "no connector res");
+      return;
+    }
+
     GST_INFO_OBJECT (self, "redPrimary x=%d y=%d", meta->hdr10meta.redPrimary[0], meta->hdr10meta.redPrimary[1]);
     GST_INFO_OBJECT (self, "greenPrimary x=%d y=%d", meta->hdr10meta.greenPrimary[0], meta->hdr10meta.greenPrimary[1]);
     GST_INFO_OBJECT (self, "bluePrimary x=%d y=%d", meta->hdr10meta.bluePrimary[0], meta->hdr10meta.bluePrimary[1]);
@@ -1643,7 +1674,90 @@
     GST_INFO_OBJECT (self, "fullRange %d", meta->hdr10meta.fullRange);
     GST_INFO_OBJECT (self, "chromaSampleLocTypeTopField %d", meta->hdr10meta.chromaSampleLocTypeTopField);
     GST_INFO_OBJECT (self, "chromaSampleLocTypeBottomField %d", meta->hdr10meta.chromaSampleLocTypeBottomField);
+
+    /* FIXME: better to use marcos instead of const value */
+    self->hdr10meta.eotf = 2;
+    self->hdr10meta.type = 0x8a48;
+    self->hdr10meta.display_primaries_x [0] = meta->hdr10meta.redPrimary[0];
+    self->hdr10meta.display_primaries_x [1] = meta->hdr10meta.greenPrimary[0];
+    self->hdr10meta.display_primaries_x [2] = meta->hdr10meta.bluePrimary[0];
+    self->hdr10meta.display_primaries_y [0] = meta->hdr10meta.redPrimary[1];
+    self->hdr10meta.display_primaries_y [1] = meta->hdr10meta.greenPrimary[1];
+    self->hdr10meta.display_primaries_y [2] = meta->hdr10meta.bluePrimary[1];
+    self->hdr10meta.white_point_x = meta->hdr10meta.whitePoint[0];
+    self->hdr10meta.white_point_y = meta->hdr10meta.whitePoint[1];
+    self->hdr10meta.max_mastering_display_luminance = meta->hdr10meta.maxMasteringLuminance;
+    self->hdr10meta.min_mastering_display_luminance = meta->hdr10meta.minMasteringLuminance;
+    self->hdr10meta.max_fall = meta->hdr10meta.maxFrameAverageLightLevel;
+    self->hdr10meta.max_cll =  meta->hdr10meta.maxContentLightLevel;
+  
+    props = drmModeObjectGetProperties (self->fd, self->conn_id, DRM_MODE_OBJECT_CONNECTOR);
+    for (i = 0; i < props->count_props; ++i) {
+      prop = drmModeGetProperty(self->fd, props->props[i]);
+      if (!strcmp(prop->name, "HDR_SOURCE_METADATA")) {
+        GST_DEBUG_OBJECT (self, "found HDR_SOURCE_METADATA property on connector %d property id %d",
+            self->conn_id, prop->prop_id);
+        prop_id = prop->prop_id;
+      }
+      drmModeFreeProperty (prop);
+      prop = NULL;
+    }
+
+    if (prop_id == 0) {
+      GST_WARNING_OBJECT (self, "no HDR_SOURCE_METADATA property found");
+      goto bail;
+    }
+
+    drmModeCreatePropertyBlob (self->fd, &self->hdr10meta, sizeof (self->hdr10meta), &blob_id);
+    GST_INFO_OBJECT (self, "create blob id %d", blob_id);
+    err = drmModeObjectSetProperty (self->ctrl_fd, self->conn_id, DRM_MODE_OBJECT_CONNECTOR, prop_id, blob_id);
+    drmModeDestroyPropertyBlob (self->fd, blob_id);
+    if (err) {
+      GST_ERROR_OBJECT (self, "set blob property fail");
+      goto bail;
+    }
+
+    GST_DEBUG_OBJECT (self, "set blob property success, continue to setCrtc");
+
+    /* FIXME: temporarily we can only enable HDR10 on 4k@60fps mode */
+    for (i = 0; i < conn->count_modes; i++) {
+      if (conn->modes[i].vdisplay == 2160 &&
+          conn->modes[i].hdisplay == 3840 &&
+          conn->modes[i].vrefresh == 60) {
+        mode = &conn->modes[i];
+        break;
+      }
+    }
+
+    if (!mode) {
+      GST_ERROR_OBJECT (self, "4k@60fps mode not found");
+      goto bail;
+    }
+
+    gst_video_info_init (&vinfo);
+    gst_video_info_set_format (&vinfo, GST_VIDEO_FORMAT_NV12_10LE, mode->hdisplay, mode->vdisplay);
+
+    ensure_kms_allocator (self);
+
+    kmsmem = (GstKMSMemory *) gst_kms_allocator_bo_alloc (self->allocator, &vinfo);
+    if (!kmsmem)
+      goto bail;
+
+    fb_id = kmsmem->fb_id;
+
+    self->old_crtc = drmModeGetCrtc (self->fd, self->crtc_id);
+
+    err = drmModeSetCrtc (self->ctrl_fd, self->crtc_id, fb_id, 0, 0,
+        (uint32_t *) & self->conn_id, 1, mode);
+    if (err) {
+      GST_ERROR_OBJECT (self, "set crtc fail");
+      goto bail;
+    }
+    self->hdr10_mem = kmsmem;
   }
+bail:
+  if (conn)
+    drmModeFreeConnector (conn);
 }
 
 static gboolean
@@ -1679,8 +1793,6 @@
   gboolean can_scale = TRUE;
   guint32 fmt, alignment;
   
-  dump_hdr10meta (GST_KMS_SINK (vsink), buf);
-
   self = GST_KMS_SINK (vsink);
 
   res = GST_FLOW_ERROR;
@@ -1706,6 +1818,9 @@
 
   if (!buffer)
     return GST_FLOW_ERROR;
+  
+  gst_kms_sink_config_hdr10 (self, buffer);
+
   fb_id = gst_kms_memory_get_fb_id (gst_buffer_peek_memory (buffer, 0));
   if (fb_id == 0)
     goto buffer_invalid;
@@ -1822,6 +1937,7 @@
   if (buffer != self->last_buffer)
     gst_buffer_replace (&self->last_buffer, buffer);
   g_clear_pointer (&self->tmp_kmsmem, gst_memory_unref);
+  g_clear_pointer (&self->hdr10_mem, gst_memory_unref);
 
   GST_OBJECT_UNLOCK (self);
   res = GST_FLOW_OK;
@@ -1962,11 +2078,13 @@
   sink->fd = -1;
   sink->conn_id = -1;
   sink->plane_id = -1;
+  sink->primary_plane_id = -1;
   sink->can_scale = TRUE;
   sink->scale_checked = FALSE;
   sink->upscale_ratio = 1;
   sink->downscale_ratio = 1;
   sink->hantro_tile_enabled = FALSE;
+  sink->old_crtc = NULL;
   gst_poll_fd_init (&sink->pollfd);
   sink->poll = gst_poll_new (TRUE);
   gst_video_info_init (&sink->vinfo);
diff --git a/sys/kms/gstkmssink.h b/sys/kms/gstkmssink.h
index 24222fd..3db971b 100644
--- a/sys/kms/gstkmssink.h
+++ b/sys/kms/gstkmssink.h
@@ -26,7 +26,9 @@
 #ifndef __GST_KMS_SINK_H__
 #define __GST_KMS_SINK_H__
 
-#include <stdint.h>
+#include <drm.h>
+#include <xf86drm.h>
+#include <xf86drmMode.h>
 
 #include <gst/video/gstvideosink.h>
 
@@ -57,6 +59,7 @@
   gint conn_id;
   gint crtc_id;
   gint plane_id;
+  gint primary_plane_id;
   guint pipe;
 
   /* fps print support */
@@ -83,6 +86,11 @@
   gboolean display_connected;
   gboolean hantro_tile_enabled;
 
+  /* hdr10 support */
+  struct hdr_static_metadata hdr10meta;
+  drmModeCrtcPtr old_crtc;
+  GstMemory *hdr10_mem;
+
   GstVideoInfo vinfo;
   GstCaps *allowed_caps;
   GstBufferPool *pool;
diff --git a/sys/kms/gstkmsutils.c b/sys/kms/gstkmsutils.c
index 2816f00..90961ca 100644
--- a/sys/kms/gstkmsutils.c
+++ b/sys/kms/gstkmsutils.c
@@ -27,6 +27,8 @@
 #include "config.h"
 #endif
 
+#include <stdint.h>
+
 #include <drm_fourcc.h>
 #include <dirent.h>
 #include <string.h>
@@ -62,9 +64,7 @@
   DEF_FMT (YVU420, YV12),
   DEF_FMT (YUV422, Y42B),
   DEF_FMT (NV12, NV12),
-  /* FIXME: just hack for debug usage, need 
-   * drm driver owner add 10bit fourcc format */
-  DEF_FMT (NV12, NV12_10LE),
+  DEF_FMT (P010, NV12_10LE),
   DEF_FMT (NV21, NV21),
   DEF_FMT (NV16, NV16),