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

Commit 6949010e 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 CSC matrix during HDR playback"

parents de1f4ef4 5920f5fe
Loading
Loading
Loading
Loading
+34 −0
Original line number Diff line number Diff line
@@ -2394,6 +2394,40 @@ bool sde_hdmi_mode_needs_full_range(void *display)
	return true;
}

enum sde_csc_type sde_hdmi_get_csc_type(struct drm_connector *conn,
	void *display)
{
	struct sde_hdmi *hdmi_display = (struct sde_hdmi *)display;
	struct sde_connector_state *c_state;
	struct drm_msm_ext_panel_hdr_ctrl *hdr_ctrl;
	struct drm_msm_ext_panel_hdr_metadata *hdr_meta;

	if (!hdmi_display || !conn) {
		SDE_ERROR("invalid input\n");
		goto error;
	}

	c_state = to_sde_connector_state(conn->state);

	if (!c_state) {
		SDE_ERROR("invalid input\n");
		goto error;
	}

	hdr_ctrl = &c_state->hdr_ctrl;
	hdr_meta = &hdr_ctrl->hdr_meta;

	if ((hdr_ctrl->hdr_state == HDR_ENABLE)
		&& (hdr_meta->eotf != 0))
		return SDE_CSC_RGB2YUV_2020L;
	else if (sde_hdmi_mode_needs_full_range(hdmi_display)
		|| conn->yuv_qs)
		return SDE_CSC_RGB2YUV_601FR;

error:
	return SDE_CSC_RGB2YUV_601L;
}

int sde_hdmi_connector_get_modes(struct drm_connector *connector, void *display)
{
	struct sde_hdmi *hdmi_display = (struct sde_hdmi *)display;
+15 −0
Original line number Diff line number Diff line
@@ -490,6 +490,15 @@ int sde_hdmi_pre_kickoff(struct drm_connector *connector,
 */
bool sde_hdmi_mode_needs_full_range(void *display);

/*
 * sde_hdmi_get_csc_type - returns the CSC type to be
 * used based on state of HDR playback
 * @conn: Pointer to DRM connector
 * @display: Pointer to private display structure
 * Returns: true or false based on mode
 */
enum sde_csc_type sde_hdmi_get_csc_type(struct drm_connector *conn,
	void *display);
#else /*#ifdef CONFIG_DRM_SDE_HDMI*/

static inline u32 sde_hdmi_get_num_of_displays(void)
@@ -609,5 +618,11 @@ static inline bool sde_hdmi_mode_needs_full_range(void *display)
	return false;
}

enum sde_csc_type sde_hdmi_get_csc_type(struct drm_connector *conn,
	void *display)
{
	return 0;
}

#endif /*#else of CONFIG_DRM_SDE_HDMI*/
#endif /* _SDE_HDMI_H_ */
+22 −0
Original line number Diff line number Diff line
@@ -90,6 +90,28 @@ int sde_connector_pre_kickoff(struct drm_connector *connector)
	return rc;
}

enum sde_csc_type sde_connector_get_csc_type(struct drm_connector *conn)
{
	struct sde_connector *c_conn;

	if (!conn) {
		SDE_ERROR("invalid argument\n");
		return -EINVAL;
	}

	c_conn = to_sde_connector(conn);

	if (!c_conn->display) {
		SDE_ERROR("invalid argument\n");
		return -EINVAL;
	}

	if (!c_conn->ops.get_csc_type)
		return SDE_CSC_RGB2YUV_601L;

	return c_conn->ops.get_csc_type(conn, c_conn->display);
}

