media: v4l2-dv-timings: add v4l2_hdmi_colorimetry()
authorHans Verkuil <hverkuil@xs4all.nl>
Thu, 15 Feb 2018 17:55:29 +0000 (12:55 -0500)
committerMauro Carvalho Chehab <mchehab@s-opensource.com>
Thu, 22 Feb 2018 17:41:09 +0000 (12:41 -0500)
Add the v4l2_hdmi_colorimetry() function so we have a single function
that determines the colorspace, YCbCr encoding, quantization range and
transfer function from the InfoFrame data.

Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
drivers/media/v4l2-core/v4l2-dv-timings.c
include/media/v4l2-dv-timings.h

index d98c4ad..c81faea 100644 (file)
@@ -14,6 +14,7 @@
 #include <linux/v4l2-dv-timings.h>
 #include <media/v4l2-dv-timings.h>
 #include <linux/math64.h>
+#include <linux/hdmi.h>
 
 MODULE_AUTHOR("Hans Verkuil");
 MODULE_DESCRIPTION("V4L2 DV Timings Helper Functions");
@@ -801,3 +802,143 @@ struct v4l2_fract v4l2_calc_aspect_ratio(u8 hor_landscape, u8 vert_portrait)
        return aspect;
 }
 EXPORT_SYMBOL_GPL(v4l2_calc_aspect_ratio);
