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

Commit 0d34fc89 authored by Ajay Singh Parmar's avatar Ajay Singh Parmar Committed by Steve Cohen
Browse files

drm/msm/dp: add support for HDR state machine



Add support for HDR enable/disable based on the user-space's
data. Switch to HDR pre-disable mode before disabling HDR for
smooth transition to HDR disabled state. Also, add debug
file system for HDR setup.

CRs-Fixed: 2110071
Change-Id: Iedd9f3224598eb967ec5029844c11152e350b250
Signed-off-by: default avatarAjay Singh Parmar <aparmar@codeaurora.org>
parent 611f3aa4
Loading
Loading
Loading
Loading
+96 −98
Original line number Diff line number Diff line
@@ -338,6 +338,7 @@ static void dp_catalog_panel_setup_infoframe_sdp(struct dp_catalog_panel *panel)
	struct drm_msm_ext_hdr_metadata *hdr;
	void __iomem *base;
	u32 header, parity, data;
	u8 buf[SZ_128], off = 0;

	if (!panel) {
		pr_err("invalid input\n");
@@ -354,8 +355,8 @@ static void dp_catalog_panel_setup_infoframe_sdp(struct dp_catalog_panel *panel)
	data   = ((header << HEADER_BYTE_1_BIT)
			| (parity << PARITY_BYTE_1_BIT));
	dp_write(base + MMSS_DP_VSCEXT_0, data);
	pr_debug("Header#1: 0x%x, parity = 0x%x\n", header, parity);
	pr_debug("DP_VSCEXT_0: 0x%x\n", data);
	memcpy(buf + off, &data, sizeof(data));
	off += sizeof(data);

	/* HEADER BYTE 2 */
	header = panel->hdr_data.vscext_header_byte2;
@@ -363,8 +364,6 @@ static void dp_catalog_panel_setup_infoframe_sdp(struct dp_catalog_panel *panel)
	data   = ((header << HEADER_BYTE_2_BIT)
			| (parity << PARITY_BYTE_2_BIT));
	dp_write(base + MMSS_DP_VSCEXT_1, data);
	pr_debug("Header#2: 0x%x, parity = 0x%x\n", header, parity);
	pr_debug("DP_VSCEXT_1: 0x%x\n", data);

	/* HEADER BYTE 3 */
	header = panel->hdr_data.vscext_header_byte3;
@@ -373,101 +372,71 @@ static void dp_catalog_panel_setup_infoframe_sdp(struct dp_catalog_panel *panel)
			| (parity << PARITY_BYTE_3_BIT));
	data |= dp_read(base + MMSS_DP_VSCEXT_1);
	dp_write(base + MMSS_DP_VSCEXT_1, data);
	pr_debug("Header#3: 0x%x, parity = 0x%x\n", header, parity);
	pr_debug("DP_VSCEXT_1: 0x%x\n", data);
	memcpy(buf + off, &data, sizeof(data));
	off += sizeof(data);

	data = panel->hdr_data.version;
	data |= panel->hdr_data.length << 8;
	data |= hdr->eotf << 16;
	pr_debug("DP_VSCEXT_2: 0x%x\n", data);
	dp_write(base + MMSS_DP_VSCEXT_2, data);
	memcpy(buf + off, &data, sizeof(data));
	off += sizeof(data);

	data = (DP_GET_LSB(hdr->display_primaries_x[0]) |
		(DP_GET_MSB(hdr->display_primaries_x[0]) << 8) |
		(DP_GET_LSB(hdr->display_primaries_y[0]) << 16) |
		(DP_GET_MSB(hdr->display_primaries_y[0]) << 24));
	pr_debug("DP_VSCEXT_3: 0x%x\n", data);
	dp_write(base + MMSS_DP_VSCEXT_3, data);
	memcpy(buf + off, &data, sizeof(data));
	off += sizeof(data);

	data = (DP_GET_LSB(hdr->display_primaries_x[1]) |
		(DP_GET_MSB(hdr->display_primaries_x[1]) << 8) |
		(DP_GET_LSB(hdr->display_primaries_y[1]) << 16) |
		(DP_GET_MSB(hdr->display_primaries_y[1]) << 24));
	pr_debug("DP_VSCEXT_4: 0x%x\n", data);
	dp_write(base + MMSS_DP_VSCEXT_4, data);
	memcpy(buf + off, &data, sizeof(data));
	off += sizeof(data);

	data = (DP_GET_LSB(hdr->display_primaries_x[2]) |
		(DP_GET_MSB(hdr->display_primaries_x[2]) << 8) |
		(DP_GET_LSB(hdr->display_primaries_y[2]) << 16) |
		(DP_GET_MSB(hdr->display_primaries_y[2]) << 24));
	pr_debug("DP_VSCEXT_5: 0x%x\n", data);
	dp_write(base + MMSS_DP_VSCEXT_5, data);
	memcpy(buf + off, &data, sizeof(data));
	off += sizeof(data);

	data = (DP_GET_LSB(hdr->white_point_x) |
		(DP_GET_MSB(hdr->white_point_x) << 8) |
		(DP_GET_LSB(hdr->white_point_y) << 16) |
		(DP_GET_MSB(hdr->white_point_y) << 24));
	pr_debug("DP_VSCEXT_6: 0x%x\n", data);
	dp_write(base + MMSS_DP_VSCEXT_6, data);
	memcpy(buf + off, &data, sizeof(data));
	off += sizeof(data);

	data = (DP_GET_LSB(hdr->max_luminance) |
		(DP_GET_MSB(hdr->max_luminance) << 8) |
		(DP_GET_LSB(hdr->min_luminance) << 16) |
		(DP_GET_MSB(hdr->min_luminance) << 24));
	pr_debug("DP_VSCEXT_7: 0x%x\n", data);
	dp_write(base + MMSS_DP_VSCEXT_7, data);
	memcpy(buf + off, &data, sizeof(data));
	off += sizeof(data);

	data = (DP_GET_LSB(hdr->max_content_light_level) |
		(DP_GET_MSB(hdr->max_content_light_level) << 8) |
		(DP_GET_LSB(hdr->max_average_light_level) << 16) |
		(DP_GET_MSB(hdr->max_average_light_level) << 24));
	pr_debug("DP_VSCEXT_8: 0x%x\n", data);
	dp_write(base + MMSS_DP_VSCEXT_8, data);
	memcpy(buf + off, &data, sizeof(data));
	off += sizeof(data);

	dp_write(base + MMSS_DP_VSCEXT_9, 0x00);
}

