mirror of
https://github.com/openwrt/openwrt.git
synced 2024-12-20 22:23:27 +00:00
7d7aa2fd92
This change makes the names of Broadcom targets consistent by using the common notation based on SoC/CPU ID (which is used internally anyway), bcmXXXX instead of brcmXXXX. This is even used for target TITLE in make menuconfig already, only the short target name used brcm so far. Despite, since subtargets range from bcm2708 to bcm2711, it seems appropriate to use bcm27xx instead of bcm2708 (again, as already done for BOARDNAME). This also renames the packages brcm2708-userland and brcm2708-gpu-fw. Signed-off-by: Adrian Schmutzler <freifunk@adrianschmutzler.de> Acked-by: Álvaro Fernández Rojas <noltari@gmail.com>
558 lines
17 KiB
Diff
558 lines
17 KiB
Diff
From 9536044338d9c341e805e288a58090c49a793638 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
|
|
@@ -88,11 +88,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 {
|
|
@@ -186,6 +235,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)
|
|
@@ -195,6 +245,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 *
|
|
@@ -212,7 +264,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 *
|
|
@@ -221,6 +275,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;
|
|
@@ -255,10 +329,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)
|
|
@@ -593,13 +672,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, mode, false);
|
|
+ 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
|
|
@@ -617,6 +785,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). */
|
|
@@ -635,12 +805,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;
|
|
}
|
|
|
|
@@ -650,6 +828,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;
|
|
|
|
@@ -717,6 +897,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;
|
|
@@ -726,6 +908,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;
|
|
}
|
|
|
|
@@ -760,36 +944,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;
|
|
}
|
|
|
|
@@ -798,11 +1038,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);
|
|
}
|
|
@@ -821,14 +1064,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) {
|
|
@@ -838,11 +1089,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);
|
|
@@ -863,6 +1124,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);
|
|
}
|
|
|
|
@@ -872,10 +1134,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 = {
|
|
@@ -907,6 +1171,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));
|
|
@@ -950,13 +1215,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
|
|
@@ -78,6 +78,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,
|
|
@@ -150,6 +151,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,
|