bcm27xx: switch to 5.15
[openwrt/openwrt.git] / target / linux / bcm27xx / patches-5.10 / 950-0417-drm-vc4-hdmi-Enable-10-12-bpc-output.patch
1 From 72a998c1462527c2d61c2f9a38525c99da442fb4 Mon Sep 17 00:00:00 2001
2 From: Maxime Ripard <maxime@cerno.tech>
3 Date: Tue, 15 Dec 2020 16:42:43 +0100
4 Subject: [PATCH] drm/vc4: hdmi: Enable 10/12 bpc output
5
6 The BCM2711 supports higher bpc count than just 8, so let's support it in
7 our driver.
8
9 Signed-off-by: Maxime Ripard <maxime@cerno.tech>
10 Reviewed-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
11 ---
12 drivers/gpu/drm/vc4/vc4_hdmi.c | 70 ++++++++++++++++++++++++++++-
13 drivers/gpu/drm/vc4/vc4_hdmi.h | 1 +
14 drivers/gpu/drm/vc4/vc4_hdmi_regs.h | 9 ++++
15 3 files changed, 79 insertions(+), 1 deletion(-)
16
17 --- a/drivers/gpu/drm/vc4/vc4_hdmi.c
18 +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
19 @@ -77,6 +77,17 @@
20 #define VC5_HDMI_VERTB_VSPO_SHIFT 16
21 #define VC5_HDMI_VERTB_VSPO_MASK VC4_MASK(29, 16)
22
23 +#define VC5_HDMI_DEEP_COLOR_CONFIG_1_INIT_PACK_PHASE_SHIFT 8
24 +#define VC5_HDMI_DEEP_COLOR_CONFIG_1_INIT_PACK_PHASE_MASK VC4_MASK(10, 8)
25 +
26 +#define VC5_HDMI_DEEP_COLOR_CONFIG_1_COLOR_DEPTH_SHIFT 0
27 +#define VC5_HDMI_DEEP_COLOR_CONFIG_1_COLOR_DEPTH_MASK VC4_MASK(3, 0)
28 +
29 +#define VC5_HDMI_GCP_CONFIG_GCP_ENABLE BIT(31)
30 +
31 +#define VC5_HDMI_GCP_WORD_1_GCP_SUBPACKET_BYTE_1_SHIFT 8
32 +#define VC5_HDMI_GCP_WORD_1_GCP_SUBPACKET_BYTE_1_MASK VC4_MASK(15, 8)
33 +
34 # define VC4_HD_M_SW_RST BIT(2)
35 # define VC4_HD_M_ENABLE BIT(0)
36
37 @@ -229,6 +240,8 @@ static void vc4_hdmi_connector_reset(str
38 if (!new_state)
39 return;
40
41 + new_state->base.max_bpc = 8;
42 + new_state->base.max_requested_bpc = 8;
43 drm_atomic_helper_connector_tv_reset(connector);
44 }
45
46 @@ -275,12 +288,20 @@ static int vc4_hdmi_connector_init(struc
47 vc4_hdmi->ddc);
48 drm_connector_helper_add(connector, &vc4_hdmi_connector_helper_funcs);
49
50 + /*
51 + * Some of the properties below require access to state, like bpc.
52 + * Allocate some default initial connector state with our reset helper.
53 + */
54 + if (connector->funcs->reset)
55 + connector->funcs->reset(connector);
56 +
57 /* Create and attach TV margin props to this connector. */
58 ret = drm_mode_create_tv_margin_properties(dev);
59 if (ret)
60 return ret;
61
62 drm_connector_attach_tv_margin_properties(connector);
63 + drm_connector_attach_max_bpc_property(connector, 8, 12);
64
65 connector->polled = (DRM_CONNECTOR_POLL_CONNECT |
66 DRM_CONNECTOR_POLL_DISCONNECT);
67 @@ -555,6 +576,7 @@ static void vc5_hdmi_csc_setup(struct vc
68 }
69
70 static void vc4_hdmi_set_timings(struct vc4_hdmi *vc4_hdmi,
71 + struct drm_connector_state *state,
72 struct drm_display_mode *mode)
73 {
74 bool hsync_pos = mode->flags & DRM_MODE_FLAG_PHSYNC;
75 @@ -598,7 +620,9 @@ static void vc4_hdmi_set_timings(struct
76 HDMI_WRITE(HDMI_VERTB0, vertb_even);
77 HDMI_WRITE(HDMI_VERTB1, vertb);
78 }
79 +
80 static void vc5_hdmi_set_timings(struct vc4_hdmi *vc4_hdmi,
81 + struct drm_connector_state *state,
82 struct drm_display_mode *mode)
83 {
84 bool hsync_pos = mode->flags & DRM_MODE_FLAG_PHSYNC;
85 @@ -618,6 +642,9 @@ static void vc5_hdmi_set_timings(struct
86 mode->crtc_vsync_end -
87 interlaced,
88 VC4_HDMI_VERTB_VBP));
89 + unsigned char gcp;
90 + bool gcp_en;
91 + u32 reg;
92
93 HDMI_WRITE(HDMI_VEC_INTERFACE_XBAR, 0x354021);
94 HDMI_WRITE(HDMI_HORZA,
95 @@ -643,6 +670,39 @@ static void vc5_hdmi_set_timings(struct
96 HDMI_WRITE(HDMI_VERTB0, vertb_even);
97 HDMI_WRITE(HDMI_VERTB1, vertb);
98
99 + switch (state->max_bpc) {
100 + case 12:
101 + gcp = 6;
102 + gcp_en = true;
103 + break;
104 + case 10:
105 + gcp = 5;
106 + gcp_en = true;
107 + break;
108 + case 8:
109 + default:
110 + gcp = 4;
111 + gcp_en = false;
112 + break;
113 + }
114 +
115 + reg = HDMI_READ(HDMI_DEEP_COLOR_CONFIG_1);
116 + reg &= ~(VC5_HDMI_DEEP_COLOR_CONFIG_1_INIT_PACK_PHASE_MASK |
117 + VC5_HDMI_DEEP_COLOR_CONFIG_1_COLOR_DEPTH_MASK);
118 + reg |= VC4_SET_FIELD(2, VC5_HDMI_DEEP_COLOR_CONFIG_1_INIT_PACK_PHASE) |
119 + VC4_SET_FIELD(gcp, VC5_HDMI_DEEP_COLOR_CONFIG_1_COLOR_DEPTH);
120 + HDMI_WRITE(HDMI_DEEP_COLOR_CONFIG_1, reg);
121 +
122 + reg = HDMI_READ(HDMI_GCP_WORD_1);
123 + reg &= ~VC5_HDMI_GCP_WORD_1_GCP_SUBPACKET_BYTE_1_MASK;
124 + reg |= VC4_SET_FIELD(gcp, VC5_HDMI_GCP_WORD_1_GCP_SUBPACKET_BYTE_1);
125 + HDMI_WRITE(HDMI_GCP_WORD_1, reg);
126 +
127 + reg = HDMI_READ(HDMI_GCP_CONFIG);
128 + reg &= ~VC5_HDMI_GCP_CONFIG_GCP_ENABLE;
129 + reg |= gcp_en ? VC5_HDMI_GCP_CONFIG_GCP_ENABLE : 0;
130 + HDMI_WRITE(HDMI_GCP_CONFIG, reg);
131 +
132 HDMI_WRITE(HDMI_CLOCK_STOP, 0);
133 }
134
135 @@ -770,7 +830,7 @@ static void vc4_hdmi_encoder_pre_crtc_co
136 VC4_HDMI_SCHEDULER_CONTROL_IGNORE_VSYNC_PREDICTS);
137
138 if (vc4_hdmi->variant->set_timings)
139 - vc4_hdmi->variant->set_timings(vc4_hdmi, mode);
140 + vc4_hdmi->variant->set_timings(vc4_hdmi, conn_state, mode);
141 }
142
143 static void vc4_hdmi_encoder_pre_crtc_enable(struct drm_encoder *encoder,
144 @@ -892,6 +952,14 @@ static int vc4_hdmi_encoder_atomic_check
145 pixel_rate = mode->clock * 1000;
146 }
147
148 + if (conn_state->max_bpc == 12) {
149 + pixel_rate = pixel_rate * 150;
150 + do_div(pixel_rate, 100);
151 + } else if (conn_state->max_bpc == 10) {
152 + pixel_rate = pixel_rate * 125;
153 + do_div(pixel_rate, 100);
154 + }
155 +
156 if (mode->flags & DRM_MODE_FLAG_DBLCLK)
157 pixel_rate = pixel_rate * 2;
158
159 --- a/drivers/gpu/drm/vc4/vc4_hdmi.h
160 +++ b/drivers/gpu/drm/vc4/vc4_hdmi.h
161 @@ -74,6 +74,7 @@ struct vc4_hdmi_variant {
162
163 /* Callback to configure the video timings in the HDMI block */
164 void (*set_timings)(struct vc4_hdmi *vc4_hdmi,
165 + struct drm_connector_state *state,
166 struct drm_display_mode *mode);
167
168 /* Callback to initialize the PHY according to the connector state */
169 --- a/drivers/gpu/drm/vc4/vc4_hdmi_regs.h
170 +++ b/drivers/gpu/drm/vc4/vc4_hdmi_regs.h
171 @@ -60,9 +60,12 @@ enum vc4_hdmi_field {
172 */
173 HDMI_CTS_0,
174 HDMI_CTS_1,
175 + HDMI_DEEP_COLOR_CONFIG_1,
176 HDMI_DVP_CTL,
177 HDMI_FIFO_CTL,
178 HDMI_FRAME_COUNT,
179 + HDMI_GCP_CONFIG,
180 + HDMI_GCP_WORD_1,
181 HDMI_HORZA,
182 HDMI_HORZB,
183 HDMI_HOTPLUG,
184 @@ -231,6 +234,9 @@ static const struct vc4_hdmi_register vc
185 VC4_HDMI_REG(HDMI_VERTB1, 0x0f8),
186 VC4_HDMI_REG(HDMI_MAI_CHANNEL_MAP, 0x09c),
187 VC4_HDMI_REG(HDMI_MAI_CONFIG, 0x0a0),
188 + VC4_HDMI_REG(HDMI_DEEP_COLOR_CONFIG_1, 0x170),
189 + VC4_HDMI_REG(HDMI_GCP_CONFIG, 0x178),
190 + VC4_HDMI_REG(HDMI_GCP_WORD_1, 0x17c),
191 VC4_HDMI_REG(HDMI_HOTPLUG, 0x1a8),
192
193 VC5_DVP_REG(HDMI_CLOCK_STOP, 0x0bc),
194 @@ -307,6 +313,9 @@ static const struct vc4_hdmi_register vc
195 VC4_HDMI_REG(HDMI_VERTB1, 0x0f8),
196 VC4_HDMI_REG(HDMI_MAI_CHANNEL_MAP, 0x09c),
197 VC4_HDMI_REG(HDMI_MAI_CONFIG, 0x0a0),
198 + VC4_HDMI_REG(HDMI_DEEP_COLOR_CONFIG_1, 0x170),
199 + VC4_HDMI_REG(HDMI_GCP_CONFIG, 0x178),
200 + VC4_HDMI_REG(HDMI_GCP_WORD_1, 0x17c),
201 VC4_HDMI_REG(HDMI_HOTPLUG, 0x1a8),
202
203 VC5_DVP_REG(HDMI_CLOCK_STOP, 0x0bc),