+
+/** v4l2_hdmi_rx_colorimetry - determine HDMI colorimetry information
+ *     based on various InfoFrames.
+ * @avi: the AVI InfoFrame
+ * @hdmi: the HDMI Vendor InfoFrame, may be NULL
+ * @height: the frame height
+ *
+ * Determines the HDMI colorimetry information, i.e. how the HDMI
+ * pixel color data should be interpreted.
+ *
+ * Note that some of the newer features (DCI-P3, HDR) are not yet
+ * implemented: the hdmi.h header needs to be updated to the HDMI 2.0
+ * and CTA-861-G standards.
+ */
+struct v4l2_hdmi_colorimetry
+v4l2_hdmi_rx_colorimetry(const struct hdmi_avi_infoframe *avi,
+                        const struct hdmi_vendor_infoframe *hdmi,
+                        unsigned int height)
+{
+       struct v4l2_hdmi_colorimetry c = {
+               V4L2_COLORSPACE_SRGB,
+               V4L2_YCBCR_ENC_DEFAULT,
+               V4L2_QUANTIZATION_FULL_RANGE,
+               V4L2_XFER_FUNC_SRGB
+       };
+       bool is_ce = avi->video_code || (hdmi && hdmi->vic);
+       bool is_sdtv = height <= 576;
+       bool default_is_lim_range_rgb = avi->video_code > 1;
+
+       switch (avi->colorspace) {
+       case HDMI_COLORSPACE_RGB:
+               /* RGB pixel encoding */
+               switch (avi->colorimetry) {
+               case HDMI_COLORIMETRY_EXTENDED:
+                       switch (avi->extended_colorimetry) {
+                       case HDMI_EXTENDED_COLORIMETRY_ADOBE_RGB:
+                               c.colorspace = V4L2_COLORSPACE_ADOBERGB;
+                               c.xfer_func = V4L2_XFER_FUNC_ADOBERGB;
+                               break;
+                       case HDMI_EXTENDED_COLORIMETRY_BT2020:
+                               c.colorspace = V4L2_COLORSPACE_BT2020;
+                               c.xfer_func = V4L2_XFER_FUNC_709;
+                               break;
+                       default:
+                               break;
+                       }
+                       break;
+               default:
+                       break;
+               }
+               switch (avi->quantization_range) {
+               case HDMI_QUANTIZATION_RANGE_LIMITED:
+                       c.quantization = V4L2_QUANTIZATION_LIM_RANGE;
+                       break;
+               case HDMI_QUANTIZATION_RANGE_FULL:
+                       break;
+               default:
+                       if (default_is_lim_range_rgb)
+                               c.quantization = V4L2_QUANTIZATION_LIM_RANGE;
+                       break;
+               }
+               break;
+
+       default:
+               /* YCbCr pixel encoding */
+               c.quantization = V4L2_QUANTIZATION_LIM_RANGE;
+               switch (avi->colorimetry) {
+               case HDMI_COLORIMETRY_NONE:
+                       if (!is_ce)
+                               break;
+                       if (is_sdtv) {
+                               c.colorspace = V4L2_COLORSPACE_SMPTE170M;
+                               c.ycbcr_enc = V4L2_YCBCR_ENC_601;
+                       } else {
+                               c.colorspace = V4L2_COLORSPACE_REC709;
+                               c.ycbcr_enc = V4L2_YCBCR_ENC_709;
+                       }
+                       c.xfer_func = V4L2_XFER_FUNC_709;
+                       break;
+               case HDMI_COLORIMETRY_ITU_601:
+                       c.colorspace = V4L2_COLORSPACE_SMPTE170M;
+                       c.ycbcr_enc = V4L2_YCBCR_ENC_601;
+                       c.xfer_func = V4L2_XFER_FUNC_709;
+                       break;
+               case HDMI_COLORIMETRY_ITU_709:
+                       c.colorspace = V4L2_COLORSPACE_REC709;
+                       c.ycbcr_enc = V4L2_YCBCR_ENC_709;
+                       c.xfer_func = V4L2_XFER_FUNC_709;
+                       break;
+               case HDMI_COLORIMETRY_EXTENDED:
+                       switch (avi->extended_colorimetry) {
+                       case HDMI_EXTENDED_COLORIMETRY_XV_YCC_601:
+                               c.colorspace = V4L2_COLORSPACE_REC709;
+                               c.ycbcr_enc = V4L2_YCBCR_ENC_XV709;
+                               c.xfer_func = V4L2_XFER_FUNC_709;
+                               break;
+                       case HDMI_EXTENDED_COLORIMETRY_XV_YCC_709:
+                               c.colorspace = V4L2_COLORSPACE_REC709;
+                               c.ycbcr_enc = V4L2_YCBCR_ENC_XV601;
+                               c.xfer_func = V4L2_XFER_FUNC_709;
+                               break;
+                       case HDMI_EXTENDED_COLORIMETRY_S_YCC_601:
+                               c.colorspace = V4L2_COLORSPACE_SRGB;
+                               c.ycbcr_enc = V4L2_YCBCR_ENC_601;
+                               c.xfer_func = V4L2_XFER_FUNC_SRGB;
+                               break;
+                       case HDMI_EXTENDED_COLORIMETRY_ADOBE_YCC_601:
+                               c.colorspace = V4L2_COLORSPACE_ADOBERGB;
+                               c.ycbcr_enc = V4L2_YCBCR_ENC_601;
+                               c.xfer_func = V4L2_XFER_FUNC_ADOBERGB;
+                               break;
+                       case HDMI_EXTENDED_COLORIMETRY_BT2020:
+                               c.colorspace = V4L2_COLORSPACE_BT2020;
+                               c.ycbcr_enc = V4L2_YCBCR_ENC_BT2020;
+                               c.xfer_func = V4L2_XFER_FUNC_709;
+                               break;
+                       case HDMI_EXTENDED_COLORIMETRY_BT2020_CONST_LUM:
+                               c.colorspace = V4L2_COLORSPACE_BT2020;
+                               c.ycbcr_enc = V4L2_YCBCR_ENC_BT2020_CONST_LUM;
+                               c.xfer_func = V4L2_XFER_FUNC_709;
+                               break;
+                       default: /* fall back to ITU_709 */
+                               c.colorspace = V4L2_COLORSPACE_REC709;
+                               c.ycbcr_enc = V4L2_YCBCR_ENC_709;
+                               c.xfer_func = V4L2_XFER_FUNC_709;
+                               break;
+                       }
+                       break;
+               default:
+                       break;
+               }
+               /*
+                * YCC Quantization Range signaling is more-or-less broken,
+                * let's just ignore this.
+                */
+               break;
+       }
+       return c;
+}
+EXPORT_SYMBOL_GPL(v4l2_hdmi_rx_colorimetry);
index 8778263..17cb27d 100644 (file)
@@ -212,5 +212,26 @@ static inline  bool can_reduce_fps(struct v4l2_bt_timings *bt)
        return false;
 }
 
+/**
+ * struct v4l2_hdmi_rx_colorimetry - describes the HDMI colorimetry information
+ * @colorspace:                enum v4l2_colorspace, the colorspace
+ * @ycbcr_enc:         enum v4l2_ycbcr_encoding, Y'CbCr encoding
+ * @quantization:      enum v4l2_quantization, colorspace quantization
+ * @xfer_func:         enum v4l2_xfer_func, colorspace transfer function
+ */
+struct v4l2_hdmi_colorimetry {
+       enum v4l2_colorspace colorspace;
+       enum v4l2_ycbcr_encoding ycbcr_enc;
+       enum v4l2_quantization quantization;
+       enum v4l2_xfer_func xfer_func;
+};
+
+struct hdmi_avi_infoframe;
+struct hdmi_vendor_infoframe;
+
+struct v4l2_hdmi_colorimetry
+v4l2_hdmi_rx_colorimetry(const struct hdmi_avi_infoframe *avi,
+                        const struct hdmi_vendor_infoframe *hdmi,
+                        unsigned int height);
 
 #endif