Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 357a856a authored by Hans Verkuil's avatar Hans Verkuil Committed by Mauro Carvalho Chehab
Browse files

media: v4l2-dv-timings: add v4l2_hdmi_colorimetry()



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: default avatarHans Verkuil <hans.verkuil@cisco.com>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@s-opensource.com>
parent bd2a0f08
Loading
Loading
Loading
Loading
+141 −0
Original line number Diff line number Diff line
@@ -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);
+21 −0
Original line number Diff line number Diff line
@@ -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