aboutsummaryrefslogtreecommitdiffstats
path: root/target/linux/layerscape/patches-5.4/805-display-0025-drm-imx-hdp-add-hdr10-metadata-property.patch
blob: 6ce4263a3f910183720bf9b1f8faf4923c318b38 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
From 7c5c4f891ce4746b52d95d9340c7cae063a48350 Mon Sep 17 00:00:00 2001
From: Laurentiu Palcu <laurentiu.palcu@nxp.com>
Date: Mon, 4 Nov 2019 13:18:48 +0200
Subject: [PATCH] drm/imx/hdp: add hdr10 metadata property

The HDR_OUTPUT_METADATA property is needed in order for userspace to instruct
the sink to switch to HDR10 mode.

Signed-off-by: Laurentiu Palcu <laurentiu.palcu@nxp.com>
---
 drivers/gpu/drm/bridge/cadence/cdns-hdmi-core.c | 72 +++++++++++++++++++++++++
 drivers/gpu/drm/imx/cdn-mhdp-imxdrv.c           |  4 ++
 include/drm/bridge/cdns-mhdp-common.h           |  1 +
 3 files changed, 77 insertions(+)

--- a/drivers/gpu/drm/bridge/cadence/cdns-hdmi-core.c
+++ b/drivers/gpu/drm/bridge/cadence/cdns-hdmi-core.c
@@ -170,6 +170,35 @@ static void hdmi_vendor_info_set(struct
 	cdns_mhdp_infoframe_set(mhdp, 3, sizeof(buf), buf, HDMI_INFOFRAME_TYPE_VENDOR);
 }
 
