mirror of
https://github.com/openwrt/openwrt.git
synced 2024-12-23 15:32:33 +00:00
f07e572f64
bcm2708: boot tested on RPi B+ v1.2 bcm2709: boot tested on RPi 3B v1.2 and RPi 4B v1.1 4G bcm2710: boot tested on RPi 3B v1.2 bcm2711: boot tested on RPi 4B v1.1 4G Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
139 lines
5.2 KiB
Diff
139 lines
5.2 KiB
Diff
From e8f126acd6da4f7d2e0df3c735fccf9971d95254 Mon Sep 17 00:00:00 2001
|
|
From: Dave Stevenson <dave.stevenson@raspberrypi.org>
|
|
Date: Tue, 21 May 2019 11:50:00 +0100
|
|
Subject: [PATCH] drm: vc4: Probe DPI/DSI timings from the firmware
|
|
|
|
For DPI and DSI displays query the firmware as to the configuration
|
|
and add it as the only mode for DRM.
|
|
|
|
In theory we can add plumbing for setting the DPI/DSI mode from
|
|
KMS, but this is not being added at present as the support frameworks
|
|
aren't present in the firmware.
|
|
|
|
Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
|
|
---
|
|
drivers/gpu/drm/vc4/vc4_firmware_kms.c | 64 ++++++++++++++++------
|
|
include/soc/bcm2835/raspberrypi-firmware.h | 1 +
|
|
2 files changed, 49 insertions(+), 16 deletions(-)
|
|
|
|
--- a/drivers/gpu/drm/vc4/vc4_firmware_kms.c
|
|
+++ b/drivers/gpu/drm/vc4/vc4_firmware_kms.c
|
|
@@ -248,7 +248,6 @@ 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 *
|
|
@@ -283,7 +282,7 @@ static u32 vc4_get_display_type(u32 disp
|
|
/* The firmware display (DispmanX) IDs map to specific types in
|
|
* a fixed manner.
|
|
*/
|
|
- DRM_MODE_ENCODER_DSI, /* MAIN_LCD */
|
|
+ DRM_MODE_ENCODER_DSI, /* MAIN_LCD - DSI or DPI */
|
|
DRM_MODE_ENCODER_DSI, /* AUX_LCD */
|
|
DRM_MODE_ENCODER_TMDS, /* HDMI0 */
|
|
DRM_MODE_ENCODER_TVDAC, /* VEC */
|
|
@@ -365,7 +364,6 @@ static void vc4_plane_atomic_update(stru
|
|
vc4_get_vc_image_fmt(drm_fmt->format);
|
|
struct vc4_fkms_plane *vc4_plane = to_vc4_fkms_plane(plane);
|
|
struct mailbox_set_plane *mb = &vc4_plane->mb;
|
|
- struct vc4_crtc *vc4_crtc = to_vc4_crtc(state->crtc);
|
|
int num_planes = fb->format->num_planes;
|
|
struct drm_display_mode *mode = &state->crtc->mode;
|
|
unsigned int rotation = SUPPORTED_ROTATIONS;
|
|
@@ -987,11 +985,6 @@ static int vc4_fkms_connector_get_modes(
|
|
|
|
vc4_encoder->hdmi_monitor = drm_detect_hdmi_monitor(edid);
|
|
|
|
- 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);
|
|
@@ -999,7 +992,9 @@ static int vc4_fkms_connector_get_modes(
|
|
return ret;
|
|
}
|
|
|
|
-/* FIXME: Read LCD mode from the firmware. This is the DSI panel resolution. */
|
|
+/* This is the DSI panel resolution. Use this as a default should the firmware
|
|
+ * not respond to our request for the timings.
|
|
+ */
|
|
static const struct drm_display_mode lcd_mode = {
|
|
DRM_MODE("800x480", DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED,
|
|
25979400 / 1000,
|
|
@@ -1010,15 +1005,52 @@ static const struct drm_display_mode lcd
|
|
|
|
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 vc4_fkms_connector *fkms_connector =
|
|
+ to_vc4_fkms_connector(connector);
|
|
+ struct vc4_dev *vc4 = fkms_connector->vc4_dev;
|
|
struct drm_display_mode *mode;
|
|
- //int ret = 0;
|
|
+ struct mailbox_set_mode mb = {
|
|
+ .tag1 = { RPI_FIRMWARE_GET_DISPLAY_TIMING,
|
|
+ sizeof(struct set_timings), 0},
|
|
+ .timings = { .display = fkms_connector->display_number },
|
|
+ };
|
|
+ struct drm_display_mode fw_mode;
|
|
+ int ret = 0;
|
|
+
|
|
+ ret = rpi_firmware_property_list(vc4->firmware, &mb, sizeof(mb));
|
|
+ if (!ret) {
|
|
+ /* Equivalent to DRM_MODE macro. */
|
|
+ memset(&fw_mode, 0, sizeof(fw_mode));
|
|
+ strncpy(fw_mode.name, "LCD_MODE", sizeof(fw_mode.name));
|
|
+ fw_mode.status = 0;
|
|
+ fw_mode.type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
|
|
+ fw_mode.clock = mb.timings.clock;
|
|
+ fw_mode.hdisplay = mb.timings.hdisplay;
|
|
+ fw_mode.hsync_start = mb.timings.hsync_start;
|
|
+ fw_mode.hsync_end = mb.timings.hsync_end;
|
|
+ fw_mode.htotal = mb.timings.htotal;
|
|
+ fw_mode.hskew = 0;
|
|
+ fw_mode.vdisplay = mb.timings.vdisplay;
|
|
+ fw_mode.vsync_start = mb.timings.vsync_start;
|
|
+ fw_mode.vsync_end = mb.timings.vsync_end;
|
|
+ fw_mode.vtotal = mb.timings.vtotal;
|
|
+ fw_mode.vscan = mb.timings.vscan;
|
|
+ if (mb.timings.flags & TIMINGS_FLAGS_H_SYNC_POS)
|
|
+ fw_mode.flags |= DRM_MODE_FLAG_PHSYNC;
|
|
+ else
|
|
+ fw_mode.flags |= DRM_MODE_FLAG_NHSYNC;
|
|
+ if (mb.timings.flags & TIMINGS_FLAGS_V_SYNC_POS)
|
|
+ fw_mode.flags |= DRM_MODE_FLAG_PVSYNC;
|
|
+ else
|
|
+ fw_mode.flags |= DRM_MODE_FLAG_NVSYNC;
|
|
+
|
|
+ mode = drm_mode_duplicate(connector->dev,
|
|
+ &fw_mode);
|
|
+ } else {
|
|
+ mode = drm_mode_duplicate(connector->dev,
|
|
+ &lcd_mode);
|
|
+ }
|
|
|
|
- mode = drm_mode_duplicate(connector->dev,
|
|
- &lcd_mode);
|
|
if (!mode) {
|
|
DRM_ERROR("Failed to create a new display mode\n");
|
|
return -ENOMEM;
|
|
--- a/include/soc/bcm2835/raspberrypi-firmware.h
|
|
+++ b/include/soc/bcm2835/raspberrypi-firmware.h
|
|
@@ -150,6 +150,7 @@ enum rpi_firmware_property_tag {
|
|
RPI_FIRMWARE_VCHIQ_INIT = 0x00048010,
|
|
|
|
RPI_FIRMWARE_SET_PLANE = 0x00048015,
|
|
+ RPI_FIRMWARE_GET_DISPLAY_TIMING = 0x00040017,
|
|
RPI_FIRMWARE_SET_TIMING = 0x00048017,
|
|
|
|
RPI_FIRMWARE_GET_COMMAND_LINE = 0x00050001,
|