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

Commit b6fb478d 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 17ed9893 1afbd178
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
+84 −5
Original line number Diff line number Diff line
/*
 * Copyright (c) 2014-2019, The Linux Foundation. All rights reserved.
 * Copyright (c) 2014-2020, The Linux Foundation. All rights reserved.
 * Copyright (C) 2013 Red Hat
 * Author: Rob Clark <robdclark@gmail.com>
 *
@@ -186,6 +186,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,},
	},
};

/**
@@ -4058,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) {
@@ -4131,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) &&
@@ -5261,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