static void dp_catalog_panel_setup_ext_sdp(struct dp_catalog_panel *panel)
{
	struct dp_catalog_private *catalog;
	void __iomem *base;
	u32 header, parity, data;
	data = 0;
	dp_write(base + MMSS_DP_VSCEXT_9, data);
	memcpy(buf + off, &data, sizeof(data));
	off += sizeof(data);

	if (!panel) {
		pr_err("invalid input\n");
		return;
	}

	dp_catalog_get_priv(panel);
	base = catalog->io->dp_link.base;

	/* HEADER BYTE 1 */
	header = panel->hdr_data.ext_header_byte1;
	parity = dp_header_get_parity(header);
	data   = ((header << HEADER_BYTE_1_BIT)
			| (parity << PARITY_BYTE_1_BIT));
	dp_write(base + MMSS_DP_EXTENSION_0, data);
	pr_debug("Header#1: 0x%x, parity = 0x%x\n", header, parity);
	pr_debug("DP_EXTENSION_0: 0x%x\n", data);

	/* HEADER BYTE 2 */
	header = panel->hdr_data.ext_header_byte2;
	parity = dp_header_get_parity(header);
	data   = ((header << HEADER_BYTE_2_BIT)
			| (parity << PARITY_BYTE_2_BIT));
	dp_write(base + MMSS_DP_EXTENSION_1, data);
	pr_debug("Header#2: 0x%x, parity = 0x%x\n", header, parity);
	pr_debug("DP_EXTENSION_1: 0x%x\n", data);

	dp_write(base + MMSS_DP_EXTENSION_1, 0x5AA55AA5);
	dp_write(base + MMSS_DP_EXTENSION_2, 0x5AA55AA5);
	dp_write(base + MMSS_DP_EXTENSION_3, 0x5AA55AA5);
	dp_write(base + MMSS_DP_EXTENSION_4, 0x5AA55AA5);
	dp_write(base + MMSS_DP_EXTENSION_5, 0x5AA55AA5);
	dp_write(base + MMSS_DP_EXTENSION_6, 0x5AA55AA5);
	dp_write(base + MMSS_DP_EXTENSION_7, 0x5AA55AA5);
	dp_write(base + MMSS_DP_EXTENSION_8, 0x5AA55AA5);
	dp_write(base + MMSS_DP_EXTENSION_9, 0x5AA55AA5);
	print_hex_dump(KERN_DEBUG, "[drm-dp] VSCEXT: ",
			DUMP_PREFIX_NONE, 16, 4, buf, off, false);
}

