aboutsummaryrefslogtreecommitdiffstats
path: root/target/linux/bcm27xx/patches-5.4/950-0248-drm-vc4-FKMS-reads-the-EDID-from-fw-and-supports-mod.patch
blob: 92400560acaf6b8756cc93e5ad5eac984e56b6b6 (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
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
From 52add140c76c0a211ab340ced8e7e1ea8bef9c79 Mon Sep 17 00:00:00 2001
From: Dave Stevenson <dave.stevenson@raspberrypi.org>
Date: Tue, 9 Apr 2019 18:23:41 +0100
Subject: [PATCH] drm: vc4: FKMS reads the EDID from fw, and supports
 mode setting

This extends FKMS to read the EDID from the display, and support
requesting a particular mode via KMS.

Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
---
 drivers/gpu/drm/vc4/vc4_firmware_kms.c     | 334 ++++++++++++++++++---
 include/soc/bcm2835/raspberrypi-firmware.h |   2 +
 2 files changed, 302 insertions(+), 34 deletions(-)

--- a/drivers/gpu/drm/vc4/vc4_firmware_kms.c
+++ b/drivers/gpu/drm/vc4/vc4_firmware_kms.c
@@ -91,11 +91,60 @@ struct mailbox_blank_display {
 	u32 blank;
 };
 
-struct mailbox_get_width_height {
+struct mailbox_get_edid {
 	struct rpi_firmware_property_tag_header tag1;
-	u32 display;
-	struct rpi_firmware_property_tag_header tag2;
-	u32 wh[2];
+	u32 block;
+	u32 display_number;
+	u8 edid[128];
+};
+
+struct set_timings {
+	u8 display;
+	u8 padding;
+	u16 video_id_code;
+
+	u32 clock;		/* in kHz */
+
+	u16 hdisplay;
+	u16 hsync_start;
+
+	u16 hsync_end;
+	u16 htotal;
+
+	u16 hskew;
+	u16 vdisplay;
+
+	u16 vsync_start;
+	u16 vsync_end;
+
+	u16 vtotal;
+	u16 vscan;
+
+	u16 vrefresh;
+	u16 padding2;
+
+	u32 flags;
+#define  TIMINGS_FLAGS_H_SYNC_POS	BIT(0)
+#define  TIMINGS_FLAGS_H_SYNC_NEG	0
+#define  TIMINGS_FLAGS_V_SYNC_POS	BIT(1)
+#define  TIMINGS_FLAGS_V_SYNC_NEG	0
+
+#define TIMINGS_FLAGS_ASPECT_MASK	GENMASK(7, 4)
+#define TIMINGS_FLAGS_ASPECT_NONE	(0 << 4)
+#define TIMINGS_FLAGS_ASPECT_4_3	(1 << 4)
+#define TIMINGS_FLAGS_ASPECT_16_9	(2 << 4)
+#define TIMINGS_FLAGS_ASPECT_64_27	(3 << 4)
+#define TIMINGS_FLAGS_ASPECT_256_135	(4 << 4)
+
+/* Limited range RGB flag. Not set corresponds to full range. */
+#define TIMINGS_FLAGS_RGB_LIMITED	BIT(8)
+/* DVI monitor, therefore disable infoframes. Not set corresponds to HDMI. */
+#define TIMINGS_FLAGS_DVI		BIT(9)
+};
+
+struct mailbox_set_mode {
+	struct rpi_firmware_property_tag_header tag1;
+	struct set_timings timings;
 };
 
 static const struct vc_image_format {
@@ -189,6 +238,7 @@ struct vc4_crtc {
 	u32 overscan[4];
 	bool vblank_enabled;
 	u32 display_number;
+	u32 display_type;
 };
 
 static inline struct vc4_crtc *to_vc4_crtc(struct drm_crtc *crtc)
@@ -198,6 +248,8 @@ static inline struct vc4_crtc *to_vc4_cr
 
 struct vc4_fkms_encoder {
 	struct drm_encoder base;
+	bool hdmi_monitor;
+	bool rgb_range_selectable;
 };
 
 static inline struct vc4_fkms_encoder *
@@ -215,7 +267,9 @@ struct vc4_fkms_connector {
 	 * hook.
 	 */
 	struct drm_encoder *encoder;
-	u32 display_idx;
+	struct vc4_dev *vc4_dev;
+	u32 display_number;
+	u32 display_type;
 };
 
 static inline struct vc4_fkms_connector *
@@ -224,6 +278,26 @@ to_vc4_fkms_connector(struct drm_connect
 	return container_of(connector, struct vc4_fkms_connector, base);
 }
 
+static u32 vc4_get_display_type(u32 display_number)
+{
+	const u32 display_types[] = {
+		/* The firmware display (DispmanX) IDs map to specific types in
+		 * a fixed manner.
+		 */
+		DRM_MODE_ENCODER_DSI,	/* MAIN_LCD */
+		DRM_MODE_ENCODER_DSI,	/* AUX_LCD */
+		DRM_MODE_ENCODER_TMDS,	/* HDMI0 */
+		DRM_MODE_ENCODER_TVDAC,	/* VEC */
+		DRM_MODE_ENCODER_NONE,	/* FORCE_LCD */
+		DRM_MODE_ENCODER_NONE,	/* FORCE_TV */
+		DRM_MODE_ENCODER_NONE,	/* FORCE_OTHER */
+		DRM_MODE_ENCODER_TMDS,	/* HDMI1 */
+		DRM_MODE_ENCODER_NONE,	/* FORCE_TV2 */
+	};
+	return display_number > ARRAY_SIZE(display_types) - 1 ?
+			DRM_MODE_ENCODER_NONE : display_types[display_number];
+}
+
 /* Firmware's structure for making an FB mbox call. */
 struct fbinfo_s {
 	u32 xres, yres, xres_virtual, yres_virtual;
@@ -258,10 +332,15 @@ static int vc4_plane_set_blank(struct dr
 			.plane_id = vc4_plane->mb.plane.plane_id,
 		}
 	};
+	static const char * const plane_types[] = {
+							"overlay",
+							"primary",
+							"cursor"
+						  };
 	int ret;
 
-	DRM_DEBUG_ATOMIC("[PLANE:%d:%s] overlay plane %s",
-			 plane->base.id, plane->name,
+	DRM_DEBUG_ATOMIC("[PLANE:%d:%s] %s plane %s",
+			 plane->base.id, plane->name, plane_types[plane->type],
 			 blank ? "blank" : "unblank");
 
 	if (blank)
@@ -595,13 +674,102 @@ fail:
 
 static void vc4_crtc_mode_set_nofb(struct drm_crtc *crtc)
 {
-	/* Everyting is handled in the planes. */
+	struct drm_device *dev = crtc->dev;
+	struct vc4_dev *vc4 = to_vc4_dev(dev);
+	struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
+	struct drm_display_mode *mode = &crtc->state->adjusted_mode;
+	struct vc4_fkms_encoder *vc4_encoder =
+					to_vc4_fkms_encoder(vc4_crtc->encoder);
+	struct mailbox_set_mode mb = {
+		.tag1 = { RPI_FIRMWARE_SET_TIMING,
+			  sizeof(struct set_timings), 0},
+	};
+	union hdmi_infoframe frame;
+	int ret;
+
+	ret = drm_hdmi_avi_infoframe_from_display_mode(&frame.avi, vc4_crtc->connector, mode);
+	if (ret < 0) {
+		DRM_ERROR("couldn't fill AVI infoframe\n");
+		return;
+	}
+
+	DRM_DEBUG_KMS("Setting mode for display num %u mode name %s, clk %d, h(disp %d, start %d, end %d, total %d, skew %d) v(disp %d, start %d, end %d, total %d, scan %d), vrefresh %d, par %u\n",
+		      vc4_crtc->display_number, mode->name, mode->clock,
+		      mode->hdisplay, mode->hsync_start, mode->hsync_end,
+		      mode->htotal, mode->hskew, mode->vdisplay,
+		      mode->vsync_start, mode->vsync_end, mode->vtotal,
+		      mode->vscan, mode->vrefresh, mode->picture_aspect_ratio);
+	mb.timings.display = vc4_crtc->display_number;
+
+	mb.timings.video_id_code = frame.avi.video_code;
+
+	mb.timings.clock = mode->clock;
+	mb.timings.hdisplay = mode->hdisplay;
+	mb.timings.hsync_start = mode->hsync_start;
+	mb.timings.hsync_end = mode->hsync_end;
+	mb.timings.htotal = mode->htotal;
+	mb.timings.hskew = mode->hskew;
+	mb.timings.vdisplay = mode->vdisplay;
+	mb.timings.vsync_start = mode->vsync_start;
+	mb.timings.vsync_end = mode->vsync_end;
+	mb.timings.vtotal = mode->vtotal;
+	mb.timings.vscan = mode->vscan;
+	mb.timings.vrefresh = 0;
+	mb.timings.flags = 0;
+	if (mode->flags & DRM_MODE_FLAG_PHSYNC)
+		mb.timings.flags |= TIMINGS_FLAGS_H_SYNC_POS;
+	if (mode->flags & DRM_MODE_FLAG_PVSYNC)
+		mb.timings.flags |= TIMINGS_FLAGS_V_SYNC_POS;
+
+	switch (frame.avi.picture_aspect) {
+	default:
+	case HDMI_PICTURE_ASPECT_NONE:
+		mode->flags |= TIMINGS_FLAGS_ASPECT_NONE;
+		break;
+	case HDMI_PICTURE_ASPECT_4_3:
+		mode->flags |= TIMINGS_FLAGS_ASPECT_4_3;
+		break;
+	case HDMI_PICTURE_ASPECT_16_9:
+		mode->flags |= TIMINGS_FLAGS_ASPECT_16_9;
+		break;
+	case HDMI_PICTURE_ASPECT_64_27:
+		mode->flags |= TIMINGS_FLAGS_ASPECT_64_27;
+		break;
+	case HDMI_PICTURE_ASPECT_256_135:
+		mode->flags |= TIMINGS_FLAGS_ASPECT_256_135;
+		break;
+	}
+
+	if (!vc4_encoder->hdmi_monitor)
+		mb.timings.flags |= TIMINGS_FLAGS_DVI;
+	else if (drm_default_rgb_quant_range(mode) ==
+					HDMI_QUANTIZATION_RANGE_LIMITED)
+		mb.timings.flags |= TIMINGS_FLAGS_RGB_LIMITED;
+
+	/*
+	FIXME: To implement
+	switch(mode->flag & DRM_MODE_FLAG_3D_MASK) {
+	case DRM_MODE_FLAG_3D_NONE:
+	case DRM_MODE_FLAG_3D_FRAME_PACKING:
+	case DRM_MODE_FLAG_3D_FIELD_ALTERNATIVE:
+	case DRM_MODE_FLAG_3D_LINE_ALTERNATIVE:
+	case DRM_MODE_FLAG_3D_SIDE_BY_SIDE_FULL:
+	case DRM_MODE_FLAG_3D_L_DEPTH:
+	case DRM_MODE_FLAG_3D_L_DEPTH_GFX_GFX_DEPTH:
+	case DRM_MODE_FLAG_3D_TOP_AND_BOTTOM:
+	case DRM_MODE_FLAG_3D_SIDE_BY_SIDE_HALF:
+	}
+	*/
+
+	ret = rpi_firmware_property_list(vc4->firmware, &mb, sizeof(mb));
 }
 
 static void vc4_crtc_disable(struct drm_crtc *crtc, struct drm_crtc_state *old_state)
 {
 	struct drm_plane *plane;
 
+	DRM_DEBUG_KMS("[CRTC:%d] vblanks off.\n",
+		      crtc->base.id);
 	drm_crtc_vblank_off(crtc);
 
 	/* Always turn the planes off on CRTC disable. In DRM, planes
@@ -619,6 +787,8 @@ static void vc4_crtc_enable(struct drm_c
 {
 	struct drm_plane *plane;
 
+	DRM_DEBUG_KMS("[CRTC:%d] vblanks on.\n",
+		      crtc->base.id);
 	drm_crtc_vblank_on(crtc);
 
 	/* Unblank the planes (if they're supposed to be displayed). */
@@ -637,12 +807,20 @@ vc4_crtc_mode_valid(struct drm_crtc *crt
 		return MODE_NO_DBLESCAN;
 	}
 
+	/* Limit the pixel clock until we can get dynamic HDMI 2.0 scrambling
+	 * working.
+	 */
+	if (mode->clock > 340000)
+		return MODE_CLOCK_HIGH;
+
 	return MODE_OK;
 }
 
 static int vc4_crtc_atomic_check(struct drm_crtc *crtc,
 				 struct drm_crtc_state *state)
 {
+	DRM_DEBUG_KMS("[CRTC:%d] crtc_atomic_check.\n",
+		      crtc->base.id);
 	return 0;
 }
 
@@ -652,6 +830,8 @@ static void vc4_crtc_atomic_flush(struct
 	struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
 	struct drm_device *dev = crtc->dev;
 
+	DRM_DEBUG_KMS("[CRTC:%d] crtc_atomic_flush.\n",
+		      crtc->base.id);
 	if (crtc->state->event) {
 		unsigned long flags;
 
@@ -719,6 +899,8 @@ static int vc4_fkms_enable_vblank(struct
 {
 	struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
 
+	DRM_DEBUG_KMS("[CRTC:%d] enable_vblank.\n",
+		      crtc->base.id);
 	vc4_crtc->vblank_enabled = true;
 
 	return 0;
@@ -728,6 +910,8 @@ static void vc4_fkms_disable_vblank(stru
 {
 	struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
 
+	DRM_DEBUG_KMS("[CRTC:%d] disable_vblank.\n",
+		      crtc->base.id);
 	vc4_crtc->vblank_enabled = false;
 }
 
@@ -762,36 +946,92 @@ static const struct of_device_id vc4_fir
 static enum drm_connector_status
 vc4_fkms_connector_detect(struct drm_connector *connector, bool force)
 {
+	DRM_DEBUG_KMS("connector detect.\n");
 	return connector_status_connected;
 }
 
-static int vc4_fkms_connector_get_modes(struct drm_connector *connector)
+static int vc4_fkms_get_edid_block(void *data, u8 *buf, unsigned int block,
+				   size_t len)
 {
-	struct drm_device *dev = connector->dev;
 	struct vc4_fkms_connector *fkms_connector =
-		to_vc4_fkms_connector(connector);
-	struct vc4_dev *vc4 = to_vc4_dev(dev);
-	struct drm_display_mode *mode;
-	struct mailbox_get_width_height wh = {
-		.tag1 = {RPI_FIRMWARE_FRAMEBUFFER_SET_DISPLAY_NUM, 4, 0, },
-		.display = fkms_connector->display_idx,
-		.tag2 = { RPI_FIRMWARE_FRAMEBUFFER_GET_PHYSICAL_WIDTH_HEIGHT,
-			  8, 0, },
+					(struct vc4_fkms_connector *)data;
+	struct vc4_dev *vc4 = fkms_connector->vc4_dev;
+	struct mailbox_get_edid mb = {
+		.tag1 = { RPI_FIRMWARE_GET_EDID_BLOCK_DISPLAY,
+			  128 + 8, 0 },
+		.block = block,
+		.display_number = fkms_connector->display_number,
 	};
-	int ret;
+	int ret = 0;
+
+	ret = rpi_firmware_property_list(vc4->firmware, &mb, sizeof(mb));
+
+	if (!ret)
+		memcpy(buf, mb.edid, len);
+
+	return ret;
+}
+
+static int vc4_fkms_connector_get_modes(struct drm_connector *connector)
+{
+	struct vc4_fkms_connector *fkms_connector =
+					to_vc4_fkms_connector(connector);
+	struct drm_encoder *encoder = fkms_connector->encoder;
+	struct vc4_fkms_encoder *vc4_encoder = to_vc4_fkms_encoder(encoder);
+	int ret = 0;
+	struct edid *edid;
+
+	edid = drm_do_get_edid(connector, vc4_fkms_get_edid_block,
+			       fkms_connector);
+
+	/* FIXME: Can we do CEC?
+	 * cec_s_phys_addr_from_edid(vc4->hdmi->cec_adap, edid);
+	 * if (!edid)
+	 *	return -ENODEV;
+	 */
+
+	vc4_encoder->hdmi_monitor = drm_detect_hdmi_monitor(edid);
 
-	ret = rpi_firmware_property_list(vc4->firmware, &wh, sizeof(wh));
+	if (edid && edid->input & DRM_EDID_INPUT_DIGITAL) {
+		vc4_encoder->rgb_range_selectable =
+			drm_rgb_quant_range_selectable(edid);
+	}
+
+	drm_connector_update_edid_property(connector, edid);
+	ret = drm_add_edid_modes(connector, edid);
+	kfree(edid);
+
+	return ret;
+}
+
+/* FIXME: Read LCD mode from the firmware. This is the DSI panel resolution. */
+static const struct drm_display_mode lcd_mode = {
+	DRM_MODE("800x480", DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED,
+		 25979400 / 1000,
+		 800, 800 + 1, 800 + 1 + 2, 800 + 1 + 2 + 46, 0,
+		 480, 480 + 7, 480 + 7 + 2, 480 + 7 + 2 + 21, 0,
+		 DRM_MODE_FLAG_INTERLACE)
+};
+
+static int vc4_fkms_lcd_connector_get_modes(struct drm_connector *connector)
+{
+	//struct vc4_fkms_connector *fkms_connector =
+	//				to_vc4_fkms_connector(connector);
+	//struct drm_encoder *encoder = fkms_connector->encoder;
+	//struct vc4_fkms_encoder *vc4_encoder = to_vc4_fkms_encoder(encoder);
+	struct drm_display_mode *mode;
+	//int ret = 0;
 
-	if (ret) {
-		DRM_ERROR("Failed to get screen size: %d (0x%08x 0x%08x)\n",
-			  ret, wh.wh[0], wh.wh[1]);
-		return 0;
+	mode = drm_mode_duplicate(connector->dev,
+				  &lcd_mode);
+	if (!mode) {
+		DRM_ERROR("Failed to create a new display mode\n");
+		return -ENOMEM;
 	}
 
-	mode = drm_cvt_mode(dev, wh.wh[0], wh.wh[1], 60 /* vrefresh */,
-			    0, 0, false);
 	drm_mode_probed_add(connector, mode);
 
+	/* We have one mode */
 	return 1;
 }
 
@@ -800,11 +1040,14 @@ vc4_fkms_connector_best_encoder(struct d
 {
 	struct vc4_fkms_connector *fkms_connector =
 		to_vc4_fkms_connector(connector);
+	DRM_DEBUG_KMS("best_connector.\n");
 	return fkms_connector->encoder;
 }
 
 static void vc4_fkms_connector_destroy(struct drm_connector *connector)
 {
+	DRM_DEBUG_KMS("[CONNECTOR:%d] destroy.\n",
+		      connector->base.id);
 	drm_connector_unregister(connector);
 	drm_connector_cleanup(connector);
 }
@@ -823,14 +1066,22 @@ static const struct drm_connector_helper
 	.best_encoder = vc4_fkms_connector_best_encoder,
 };
 
+static const struct drm_connector_helper_funcs vc4_fkms_lcd_conn_helper_funcs = {
+	.get_modes = vc4_fkms_lcd_connector_get_modes,
+	.best_encoder = vc4_fkms_connector_best_encoder,
+};
+
 static struct drm_connector *
 vc4_fkms_connector_init(struct drm_device *dev, struct drm_encoder *encoder,
-			u32 display_idx)
+			u32 display_num)
 {
 	struct drm_connector *connector = NULL;
 	struct vc4_fkms_connector *fkms_connector;
+	struct vc4_dev *vc4_dev = to_vc4_dev(dev);
 	int ret = 0;
 
+	DRM_DEBUG_KMS("connector_init, display_num %u\n", display_num);
+
 	fkms_connector = devm_kzalloc(dev->dev, sizeof(*fkms_connector),
 				      GFP_KERNEL);
 	if (!fkms_connector) {
@@ -840,11 +1091,21 @@ vc4_fkms_connector_init(struct drm_devic
 	connector = &fkms_connector->base;
 
 	fkms_connector->encoder = encoder;
-	fkms_connector->display_idx = display_idx;
-
-	drm_connector_init(dev, connector, &vc4_fkms_connector_funcs,
-			   DRM_MODE_CONNECTOR_HDMIA);
-	drm_connector_helper_add(connector, &vc4_fkms_connector_helper_funcs);
+	fkms_connector->display_number = display_num;
+	fkms_connector->display_type = vc4_get_display_type(display_num);
+	fkms_connector->vc4_dev = vc4_dev;
+
+	if (fkms_connector->display_type == DRM_MODE_ENCODER_DSI) {
+		drm_connector_init(dev, connector, &vc4_fkms_connector_funcs,
+				   DRM_MODE_CONNECTOR_DSI);
+		drm_connector_helper_add(connector,
+					 &vc4_fkms_lcd_conn_helper_funcs);
+	} else {
+		drm_connector_init(dev, connector, &vc4_fkms_connector_funcs,
+				   DRM_MODE_CONNECTOR_HDMIA);
+		drm_connector_helper_add(connector,
+					 &vc4_fkms_connector_helper_funcs);
+	}
 
 	connector->polled = (DRM_CONNECTOR_POLL_CONNECT |
 			     DRM_CONNECTOR_POLL_DISCONNECT);
@@ -865,6 +1126,7 @@ vc4_fkms_connector_init(struct drm_devic
 
 static void vc4_fkms_encoder_destroy(struct drm_encoder *encoder)
 {
+	DRM_DEBUG_KMS("Encoder_destroy\n");
 	drm_encoder_cleanup(encoder);
 }
 
@@ -874,10 +1136,12 @@ static const struct drm_encoder_funcs vc
 
 static void vc4_fkms_encoder_enable(struct drm_encoder *encoder)
 {
+	DRM_DEBUG_KMS("Encoder_enable\n");
 }
 
 static void vc4_fkms_encoder_disable(struct drm_encoder *encoder)
 {
+	DRM_DEBUG_KMS("Encoder_disable\n");
 }
 
 static const struct drm_encoder_helper_funcs vc4_fkms_encoder_helper_funcs = {
@@ -909,6 +1173,7 @@ static int vc4_fkms_create_screen(struct
 	crtc = &vc4_crtc->base;
 
 	vc4_crtc->display_number = display_ref;
+	vc4_crtc->display_type = vc4_get_display_type(display_ref);
 
 	/* Blank the firmware provided framebuffer */
 	rpi_firmware_property_list(vc4->firmware, &blank, sizeof(blank));
@@ -952,13 +1217,14 @@ static int vc4_fkms_create_screen(struct
 		return -ENOMEM;
 	vc4_crtc->encoder = &vc4_encoder->base;
 	vc4_encoder->base.possible_crtcs |= drm_crtc_mask(crtc) ;
+
 	drm_encoder_init(drm, &vc4_encoder->base, &vc4_fkms_encoder_funcs,
-			 DRM_MODE_ENCODER_TMDS, NULL);
+			 vc4_crtc->display_type, NULL);
 	drm_encoder_helper_add(&vc4_encoder->base,
 			       &vc4_fkms_encoder_helper_funcs);
 
 	vc4_crtc->connector = vc4_fkms_connector_init(drm, &vc4_encoder->base,
-						      display_idx);
+						      display_ref);
 	if (IS_ERR(vc4_crtc->connector)) {
 		ret = PTR_ERR(vc4_crtc->connector);
 		goto err_destroy_encoder;
--- a/include/soc/bcm2835/raspberrypi-firmware.h
+++ b/include/soc/bcm2835/raspberrypi-firmware.h
@@ -75,6 +75,7 @@ enum rpi_firmware_property_tag {
 	RPI_FIRMWARE_GET_DISPMANX_RESOURCE_MEM_HANDLE =       0x00030014,
 	RPI_FIRMWARE_GET_EDID_BLOCK =                         0x00030020,
 	RPI_FIRMWARE_GET_CUSTOMER_OTP =                       0x00030021,
+	RPI_FIRMWARE_GET_EDID_BLOCK_DISPLAY =                 0x00030023,
 	RPI_FIRMWARE_GET_DOMAIN_STATE =                       0x00030030,
 	RPI_FIRMWARE_GET_THROTTLED =                          0x00030046,
 	RPI_FIRMWARE_GET_CLOCK_MEASURED =                     0x00030047,
@@ -149,6 +150,7 @@ enum rpi_firmware_property_tag {
 	RPI_FIRMWARE_VCHIQ_INIT =                             0x00048010,
 
 	RPI_FIRMWARE_SET_PLANE =                              0x00048015,
+	RPI_FIRMWARE_SET_TIMING =                             0x00048017,
 
 	RPI_FIRMWARE_GET_COMMAND_LINE =                       0x00050001,
 	RPI_FIRMWARE_GET_DMA_CHANNELS =                       0x00060001,