aboutsummaryrefslogtreecommitdiffstats
path: root/target/linux/bcm27xx/patches-5.4/950-0560-drm-vc4-crtc-Enable-and-disable-the-PV-in-atomic_ena.patch
blob: c5f06f20ea8416fbbe6b7ef7a10d6f591d525cb8 (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
From 7bbbfef1c98e832cbd55e66ac2d7f13ec0a2b11e Mon Sep 17 00:00:00 2001
From: Maxime Ripard <maxime@cerno.tech>
Date: Fri, 21 Feb 2020 14:34:31 +0100
Subject: [PATCH] drm/vc4: crtc: Enable and disable the PV in
 atomic_enable / disable

The VIDEN bit in the pixelvalve currently being used to enable or disable
the pixelvalve seems to not be enough in some situations, which whill end
up with the pixelvalve stalling.

In such a case, even re-enabling VIDEN doesn't bring it back and we need to
clear the FIFO. This can only be done if the pixelvalve is disabled though.

In order to overcome this, we can configure the pixelvalve during
mode_set_no_fb, but only enable it in atomic_enable and flush the FIFO
there, and in atomic_disable disable the pixelvalve again.

Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_crtc.c | 10 +++++++---
 1 file changed, 7 insertions(+), 3 deletions(-)

--- a/drivers/gpu/drm/vc4/vc4_crtc.c
+++ b/drivers/gpu/drm/vc4/vc4_crtc.c
@@ -374,9 +374,7 @@ static void vc4_crtc_config_pv(struct dr
 		   PV_CONTROL_TRIGGER_UNDERFLOW |
 		   PV_CONTROL_WAIT_HSTART |
 		   VC4_SET_FIELD(vc4_encoder->clock_select,
-				 PV_CONTROL_CLK_SELECT) |
-		   PV_CONTROL_FIFO_CLR |
-		   PV_CONTROL_EN);
+				 PV_CONTROL_CLK_SELECT));
 }
 
 static void vc4_crtc_mode_set_nofb(struct drm_crtc *crtc)
@@ -467,6 +465,8 @@ static void vc4_crtc_atomic_disable(stru
 	ret = wait_for(!(CRTC_READ(PV_V_CONTROL) & PV_VCONTROL_VIDEN), 1);
 	WARN_ONCE(ret, "Timeout waiting for !PV_VCONTROL_VIDEN\n");
 
+	CRTC_WRITE(PV_CONTROL, CRTC_READ(PV_CONTROL) & ~PV_CONTROL_EN);
+
 	if (HVS_READ(SCALER_DISPCTRLX(chan)) &
 	    SCALER_DISPCTRLX_ENABLE) {
 		HVS_WRITE(SCALER_DISPCTRLX(chan),
@@ -554,6 +554,10 @@ static void vc4_crtc_atomic_enable(struc
 
 	require_hvs_enabled(dev);
 
+	/* Reset the PV fifo. */
+	CRTC_WRITE(PV_CONTROL, CRTC_READ(PV_CONTROL) |
+		   PV_CONTROL_FIFO_CLR | PV_CONTROL_EN);
+
 	/* Enable vblank irq handling before crtc is started otherwise
 	 * drm_crtc_get_vblank() fails in vc4_crtc_update_dlist().
 	 */
href='#n297'>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,