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

Commit 1afbd178 authored by Narender Ankam's avatar Narender Ankam
Browse files

drm/msm: update CSC matrix during HDR playback



Update the CSC matrix used in the CDM block
to BT2020 format from the default value
during HDR video playback.

Add support in the SDE driver to enable switching
CSC matrix of CDM block to BT2020 during start of
HDR playback and restore it at the stop of the
playback to the default CSC.

Change-Id: Ic589380188ddef8ada2c8bbc0ca945bb1f319c85
Signed-off-by: default avatarAbhinav Kumar <abhinavk@codeaurora.org>
Signed-off-by: default avatarAjay Singh Parmar <aparmar@codeaurora.org>
Signed-off-by: default avatarChirag Khurana <ckhurana@codeaurora.org>
Signed-off-by: default avatarNarender Ankam <nankam@codeaurora.org>
parent dc32cdff
Loading
Loading
Loading
Loading
+3 −1
Original line number Diff line number Diff line
/*
 * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
 * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 and
@@ -51,4 +51,6 @@ struct dp_display {
int dp_display_get_num_of_displays(void);
int dp_display_get_displays(void **displays, int count);
bool dp_connector_mode_needs_full_range(void *display);
enum sde_csc_type dp_connector_get_csc_type(struct drm_connector *conn,
	void *data);
#endif /* _DP_DISPLAY_H_ */
+38 −1
Original line number Diff line number Diff line
/*
 * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
 * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 and
@@ -26,6 +26,11 @@

#define to_dp_bridge(x)     container_of((x), struct dp_bridge, base)

enum dp_connector_hdr_state {
	HDR_DISABLE,
	HDR_ENABLE
};

static void convert_to_dp_mode(const struct drm_display_mode *drm_mode,
			struct dp_display_mode *dp_mode, struct dp_display *dp)
{
@@ -384,6 +389,38 @@ bool dp_connector_mode_needs_full_range(void *data)
	return false;
}

enum sde_csc_type dp_connector_get_csc_type(struct drm_connector *conn,
	void *data)
{
	struct dp_display *display = data;
	struct sde_connector_state *c_state;
	struct drm_msm_ext_hdr_metadata *hdr_meta;

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

	c_state = to_sde_connector_state(conn->state);

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

	hdr_meta = &c_state->hdr_meta;

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

error:
	return SDE_CSC_RGB2YUV_601L;
}

enum drm_connector_status dp_connector_detect(struct drm_connector *conn,
		bool force,
		void *display)
+23 −1
Original line number Diff line number Diff line
/* Copyright (c) 2016-2019, The Linux Foundation. All rights reserved.
/* Copyright (c) 2016-2020, The Linux Foundation. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 and
@@ -724,6 +724,28 @@ int sde_connector_clk_ctrl(struct drm_connector *connector, bool enable)
	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;
+18 −1
Original line number Diff line number Diff line
/* Copyright (c) 2016-2019, The Linux Foundation. All rights reserved.
/* Copyright (c) 2016-2020, The Linux Foundation. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 and
@@ -198,6 +198,15 @@ struct sde_connector_ops {
	 * @enable: State of clks
	 */
	int (*clk_ctrl)(void *handle, u32 type, u32 state);
	/**
	 * 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);

	/**
	 * set_power - update dpms setting
@@ -718,6 +727,14 @@ static inline bool sde_connector_needs_offset(struct drm_connector *connector)
 */
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);

/**
 * sde_connector_get_dither_cfg - get dither property data
 * @conn: Pointer to drm_connector struct
+47 −4
Original line number Diff line number Diff line
@@ -4094,10 +4094,15 @@ int sde_encoder_prepare_for_kickoff(struct drm_encoder *drm_enc,
	struct sde_encoder_phys *phys;
	struct sde_kms *sde_kms = NULL;
	struct msm_drm_private *priv = NULL;
	struct drm_connector *conn_mas = NULL;
	struct drm_display_mode *mode;
	struct sde_hw_cdm *hw_cdm;
	enum sde_csc_type conn_csc;
	bool needs_hw_reset = false;
	uint32_t ln_cnt1, ln_cnt2;
	unsigned int i;
	int rc, ret = 0;
	int mode_is_yuv = 0;

	if (!drm_enc || !params || !drm_enc->dev ||
		!drm_enc->dev->dev_private) {
@@ -4167,13 +4172,48 @@ int sde_encoder_prepare_for_kickoff(struct drm_encoder *drm_enc,
	_sde_encoder_update_roi(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",
					sde_enc->cur_master->connector->base.id,
			SDE_ERROR_ENC(sde_enc,
				"kickoff conn%d failed rc %d\n",
				conn_mas->base.id,
				rc);
			ret = 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,
							"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;

				}
			}
		}
	}

	if (_sde_encoder_is_dsc_enabled(drm_enc) &&
@@ -5297,6 +5337,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