static void dp_catalog_panel_setup_vsc_sdp(struct dp_catalog_panel *panel)
@@ -475,7 +444,8 @@ static void dp_catalog_panel_setup_vsc_sdp(struct dp_catalog_panel *panel)
	struct dp_catalog_private *catalog;
	void __iomem *base;
	u32 header, parity, data;
	u8 bpc;
	u8 bpc, off = 0;
	u8 buf[SZ_128];

	if (!panel) {
		pr_err("invalid input\n");
@@ -483,7 +453,7 @@ static void dp_catalog_panel_setup_vsc_sdp(struct dp_catalog_panel *panel)
	}

	dp_catalog_get_priv(panel);
	base = catalog->io->ctrl_io.base;
	base = catalog->io->dp_link.base;

	/* HEADER BYTE 1 */
	header = panel->hdr_data.vsc_header_byte1;
@@ -491,8 +461,8 @@ static void dp_catalog_panel_setup_vsc_sdp(struct dp_catalog_panel *panel)
	data   = ((header << HEADER_BYTE_1_BIT)
			| (parity << PARITY_BYTE_1_BIT));
	dp_write(base + MMSS_DP_GENERIC0_0, data);
	pr_debug("Header#1: 0x%x, parity = 0x%x\n", header, parity);
	pr_debug("DP_GENERIC0_0: 0x%x\n", data);
	memcpy(buf + off, &data, sizeof(data));
	off += sizeof(data);

	/* HEADER BYTE 2 */
	header = panel->hdr_data.vsc_header_byte2;
@@ -500,8 +470,6 @@ static void dp_catalog_panel_setup_vsc_sdp(struct dp_catalog_panel *panel)
	data   = ((header << HEADER_BYTE_2_BIT)
			| (parity << PARITY_BYTE_2_BIT));
	dp_write(base + MMSS_DP_GENERIC0_1, data);
	pr_debug("Header#2: 0x%x, parity = 0x%x\n", header, parity);
	pr_debug("DP_GENERIC0_1: 0x%x\n", data);

	/* HEADER BYTE 3 */
	header = panel->hdr_data.vsc_header_byte3;
