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

Commit 842f75d2 authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "drm/msm: update HDMI AVI infoframe during HDR playback"

parents 6949010e 86d73ba3
Loading
Loading
Loading
Loading
+132 −1
Original line number Diff line number Diff line
@@ -1970,6 +1970,123 @@ enable_packet_control:
	hdmi_write(hdmi, HDMI_GEN_PKT_CTRL, packet_control);
}

static void sde_hdmi_update_colorimetry(struct sde_hdmi *display,
	bool use_bt2020)
{
	struct hdmi *hdmi;
	struct drm_connector *connector;
	bool mode_is_yuv = false;
	struct drm_display_mode *mode;
	u32 mode_fmt_flags = 0;
	u8 checksum;
	u32 avi_info0 = 0;
	u32 avi_info1 = 0;
	u8 avi_iframe[HDMI_AVI_INFOFRAME_BUFFER_SIZE] = {0};
	u8 *avi_frame = &avi_iframe[HDMI_INFOFRAME_HEADER_SIZE];
	struct hdmi_avi_infoframe info;

	if (!display) {
		SDE_ERROR("invalid input\n");
		return;
	}

	hdmi = display->ctrl.ctrl;

	if (!hdmi) {
		SDE_ERROR("invalid input\n");
		return;
	}

	connector = display->ctrl.ctrl->connector;

	if (!connector) {
		SDE_ERROR("invalid input\n");
		return;
	}

	if (!connector->hdr_supported) {
		SDE_DEBUG("HDR is not supported\n");
		return;
	}

	/* If sink doesn't support BT2020, just return */
	if (!(connector->color_enc_fmt & DRM_EDID_COLORIMETRY_BT2020_YCC) ||
	    !(connector->color_enc_fmt & DRM_EDID_COLORIMETRY_BT2020_RGB)) {
		SDE_DEBUG("BT2020 colorimetry is not supported\n");
		return;
	}

	/* If there is no change in colorimetry, just return */
	if (use_bt2020 && display->bt2020_colorimetry)
		return;
	else if (!use_bt2020 && !display->bt2020_colorimetry)
		return;

	mode = &display->mode;
	/* Cache the format flags before clearing */
	mode_fmt_flags = mode->flags;
	/**
	 * Clear the RGB/YUV format flags before calling upstream API
	 * as the API also compares the flags and then returns a mode
	 */
	mode->flags &= ~SDE_DRM_MODE_FLAG_FMT_MASK;
	drm_hdmi_avi_infoframe_from_display_mode(&info, mode);
	/* Restore the format flags */
	mode->flags = mode_fmt_flags;

	/* Mode should only support YUV and not both to set the flag */
	if ((mode->private_flags & MSM_MODE_FLAG_COLOR_FORMAT_YCBCR420)
	    && !(mode->private_flags & MSM_MODE_FLAG_COLOR_FORMAT_RGB444)) {
		mode_is_yuv = true;
	}


	if (!display->bt2020_colorimetry && use_bt2020) {
		/**
		 * 1. Update colorimetry to use extended
		 * 2. Change extended to use BT2020
		 * 3. Change colorspace based on mode
		 * 4. Use limited as BT2020 is always limited
		 */
		info.colorimetry = SDE_HDMI_USE_EXTENDED_COLORIMETRY;
		info.extended_colorimetry = SDE_HDMI_BT2020_COLORIMETRY;
		if (mode_is_yuv)
			info.colorspace = HDMI_COLORSPACE_YUV420;
		if (connector->yuv_qs)
			info.ycc_quantization_range =
				HDMI_YCC_QUANTIZATION_RANGE_LIMITED;
	} else if (display->bt2020_colorimetry && !use_bt2020) {
		/**
		 * 1. Update colorimetry to non-extended
		 * 2. Change colorspace based on mode
		 * 3. Restore quantization to full if QS
		 *	  is enabled
		 */
		info.colorimetry = SDE_HDMI_DEFAULT_COLORIMETRY;
		if (mode_is_yuv)
			info.colorspace = HDMI_COLORSPACE_YUV420;
		if (connector->yuv_qs)
			info.ycc_quantization_range =
				HDMI_YCC_QUANTIZATION_RANGE_FULL;
	}

	hdmi_avi_infoframe_pack(&info, avi_iframe, sizeof(avi_iframe));
	checksum = avi_iframe[HDMI_INFOFRAME_HEADER_SIZE - 1];
	avi_info0 = checksum |
		LEFT_SHIFT_BYTE(avi_frame[0]) |
		LEFT_SHIFT_WORD(avi_frame[1]) |
		LEFT_SHIFT_24BITS(avi_frame[2]);

	avi_info1 = avi_frame[3] |
		LEFT_SHIFT_BYTE(avi_frame[4]) |
		LEFT_SHIFT_WORD(avi_frame[5]) |
		LEFT_SHIFT_24BITS(avi_frame[6]);

	hdmi_write(hdmi, REG_HDMI_AVI_INFO(0), avi_info0);
	hdmi_write(hdmi, REG_HDMI_AVI_INFO(1), avi_info1);
	display->bt2020_colorimetry = use_bt2020;
}