bool sde_connector_mode_needs_full_range(struct drm_connector *connector)
{
	struct sde_connector *c_conn;
+19 −0
Original line number Diff line number Diff line
@@ -143,6 +143,16 @@ struct sde_connector_ops {
	 * Returns: true or false based on whether full range is needed
	 */
	bool (*mode_needs_full_range)(void *display);

	/**
	 * get_csc_type - returns the CSC type to be used
	 * by the CDM block based on HDR state
	 * @connector: Pointer to drm connector structure
	 * @display: Pointer to private display structure
	 * Returns: type of CSC matrix to be used
	 */
	enum sde_csc_type (*get_csc_type)(struct drm_connector *connector,
		void *display);
};

/**
@@ -342,5 +352,14 @@ int sde_connector_pre_kickoff(struct drm_connector *connector);
 * Returns: true OR false based on connector mode
 */
bool sde_connector_mode_needs_full_range(struct drm_connector *connector);

/**
 * sde_connector_get_csc_type - query csc type
 * to be used for the connector
 * @connector: Pointer to drm connector object
 * Returns: csc type based on connector HDR state
 */
enum sde_csc_type sde_connector_get_csc_type(struct drm_connector *conn);

#endif /* _SDE_CONNECTOR_H_ */
+83 −4
Original line number Diff line number Diff line
@@ -80,6 +80,42 @@ static struct sde_csc_cfg sde_csc_10bit_convert[SDE_MAX_CSC] = {
		{ 0x0, 0x3ff, 0x0, 0x3ff, 0x0, 0x3ff,},
		{ 0x0, 0x3ff, 0x0, 0x3ff, 0x0, 0x3ff,},
	},

	[SDE_CSC_RGB2YUV_709L] = {
		{
			TO_S15D16(0x005d), TO_S15D16(0x013a), TO_S15D16(0x0020),
			TO_S15D16(0xffcc), TO_S15D16(0xff53), TO_S15D16(0x00e1),
			TO_S15D16(0x00e1), TO_S15D16(0xff34), TO_S15D16(0xffeb),
		},
		{ 0x0, 0x0, 0x0,},
		{ 0x0040, 0x0200, 0x0200,},
		{ 0x0, 0x3ff, 0x0, 0x3ff, 0x0, 0x3ff,},
		{ 0x0040, 0x03ac, 0x0040, 0x03c0, 0x0040, 0x03c0,},
	},

	[SDE_CSC_RGB2YUV_2020L] = {
		{
			TO_S15D16(0x0073), TO_S15D16(0x0129), TO_S15D16(0x001a),
			TO_S15D16(0xffc1), TO_S15D16(0xff5e), TO_S15D16(0x00e0),
			TO_S15D16(0x00e0), TO_S15D16(0xff32), TO_S15D16(0xffee),
		},
		{ 0x0, 0x0, 0x0,},
		{ 0x0040, 0x0200, 0x0200,},
		{ 0x0, 0x3ff, 0x0, 0x3ff, 0x0, 0x3ff,},
		{ 0x0040, 0x03ac, 0x0040, 0x03c0, 0x0040, 0x03c0,},
	},

	[SDE_CSC_RGB2YUV_2020FR] = {
		{
			TO_S15D16(0x0086), TO_S15D16(0x015b), TO_S15D16(0x001e),
			TO_S15D16(0xffb9), TO_S15D16(0xff47), TO_S15D16(0x0100),
			TO_S15D16(0x0100), TO_S15D16(0xff15), TO_S15D16(0xffeb),
		},
		{ 0x0, 0x0, 0x0,},
		{ 0x0, 0x0200, 0x0200,},
		{ 0x0, 0x3ff, 0x0, 0x3ff, 0x0, 0x3ff,},
		{ 0x0, 0x3ff, 0x0, 0x3ff, 0x0, 0x3ff,},
	},
};

/**
@@ -826,7 +862,12 @@ void sde_encoder_prepare_for_kickoff(struct drm_encoder *drm_enc)
{
	struct sde_encoder_virt *sde_enc;
	struct sde_encoder_phys *phys;
	struct drm_connector *conn_mas = NULL;
	unsigned int i;
	enum sde_csc_type conn_csc;
	struct drm_display_mode *mode;
	struct sde_hw_cdm *hw_cdm;
	int mode_is_yuv = 0;
	int rc;

	if (!drm_enc) {
@@ -846,11 +887,46 @@ void sde_encoder_prepare_for_kickoff(struct drm_encoder *drm_enc)
	}

	if (sde_enc->cur_master && sde_enc->cur_master->connector) {
		rc = sde_connector_pre_kickoff(sde_enc->cur_master->connector);
		conn_mas = sde_enc->cur_master->connector;
		rc = sde_connector_pre_kickoff(conn_mas);
		if (rc)
			SDE_ERROR_ENC(sde_enc,
				"kickoff conn%d failed rc %d\n",
				conn_mas->base.id,
				rc);

		for (i = 0; i < sde_enc->num_phys_encs; i++) {
			phys = sde_enc->phys_encs[i];
			if (phys) {
				mode = &phys->cached_mode;
				mode_is_yuv = (mode->private_flags &
					MSM_MODE_FLAG_COLOR_FORMAT_YCBCR420);
			}
			/**
			 * Check the CSC matrix type to which the
			 * CDM CSC matrix should be updated to based
			 * on the connector HDR state
			 */
			conn_csc = sde_connector_get_csc_type(conn_mas);
			if (phys && mode_is_yuv) {
				if (phys->enc_cdm_csc != conn_csc) {
					hw_cdm = phys->hw_cdm;
					rc = hw_cdm->ops.setup_csc_data(hw_cdm,
					&sde_csc_10bit_convert[conn_csc]);

					if (rc)
			SDE_ERROR_ENC(sde_enc, "kickoff conn%d failed rc %d\n",
					sde_enc->cur_master->connector->base.id,
						SDE_ERROR_ENC(sde_enc,
							"CSC setup failed rc %d\n",
							rc);
					SDE_DEBUG_ENC(sde_enc,
						"updating CSC %d to %d\n",
						phys->enc_cdm_csc,
						conn_csc);
					phys->enc_cdm_csc = conn_csc;

				}
			}
		}
	}
}

@@ -1507,6 +1583,9 @@ void sde_encoder_phys_setup_cdm(struct sde_encoder_phys *phys_enc,
		}
	}

	/* Cache the CSC default matrix type */
	phys_enc->enc_cdm_csc = csc_type;

	if (hw_cdm && hw_cdm->ops.setup_cdwn) {
		ret = hw_cdm->ops.setup_cdwn(hw_cdm, cdm_cfg);
		if (ret < 0) {
Loading