+static void hdmi_drm_info_set(struct cdns_mhdp_device *mhdp)
+{
+	struct drm_connector_state *conn_state;
+	struct hdmi_drm_infoframe frame;
+	u8 buf[32];
+	int ret;
+
+	conn_state = mhdp->connector.base.state;
+
+	if (!conn_state->hdr_output_metadata)
+		return;
+
+	ret = drm_hdmi_infoframe_set_hdr_metadata(&frame, conn_state);
+	if (ret < 0) {
+		DRM_DEBUG_KMS("couldn't set HDR metadata in infoframe\n");
+		return;
+	}
+
+	ret = hdmi_drm_infoframe_pack(&frame, buf + 1, sizeof(buf) - 1);
+	if (ret < 0) {
+		DRM_DEBUG_KMS("couldn't pack HDR infoframe\n");
+		return;
+	}
+
+	buf[0] = 0;
+	cdns_mhdp_infoframe_set(mhdp, 3, sizeof(buf),
+				buf, HDMI_INFOFRAME_TYPE_DRM);
+}
+
 void cdns_hdmi_mode_set(struct cdns_mhdp_device *mhdp)
 {
 	struct drm_display_mode *mode = &mhdp->mode;
@@ -207,6 +236,8 @@ void cdns_hdmi_mode_set(struct cdns_mhdp
 	/* vendor info frame is enable only  when HDMI1.4 4K mode */
 	hdmi_vendor_info_set(mhdp, mode);
 
+	hdmi_drm_info_set(mhdp);
+
 	ret = cdns_hdmi_mode_config(mhdp, mode, &mhdp->video_info);
 	if (ret < 0) {
 		DRM_ERROR("CDN_API_HDMITX_SetVic_blocking ret = %d\n", ret);
@@ -262,6 +293,40 @@ static int cdns_hdmi_connector_get_modes
 	return num_modes;
 }
 
+static bool blob_equal(const struct drm_property_blob *a,
+		       const struct drm_property_blob *b)
+{
+	if (a && b)
+		return a->length == b->length &&
+			!memcmp(a->data, b->data, a->length);
+
+	return !a == !b;
+}
+
+static int cdns_hdmi_connector_atomic_check(struct drm_connector *connector,
+					    struct drm_atomic_state *state)
+{
+	struct drm_connector_state *new_con_state =
+		drm_atomic_get_new_connector_state(state, connector);
+	struct drm_connector_state *old_con_state =
+		drm_atomic_get_old_connector_state(state, connector);
+	struct drm_crtc *crtc = new_con_state->crtc;
+	struct drm_crtc_state *new_crtc_state;
+
+	if (!blob_equal(new_con_state->hdr_output_metadata,
+			old_con_state->hdr_output_metadata)) {
+		new_crtc_state = drm_atomic_get_crtc_state(state, crtc);
+		if (IS_ERR(new_crtc_state))
+			return PTR_ERR(new_crtc_state);
+
+		new_crtc_state->mode_changed =
+			!new_con_state->hdr_output_metadata ||
+			!old_con_state->hdr_output_metadata;
+	}
+
+	return 0;
+}
+
 static const struct drm_connector_funcs cdns_hdmi_connector_funcs = {
 	.fill_modes = drm_helper_probe_single_connector_modes,
 	.detect = cdns_hdmi_connector_detect,
@@ -273,11 +338,13 @@ static const struct drm_connector_funcs
 
 static const struct drm_connector_helper_funcs cdns_hdmi_connector_helper_funcs = {
 	.get_modes = cdns_hdmi_connector_get_modes,
+	.atomic_check = cdns_hdmi_connector_atomic_check,
 };
 
 static int cdns_hdmi_bridge_attach(struct drm_bridge *bridge)
 {
 	struct cdns_mhdp_device *mhdp = bridge->driver_private;
+	struct drm_mode_config *config = &bridge->dev->mode_config;
 	struct drm_encoder *encoder = bridge->encoder;
 	struct drm_connector *connector = &mhdp->connector.base;
 
@@ -289,6 +356,11 @@ static int cdns_hdmi_bridge_attach(struc
 	drm_connector_init(bridge->dev, connector, &cdns_hdmi_connector_funcs,
 			   DRM_MODE_CONNECTOR_HDMIA);
 
+	if (!strncmp("imx8mq-hdmi", mhdp->plat_data->plat_name, 11))
+		drm_object_attach_property(&connector->base,
+					   config->hdr_output_metadata_property,
+					   0);
+
 	drm_connector_attach_encoder(connector, encoder);
 
 	return 0;
--- a/drivers/gpu/drm/imx/cdn-mhdp-imxdrv.c
+++ b/drivers/gpu/drm/imx/cdn-mhdp-imxdrv.c
@@ -54,6 +54,7 @@ static const struct drm_encoder_funcs cd
 };
 
 static struct cdns_plat_data imx8mq_hdmi_drv_data = {
+	.plat_name = "imx8mq-hdmi",
 	.bind	= cdns_hdmi_bind,
 	.unbind	= cdns_hdmi_unbind,
 	.phy_set = cdns_hdmi_phy_set_imx8mq,
@@ -61,6 +62,7 @@ static struct cdns_plat_data imx8mq_hdmi
 };
 
 static struct cdns_plat_data imx8mq_dp_drv_data = {
+	.plat_name = "imx8mq-dp",
 	.bind	= cdns_dp_bind,
 	.unbind	= cdns_dp_unbind,
 	.phy_set = cdns_dp_phy_set_imx8mq,
@@ -68,6 +70,7 @@ static struct cdns_plat_data imx8mq_dp_d
 };
 
 static struct cdns_plat_data imx8qm_hdmi_drv_data = {
+	.plat_name = "imx8qm-hdmi",
 	.bind	= cdns_hdmi_bind,
 	.unbind	= cdns_hdmi_unbind,
 	.phy_set = cdns_hdmi_phy_set_imx8qm,
@@ -81,6 +84,7 @@ static struct cdns_plat_data imx8qm_hdmi
 };
 
 static struct cdns_plat_data imx8qm_dp_drv_data = {
+	.plat_name = "imx8qm-dp",
 	.bind	= cdns_dp_bind,
 	.unbind	= cdns_dp_unbind,
 	.phy_set = cdns_dp_phy_set_imx8qm,
--- a/include/drm/bridge/cdns-mhdp-common.h
+++ b/include/drm/bridge/cdns-mhdp-common.h
@@ -652,6 +652,7 @@ struct cdns_plat_data {
 	int bus_type;
 	int video_format;
 	char is_dp;
+	char *plat_name;
 };
 
 struct cdns_mhdp_device {