static void sde_hdmi_clear_hdr_infoframe(struct sde_hdmi *display)
{
	struct hdmi *hdmi;
@@ -2340,14 +2457,22 @@ int sde_hdmi_pre_kickoff(struct drm_connector *connector,
{
	struct sde_hdmi *hdmi_display = (struct sde_hdmi *)display;
	struct drm_msm_ext_panel_hdr_ctrl *hdr_ctrl;
	struct drm_msm_ext_panel_hdr_metadata *hdr_meta;
	u8 hdr_op;

	if (!connector || !display || !params) {
	if (!connector || !display || !params ||
		!params->hdr_ctrl) {
		pr_err("Invalid params\n");
		return -EINVAL;
	}

	hdr_ctrl = params->hdr_ctrl;
	hdr_meta = &hdr_ctrl->hdr_meta;

	if (!hdr_meta) {
		SDE_ERROR("Invalid params\n");
		return -EINVAL;
	}

	hdr_op = sde_hdmi_hdr_get_ops(hdmi_display->curr_hdr_state,
		hdr_ctrl->hdr_state);
@@ -2356,6 +2481,12 @@ int sde_hdmi_pre_kickoff(struct drm_connector *connector,
		if (connector->hdr_supported)
			sde_hdmi_panel_set_hdr_infoframe(display,
				&hdr_ctrl->hdr_meta);
		if (hdr_meta->eotf)
			sde_hdmi_update_colorimetry(hdmi_display,
				true);
		else
			sde_hdmi_update_colorimetry(hdmi_display,
				false);
	} else if (hdr_op == HDR_CLEAR_INFO)
		sde_hdmi_clear_hdr_infoframe(display);

+10 −0
Original line number Diff line number Diff line
@@ -169,6 +169,7 @@ struct sde_hdmi {
	bool pll_update_enable;
	bool dc_enable;
	bool dc_feature_supported;
	bool bt2020_colorimetry;

	struct delayed_work hdcp_cb_work;
	struct dss_io_data io[HDMI_TX_MAX_IO];
@@ -201,6 +202,15 @@ enum hdmi_tx_scdc_access_type {

#define HDMI_GEN_PKT_CTRL_CLR_MASK 0x7

/* for AVI program */
#define HDMI_AVI_INFOFRAME_BUFFER_SIZE \
	(HDMI_INFOFRAME_HEADER_SIZE + HDMI_AVI_INFOFRAME_SIZE)
#define HDMI_VS_INFOFRAME_BUFFER_SIZE (HDMI_INFOFRAME_HEADER_SIZE + 6)

#define LEFT_SHIFT_BYTE(x) ((x) << 8)
#define LEFT_SHIFT_WORD(x) ((x) << 16)
#define LEFT_SHIFT_24BITS(x) ((x) << 24)

/* Maximum pixel clock rates for hdmi tx */
#define HDMI_DEFAULT_MAX_PCLK_RATE	148500
#define HDMI_TX_3_MAX_PCLK_RATE		297000
+0 −7
Original line number Diff line number Diff line
@@ -99,17 +99,10 @@ struct sde_hdmi_bridge {
#define HDMI_TX_SCRAMBLER_TIMEOUT_MSEC 200


/* for AVI program */
#define HDMI_AVI_INFOFRAME_BUFFER_SIZE \
	(HDMI_INFOFRAME_HEADER_SIZE + HDMI_AVI_INFOFRAME_SIZE)
#define HDMI_VS_INFOFRAME_BUFFER_SIZE (HDMI_INFOFRAME_HEADER_SIZE + 6)
#define HDMI_SPD_INFOFRAME_BUFFER_SIZE \
	(HDMI_INFOFRAME_HEADER_SIZE + HDMI_SPD_INFOFRAME_SIZE)
#define HDMI_DEFAULT_VENDOR_NAME "unknown"
#define HDMI_DEFAULT_PRODUCT_NAME "msm"
#define LEFT_SHIFT_BYTE(x) ((x) << 8)
#define LEFT_SHIFT_WORD(x) ((x) << 16)
#define LEFT_SHIFT_24BITS(x) ((x) << 24)
#define HDMI_AVI_IFRAME_LINE_NUMBER 1
#define HDMI_VENDOR_IFRAME_LINE_NUMBER 3

+6 −0
Original line number Diff line number Diff line
@@ -98,6 +98,12 @@
#define HDMI_GET_LSB(x)(x & 0xff)

#define SDE_HDMI_VIC_640x480 0x1
#define SDE_HDMI_YCC_QUANT_MASK (0x3 << 14)
#define SDE_HDMI_COLORIMETRY_MASK (0x3 << 22)

#define SDE_HDMI_DEFAULT_COLORIMETRY 0x0
#define SDE_HDMI_USE_EXTENDED_COLORIMETRY 0x3
#define SDE_HDMI_BT2020_COLORIMETRY 0x6

/*
 * Bits 1:0 in HDMI_HW_DDC_CTRL that dictate how the HDCP 2.2 RxStatus will be