@@ -510,14 +478,25 @@ static void dp_catalog_panel_setup_vsc_sdp(struct dp_catalog_panel *panel)
			| (parity << PARITY_BYTE_3_BIT));
	data |= dp_read(base + MMSS_DP_GENERIC0_1);
	dp_write(base + MMSS_DP_GENERIC0_1, data);
	pr_debug("Header#3: 0x%x, parity = 0x%x\n", header, parity);
	pr_debug("DP_GENERIC0_1: 0x%x\n", data);
	memcpy(buf + off, &data, sizeof(data));
	off += sizeof(data);

	data = 0;
	dp_write(base + MMSS_DP_GENERIC0_2, data);
	memcpy(buf + off, &data, sizeof(data));
	off += sizeof(data);

	dp_write(base + MMSS_DP_GENERIC0_2, 0x00);
	dp_write(base + MMSS_DP_GENERIC0_3, 0x00);
	dp_write(base + MMSS_DP_GENERIC0_4, 0x00);
	dp_write(base + MMSS_DP_GENERIC0_5, 0x00);
	dp_write(base + MMSS_DP_GENERIC0_3, data);
	memcpy(buf + off, &data, sizeof(data));
	off += sizeof(data);

	dp_write(base + MMSS_DP_GENERIC0_4, data);
	memcpy(buf + off, &data, sizeof(data));
	off += sizeof(data);

	dp_write(base + MMSS_DP_GENERIC0_5, data);
	memcpy(buf + off, &data, sizeof(data));
	off += sizeof(data);

	switch (panel->hdr_data.bpc) {
	default:
@@ -538,18 +517,32 @@ static void dp_catalog_panel_setup_vsc_sdp(struct dp_catalog_panel *panel)
		((panel->hdr_data.dynamic_range & 0x1) << 15) |
		((panel->hdr_data.content_type & 0x7) << 16);

	pr_debug("DP_GENERIC0_6: 0x%x\n", data);
	dp_write(base + MMSS_DP_GENERIC0_6, data);
	dp_write(base + MMSS_DP_GENERIC0_7, 0x00);
	dp_write(base + MMSS_DP_GENERIC0_8, 0x00);
	dp_write(base + MMSS_DP_GENERIC0_9, 0x00);
	memcpy(buf + off, &data, sizeof(data));
	off += sizeof(data);

	data = 0;
	dp_write(base + MMSS_DP_GENERIC0_7, data);
	memcpy(buf + off, &data, sizeof(data));
	off += sizeof(data);

	dp_write(base + MMSS_DP_GENERIC0_8, data);
	memcpy(buf + off, &data, sizeof(data));
	off += sizeof(data);

	dp_write(base + MMSS_DP_GENERIC0_9, data);
	memcpy(buf + off, &data, sizeof(data));
	off += sizeof(data);

	print_hex_dump(KERN_DEBUG, "[drm-dp] VSC: ",
			DUMP_PREFIX_NONE, 16, 4, buf, off, false);
}

static void dp_catalog_panel_config_hdr(struct dp_catalog_panel *panel)
static void dp_catalog_panel_config_hdr(struct dp_catalog_panel *panel, bool en)
{
	struct dp_catalog_private *catalog;
	void __iomem *base;
	u32 cfg, cfg2;
	u32 cfg, cfg2, misc;

	if (!panel) {
		pr_err("invalid input\n");
@@ -560,39 +553,44 @@ static void dp_catalog_panel_config_hdr(struct dp_catalog_panel *panel)
	base = catalog->io->dp_link.base;

	cfg = dp_read(base + MMSS_DP_SDP_CFG);
	/* EXTENSION_SDP_EN */
	cfg |= BIT(4);
	cfg2 = dp_read(base + MMSS_DP_SDP_CFG2);
	misc = dp_read(base + DP_MISC1_MISC0);

	/* VSCEXT_SDP_EN */
	cfg |= BIT(16);
	if (en) {
		/* VSCEXT_SDP_EN, GEN0_SDP_EN */
		cfg |= BIT(16) | BIT(17);
		dp_write(base + MMSS_DP_SDP_CFG, cfg);

	/* GEN0_SDP_EN */
	cfg |= BIT(17);
		/* EXTN_SDPSIZE GENERIC0_SDPSIZE */
		cfg2 |= BIT(15) | BIT(16);
		dp_write(base + MMSS_DP_SDP_CFG2, cfg2);

	/* GEN1_SDP_EN */
	cfg |= BIT(18);
	dp_write(base + MMSS_DP_SDP_CFG, cfg);
		dp_catalog_panel_setup_vsc_sdp(panel);
		dp_catalog_panel_setup_infoframe_sdp(panel);

	cfg2 = dp_read(base + MMSS_DP_SDP_CFG2);
	/* EXTN_SDPSIZE */
	cfg2 |= BIT(15);
		/* indicates presence of VSC (BIT(6) of MISC1) */
		misc |= BIT(14);

	/* GENERIC0_SDPSIZE */
	cfg |= BIT(16);
		if (panel->hdr_data.hdr_meta.eotf)
			pr_debug("Enabled\n");
		else
			pr_debug("Reset\n");
	} else {
		/* VSCEXT_SDP_EN, GEN0_SDP_EN */
		cfg &= ~BIT(16) & ~BIT(17);
		dp_write(base + MMSS_DP_SDP_CFG, cfg);

	/* GENERIC1_SDPSIZE */
	cfg |= BIT(17);
		/* EXTN_SDPSIZE GENERIC0_SDPSIZE */
		cfg2 &= ~BIT(15) & ~BIT(16);
		dp_write(base + MMSS_DP_SDP_CFG2, cfg2);

	dp_catalog_panel_setup_ext_sdp(panel);
	dp_catalog_panel_setup_vsc_sdp(panel);
	dp_catalog_panel_setup_infoframe_sdp(panel);
		/* switch back to MSA */
		misc &= ~BIT(14);

	cfg = dp_read(base + DP_MISC1_MISC0);
	/* Indicates presence of VSC */
	cfg |= BIT(6) << 8;
		pr_debug("Disabled\n");
	}

	dp_write(base + DP_MISC1_MISC0, cfg);
	dp_write(base + DP_MISC1_MISC0, misc);

	dp_write(base + MMSS_DP_SDP_CFG3, 0x01);
	dp_write(base + MMSS_DP_SDP_CFG3, 0x00);
+1 −1
Original line number Diff line number Diff line
@@ -171,7 +171,7 @@ struct dp_catalog_panel {
	u32 display_hctl;

	int (*timing_cfg)(struct dp_catalog_panel *panel);
	void (*config_hdr)(struct dp_catalog_panel *panel);
	void (*config_hdr)(struct dp_catalog_panel *panel, bool en);
	void (*tpg_config)(struct dp_catalog_panel *panel, bool enable);
	void (*config_spd)(struct dp_catalog_panel *panel);
};
+212 −0
Original line number Diff line number Diff line
@@ -23,6 +23,7 @@
#include "dp_ctrl.h"
#include "dp_debug.h"
#include "drm_connector.h"
#include "sde_connector.h"
#include "dp_display.h"

#define DEBUG_NAME "drm_dp"
@@ -618,6 +619,201 @@ static ssize_t dp_debug_tpg_read(struct file *file,
	return len;
}

static ssize_t dp_debug_write_hdr(struct file *file,
	const char __user *user_buff, size_t count, loff_t *ppos)
{
	struct drm_connector *connector;
	struct sde_connector *c_conn;
	struct sde_connector_state *c_state;
	struct dp_debug_private *debug = file->private_data;
	char buf[SZ_1K];
	size_t len = 0;

	if (!debug)
		return -ENODEV;

	if (*ppos)
		return 0;

	connector = *debug->connector;
	c_conn = to_sde_connector(connector);
	c_state = to_sde_connector_state(connector->state);

	/* Leave room for termination char */
	len = min_t(size_t, count, SZ_1K - 1);
	if (copy_from_user(buf, user_buff, len))
		goto end;

	buf[len] = '\0';

	if (sscanf(buf, "%x %x %x %x %x %x %x %x %x %x %x %x %x %x %x",
			&c_state->hdr_meta.hdr_supported,
			&c_state->hdr_meta.hdr_state,
			&c_state->hdr_meta.eotf,
			&c_state->hdr_meta.display_primaries_x[0],
			&c_state->hdr_meta.display_primaries_x[1],
			&c_state->hdr_meta.display_primaries_x[2],
			&c_state->hdr_meta.display_primaries_y[0],
			&c_state->hdr_meta.display_primaries_y[1],
			&c_state->hdr_meta.display_primaries_y[2],
			&c_state->hdr_meta.white_point_x,
			&c_state->hdr_meta.white_point_y,
			&c_state->hdr_meta.max_luminance,
			&c_state->hdr_meta.min_luminance,
			&c_state->hdr_meta.max_content_light_level,
			&c_state->hdr_meta.max_average_light_level) != 15) {
		pr_err("invalid input\n");
		len = -EINVAL;
	}
end:
	return len;
}

static ssize_t dp_debug_read_hdr(struct file *file,
		char __user *user_buff, size_t count, loff_t *ppos)
{
	struct dp_debug_private *debug = file->private_data;
	char *buf;
	u32 len = 0, i;
	u32 max_size = SZ_4K;
	int rc = 0;
	struct drm_connector *connector;
	struct sde_connector *c_conn;
	struct sde_connector_state *c_state;
	struct drm_msm_ext_hdr_metadata *hdr;

	if (!debug) {
		pr_err("invalid data\n");
		rc = -ENODEV;
		goto error;
	}

	connector = *debug->connector;

	if (!connector) {
		pr_err("connector is NULL\n");
		rc = -EINVAL;
		goto error;
	}

	if (*ppos)
		goto error;

	buf = kzalloc(SZ_4K, GFP_KERNEL);
	if (!buf) {
		rc = -ENOMEM;
		goto error;
	}

	c_conn = to_sde_connector(connector);
	c_state = to_sde_connector_state(connector->state);

	hdr = &c_state->hdr_meta;

	rc = snprintf(buf + len, max_size,
		"============SINK HDR PARAMETERS===========\n");
	if (dp_debug_check_buffer_overflow(rc, &max_size, &len))
		goto error;

	rc = snprintf(buf + len, max_size, "eotf = %d\n",
		connector->hdr_eotf);
	if (dp_debug_check_buffer_overflow(rc, &max_size, &len))
		goto error;

	rc = snprintf(buf + len, max_size, "type_one = %d\n",
		connector->hdr_metadata_type_one);
	if (dp_debug_check_buffer_overflow(rc, &max_size, &len))
		goto error;

	rc = snprintf(buf + len, max_size, "max_luminance = %d\n",
		connector->hdr_max_luminance);
	if (dp_debug_check_buffer_overflow(rc, &max_size, &len))
		goto error;

	rc = snprintf(buf + len, max_size, "avg_luminance = %d\n",
		connector->hdr_avg_luminance);
	if (dp_debug_check_buffer_overflow(rc, &max_size, &len))
		goto error;

	rc = snprintf(buf + len, max_size, "min_luminance = %d\n",
		connector->hdr_min_luminance);
	if (dp_debug_check_buffer_overflow(rc, &max_size, &len))
		goto error;

	rc = snprintf(buf + len, max_size,
		"============VIDEO HDR PARAMETERS===========\n");
	if (dp_debug_check_buffer_overflow(rc, &max_size, &len))
		goto error;

	rc = snprintf(buf + len, max_size, "hdr_state = %d\n", hdr->hdr_state);
	if (dp_debug_check_buffer_overflow(rc, &max_size, &len))
		goto error;

	rc = snprintf(buf + len, max_size, "hdr_supported = %d\n",
			hdr->hdr_supported);
	if (dp_debug_check_buffer_overflow(rc, &max_size, &len))
		goto error;

	rc = snprintf(buf + len, max_size, "eotf = %d\n", hdr->eotf);
	if (dp_debug_check_buffer_overflow(rc, &max_size, &len))
		goto error;

	rc = snprintf(buf + len, max_size, "white_point_x = %d\n",
		hdr->white_point_x);
	if (dp_debug_check_buffer_overflow(rc, &max_size, &len))
		goto error;

	rc = snprintf(buf + len, max_size, "white_point_y = %d\n",
		hdr->white_point_y);
	if (dp_debug_check_buffer_overflow(rc, &max_size, &len))
		goto error;

	rc = snprintf(buf + len, max_size, "max_luminance = %d\n",
		hdr->max_luminance);
	if (dp_debug_check_buffer_overflow(rc, &max_size, &len))
		goto error;

	rc = snprintf(buf + len, max_size, "min_luminance = %d\n",
		hdr->min_luminance);
	if (dp_debug_check_buffer_overflow(rc, &max_size, &len))
		goto error;

	rc = snprintf(buf + len, max_size, "max_content_light_level = %d\n",
		hdr->max_content_light_level);
	if (dp_debug_check_buffer_overflow(rc, &max_size, &len))
		goto error;

	rc = snprintf(buf + len, max_size, "min_content_light_level = %d\n",
		hdr->max_average_light_level);
	if (dp_debug_check_buffer_overflow(rc, &max_size, &len))
		goto error;

	for (i = 0; i < HDR_PRIMARIES_COUNT; i++) {
		rc = snprintf(buf + len, max_size, "primaries_x[%d] = %d\n",
			i, hdr->display_primaries_x[i]);
		if (dp_debug_check_buffer_overflow(rc, &max_size, &len))
			goto error;

		rc = snprintf(buf + len, max_size, "primaries_y[%d] = %d\n",
			i, hdr->display_primaries_y[i]);
		if (dp_debug_check_buffer_overflow(rc, &max_size, &len))
			goto error;
	}

	if (copy_to_user(user_buff, buf, len)) {
		kfree(buf);
		rc = -EFAULT;
		goto error;
	}

	*ppos += len;
	kfree(buf);

	return len;
error:
	return rc;
}

static const struct file_operations dp_debug_fops = {
	.open = simple_open,
	.read = dp_debug_read_info,
@@ -661,6 +857,12 @@ static const struct file_operations tpg_fops = {
	.write = dp_debug_tpg_write,
};

static const struct file_operations hdr_fops = {
	.open = simple_open,
	.write = dp_debug_write_hdr,
	.read = dp_debug_read_hdr,
};

static int dp_debug_init(struct dp_debug *dp_debug)
{
	int rc = 0;
@@ -753,6 +955,16 @@ static int dp_debug_init(struct dp_debug *dp_debug)
		goto error_remove_dir;
	}

	file = debugfs_create_file("hdr", 0644, dir,
		debug, &hdr_fops);

	if (IS_ERR_OR_NULL(file)) {
		rc = PTR_ERR(file);
		pr_err("[%s] debugfs hdr failed, rc=%d\n",
			DEBUG_NAME, rc);
		goto error_remove_dir;
	}

	return 0;

error_remove_dir:
+5 −1
Original line number Diff line number Diff line
@@ -1195,6 +1195,7 @@ static int dp_display_get_modes(struct dp_display *dp,
static int dp_display_pre_kickoff(struct dp_display *dp_display,
			struct drm_msm_ext_hdr_metadata *hdr)
{
	int rc = 0;
	struct dp_display_private *dp;

	if (!dp_display) {
@@ -1204,7 +1205,10 @@ static int dp_display_pre_kickoff(struct dp_display *dp_display,

	dp = container_of(dp_display, struct dp_display_private, dp_display);

	return dp->panel->setup_hdr(dp->panel, hdr);
	if (hdr->hdr_supported)
		rc = dp->panel->setup_hdr(dp->panel, hdr);

	return rc;
}

static int dp_display_create_workqueue(struct dp_display_private *dp)
+68 −39
Original line number Diff line number Diff line
@@ -19,8 +19,41 @@
#define DP_PANEL_DEFAULT_BPP 24
#define DP_MAX_DS_PORT_COUNT 1

enum {
	DP_LINK_RATE_MULTIPLIER = 27000000,
enum dp_panel_hdr_pixel_encoding {
	RGB,
	YCbCr444,
	YCbCr422,
	YCbCr420,
	YONLY,
	RAW,
};

enum dp_panel_hdr_rgb_colorimetry {
	sRGB,
	RGB_WIDE_GAMUT_FIXED_POINT,
	RGB_WIDE_GAMUT_FLOATING_POINT,
	ADOBERGB,
	DCI_P3,
	CUSTOM_COLOR_PROFILE,
	ITU_R_BT_2020_RGB,
};

enum dp_panel_hdr_dynamic_range {
	VESA,
	CEA,
};

enum dp_panel_hdr_content_type {
	NOT_DEFINED,
	GRAPHICS,
	PHOTO,
	VIDEO,
	GAME,
};

enum dp_panel_hdr_state {
	HDR_DISABLED,
	HDR_ENABLED,
};

struct dp_panel_private {
@@ -32,6 +65,7 @@ struct dp_panel_private {
	bool custom_edid;
	bool custom_dpcd;
	bool panel_on;
	enum dp_panel_hdr_state hdr_state;
	u8 spd_vendor_name[8];
	u8 spd_product_description[16];
};
@@ -622,37 +656,29 @@ static u32 dp_panel_get_min_req_link_rate(struct dp_panel *dp_panel)
	return min_link_rate_khz;
}

enum dp_panel_hdr_pixel_encoding {
	RGB,
	YCbCr444,
	YCbCr422,
	YCbCr420,
	YONLY,
	RAW,
};
static bool dp_panel_is_validate_hdr_state(struct dp_panel_private *panel,
		struct drm_msm_ext_hdr_metadata *hdr_meta)
{
	struct drm_msm_ext_hdr_metadata *panel_hdr_meta =
			&panel->catalog->hdr_data.hdr_meta;

enum dp_panel_hdr_rgb_colorimetry {
	sRGB,
	RGB_WIDE_GAMUT_FIXED_POINT,
	RGB_WIDE_GAMUT_FLOATING_POINT,
	ADOBERGB,
	DCI_P3,
	CUSTOM_COLOR_PROFILE,
	ITU_R_BT_2020_RGB,
};
	if (!hdr_meta)
		goto end;

enum dp_panel_hdr_dynamic_range {
	VESA,
	CEA,
};
	/* bail out if HDR not active */
	if (hdr_meta->hdr_state == HDR_DISABLED &&
	    panel->hdr_state == HDR_DISABLED)
		goto end;

enum dp_panel_hdr_content_type {
	NOT_DEFINED,
	GRAPHICS,
	PHOTO,
	VIDEO,
	GAME,
};
	/* bail out if same meta data is received */
	if (hdr_meta->hdr_state == HDR_ENABLED &&
		panel_hdr_meta->eotf == hdr_meta->eotf)
		goto end;

	return true;
end:
	return false;
}

static int dp_panel_setup_hdr(struct dp_panel *dp_panel,
		struct drm_msm_ext_hdr_metadata *hdr_meta)
@@ -661,9 +687,6 @@ static int dp_panel_setup_hdr(struct dp_panel *dp_panel,
	struct dp_panel_private *panel;
	struct dp_catalog_hdr_data *hdr;

	if (!hdr_meta || !hdr_meta->hdr_state)
		goto end;

	if (!dp_panel) {
		pr_err("invalid input\n");
		rc = -EINVAL;
@@ -671,6 +694,12 @@ static int dp_panel_setup_hdr(struct dp_panel *dp_panel,
	}

	panel = container_of(dp_panel, struct dp_panel_private, dp_panel);

	if (!dp_panel_is_validate_hdr_state(panel, hdr_meta))
		goto end;

	panel->hdr_state = hdr_meta->hdr_state;

	hdr = &panel->catalog->hdr_data;

	hdr->ext_header_byte0 = 0x00;
@@ -683,6 +712,11 @@ static int dp_panel_setup_hdr(struct dp_panel *dp_panel,
	hdr->vsc_header_byte2 = 0x05;
	hdr->vsc_header_byte3 = 0x13;

	hdr->vscext_header_byte0 = 0x00;
	hdr->vscext_header_byte1 = 0x87;
	hdr->vscext_header_byte2 = 0x1D;
	hdr->vscext_header_byte3 = 0x13 << 2;

	/* VSC SDP Payload for DB16 */
	hdr->pixel_encoding = RGB;
	hdr->colorimetry = ITU_R_BT_2020_RGB;
@@ -695,17 +729,12 @@ static int dp_panel_setup_hdr(struct dp_panel *dp_panel,

	hdr->bpc = dp_panel->pinfo.bpp / 3;

	hdr->vscext_header_byte0 = 0x00;
	hdr->vscext_header_byte1 = 0x87;
	hdr->vscext_header_byte2 = 0x1D;
	hdr->vscext_header_byte3 = 0x13 << 2;

	hdr->version = 0x01;
	hdr->length = 0x1A;

	memcpy(&hdr->hdr_meta, hdr_meta, sizeof(hdr->hdr_meta));

	panel->catalog->config_hdr(panel->catalog);
	panel->catalog->config_hdr(panel->catalog, panel->hdr_state);
end:
	return rc;
}